aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2011-11-16 18:24:14 +0100
committerMartin Willi <martin@revosec.ch>2012-03-20 17:30:41 +0100
commit3a470f303542dfb127eb8b17553da06a92892ebb (patch)
treea9a8b618c387f9026651a234d5b273c02d5e3be6
parent2bcd51b3893b50acaad80ed2cc9c86e2e01f2f62 (diff)
downloadstrongswan-3a470f303542dfb127eb8b17553da06a92892ebb.tar.bz2
strongswan-3a470f303542dfb127eb8b17553da06a92892ebb.tar.xz
Added limiting encoding of IKEv1 SA payloads
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c274
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c2
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c9
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.h9
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.c16
-rw-r--r--src/libcharon/encoding/payloads/transform_substructure.h3
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_ @}*/