diff options
author | Martin Willi <martin@revosec.ch> | 2011-11-16 18:24:14 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-20 17:30:41 +0100 |
commit | 3a470f303542dfb127eb8b17553da06a92892ebb (patch) | |
tree | a9a8b618c387f9026651a234d5b273c02d5e3be6 | |
parent | 2bcd51b3893b50acaad80ed2cc9c86e2e01f2f62 (diff) | |
download | strongswan-3a470f303542dfb127eb8b17553da06a92892ebb.tar.bz2 strongswan-3a470f303542dfb127eb8b17553da06a92892ebb.tar.xz |
Added limiting encoding of IKEv1 SA payloads
6 files changed, 231 insertions, 82 deletions
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c index efa748bd0..2a033b6a8 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.c +++ b/src/libcharon/encoding/payloads/proposal_substructure.c @@ -433,63 +433,77 @@ static void add_to_proposal_v2(proposal_t *proposal, } /** + * Map IKEv1 to IKEv2 algorithms + */ +typedef struct { + u_int16_t ikev1; + u_int16_t ikev2; +} algo_map_t; + +/** + * Encryption algorithm mapping + */ +static algo_map_t map_encr[] = { + { IKEV1_ENCR_DES_CBC, ENCR_DES }, + { IKEV1_ENCR_IDEA_CBC, ENCR_IDEA }, + { IKEV1_ENCR_BLOWFISH_CBC, ENCR_BLOWFISH }, + { IKEV1_ENCR_3DES_CBC, ENCR_3DES }, + { IKEV1_ENCR_CAST_CBC, ENCR_CAST }, + { IKEV1_ENCR_AES_CBC, ENCR_AES_CBC }, + { IKEV1_ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CBC }, +}; + +/** + * Integrity algorithm mapping + */ +static algo_map_t map_integ[] = { + { IKEV1_HASH_MD5, AUTH_HMAC_MD5_96 }, + { IKEV1_HASH_SHA1, AUTH_HMAC_SHA1_96 }, + { IKEV1_HASH_SHA2_256, AUTH_HMAC_SHA2_256_128 }, + { IKEV1_HASH_SHA2_384, AUTH_HMAC_SHA2_384_192 }, + { IKEV1_HASH_SHA2_512, AUTH_HMAC_SHA2_512_256 }, +}; + +/** + * PRF algorithm mapping + */ +static algo_map_t map_prf[] = { + { IKEV1_HASH_MD5, PRF_HMAC_MD5 }, + { IKEV1_HASH_SHA1, PRF_HMAC_SHA1 }, + { IKEV1_HASH_SHA2_256, PRF_HMAC_SHA2_256 }, + { IKEV1_HASH_SHA2_384, PRF_HMAC_SHA2_384 }, + { IKEV1_HASH_SHA2_512, PRF_HMAC_SHA2_512 }, +}; + +/** * Get IKEv2 algorithm from IKEv1 identifier */ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value) { - typedef struct { - u_int16_t ikev1; - u_int16_t ikev2; - } algo_map_t; - - static algo_map_t encr[] = { - { IKEV1_ENCR_DES_CBC, ENCR_DES }, - { IKEV1_ENCR_IDEA_CBC, ENCR_IDEA }, - { IKEV1_ENCR_BLOWFISH_CBC, ENCR_BLOWFISH }, - { IKEV1_ENCR_3DES_CBC, ENCR_3DES }, - { IKEV1_ENCR_CAST_CBC, ENCR_CAST }, - { IKEV1_ENCR_AES_CBC, ENCR_AES_CBC }, - { IKEV1_ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CBC }, - }; - static algo_map_t integ[] = { - { IKEV1_HASH_MD5, AUTH_HMAC_MD5_96 }, - { IKEV1_HASH_SHA1, AUTH_HMAC_SHA1_96 }, - { IKEV1_HASH_SHA2_256, AUTH_HMAC_SHA2_256_128 }, - { IKEV1_HASH_SHA2_384, AUTH_HMAC_SHA2_384_192 }, - { IKEV1_HASH_SHA2_512, AUTH_HMAC_SHA2_512_256 }, - }; - static algo_map_t prf[] = { - { IKEV1_HASH_MD5, PRF_HMAC_MD5 }, - { IKEV1_HASH_SHA1, PRF_HMAC_SHA1 }, - { IKEV1_HASH_SHA2_256, PRF_HMAC_SHA2_256 }, - { IKEV1_HASH_SHA2_384, PRF_HMAC_SHA2_384 }, - { IKEV1_HASH_SHA2_512, PRF_HMAC_SHA2_512 }, - }; - int i, count; - u_int16_t def; algo_map_t *map; + u_int16_t def; + int i, count; switch (type) { case ENCRYPTION_ALGORITHM: - map = encr; - count = countof(encr); + map = map_encr; + count = countof(map_encr); def = ENCR_UNDEFINED; break; case INTEGRITY_ALGORITHM: - map = integ; - count = countof(integ); + map = map_integ; + count = countof(map_integ); def = AUTH_UNDEFINED; break; case PSEUDO_RANDOM_FUNCTION: - map = prf; - count = countof(prf); + map = map_prf; + count = countof(map_prf); def = PRF_UNDEFINED; break; default: return 0; } - for (i = 0; i < count; i++) { if (map[i].ikev1 == value) @@ -501,6 +515,41 @@ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value) } /** + * Get IKEv1 algorithm from IKEv2 identifier + */ +static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value) +{ + algo_map_t *map; + int i, count; + + switch (type) + { + case ENCRYPTION_ALGORITHM: + map = map_encr; + count = countof(map_encr); + break; + case INTEGRITY_ALGORITHM: + map = map_integ; + count = countof(map_integ); + break; + case PSEUDO_RANDOM_FUNCTION: + map = map_prf; + count = countof(map_prf); + break; + default: + return 0; + } + for (i = 0; i < count; i++) + { + if (map[i].ikev2 == value) + { + return map[i].ikev1; + } + } + return 0; +} + +/** * Add an IKE transform to a proposal for IKEv1 */ static void add_to_proposal_v1_ike(proposal_t *proposal, @@ -606,7 +655,6 @@ METHOD(proposal_substructure_t, get_proposal, proposal_t*, default: break; } - return proposal; } @@ -663,32 +711,97 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type) return &this->public; } -/* - * Described in header. +/** + * Add an IKEv1 IKE proposal to the substructure */ -proposal_substructure_t *proposal_substructure_create_from_proposal( - payload_type_t type, proposal_t *proposal) +static void set_from_proposal_v1_ike(private_proposal_substructure_t *this, + proposal_t *proposal) { transform_substructure_t *transform; - private_proposal_substructure_t *this; u_int16_t alg, key_size; enumerator_t *enumerator; - payload_type_t subtype = TRANSFORM_SUBSTRUCTURE; - if (type == PROPOSAL_SUBSTRUCTURE_V1) + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1, + 0, IKEV1_TRANSID_KEY_IKE); + + enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) + { + alg = get_ikev1_from_alg(ENCRYPTION_ALGORITHM, alg); + if (alg) + { + transform->add_transform_attribute(transform, + transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, + TATTR_PH1_ENCRYPTION_ALGORITHM, alg)); + if (key_size) + { + transform->add_transform_attribute(transform, + transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, + TATTR_PH1_KEY_LENGTH, key_size)); + } + } + } + enumerator->destroy(enumerator); + + /* encode the integrity algorithm as hash and assume use the same PRF */ + enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { - /* TODO-IKEv1: IKEv1 specific proposal encoding */ - subtype = TRANSFORM_SUBSTRUCTURE_V1; + alg = get_ikev1_from_alg(INTEGRITY_ALGORITHM, alg); + if (alg) + { + transform->add_transform_attribute(transform, + transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, + TATTR_PH1_HASH_ALGORITHM, alg)); + } } + enumerator->destroy(enumerator); - this = (private_proposal_substructure_t*)proposal_substructure_create(type); + enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP); + while (enumerator->enumerate(enumerator, &alg, &key_size)) + { + transform->add_transform_attribute(transform, + transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, + TATTR_PH1_GROUP, alg)); + } + enumerator->destroy(enumerator); + + /* TODO-IKEv1: Add lifetime, auth and other attributes */ + + add_transform_substructure(this, transform); +} + +/** + * Add an IKEv1 ESP proposal to the substructure + */ +static void set_from_proposal_v1_esp(private_proposal_substructure_t *this, + proposal_t *proposal) +{ + /* TODO-IKEv1: add ESP proposal to transform substr */ +} + +/** + * Add an IKEv2 proposal to the substructure + */ +static void set_from_proposal_v2(private_proposal_substructure_t *this, + proposal_t *proposal) +{ + transform_substructure_t *transform; + u_int16_t alg, key_size; + enumerator_t *enumerator; /* encryption algorithm is only available in ESP */ enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM); while (enumerator->enumerate(enumerator, &alg, &key_size)) { - transform = transform_substructure_create_type(subtype, - ENCRYPTION_ALGORITHM, alg, key_size); + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE, + ENCRYPTION_ALGORITHM, alg); + if (key_size) + { + transform->add_transform_attribute(transform, + transform_attribute_create_value(TRANSFORM_ATTRIBUTE, + TATTR_IKEV2_KEY_LENGTH, key_size)); + } add_transform_substructure(this, transform); } enumerator->destroy(enumerator); @@ -697,8 +810,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal( enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM); while (enumerator->enumerate(enumerator, &alg, &key_size)) { - transform = transform_substructure_create_type(subtype, - INTEGRITY_ALGORITHM, alg, key_size); + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE, + INTEGRITY_ALGORITHM, alg); add_transform_substructure(this, transform); } enumerator->destroy(enumerator); @@ -707,8 +820,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal( enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION); while (enumerator->enumerate(enumerator, &alg, &key_size)) { - transform = transform_substructure_create_type(subtype, - PSEUDO_RANDOM_FUNCTION, alg, key_size); + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE, + PSEUDO_RANDOM_FUNCTION, alg); add_transform_substructure(this, transform); } enumerator->destroy(enumerator); @@ -717,8 +830,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal( enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP); while (enumerator->enumerate(enumerator, &alg, NULL)) { - transform = transform_substructure_create_type(subtype, - DIFFIE_HELLMAN_GROUP, alg, 0); + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE, + DIFFIE_HELLMAN_GROUP, alg); add_transform_substructure(this, transform); } enumerator->destroy(enumerator); @@ -727,27 +840,58 @@ proposal_substructure_t *proposal_substructure_create_from_proposal( enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS); while (enumerator->enumerate(enumerator, &alg, NULL)) { - transform = transform_substructure_create_type(subtype, - EXTENDED_SEQUENCE_NUMBERS, alg, 0); + transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE, + EXTENDED_SEQUENCE_NUMBERS, alg); add_transform_substructure(this, transform); } enumerator->destroy(enumerator); +} + +/* + * Described in header. + */ +proposal_substructure_t *proposal_substructure_create_from_proposal( + payload_type_t type, proposal_t *proposal) +{ + private_proposal_substructure_t *this; + u_int64_t spi64; + u_int32_t spi32; + + this = (private_proposal_substructure_t*)proposal_substructure_create(type); + if (type == PROPOSAL_SUBSTRUCTURE) + { + set_from_proposal_v2(this, proposal); + } + else + { + switch (proposal->get_protocol(proposal)) + { + case PROTO_IKE: + set_from_proposal_v1_ike(this, proposal); + break; + case PROTO_ESP: + set_from_proposal_v1_esp(this, proposal); + break; + default: + break; + } + } /* add SPI, if necessary */ switch (proposal->get_protocol(proposal)) { case PROTO_AH: case PROTO_ESP: - this->spi_size = this->spi.len = 4; - this->spi.ptr = malloc(this->spi_size); - *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal); + spi32 = proposal->get_spi(proposal); + this->spi = chunk_clone(chunk_from_thing(spi32)); + this->spi_size = this->spi.len; break; case PROTO_IKE: - if (proposal->get_spi(proposal)) + spi64 = proposal->get_spi(proposal); + if (spi64) { /* IKE only uses SPIS when rekeying, but on initial setup */ - this->spi_size = this->spi.len = 8; - this->spi.ptr = malloc(this->spi_size); - *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal); + this->spi = chunk_clone(chunk_from_thing(spi64)); + this->spi_size = this->spi.len; } break; default: diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c index 061226310..8f9dda411 100644 --- a/src/libcharon/encoding/payloads/sa_payload.c +++ b/src/libcharon/encoding/payloads/sa_payload.c @@ -272,12 +272,12 @@ METHOD(sa_payload_t, add_proposal, void, payload_type_t subtype = PROPOSAL_SUBSTRUCTURE; u_int count; - count = this->proposals->get_count(this->proposals); if (this->type == SECURITY_ASSOCIATION_V1) { subtype = PROPOSAL_SUBSTRUCTURE_V1; } substruct = proposal_substructure_create_from_proposal(subtype, proposal); + count = this->proposals->get_count(this->proposals); if (count > 0) { this->proposals->get_last(this->proposals, (void**)&last); diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c index e928dcddb..97bde8bce 100644 --- a/src/libcharon/encoding/payloads/transform_attribute.c +++ b/src/libcharon/encoding/payloads/transform_attribute.c @@ -283,13 +283,14 @@ transform_attribute_t *transform_attribute_create(payload_type_t type) /* * Described in header. */ -transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length) +transform_attribute_t *transform_attribute_create_value(payload_type_t type, + transform_attribute_type_t kind, u_int16_t value) { transform_attribute_t *attribute; - attribute = transform_attribute_create(TRANSFORM_ATTRIBUTE); - attribute->set_attribute_type(attribute, TATTR_IKEV2_KEY_LENGTH); - attribute->set_value(attribute, key_length); + attribute = transform_attribute_create(type); + attribute->set_attribute_type(attribute, kind); + attribute->set_value(attribute, value); return attribute; } diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h index 21bde46b8..eedb3be21 100644 --- a/src/libcharon/encoding/payloads/transform_attribute.h +++ b/src/libcharon/encoding/payloads/transform_attribute.h @@ -163,11 +163,14 @@ struct transform_attribute_t { transform_attribute_t *transform_attribute_create(payload_type_t type); /** - * Creates an transform_attribute_t of type KEY_LENGTH. + * Creates a two byte value attribute for a given attribute kind. * - * @param key_length key length in bytes + * @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1 + * @param kind attribute kind + * @param value fixed two byte value * @return transform_attribute_t object */ -transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length); +transform_attribute_t *transform_attribute_create_value(payload_type_t type, + transform_attribute_type_t kind, u_int16_t value); #endif /** TRANSFORM_ATTRIBUTE_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c index 141898a5b..54463cbc3 100644 --- a/src/libcharon/encoding/payloads/transform_substructure.c +++ b/src/libcharon/encoding/payloads/transform_substructure.c @@ -213,6 +213,13 @@ METHOD(payload_t, get_length, size_t, return this->transform_length; } +METHOD(transform_substructure_t, add_transform_attribute, void, + private_transform_substructure_t *this, transform_attribute_t *attribute) +{ + this->attributes->insert_last(this->attributes, attribute); + compute_length(this); +} + METHOD(transform_substructure_t, set_is_last_transform, void, private_transform_substructure_t *this, bool is_last) { @@ -272,6 +279,7 @@ transform_substructure_t *transform_substructure_create(payload_type_t type) .get_type = _get_type, .destroy = _destroy, }, + .add_transform_attribute = _add_transform_attribute, .set_is_last_transform = _set_is_last_transform, .get_transform_type_or_number = _get_transform_type_or_number, .get_transform_id = _get_transform_id, @@ -290,7 +298,7 @@ transform_substructure_t *transform_substructure_create(payload_type_t type) * Described in header */ transform_substructure_t *transform_substructure_create_type(payload_type_t type, - u_int8_t type_or_number, u_int16_t id, u_int16_t key_length) + u_int8_t type_or_number, u_int16_t id) { private_transform_substructure_t *this; @@ -305,12 +313,6 @@ transform_substructure_t *transform_substructure_create_type(payload_type_t type { this->transform_id_v1 = id; } - if (key_length) - { - this->attributes->insert_last(this->attributes, - (void*)transform_attribute_create_key_length(key_length)); - compute_length(this); - } return &this->public; } diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h index e6a7f8e4d..7b1071275 100644 --- a/src/libcharon/encoding/payloads/transform_substructure.h +++ b/src/libcharon/encoding/payloads/transform_substructure.h @@ -113,10 +113,9 @@ transform_substructure_t *transform_substructure_create(payload_type_t type); * @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1 * @param type_or_number Type (IKEv2) or number (IKEv1) of transform * @param id transform id specifc for the transform type - * @param key_length key length for key length attribute, 0 to omit * @return transform_substructure_t object */ transform_substructure_t *transform_substructure_create_type(payload_type_t type, - u_int8_t type_or_number, u_int16_t id, u_int16_t key_length); + u_int8_t type_or_number, u_int16_t id); #endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/ |