summaryrefslogtreecommitdiff
path: root/src/libcharon/encoding
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/encoding')
-rw-r--r--src/libcharon/encoding/message.c31
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.c14
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.h4
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c130
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c20
5 files changed, 150 insertions, 49 deletions
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 9bb8e5145..11e735a37 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -439,7 +439,7 @@ static payload_rule_t id_prot_i_rules[] = {
{NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
{NAT_D_DRAFT_00_03_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
{ID_V1, 0, 1, TRUE, FALSE},
- {CERTIFICATE_V1, 0, 2, TRUE, FALSE},
+ {CERTIFICATE_V1, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
{SIGNATURE_V1, 0, 1, TRUE, FALSE},
{HASH_V1, 0, 1, TRUE, FALSE},
{FRAGMENT_V1, 0, 1, FALSE, TRUE},
@@ -479,7 +479,7 @@ static payload_rule_t id_prot_r_rules[] = {
{NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
{NAT_D_DRAFT_00_03_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
{ID_V1, 0, 1, TRUE, FALSE},
- {CERTIFICATE_V1, 0, 2, TRUE, FALSE},
+ {CERTIFICATE_V1, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
{SIGNATURE_V1, 0, 1, TRUE, FALSE},
{HASH_V1, 0, 1, TRUE, FALSE},
{FRAGMENT_V1, 0, 1, FALSE, TRUE},
@@ -1268,17 +1268,38 @@ static char* get_string(private_message_t *this, char *buf, int len)
pos += written;
len -= written;
}
- if (payload->get_type(payload) == CONFIGURATION)
+ if (payload->get_type(payload) == CONFIGURATION ||
+ payload->get_type(payload) == CONFIGURATION_V1)
{
cp_payload_t *cp = (cp_payload_t*)payload;
enumerator_t *attributes;
configuration_attribute_t *attribute;
bool first = TRUE;
+ char *pfx;
+
+ switch (cp->get_type(cp))
+ {
+ case CFG_REQUEST:
+ pfx = "RQ(";
+ break;
+ case CFG_REPLY:
+ pfx = "RP(";
+ break;
+ case CFG_SET:
+ pfx = "S(";
+ break;
+ case CFG_ACK:
+ pfx = "A(";
+ break;
+ default:
+ pfx = "(";
+ break;
+ }
attributes = cp->create_attribute_enumerator(cp);
while (attributes->enumerate(attributes, &attribute))
{
- written = snprintf(pos, len, "%s%N", first ? "(" : " ",
+ written = snprintf(pos, len, "%s%N", first ? pfx : " ",
configuration_attribute_type_short_names,
attribute->get_type(attribute));
if (written >= len || written < 0)
@@ -1601,7 +1622,7 @@ METHOD(message_t, generate, status_t,
htoun32(lenpos, chunk.len + encryption->get_length(encryption));
}
this->payloads->insert_last(this->payloads, encryption);
- if (encryption->encrypt(encryption, chunk) != SUCCESS)
+ if (encryption->encrypt(encryption, this->message_id, chunk) != SUCCESS)
{
generator->destroy(generator);
return INVALID_STATE;
diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
index 6ba1b23a0..6a9f9c3bd 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.c
+++ b/src/libcharon/encoding/payloads/encryption_payload.c
@@ -309,10 +309,11 @@ static chunk_t append_header(private_encryption_payload_t *this, chunk_t assoc)
}
METHOD(encryption_payload_t, encrypt, status_t,
- private_encryption_payload_t *this, chunk_t assoc)
+ private_encryption_payload_t *this, u_int64_t mid, chunk_t assoc)
{
chunk_t iv, plain, padding, icv, crypt;
generator_t *generator;
+ iv_gen_t *iv_gen;
rng_t *rng;
size_t bs;
@@ -329,6 +330,13 @@ METHOD(encryption_payload_t, encrypt, status_t,
return NOT_SUPPORTED;
}
+ iv_gen = this->aead->get_iv_gen(this->aead);
+ if (!iv_gen)
+ {
+ DBG1(DBG_ENC, "encrypting encryption payload failed, no IV generator");
+ return NOT_SUPPORTED;
+ }
+
assoc = append_header(this, assoc);
generator = generator_create();
@@ -356,7 +364,7 @@ METHOD(encryption_payload_t, encrypt, status_t,
crypt = chunk_create(plain.ptr, plain.len + padding.len);
generator->destroy(generator);
- if (!rng->get_bytes(rng, iv.len, iv.ptr) ||
+ if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) ||
!rng->get_bytes(rng, padding.len - 1, padding.ptr))
{
DBG1(DBG_ENC, "encrypting encryption payload failed, no IV or padding");
@@ -388,7 +396,7 @@ METHOD(encryption_payload_t, encrypt, status_t,
}
METHOD(encryption_payload_t, encrypt_v1, status_t,
- private_encryption_payload_t *this, chunk_t iv)
+ private_encryption_payload_t *this, u_int64_t mid, chunk_t iv)
{
generator_t *generator;
chunk_t plain, padding;
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h
index 5c6069339..f4fc7d667 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.h
+++ b/src/libcharon/encoding/payloads/encryption_payload.h
@@ -71,13 +71,15 @@ struct encryption_payload_t {
/**
* Generate, encrypt and sign contained payloads.
*
+ * @param mid message ID
* @param assoc associated data
* @return
* - SUCCESS if encryption successful
* - FAILED if encryption failed
* - INVALID_STATE if aead not supplied, but needed
*/
- status_t (*encrypt) (encryption_payload_t *this, chunk_t assoc);
+ status_t (*encrypt) (encryption_payload_t *this, u_int64_t mid,
+ chunk_t assoc);
/**
* Decrypt, verify and parse contained payloads.
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 3cf22aefd..cb9b359b3 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -246,6 +246,24 @@ typedef enum {
} 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.
*/
typedef enum {
@@ -637,6 +655,22 @@ static algo_map_t map_esp_auth[] = {
};
/**
+ * 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
*/
static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
@@ -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
*/
-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;
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;
break;
case INTEGRITY_ALGORITHM:
- map = map_esp_auth;
- count = countof(map_esp_auth);
+ 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;
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;
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);
break;
case INTEGRITY_ALGORITHM:
- map = map_esp_auth;
- count = countof(map_esp_auth);
+ if (proto == PROTO_ESP)
+ {
+ map = map_esp_auth;
+ count = countof(map_esp_auth);
+ }
+ else
+ {
+ map = map_ah;
+ count = countof(map_ah);
+ }
break;
default:
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,
- transform_substructure_t *transform)
+static void add_to_proposal_v1(proposal_t *proposal,
+ transform_substructure_t *transform, protocol_id_t proto)
{
transform_attribute_type_t type;
transform_attribute_t *tattr;
@@ -911,7 +963,7 @@ static void add_to_proposal_v1_esp(proposal_t *proposal,
break;
case TATTR_PH2_AUTH_ALGORITHM:
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
- get_alg_from_ikev1_transid(INTEGRITY_ALGORITHM,
+ get_alg_from_ikev1_transid(proto, INTEGRITY_ALGORITHM,
value), 0);
break;
case TATTR_PH2_GROUP:
@@ -927,12 +979,15 @@ static void add_to_proposal_v1_esp(proposal_t *proposal,
/* TODO-IKEv1: handle ESN attribute */
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
NO_EXT_SEQ_NUMBERS, 0);
- encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
- transform->get_transform_id(transform));
- if (encr)
+ if (proto == PROTO_ESP)
{
- proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
- key_length);
+ encr = get_alg_from_ikev1_transid(proto, ENCRYPTION_ALGORITHM,
+ 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);
break;
case PROTO_ESP:
- add_to_proposal_v1_esp(proposal, transform);
+ case PROTO_AH:
+ add_to_proposal_v1(proposal, transform, this->protocol_id);
break;
default:
break;
@@ -1072,6 +1128,7 @@ METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
return get_life_duration(this, TATTR_PH1_LIFE_TYPE,
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
case PROTO_ESP:
+ case PROTO_AH:
duration = get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
IKEV1_LIFE_TYPE_SECONDS, TATTR_PH2_SA_LIFE_DURATION);
if (!duration)
@@ -1090,6 +1147,7 @@ METHOD(proposal_substructure_t, get_lifebytes, u_int64_t,
switch (this->protocol_id)
{
case PROTO_ESP:
+ case PROTO_AH:
return 1000 * get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
IKEV1_LIFE_TYPE_KILOBYTES, TATTR_PH2_SA_LIFE_DURATION);
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,
ipsec_mode_t mode, encap_t udp, int number)
{
transform_substructure_t *transform = NULL;
u_int16_t alg, 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(ENCRYPTION_ALGORITHM, alg);
+ alg = get_ikev1_transid_from_alg(proto, ENCRYPTION_ALGORITHM, alg);
if (alg)
{
- transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
- number, alg);
+ transform = transform_substructure_create_type(
+ TRANSFORM_SUBSTRUCTURE_V1, number, alg);
if (key_size)
{
transform->add_transform_attribute(transform,
@@ -1308,17 +1368,18 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
}
}
enumerator->destroy(enumerator);
- if (!transform)
- {
- return;
- }
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
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 (!transform)
+ {
+ transform = transform_substructure_create_type(
+ TRANSFORM_SUBSTRUCTURE_V1, number, alg);
+ }
transform->add_transform_attribute(transform,
transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
TATTR_PH2_AUTH_ALGORITHM, alg));
@@ -1326,6 +1387,11 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
}
enumerator->destroy(enumerator);
+ if (!transform)
+ {
+ return;
+ }
+
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
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);
break;
case PROTO_ESP:
- set_from_proposal_v1_esp(this, proposal, lifetime,
- lifebytes, mode, udp, 1);
+ case PROTO_AH:
+ set_from_proposal_v1(this, proposal, lifetime,
+ lifebytes, mode, udp, 1);
break;
default:
break;
@@ -1535,8 +1602,9 @@ proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
auth, ++number);
break;
case PROTO_ESP:
- set_from_proposal_v1_esp(this, proposal, lifetime,
- lifebytes, mode, udp, ++number);
+ case PROTO_AH:
+ set_from_proposal_v1(this, proposal, lifetime,
+ lifebytes, mode, udp, ++number);
break;
default:
break;
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 613412014..3a5bb43a6 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -341,10 +341,10 @@ METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
{
int current_proposal = -1, unsupported_proposal = -1;
enumerator_t *enumerator;
- proposal_substructure_t *substruct, *esp = NULL, *ipcomp = NULL;
+ proposal_substructure_t *substruct, *espah = NULL, *ipcomp = NULL;
linked_list_t *list;
- /* we currently only support the combination ESP+IPComp, find the first */
+ /* we currently only support the combination ESP|AH+IPComp, find the first */
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, &substruct))
{
@@ -355,25 +355,27 @@ METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
{
continue;
}
- if (protocol_id != PROTO_ESP && protocol_id != PROTO_IPCOMP)
+ if (protocol_id != PROTO_ESP && protocol_id != PROTO_AH &&
+ protocol_id != PROTO_IPCOMP)
{ /* unsupported combination */
- esp = ipcomp = NULL;
+ espah = ipcomp = NULL;
unsupported_proposal = current_proposal;
continue;
}
if (proposal_number != current_proposal)
{ /* start of a new proposal */
- if (esp && ipcomp)
+ if (espah && ipcomp)
{ /* previous proposal is valid */
break;
}
- esp = ipcomp = NULL;
+ espah = ipcomp = NULL;
current_proposal = proposal_number;
}
switch (protocol_id)
{
case PROTO_ESP:
- esp = substruct;
+ case PROTO_AH:
+ espah = substruct;
break;
case PROTO_IPCOMP:
ipcomp = substruct;
@@ -383,9 +385,9 @@ METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
enumerator->destroy(enumerator);
list = linked_list_create();
- if (esp && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
+ if (espah && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
{
- esp->get_proposals(esp, list);
+ espah->get_proposals(espah, list);
}
return list;
}