Added limiting encoding of IKEv1 SA payloads
authorMartin Willi <martin@revosec.ch>
Wed, 16 Nov 2011 17:24:14 +0000 (18:24 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:30:41 +0000 (17:30 +0100)
src/libcharon/encoding/payloads/proposal_substructure.c
src/libcharon/encoding/payloads/sa_payload.c
src/libcharon/encoding/payloads/transform_attribute.c
src/libcharon/encoding/payloads/transform_attribute.h
src/libcharon/encoding/payloads/transform_substructure.c
src/libcharon/encoding/payloads/transform_substructure.h

index efa748b..2a033b6 100644 (file)
@@ -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:
index 0612263..8f9dda4 100644 (file)
@@ -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);
index e928dcd..97bde8b 100644 (file)
@@ -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;
 }
index 21bde46..eedb3be 100644 (file)
@@ -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_ @}*/
index 141898a..54463cb 100644 (file)
@@ -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;
 }
 
index e6a7f8e..7b10712 100644 (file)
@@ -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_ @}*/