aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/tasks/main_mode.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/src/libcharon/sa/tasks/main_mode.c b/src/libcharon/sa/tasks/main_mode.c
index 2d9acf611..89ecaf408 100644
--- a/src/libcharon/sa/tasks/main_mode.c
+++ b/src/libcharon/sa/tasks/main_mode.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2011 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
@@ -18,6 +21,7 @@
#include <string.h>
#include <daemon.h>
+#include <sa/keymat_v1.h>
#include <crypto/diffie_hellman.h>
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/ke_payload.h>
@@ -77,6 +81,11 @@ struct private_main_mode_t {
diffie_hellman_t *dh;
/**
+ * Keymat derivation (from SA)
+ */
+ keymat_v1_t *keymat;
+
+ /**
* Received public DH value from peer
*/
chunk_t dh_value;
@@ -156,7 +165,8 @@ METHOD(task_t, build_i, status_t,
DBG1(DBG_IKE, "DH group selection failed");
return FAILED;
}
- this->dh = lib->crypto->create_dh(lib->crypto, group);
+ this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
+ group);
if (!this->dh)
{
DBG1(DBG_IKE, "negotiated DH group not supported");
@@ -355,6 +365,68 @@ METHOD(task_t, process_r, status_t,
}
}
+/**
+ * Lookup a shared secret for this IKE_SA
+ */
+static shared_key_t *lookup_shared_key(private_main_mode_t *this)
+{
+ host_t *me, *other;
+ identification_t *my_id, *other_id;
+ shared_key_t *shared_key;
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
+ other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
+ if (!my_id || !other_id)
+ {
+ DESTROY_IF(my_id);
+ DESTROY_IF(other_id);
+ return NULL;
+ }
+ shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id,
+ other_id);
+ if (!shared_key)
+ {
+ DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
+ }
+ my_id->destroy(my_id);
+ other_id->destroy(other_id);
+ return shared_key;
+}
+
+/**
+ * Derive key material for this IKE_SA
+ */
+static bool derive_keys(private_main_mode_t *this, chunk_t nonce_i,
+ chunk_t nonce_r)
+{
+ ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
+ shared_key_t *shared_key = NULL;
+ auth_class_t auth;
+
+ /* TODO-IKEv1: support other authentication classes */
+ auth = AUTH_CLASS_PSK;
+ switch (auth)
+ {
+ case AUTH_CLASS_PSK:
+ shared_key = lookup_shared_key(this);
+ break;
+ default:
+ break;
+ }
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ this->dh_value, nonce_i, nonce_r, id, auth, shared_key))
+ {
+ DESTROY_IF(shared_key);
+ return FALSE;
+ }
+ DESTROY_IF(shared_key);
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, nonce_i, nonce_r,
+ NULL);
+ return TRUE;
+}
+
METHOD(task_t, build_r, status_t,
private_main_mode_t *this, message_t *message)
{
@@ -388,6 +460,12 @@ METHOD(task_t, build_r, status_t,
rng->allocate_bytes(rng, NONCE_SIZE, &this->nonce_r);
rng->destroy(rng);
+ if (!derive_keys(this, this->nonce_i, this->nonce_r))
+ {
+ DBG1(DBG_IKE, "key derivation failed");
+ return FAILED;
+ }
+
nonce_payload = nonce_payload_create(NONCE_V1);
nonce_payload->set_nonce(nonce_payload, this->nonce_r);
message->add_payload(message, &nonce_payload->payload_interface);
@@ -564,6 +642,7 @@ main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator)
},
},
.ike_sa = ike_sa,
+ .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
.initiator = initiator,
.state = MM_INIT,
);