diff options
author | Martin Willi <martin@revosec.ch> | 2012-01-19 11:11:22 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-20 17:31:37 +0100 |
commit | 8bcd9bd1611ab83d43774a99d01779e123e95f40 (patch) | |
tree | 55294a8f3774233cbb53aabdad02dc86cbaede16 /src | |
parent | 23f9e7a18dde587557e4ee8c34acc60211d947f3 (diff) | |
download | strongswan-8bcd9bd1611ab83d43774a99d01779e123e95f40.tar.bz2 strongswan-8bcd9bd1611ab83d43774a99d01779e123e95f40.tar.xz |
Added support to sync IKEv1 SAs key material in HA plugin
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.c | 75 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_ike.c | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.c | 8 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.h | 10 |
4 files changed, 95 insertions, 10 deletions
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index f0e6e5ecf..b20ced473 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -17,6 +17,7 @@ #include <daemon.h> #include <sa/ikev2/keymat_v2.h> +#include <sa/ikev1/keymat_v1.h> #include <processing/jobs/callback_job.h> typedef struct private_ha_dispatcher_t private_ha_dispatcher_t; @@ -77,6 +78,11 @@ struct ha_diffie_hellman_t { * Shared secret */ chunk_t secret; + + /** + * Own public value + */ + chunk_t pub; }; METHOD(diffie_hellman_t, dh_get_shared_secret, status_t, @@ -86,6 +92,12 @@ METHOD(diffie_hellman_t, dh_get_shared_secret, status_t, return SUCCESS; } +METHOD(diffie_hellman_t, dh_get_my_public_value, void, + ha_diffie_hellman_t *this, chunk_t *value) +{ + *value = chunk_clone(this->pub); +} + METHOD(diffie_hellman_t, dh_destroy, void, ha_diffie_hellman_t *this) { @@ -95,16 +107,18 @@ METHOD(diffie_hellman_t, dh_destroy, void, /** * Create a HA synced DH implementation */ -static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret) +static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub) { ha_diffie_hellman_t *this; INIT(this, .dh = { .get_shared_secret = _dh_get_shared_secret, + .get_my_public_value = _dh_get_my_public_value, .destroy = _dh_destroy, }, .secret = secret, + .pub = pub, ); return &this->dh; @@ -119,9 +133,11 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message ha_message_value_t value; enumerator_t *enumerator; ike_sa_t *ike_sa = NULL, *old_sa = NULL; + ike_version_t version = IKEV2; u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty; chunk_t secret = chunk_empty, old_skd = chunk_empty; + chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty; bool ok = FALSE; enumerator = message->create_attribute_enumerator(message); @@ -131,12 +147,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message { case HA_IKE_ID: ike_sa = ike_sa_create(value.ike_sa_id, - value.ike_sa_id->is_initiator(value.ike_sa_id), IKEV2); + value.ike_sa_id->is_initiator(value.ike_sa_id), version); break; case HA_IKE_REKEY_ID: old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, value.ike_sa_id); break; + case HA_IKE_VERSION: + version = value.u8; + break; case HA_NONCE_I: nonce_i = value.chunk; break; @@ -146,6 +165,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message case HA_SECRET: secret = value.chunk; break; + case HA_LOCAL_DH: + dh_local = value.chunk; + break; + case HA_REMOTE_DH: + dh_remote = value.chunk; + break; + case HA_PSK: + psk = value.chunk; + break; case HA_OLD_SKD: old_skd = value.chunk; break; @@ -189,7 +217,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); } charon->bus->set_sa(charon->bus, ike_sa); - dh = ha_diffie_hellman_create(secret); + dh = ha_diffie_hellman_create(secret, dh_local); if (ike_sa->get_version(ike_sa) == IKEV2) { keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); @@ -197,6 +225,22 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i, nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd); } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + shared_key_t *shared = NULL; + auth_method_t method = AUTH_RSA; + + if (psk.len) + { + method = AUTH_PSK; + shared = shared_key_create(SHARED_IKE, chunk_clone(psk)); + } + ok = keymat_v1->derive_ike_keys(keymat_v1, proposal, + dh, dh_remote, nonce_i, nonce_r, + ike_sa->get_id(ike_sa), method, shared); + DESTROY_IF(shared); + } dh->destroy(dh); if (ok) { @@ -518,7 +562,7 @@ static void process_child_add(private_ha_dispatcher_t *this, chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; chunk_t encr_i, integ_i, encr_r, integ_r; linked_list_t *local_ts, *remote_ts; - diffie_hellman_t *dh; + diffie_hellman_t *dh = NULL; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -612,16 +656,29 @@ static void process_child_add(private_ha_dispatcher_t *this, proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); } proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); - dh = ha_diffie_hellman_create(secret); + if (secret.len) + { + dh = ha_diffie_hellman_create(secret, chunk_empty); + } if (ike_sa->get_version(ike_sa) == IKEV2) { keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); - ok = keymat_v2->derive_child_keys(keymat_v2, - proposal, secret.ptr ? dh : NULL, nonce_i, nonce_r, - &encr_i, &integ_i, &encr_r, &integ_r); + ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); + } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + u_int32_t spi_i, spi_r; + + spi_i = initiator ? inbound_spi : outbound_spi; + spi_r = initiator ? outbound_spi : inbound_spi; + + ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); } - dh->destroy(dh); + DESTROY_IF(dh); if (!ok) { DBG1(DBG_CHD, "HA CHILD_SA key derivation failed"); diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index bcdd09b3e..bee6e2a6d 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -89,6 +89,7 @@ METHOD(listener_t, ike_keys, bool, } m = ha_message_create(HA_IKE_ADD); + m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa)); m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); if (rekey && rekey->get_version(rekey) == IKEV2) @@ -123,6 +124,17 @@ METHOD(listener_t, ike_keys, bool, m->add_attribute(m, HA_NONCE_R, nonce_r); m->add_attribute(m, HA_SECRET, secret); chunk_clear(&secret); + if (ike_sa->get_version(ike_sa) == IKEV1) + { + dh->get_my_public_value(dh, &secret); + m->add_attribute(m, HA_LOCAL_DH, secret); + chunk_free(&secret); + m->add_attribute(m, HA_REMOTE_DH, dh_other); + if (shared) + { + m->add_attribute(m, HA_PSK, shared->get_key(shared)); + } + } this->socket->push(this->socket, m); this->cache->cache(this->cache, ike_sa, m); diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index f98f78dd4..7df705a8a 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -213,6 +213,7 @@ METHOD(ha_message_t, add_attribute, void, break; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -263,6 +264,9 @@ METHOD(ha_message_t, add_attribute, void, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: case HA_OLD_SKD: { chunk_t chunk; @@ -426,6 +430,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, return TRUE; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -479,6 +484,9 @@ METHOD(enumerator_t, attribute_enumerate, bool, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: case HA_OLD_SKD: { size_t len; diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index 1f8eabd62..b937d39b5 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -76,7 +76,7 @@ extern enum_name_t *ha_message_type_names; enum ha_message_attribute_t { /** ike_sa_id_t*, to identify IKE_SA */ HA_IKE_ID = 1, - /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */ + /** ike_sa_id_t*, identifies IKE_SA which gets rekeyed */ HA_IKE_REKEY_ID, /** identification_t*, local identity */ HA_LOCAL_ID, @@ -142,6 +142,14 @@ enum ha_message_attribute_t { HA_SEGMENT, /** u_int16_t, Extended Sequence numbers */ HA_ESN, + /** u_int8_t, IKE version */ + HA_IKE_VERSION, + /** chunk_t, own DH public value */ + HA_LOCAL_DH, + /** chunk_t, remote DH public value */ + HA_REMOTE_DH, + /** chunk_t, shared secret for IKEv1 key derivation */ + HA_PSK, }; /** |