]> git.ipfire.org Git - thirdparty/strongswan.git/blobdiff - src/libcharon/encoding/payloads/proposal_substructure.c
proposal-substructure: Fix incorrect type for IKEv2 proposals
[thirdparty/strongswan.git] / src / libcharon / encoding / payloads / proposal_substructure.c
index 53e8cf3ad338c5ac23ebe119bd782590d9c1bddc..2d0cb1f829f0f89be820a80eb4d618cb9dd4c921 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
  * Copyright (C) 2005-2010 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -45,37 +45,37 @@ struct private_proposal_substructure_t {
        /**
         * Next payload type.
         */
-       u_int8_t  next_payload;
+       uint8_t  next_payload;
 
        /**
         * reserved byte
         */
-       u_int8_t reserved;
+       uint8_t reserved;
 
        /**
         * Length of this payload.
         */
-       u_int16_t proposal_length;
+       uint16_t proposal_length;
 
        /**
         * Proposal number.
         */
-       u_int8_t proposal_number;
+       uint8_t proposal_number;
 
        /**
         * Protocol ID.
         */
-       u_int8_t protocol_id;
+       uint8_t protocol_id;
 
        /**
         * SPI size of the following SPI.
         */
-       u_int8_t  spi_size;
+       uint8_t  spi_size;
 
        /**
         * Number of transforms.
         */
-       u_int8_t  transforms_count;
+       uint8_t  transforms_count;
 
        /**
         * SPI is stored as chunk.
@@ -224,26 +224,7 @@ typedef enum {
        /* FreeS/WAN proprietary */
        IKEV1_ESP_ENCR_SERPENT = 252,
        IKEV1_ESP_ENCR_TWOFISH = 253,
-} ikev1_esp_encr_transid_t;
-
-/**
- * IKEv1 Transform ID ESP authentication algorithm.
- */
-typedef enum {
-       IKEV1_ESP_AUTH_HMAC_MD5 = 1,
-       IKEV1_ESP_AUTH_HMAC_SHA = 2,
-       IKEV1_ESP_AUTH_DES_MAC = 3,
-       IKEV1_ESP_AUTH_KPDK = 4,
-       IKEV1_ESP_AUTH_HMAC_SHA2_256 = 5,
-       IKEV1_ESP_AUTH_HMAC_SHA2_384 = 6,
-       IKEV1_ESP_AUTH_HMAC_SHA2_512 = 7,
-       IKEV1_ESP_AUTH_HMAC_RIPEMD = 8,
-       IKEV1_ESP_AUTH_AES_XCBC_MAC = 9,
-       IKEV1_ESP_AUTH_SIG_RSA = 10,
-       IKEV1_ESP_AUTH_AES_128_GMAC = 11,
-       IKEV1_ESP_AUTH_AES_192_GMAC = 12,
-       IKEV1_ESP_AUTH_AES_256_GMAC = 13,
-} ikev1_esp_auth_transid_it;
+} ikev1_esp_transid_t;
 
 /**
  * IKEv1 Transform ID AH authentication algorithm.
@@ -263,6 +244,25 @@ typedef enum {
        IKEV1_AH_AES_256_GMAC = 13,
 } ikev1_ah_transid_t;
 
+/**
+ * IKEv1 authentication algorithm.
+ */
+typedef enum {
+       IKEV1_AUTH_HMAC_MD5 = 1,
+       IKEV1_AUTH_HMAC_SHA = 2,
+       IKEV1_AUTH_DES_MAC = 3,
+       IKEV1_AUTH_KPDK = 4,
+       IKEV1_AUTH_HMAC_SHA2_256 = 5,
+       IKEV1_AUTH_HMAC_SHA2_384 = 6,
+       IKEV1_AUTH_HMAC_SHA2_512 = 7,
+       IKEV1_AUTH_HMAC_RIPEMD = 8,
+       IKEV1_AUTH_AES_XCBC_MAC = 9,
+       IKEV1_AUTH_SIG_RSA = 10,
+       IKEV1_AUTH_AES_128_GMAC = 11,
+       IKEV1_AUTH_AES_192_GMAC = 12,
+       IKEV1_AUTH_AES_256_GMAC = 13,
+} ikev1_auth_algo_t;
+
 /**
  * IKEv1 ESP Encapsulation mode.
  */
@@ -345,7 +345,7 @@ METHOD(payload_t, verify, status_t,
        switch (this->protocol_id)
        {
                case PROTO_IPCOMP:
-                       if (this->spi.len != 2)
+                       if (this->spi.len != 2 && this->spi.len != 4)
                        {
                                DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
                                return FAILED;
@@ -479,24 +479,24 @@ METHOD(proposal_substructure_t, set_is_last_proposal, void,
 }
 
 METHOD(proposal_substructure_t, set_proposal_number, void,
-       private_proposal_substructure_t *this,u_int8_t proposal_number)
+       private_proposal_substructure_t *this,uint8_t proposal_number)
 {
        this->proposal_number = proposal_number;
 }
 
-METHOD(proposal_substructure_t, get_proposal_number, u_int8_t,
+METHOD(proposal_substructure_t, get_proposal_number, uint8_t,
        private_proposal_substructure_t *this)
 {
        return this->proposal_number;
 }
 
 METHOD(proposal_substructure_t, set_protocol_id, void,
-       private_proposal_substructure_t *this,u_int8_t protocol_id)
+       private_proposal_substructure_t *this,uint8_t protocol_id)
 {
        this->protocol_id = protocol_id;
 }
 
-METHOD(proposal_substructure_t, get_protocol_id, u_int8_t,
+METHOD(proposal_substructure_t, get_protocol_id, uint8_t,
        private_proposal_substructure_t *this)
 {
        return this->protocol_id;
@@ -518,7 +518,7 @@ METHOD(proposal_substructure_t, get_spi, chunk_t,
 }
 
 METHOD(proposal_substructure_t, get_cpi, bool,
-       private_proposal_substructure_t *this, u_int16_t *cpi)
+       private_proposal_substructure_t *this, uint16_t *cpi)
 {
 
        transform_substructure_t *transform;
@@ -536,7 +536,7 @@ METHOD(proposal_substructure_t, get_cpi, bool,
                {
                        if (cpi)
                        {
-                               *cpi = *((u_int16_t*)this->spi.ptr);
+                               *cpi = htons(untoh16(this->spi.ptr + this->spi.len - 2));
                        }
                        enumerator->destroy(enumerator);
                        return TRUE;
@@ -554,7 +554,7 @@ static void add_to_proposal_v2(proposal_t *proposal,
 {
        transform_attribute_t *tattr;
        enumerator_t *enumerator;
-       u_int16_t key_length = 0;
+       uint16_t key_length = 0;
 
        enumerator = transform->create_attribute_enumerator(transform);
        while (enumerator->enumerate(enumerator, &tattr))
@@ -576,8 +576,8 @@ static void add_to_proposal_v2(proposal_t *proposal,
  * Map IKEv1 to IKEv2 algorithms
  */
 typedef struct {
-       u_int16_t ikev1;
-       u_int16_t ikev2;
+       uint16_t ikev1;
+       uint16_t ikev2;
 } algo_map_t;
 
 /**
@@ -620,7 +620,7 @@ static algo_map_t map_prf[] = {
 /**
  * ESP encryption algorithm mapping
  */
-static algo_map_t map_esp_encr[] = {
+static algo_map_t map_esp[] = {
        { IKEV1_ESP_ENCR_DES_IV64,                              ENCR_DES_IV64 },
        { IKEV1_ESP_ENCR_DES,                                   ENCR_DES },
        { IKEV1_ESP_ENCR_3DES,                                  ENCR_3DES },
@@ -645,23 +645,6 @@ static algo_map_t map_esp_encr[] = {
        { IKEV1_ESP_ENCR_TWOFISH,                               ENCR_TWOFISH_CBC },
 };
 
-/**
- * ESP authentication algorithm mapping
- */
-static algo_map_t map_esp_auth[] = {
-       { IKEV1_ESP_AUTH_HMAC_MD5,                      AUTH_HMAC_MD5_96 },
-       { IKEV1_ESP_AUTH_HMAC_SHA,                      AUTH_HMAC_SHA1_96 },
-       { IKEV1_ESP_AUTH_DES_MAC,                       AUTH_DES_MAC },
-       { IKEV1_ESP_AUTH_KPDK,                          AUTH_KPDK_MD5 },
-       { IKEV1_ESP_AUTH_HMAC_SHA2_256,         AUTH_HMAC_SHA2_256_128 },
-       { IKEV1_ESP_AUTH_HMAC_SHA2_384,         AUTH_HMAC_SHA2_384_192 },
-       { IKEV1_ESP_AUTH_HMAC_SHA2_512,         AUTH_HMAC_SHA2_512_256 },
-       { IKEV1_ESP_AUTH_AES_XCBC_MAC,          AUTH_AES_XCBC_96 },
-       { IKEV1_ESP_AUTH_AES_128_GMAC,          AUTH_AES_128_GMAC },
-       { IKEV1_ESP_AUTH_AES_192_GMAC,          AUTH_AES_192_GMAC },
-       { IKEV1_ESP_AUTH_AES_256_GMAC,          AUTH_AES_256_GMAC },
-};
-
 /**
  * AH authentication algorithm mapping
  */
@@ -679,34 +662,30 @@ static algo_map_t map_ah[] = {
 };
 
 /**
- * Get IKEv2 algorithm from IKEv1 identifier
+ * ESP/AH authentication algorithm mapping
+ */
+static algo_map_t map_auth[] = {
+       { IKEV1_AUTH_HMAC_MD5,                  AUTH_HMAC_MD5_96 },
+       { IKEV1_AUTH_HMAC_SHA,                  AUTH_HMAC_SHA1_96 },
+       { IKEV1_AUTH_DES_MAC,                   AUTH_DES_MAC },
+       { IKEV1_AUTH_KPDK,                              AUTH_KPDK_MD5 },
+       { IKEV1_AUTH_HMAC_SHA2_256,             AUTH_HMAC_SHA2_256_128 },
+       { IKEV1_AUTH_HMAC_SHA2_384,             AUTH_HMAC_SHA2_384_192 },
+       { IKEV1_AUTH_HMAC_SHA2_512,             AUTH_HMAC_SHA2_512_256 },
+       { IKEV1_AUTH_AES_XCBC_MAC,              AUTH_AES_XCBC_96 },
+       { IKEV1_AUTH_AES_128_GMAC,              AUTH_AES_128_GMAC },
+       { IKEV1_AUTH_AES_192_GMAC,              AUTH_AES_192_GMAC },
+       { IKEV1_AUTH_AES_256_GMAC,              AUTH_AES_256_GMAC },
+};
+
+/**
+ * Map an IKEv1 to an IKEv2 identifier
  */
-static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
+static uint16_t ikev2_from_ikev1(algo_map_t *map, int count, uint16_t def,
+                                                                 uint16_t value)
 {
-       algo_map_t *map;
-       u_int16_t def;
-       int i, count;
+       int i;
 
-       switch (type)
-       {
-               case ENCRYPTION_ALGORITHM:
-                       map = map_encr;
-                       count = countof(map_encr);
-                       def = ENCR_UNDEFINED;
-                       break;
-               case INTEGRITY_ALGORITHM:
-                       map = map_integ;
-                       count = countof(map_integ);
-                       def = AUTH_UNDEFINED;
-                       break;
-               case PSEUDO_RANDOM_FUNCTION:
-                       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)
@@ -718,30 +697,12 @@ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
 }
 
 /**
- * Get IKEv1 algorithm from IKEv2 identifier
+ * Map an IKEv2 to an IKEv1 identifier
  */
-static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
+static uint16_t ikev1_from_ikev2(algo_map_t *map, int count, uint16_t value)
 {
-       algo_map_t *map;
-       int i, count;
+       int i;
 
-       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)
@@ -753,91 +714,100 @@ static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
 }
 
 /**
- * Get IKEv2 algorithm from IKEv1 ESP transaction ID
+ * Get IKEv2 algorithm from IKEv1 identifier
  */
-static u_int16_t get_alg_from_ikev1_transid(protocol_id_t proto,
-                                                                               transform_type_t type, u_int16_t value)
+static uint16_t get_alg_from_ikev1(transform_type_t type, uint16_t value)
 {
-       algo_map_t *map;
-       u_int16_t def;
-       int i, count;
-
        switch (type)
        {
                case ENCRYPTION_ALGORITHM:
-                       map = map_esp_encr;
-                       count = countof(map_esp_encr);
-                       def = ENCR_UNDEFINED;
-                       break;
+                       return ikev2_from_ikev1(map_encr, countof(map_encr),
+                                                                       ENCR_UNDEFINED, value);
                case INTEGRITY_ALGORITHM:
-                       if (proto == PROTO_ESP)
-                       {
-                               map = map_esp_auth;
-                               count = countof(map_esp_auth);
-                       }
-                       else
-                       {
-                               map = map_ah;
-                               count = countof(map_ah);
-                       }
-                       def = AUTH_UNDEFINED;
-                       break;
+                       return ikev2_from_ikev1(map_integ, countof(map_integ),
+                                                                       AUTH_UNDEFINED, value);
+               case PSEUDO_RANDOM_FUNCTION:
+                       return ikev2_from_ikev1(map_prf, countof(map_prf),
+                                                                       PRF_UNDEFINED, value);
                default:
                        return 0;
        }
-       for (i = 0; i < count; i++)
+}
+
+/**
+ * Get IKEv1 algorithm from IKEv2 identifier
+ */
+static uint16_t get_ikev1_from_alg(transform_type_t type, uint16_t value)
+{
+       switch (type)
        {
-               if (map[i].ikev1 == value)
-               {
-                       return map[i].ikev2;
-               }
+               case ENCRYPTION_ALGORITHM:
+                       return ikev1_from_ikev2(map_encr, countof(map_encr), value);
+               case INTEGRITY_ALGORITHM:
+                       return ikev1_from_ikev2(map_integ, countof(map_integ), value);
+               case PSEUDO_RANDOM_FUNCTION:
+                       return ikev1_from_ikev2(map_prf, countof(map_prf), value);
+               default:
+                       return 0;
        }
-       return def;
 }
 
 /**
- * Get IKEv1 ESP/AH transaction ID from IKEv2 identifier
+ * Get IKEv2 algorithm from IKEv1 ESP/AH transform ID
  */
-static u_int16_t get_ikev1_transid_from_alg(protocol_id_t proto,
-                                                                               transform_type_t type, u_int16_t value)
+static uint16_t get_alg_from_ikev1_transid(transform_type_t type,
+                                                                                       uint16_t value)
 {
-       algo_map_t *map;
-       int i, count;
-
        switch (type)
        {
                case ENCRYPTION_ALGORITHM:
-                       map = map_esp_encr;
-                       count = countof(map_esp_encr);
-                       break;
+                       return ikev2_from_ikev1(map_esp, countof(map_esp),
+                                                                       ENCR_UNDEFINED, value);
                case INTEGRITY_ALGORITHM:
-                       if (proto == PROTO_ESP)
-                       {
-                               map = map_esp_auth;
-                               count = countof(map_esp_auth);
-                       }
-                       else
-                       {
-                               map = map_ah;
-                               count = countof(map_ah);
-                       }
-                       break;
+                       return ikev2_from_ikev1(map_ah, countof(map_ah),
+                                                                       AUTH_UNDEFINED, value);
                default:
                        return 0;
        }
-       for (i = 0; i < count; i++)
+}
+
+/**
+ * Get IKEv1 ESP/AH transform ID from IKEv2 identifier
+ */
+static uint16_t get_ikev1_transid_from_alg(transform_type_t type,
+                                                                                       uint16_t value)
+{
+       switch (type)
        {
-               if (map[i].ikev2 == value)
-               {
-                       return map[i].ikev1;
-               }
+               case ENCRYPTION_ALGORITHM:
+                       return ikev1_from_ikev2(map_esp, countof(map_esp), value);
+               case INTEGRITY_ALGORITHM:
+                       return ikev1_from_ikev2(map_ah, countof(map_ah), value);
+               default:
+                       return 0;
        }
-       return 0;
 }
+
+/**
+ * Get IKEv1 authentication algorithm from IKEv2 identifier
+ */
+static uint16_t get_alg_from_ikev1_auth(uint16_t value)
+{
+       return ikev2_from_ikev1(map_auth, countof(map_auth), AUTH_UNDEFINED, value);
+}
+
+/**
+ * Get IKEv1 authentication algorithm from IKEv2 identifier
+ */
+static uint16_t get_ikev1_auth_from_alg(uint16_t value)
+{
+       return ikev1_from_ikev2(map_auth, countof(map_auth), value);
+}
+
 /**
  * Get IKEv1 authentication attribute from auth_method_t
  */
-static u_int16_t get_ikev1_auth(auth_method_t method)
+static uint16_t get_ikev1_auth(auth_method_t method)
 {
        switch (method)
        {
@@ -872,7 +842,7 @@ static u_int16_t get_ikev1_auth(auth_method_t method)
 /**
  * Get IKEv1 encapsulation mode
  */
-static u_int16_t get_ikev1_mode(ipsec_mode_t mode, encap_t udp)
+static uint16_t get_ikev1_mode(ipsec_mode_t mode, encap_t udp)
 {
        switch (mode)
        {
@@ -910,8 +880,8 @@ static void add_to_proposal_v1_ike(proposal_t *proposal,
        transform_attribute_type_t type;
        transform_attribute_t *tattr;
        enumerator_t *enumerator;
-       u_int16_t value, key_length = 0;
-       u_int16_t encr = ENCR_UNDEFINED;
+       uint16_t value, key_length = 0;
+       uint16_t encr = ENCR_UNDEFINED;
 
        enumerator = transform->create_attribute_enumerator(transform);
        while (enumerator->enumerate(enumerator, &tattr))
@@ -944,6 +914,11 @@ static void add_to_proposal_v1_ike(proposal_t *proposal,
 
        if (encr != ENCR_UNDEFINED)
        {
+               if (encr == ENCR_AES_CBC && !key_length)
+               {       /* some implementations don't send a Key Length attribute for
+                        * AES-128, early drafts of RFC 3602 allowed that */
+                       key_length = 128;
+               }
                proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
        }
 }
@@ -957,7 +932,8 @@ static void add_to_proposal_v1(proposal_t *proposal,
        transform_attribute_type_t type;
        transform_attribute_t *tattr;
        enumerator_t *enumerator;
-       u_int16_t encr, value, key_length = 0;
+       uint16_t encr, value, key_length = 0;
+       extended_sequence_numbers_t esn = NO_EXT_SEQ_NUMBERS;
 
        enumerator = transform->create_attribute_enumerator(transform);
        while (enumerator->enumerate(enumerator, &tattr))
@@ -971,28 +947,34 @@ static void add_to_proposal_v1(proposal_t *proposal,
                                break;
                        case TATTR_PH2_AUTH_ALGORITHM:
                                proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
-                                               get_alg_from_ikev1_transid(proto, INTEGRITY_ALGORITHM,
-                                                                                                  value), 0);
+                                                                               get_alg_from_ikev1_auth(value), 0);
                                break;
                        case TATTR_PH2_GROUP:
                                proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
                                                value, 0);
                                break;
+                       case TATTR_PH2_EXT_SEQ_NUMBER:
+                               esn = EXT_SEQ_NUMBERS;
+                               break;
                        default:
                                break;
                }
        }
        enumerator->destroy(enumerator);
 
-       /* TODO-IKEv1: handle ESN attribute */
-       proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
-                                                       NO_EXT_SEQ_NUMBERS, 0);
+       proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
        if (proto == PROTO_ESP)
        {
-               encr = get_alg_from_ikev1_transid(proto, ENCRYPTION_ALGORITHM,
+               encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
                                                                        transform->get_transform_id(transform));
                if (encr)
                {
+                       if (encr == ENCR_AES_CBC && !key_length)
+                       {       /* some implementations don't send a Key Length attribute for
+                                * AES-128, early drafts of RFC 3602 allowed that for IKE, some
+                                * also seem to do it for ESP */
+                               key_length = 128;
+                       }
                        proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
                                                                        key_length);
                }
@@ -1005,15 +987,15 @@ METHOD(proposal_substructure_t, get_proposals, void,
        transform_substructure_t *transform;
        enumerator_t *enumerator;
        proposal_t *proposal = NULL;
-       u_int64_t spi = 0;
+       uint64_t spi = 0;
 
        switch (this->spi.len)
        {
                case 4:
-                       spi =  *((u_int32_t*)this->spi.ptr);
+                       spi =  *((uint32_t*)this->spi.ptr);
                        break;
                case 8:
-                       spi = *((u_int64_t*)this->spi.ptr);
+                       spi = *((uint64_t*)this->spi.ptr);
                        break;
                default:
                        break;
@@ -1062,7 +1044,7 @@ METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
 /**
  * Get an attribute from any transform, 0 if not found
  */
-static u_int64_t get_attr(private_proposal_substructure_t *this,
+static uint64_t get_attr(private_proposal_substructure_t *this,
                                                  transform_attribute_type_t type)
 {
        enumerator_t *transforms, *attributes;
@@ -1091,7 +1073,7 @@ static u_int64_t get_attr(private_proposal_substructure_t *this,
 /**
  * Look up a lifetime duration of a given kind in all transforms
  */
-static u_int64_t get_life_duration(private_proposal_substructure_t *this,
+static uint64_t get_life_duration(private_proposal_substructure_t *this,
                                transform_attribute_type_t type_attr, ikev1_life_type_t type,
                                transform_attribute_type_t dur_attr)
 {
@@ -1125,10 +1107,10 @@ static u_int64_t get_life_duration(private_proposal_substructure_t *this,
        return 0;
 }
 
-METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
+METHOD(proposal_substructure_t, get_lifetime, uint32_t,
        private_proposal_substructure_t *this)
 {
-       u_int32_t duration;
+       uint32_t duration;
 
        switch (this->protocol_id)
        {
@@ -1149,7 +1131,7 @@ METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
        }
 }
 
-METHOD(proposal_substructure_t, get_lifebytes, u_int64_t,
+METHOD(proposal_substructure_t, get_lifebytes, uint64_t,
        private_proposal_substructure_t *this)
 {
        switch (this->protocol_id)
@@ -1279,11 +1261,11 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type)
  * Add an IKEv1 IKE proposal to the substructure
  */
 static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
-                                                                        proposal_t *proposal, u_int32_t lifetime,
+                                                                        proposal_t *proposal, uint32_t lifetime,
                                                                         auth_method_t method, int number)
 {
        transform_substructure_t *transform;
-       u_int16_t alg, key_size;
+       uint16_t alg, key_size;
        enumerator_t *enumerator;
 
        transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
@@ -1350,23 +1332,21 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
  * Add an IKEv1 ESP/AH proposal to the substructure
  */
 static void set_from_proposal_v1(private_proposal_substructure_t *this,
-                               proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+                               proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
                                ipsec_mode_t mode, encap_t udp, int number)
 {
        transform_substructure_t *transform = NULL;
-       u_int16_t alg, key_size;
+       uint16_t alg, transid, key_size;
        enumerator_t *enumerator;
-       protocol_id_t proto;
 
-       proto = proposal->get_protocol(proposal);
        enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
        if (enumerator->enumerate(enumerator, &alg, &key_size))
        {
-               alg = get_ikev1_transid_from_alg(proto, ENCRYPTION_ALGORITHM, alg);
-               if (alg)
+               transid = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
+               if (transid)
                {
                        transform = transform_substructure_create_type(
-                                                                       PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
+                                                               PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
                        if (key_size)
                        {
                                transform->add_transform_attribute(transform,
@@ -1380,17 +1360,21 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
        enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
        if (enumerator->enumerate(enumerator, &alg, &key_size))
        {
-               alg = get_ikev1_transid_from_alg(proto, INTEGRITY_ALGORITHM, alg);
+               transid = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
+               alg = get_ikev1_auth_from_alg(alg);
                if (alg)
                {
-                       if (!transform)
+                       if (!transform && transid)
                        {
                                transform = transform_substructure_create_type(
-                                                                       PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
+                                                               PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
+                       }
+                       if (transform)
+                       {
+                               transform->add_transform_attribute(transform,
+                                       transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
+                                                                               TATTR_PH2_AUTH_ALGORITHM, alg));
                        }
-                       transform->add_transform_attribute(transform,
-                               transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
-                                                                       TATTR_PH2_AUTH_ALGORITHM, alg));
                }
        }
        enumerator->destroy(enumerator);
@@ -1431,6 +1415,18 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
                                                        TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
        }
 
+       enumerator = proposal->create_enumerator(proposal,
+                       EXTENDED_SEQUENCE_NUMBERS);
+       while (enumerator->enumerate(enumerator, &alg, NULL))
+       {
+               if (alg == EXT_SEQ_NUMBERS)
+               {
+                       transform->add_transform_attribute(transform,
+                               transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
+                                                               TATTR_PH2_EXT_SEQ_NUMBER, alg));
+               }
+       }
+       enumerator->destroy(enumerator);
        add_transform_substructure(this, transform);
 }
 
@@ -1441,7 +1437,7 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
                                                                 proposal_t *proposal)
 {
        transform_substructure_t *transform;
-       u_int16_t alg, key_size;
+       uint16_t alg, key_size;
        enumerator_t *enumerator;
 
        /* encryption algorithm is only available in ESP */
@@ -1506,8 +1502,8 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
  */
 static void set_data(private_proposal_substructure_t *this, proposal_t *proposal)
 {
-       u_int64_t spi64;
-       u_int32_t spi32;
+       uint64_t spi64;
+       uint32_t spi32;
 
        /* add SPI, if necessary */
        switch (proposal->get_protocol(proposal))
@@ -1543,7 +1539,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
        private_proposal_substructure_t *this;
 
        this = (private_proposal_substructure_t*)
-                                                       proposal_substructure_create(PLV2_SECURITY_ASSOCIATION);
+                                               proposal_substructure_create(PLV2_PROPOSAL_SUBSTRUCTURE);
        set_from_proposal_v2(this, proposal);
        set_data(this, proposal);
 
@@ -1554,7 +1550,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
  * See header.
  */
 proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
-                       proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
+                       proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
                        auth_method_t auth, ipsec_mode_t mode, encap_t udp)
 {
        private_proposal_substructure_t *this;
@@ -1583,7 +1579,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
  * See header.
  */
 proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
-                       linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
+                       linked_list_t *proposals, uint32_t lifetime, uint64_t lifebytes,
                        auth_method_t auth, ipsec_mode_t mode, encap_t udp)
 {
        private_proposal_substructure_t *this = NULL;
@@ -1628,8 +1624,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
  * See header.
  */
 proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
-                       u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
-                       ipsec_mode_t mode, encap_t udp, u_int8_t proposal_number)
+                       uint32_t lifetime, uint64_t lifebytes, uint16_t cpi,
+                       ipsec_mode_t mode, encap_t udp, uint8_t proposal_number)
 {
        private_proposal_substructure_t *this;
        transform_substructure_t *transform;