ikev1: Support en-/decoding of SA payloads with AH algorithms
This commit is contained in:
@@ -245,6 +245,24 @@ typedef enum {
|
|||||||
IKEV1_ESP_AUTH_AES_256_GMAC = 13,
|
IKEV1_ESP_AUTH_AES_256_GMAC = 13,
|
||||||
} ikev1_esp_auth_transid_it;
|
} ikev1_esp_auth_transid_it;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IKEv1 Transform ID AH authentication algorithm.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
IKEV1_AH_HMAC_MD5 = 2,
|
||||||
|
IKEV1_AH_HMAC_SHA = 3,
|
||||||
|
IKEV1_AH_DES_MAC = 4,
|
||||||
|
IKEV1_AH_HMAC_SHA2_256 = 5,
|
||||||
|
IKEV1_AH_HMAC_SHA2_384 = 6,
|
||||||
|
IKEV1_AH_HMAC_SHA2_512 = 7,
|
||||||
|
IKEV1_AH_RIPEMD = 8,
|
||||||
|
IKEV1_AH_AES_XCBC_MAC = 9,
|
||||||
|
IKEV1_AH_RSA = 10,
|
||||||
|
IKEV1_AH_AES_128_GMAC = 11,
|
||||||
|
IKEV1_AH_AES_192_GMAC = 12,
|
||||||
|
IKEV1_AH_AES_256_GMAC = 13,
|
||||||
|
} ikev1_ah_transid_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IKEv1 ESP Encapsulation mode.
|
* IKEv1 ESP Encapsulation mode.
|
||||||
*/
|
*/
|
||||||
@@ -636,6 +654,22 @@ static algo_map_t map_esp_auth[] = {
|
|||||||
{ IKEV1_ESP_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
|
{ IKEV1_ESP_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AH authentication algorithm mapping
|
||||||
|
*/
|
||||||
|
static algo_map_t map_ah[] = {
|
||||||
|
{ IKEV1_AH_HMAC_MD5, AUTH_HMAC_MD5_96 },
|
||||||
|
{ IKEV1_AH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
|
||||||
|
{ IKEV1_AH_DES_MAC, AUTH_DES_MAC },
|
||||||
|
{ IKEV1_AH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
|
||||||
|
{ IKEV1_AH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
|
||||||
|
{ IKEV1_AH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
|
||||||
|
{ IKEV1_AH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
|
||||||
|
{ IKEV1_AH_AES_128_GMAC, AUTH_AES_128_GMAC },
|
||||||
|
{ IKEV1_AH_AES_192_GMAC, AUTH_AES_192_GMAC },
|
||||||
|
{ IKEV1_AH_AES_256_GMAC, AUTH_AES_256_GMAC },
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get IKEv2 algorithm from IKEv1 identifier
|
* Get IKEv2 algorithm from IKEv1 identifier
|
||||||
*/
|
*/
|
||||||
@@ -713,7 +747,8 @@ 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 ESP transaction ID
|
||||||
*/
|
*/
|
||||||
static u_int16_t get_alg_from_ikev1_transid(transform_type_t type, u_int16_t value)
|
static u_int16_t get_alg_from_ikev1_transid(protocol_id_t proto,
|
||||||
|
transform_type_t type, u_int16_t value)
|
||||||
{
|
{
|
||||||
algo_map_t *map;
|
algo_map_t *map;
|
||||||
u_int16_t def;
|
u_int16_t def;
|
||||||
@@ -727,8 +762,16 @@ static u_int16_t get_alg_from_ikev1_transid(transform_type_t type, u_int16_t val
|
|||||||
def = ENCR_UNDEFINED;
|
def = ENCR_UNDEFINED;
|
||||||
break;
|
break;
|
||||||
case INTEGRITY_ALGORITHM:
|
case INTEGRITY_ALGORITHM:
|
||||||
map = map_esp_auth;
|
if (proto == PROTO_ESP)
|
||||||
count = countof(map_esp_auth);
|
{
|
||||||
|
map = map_esp_auth;
|
||||||
|
count = countof(map_esp_auth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map = map_ah;
|
||||||
|
count = countof(map_ah);
|
||||||
|
}
|
||||||
def = AUTH_UNDEFINED;
|
def = AUTH_UNDEFINED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -745,9 +788,10 @@ static u_int16_t get_alg_from_ikev1_transid(transform_type_t type, u_int16_t val
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get IKEv1 ESP transaction ID from IKEv2 identifier
|
* Get IKEv1 ESP/AH transaction ID from IKEv2 identifier
|
||||||
*/
|
*/
|
||||||
static u_int16_t get_ikev1_transid_from_alg(transform_type_t type, u_int16_t value)
|
static u_int16_t get_ikev1_transid_from_alg(protocol_id_t proto,
|
||||||
|
transform_type_t type, u_int16_t value)
|
||||||
{
|
{
|
||||||
algo_map_t *map;
|
algo_map_t *map;
|
||||||
int i, count;
|
int i, count;
|
||||||
@@ -759,8 +803,16 @@ static u_int16_t get_ikev1_transid_from_alg(transform_type_t type, u_int16_t val
|
|||||||
count = countof(map_esp_encr);
|
count = countof(map_esp_encr);
|
||||||
break;
|
break;
|
||||||
case INTEGRITY_ALGORITHM:
|
case INTEGRITY_ALGORITHM:
|
||||||
map = map_esp_auth;
|
if (proto == PROTO_ESP)
|
||||||
count = countof(map_esp_auth);
|
{
|
||||||
|
map = map_esp_auth;
|
||||||
|
count = countof(map_esp_auth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map = map_ah;
|
||||||
|
count = countof(map_ah);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -889,10 +941,10 @@ static void add_to_proposal_v1_ike(proposal_t *proposal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an ESP transform to a proposal for IKEv1
|
* Add an ESP/AH transform to a proposal for IKEv1
|
||||||
*/
|
*/
|
||||||
static void add_to_proposal_v1_esp(proposal_t *proposal,
|
static void add_to_proposal_v1(proposal_t *proposal,
|
||||||
transform_substructure_t *transform)
|
transform_substructure_t *transform, protocol_id_t proto)
|
||||||
{
|
{
|
||||||
transform_attribute_type_t type;
|
transform_attribute_type_t type;
|
||||||
transform_attribute_t *tattr;
|
transform_attribute_t *tattr;
|
||||||
@@ -911,7 +963,7 @@ static void add_to_proposal_v1_esp(proposal_t *proposal,
|
|||||||
break;
|
break;
|
||||||
case TATTR_PH2_AUTH_ALGORITHM:
|
case TATTR_PH2_AUTH_ALGORITHM:
|
||||||
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
|
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
|
||||||
get_alg_from_ikev1_transid(INTEGRITY_ALGORITHM,
|
get_alg_from_ikev1_transid(proto, INTEGRITY_ALGORITHM,
|
||||||
value), 0);
|
value), 0);
|
||||||
break;
|
break;
|
||||||
case TATTR_PH2_GROUP:
|
case TATTR_PH2_GROUP:
|
||||||
@@ -927,12 +979,15 @@ static void add_to_proposal_v1_esp(proposal_t *proposal,
|
|||||||
/* TODO-IKEv1: handle ESN attribute */
|
/* TODO-IKEv1: handle ESN attribute */
|
||||||
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
|
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
|
||||||
NO_EXT_SEQ_NUMBERS, 0);
|
NO_EXT_SEQ_NUMBERS, 0);
|
||||||
encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
|
if (proto == PROTO_ESP)
|
||||||
transform->get_transform_id(transform));
|
|
||||||
if (encr)
|
|
||||||
{
|
{
|
||||||
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
|
encr = get_alg_from_ikev1_transid(proto, ENCRYPTION_ALGORITHM,
|
||||||
key_length);
|
transform->get_transform_id(transform));
|
||||||
|
if (encr)
|
||||||
|
{
|
||||||
|
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
|
||||||
|
key_length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,7 +1032,8 @@ METHOD(proposal_substructure_t, get_proposals, void,
|
|||||||
add_to_proposal_v1_ike(proposal, transform);
|
add_to_proposal_v1_ike(proposal, transform);
|
||||||
break;
|
break;
|
||||||
case PROTO_ESP:
|
case PROTO_ESP:
|
||||||
add_to_proposal_v1_esp(proposal, transform);
|
case PROTO_AH:
|
||||||
|
add_to_proposal_v1(proposal, transform, this->protocol_id);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1072,6 +1128,7 @@ METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
|
|||||||
return get_life_duration(this, TATTR_PH1_LIFE_TYPE,
|
return get_life_duration(this, TATTR_PH1_LIFE_TYPE,
|
||||||
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
|
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
|
||||||
case PROTO_ESP:
|
case PROTO_ESP:
|
||||||
|
case PROTO_AH:
|
||||||
duration = get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
|
duration = get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
|
||||||
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH2_SA_LIFE_DURATION);
|
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH2_SA_LIFE_DURATION);
|
||||||
if (!duration)
|
if (!duration)
|
||||||
@@ -1090,6 +1147,7 @@ METHOD(proposal_substructure_t, get_lifebytes, u_int64_t,
|
|||||||
switch (this->protocol_id)
|
switch (this->protocol_id)
|
||||||
{
|
{
|
||||||
case PROTO_ESP:
|
case PROTO_ESP:
|
||||||
|
case PROTO_AH:
|
||||||
return 1000 * get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
|
return 1000 * get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
|
||||||
IKEV1_LIFE_TYPE_KILOBYTES, TATTR_PH2_SA_LIFE_DURATION);
|
IKEV1_LIFE_TYPE_KILOBYTES, TATTR_PH2_SA_LIFE_DURATION);
|
||||||
case PROTO_IKE:
|
case PROTO_IKE:
|
||||||
@@ -1281,24 +1339,26 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an IKEv1 ESP proposal to the substructure
|
* Add an IKEv1 ESP/AH proposal to the substructure
|
||||||
*/
|
*/
|
||||||
static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
|
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, u_int32_t lifetime, u_int64_t lifebytes,
|
||||||
ipsec_mode_t mode, encap_t udp, int number)
|
ipsec_mode_t mode, encap_t udp, int number)
|
||||||
{
|
{
|
||||||
transform_substructure_t *transform = NULL;
|
transform_substructure_t *transform = NULL;
|
||||||
u_int16_t alg, key_size;
|
u_int16_t alg, key_size;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
|
protocol_id_t proto;
|
||||||
|
|
||||||
|
proto = proposal->get_protocol(proposal);
|
||||||
enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
|
enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
|
||||||
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
||||||
{
|
{
|
||||||
alg = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
|
alg = get_ikev1_transid_from_alg(proto, ENCRYPTION_ALGORITHM, alg);
|
||||||
if (alg)
|
if (alg)
|
||||||
{
|
{
|
||||||
transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
|
transform = transform_substructure_create_type(
|
||||||
number, alg);
|
TRANSFORM_SUBSTRUCTURE_V1, number, alg);
|
||||||
if (key_size)
|
if (key_size)
|
||||||
{
|
{
|
||||||
transform->add_transform_attribute(transform,
|
transform->add_transform_attribute(transform,
|
||||||
@@ -1308,17 +1368,18 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
|
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
|
||||||
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
||||||
{
|
{
|
||||||
alg = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
|
alg = get_ikev1_transid_from_alg(proto, INTEGRITY_ALGORITHM, alg);
|
||||||
if (alg)
|
if (alg)
|
||||||
{
|
{
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
transform = transform_substructure_create_type(
|
||||||
|
TRANSFORM_SUBSTRUCTURE_V1, number, alg);
|
||||||
|
}
|
||||||
transform->add_transform_attribute(transform,
|
transform->add_transform_attribute(transform,
|
||||||
transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
|
transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
|
||||||
TATTR_PH2_AUTH_ALGORITHM, alg));
|
TATTR_PH2_AUTH_ALGORITHM, alg));
|
||||||
@@ -1326,6 +1387,11 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
|
|||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
|
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
|
||||||
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
||||||
{
|
{
|
||||||
@@ -1493,8 +1559,9 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
|
|||||||
set_from_proposal_v1_ike(this, proposal, lifetime, auth, 1);
|
set_from_proposal_v1_ike(this, proposal, lifetime, auth, 1);
|
||||||
break;
|
break;
|
||||||
case PROTO_ESP:
|
case PROTO_ESP:
|
||||||
set_from_proposal_v1_esp(this, proposal, lifetime,
|
case PROTO_AH:
|
||||||
lifebytes, mode, udp, 1);
|
set_from_proposal_v1(this, proposal, lifetime,
|
||||||
|
lifebytes, mode, udp, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1535,8 +1602,9 @@ proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
|
|||||||
auth, ++number);
|
auth, ++number);
|
||||||
break;
|
break;
|
||||||
case PROTO_ESP:
|
case PROTO_ESP:
|
||||||
set_from_proposal_v1_esp(this, proposal, lifetime,
|
case PROTO_AH:
|
||||||
lifebytes, mode, udp, ++number);
|
set_from_proposal_v1(this, proposal, lifetime,
|
||||||
|
lifebytes, mode, udp, ++number);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user