Added limiting encoding of IKEv1 SA payloads

This commit is contained in:
Martin Willi 2011-11-16 18:24:14 +01:00
parent 2bcd51b389
commit 3a470f3035
6 changed files with 231 additions and 82 deletions

View File

@ -432,64 +432,78 @@ static void add_to_proposal_v2(proposal_t *proposal,
transform->get_transform_id(transform), key_length);
}
/**
* 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)
@ -500,6 +514,41 @@ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
return def;
}
/**
* 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
*/
@ -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))
{
/* TODO-IKEv1: IKEv1 specific proposal encoding */
subtype = TRANSFORM_SUBSTRUCTURE_V1;
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);
this = (private_proposal_substructure_t*)proposal_substructure_create(type);
/* 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))
{
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);
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:

View 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);

View 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;
}

View 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_ @}*/

View 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;
}

View 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_ @}*/