#include <daemon.h>
/**
- * IKEv1 Value for a proposal payload.
+ * IKEv2 Value for a proposal payload.
*/
#define PROPOSAL_TYPE_VALUE 2
/**
* Transforms are stored in a linked_list_t.
*/
- linked_list_t * transforms;
+ linked_list_t *transforms;
+
+ /**
+ * Type of this payload, PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a Proposal substructure.
- *
- * The defined offsets are the positions in a object of type
- * private_proposal_substructure_t.
+ * Encoding rules for a IKEv1 Proposal substructure.
*/
-encoding_rule_t proposal_substructure_encodings[] = {
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
+ /* 1 Reserved Byte */
+ { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
+ /* Length of the whole proposal substructure payload*/
+ { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
+ /* proposal number is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
+ /* protocol ID is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
+ /* SPI Size has its own type */
+ { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
+ /* Number of transforms is a number of 8 bit */
+ { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
+ /* SPI is a chunk of variable size*/
+ { SPI, offsetof(private_proposal_substructure_t, spi) },
+ /* Transforms are stored in a transform substructure,
+ offset points to a linked_list_t pointer */
+ { TRANSFORMS_V1, offsetof(private_proposal_substructure_t, transforms) }
+};
+
+/**
+ * Encoding rules for a IKEv2 Proposal substructure.
+ */
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
/* 1 Reserved Byte */
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encryption.
+ */
+typedef enum {
+ IKEV1_ENCR_DES_CBC = 1,
+ IKEV1_ENCR_IDEA_CBC = 2,
+ IKEV1_ENCR_BLOWFISH_CBC = 3,
+ IKEV1_ENCR_RC5_R16_B64_CBC = 4,
+ IKEV1_ENCR_3DES_CBC = 5,
+ IKEV1_ENCR_CAST_CBC = 6,
+ IKEV1_ENCR_AES_CBC = 7,
+ IKEV1_ENCR_CAMELLIA_CBC = 8,
+ IKEV1_ENCR_LAST = 9,
+} ikev1_encryption_t;
+
+/**
+ * IKEv1 hash.
+ */
+typedef enum {
+ IKEV1_HASH_MD5 = 1,
+ IKEV1_HASH_SHA1 = 2,
+ IKEV1_HASH_TIGER = 3,
+ IKEV1_HASH_SHA2_256 = 4,
+ IKEV1_HASH_SHA2_384 = 5,
+ IKEV1_HASH_SHA2_512 = 6,
+} ikev1_hash_t;
+
+/**
+ * IKEv1 Transform ID IKE.
+ */
+typedef enum {
+ IKEV1_TRANSID_KEY_IKE = 1,
+} ikev1_ike_transid_t;
+
+/**
+ * IKEv1 Transform ID ESP.
+ */
+typedef enum {
+ IKEV1_TRANSID_ESP_DES_IV64 = 1,
+ IKEV1_TRANSID_ESP_DES = 2,
+ IKEV1_TRANSID_ESP_3DES = 3,
+ IKEV1_TRANSID_ESP_RC5 = 4,
+ IKEV1_TRANSID_ESP_IDEA = 5,
+ IKEV1_TRANSID_ESP_CAST = 6,
+ IKEV1_TRANSID_ESP_BLOWFISH = 7,
+ IKEV1_TRANSID_ESP_3IDEA = 8,
+ IKEV1_TRANSID_ESP_DES_IV32 = 9,
+ IKEV1_TRANSID_ESP_RC4 = 10,
+ IKEV1_TRANSID_ESP_NULL = 11,
+ IKEV1_TRANSID_ESP_AES_CBC = 12,
+} ikev1_esp_transid_t;
+
+/**
+ * IKEv1 ESP Encapsulation mode.
+ */
+typedef enum {
+ IKEV1_ENCAP_TUNNEL = 1,
+ IKEV1_ENCAP_TRANSPORT = 2,
+ IKEV1_ENCAP_UDP_TUNNEL = 3,
+ IKEV1_ENCAP_UDP_TRANSPORT = 4,
+} ikev1_esp_encap_t;
+
+/**
+ * IKEv1 Life duration types.
+ */
+typedef enum {
+ IKEV1_LIFE_TYPE_SECONDS = 1,
+ IKEV1_LIFE_TYPE_KILOBYTES = 2,
+} ikev1_life_type_t;
+
METHOD(payload_t, verify, status_t,
private_proposal_substructure_t *this)
{
private_proposal_substructure_t *this, encoding_rule_t **rules,
size_t *rule_count)
{
- *rules = proposal_substructure_encodings;
- *rule_count = countof(proposal_substructure_encodings);
+ if (this->type == PROPOSAL_SUBSTRUCTURE)
+ {
+ *rules = encodings_v2;
+ *rule_count = countof(encodings_v2);
+ }
+ else
+ {
+ *rules = encodings_v1;
+ *rule_count = countof(encodings_v1);
+ }
}
METHOD(payload_t, get_type, payload_type_t,
private_proposal_substructure_t *this)
{
- return PROPOSAL_SUBSTRUCTURE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
return this->spi;
}
+/**
+ * Add a transform to a proposal for IKEv2
+ */
+static void add_to_proposal_v2(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ transform_attribute_t *tattr;
+ enumerator_t *enumerator;
+ u_int16_t key_length = 0;
+
+ enumerator = transform->create_attribute_enumerator(transform);
+ while (enumerator->enumerate(enumerator, &tattr))
+ {
+ if (tattr->get_attribute_type(tattr) == TATTR_IKEV2_KEY_LENGTH)
+ {
+ key_length = tattr->get_value(tattr);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ proposal->add_algorithm(proposal,
+ transform->get_transform_type_or_number(transform),
+ transform->get_transform_id(transform), key_length);
+}
+
+/**
+ * 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;
+
+ switch (type)
+ {
+ case ENCRYPTION_ALGORITHM:
+ map = encr;
+ count = countof(encr);
+ def = ENCR_UNDEFINED;
+ break;
+ case INTEGRITY_ALGORITHM:
+ map = integ;
+ count = countof(integ);
+ def = AUTH_UNDEFINED;
+ break;
+ case PSEUDO_RANDOM_FUNCTION:
+ map = prf;
+ count = countof(prf);
+ def = PRF_UNDEFINED;
+ break;
+ default:
+ return 0;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (map[i].ikev1 == value)
+ {
+ return map[i].ikev2;
+ }
+ }
+ return def;
+}
+
+/**
+ * Add an IKE transform to a proposal for IKEv1
+ */
+static void add_to_proposal_v1_ike(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ 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;
+
+ enumerator = transform->create_attribute_enumerator(transform);
+ while (enumerator->enumerate(enumerator, &tattr))
+ {
+ type = tattr->get_attribute_type(tattr);
+ value = tattr->get_value(tattr);
+ switch (type)
+ {
+ case TATTR_PH1_ENCRYPTION_ALGORITHM:
+ encr = get_alg_from_ikev1(ENCRYPTION_ALGORITHM, value);
+ break;
+ case TATTR_PH1_KEY_LENGTH:
+ key_length = value;
+ break;
+ case TATTR_PH1_HASH_ALGORITHM:
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
+ get_alg_from_ikev1(INTEGRITY_ALGORITHM, value), 0);
+ proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
+ get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION, value), 0);
+ break;
+ case TATTR_PH1_GROUP:
+ proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+ value, 0);
+ break;
+ default:
+ /* TODO-IKEv1: lifetimes, authentication and other attributes */
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (encr != ENCR_UNDEFINED)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
+ }
+}
+
+/**
+ * Add an ESP transform to a proposal for IKEv1
+ */
+static void add_to_proposal_v1_esp(proposal_t *proposal,
+ transform_substructure_t *transform)
+{
+ /* TODO-IKEv1: create ESP proposals */
+}
+
METHOD(proposal_substructure_t, get_proposal, proposal_t*,
private_proposal_substructure_t *this)
{
- enumerator_t *enumerator;
transform_substructure_t *transform;
+ enumerator_t *enumerator;
proposal_t *proposal;
- u_int64_t spi;
proposal = proposal_create(this->protocol_id, this->proposal_number);
enumerator = this->transforms->create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &transform))
{
- transform_type_t transform_type;
- u_int16_t transform_id;
- u_int16_t key_length = 0;
-
- transform_type = transform->get_transform_type(transform);
- transform_id = transform->get_transform_id(transform);
- transform->get_key_length(transform, &key_length);
-
- proposal->add_algorithm(proposal, transform_type, transform_id, key_length);
+ if (this->type == PROPOSAL_SUBSTRUCTURE)
+ {
+ add_to_proposal_v2(proposal, transform);
+ }
+ else
+ {
+ switch (this->protocol_id)
+ {
+ case PROTO_IKE:
+ add_to_proposal_v1_ike(proposal, transform);
+ break;
+ case PROTO_ESP:
+ add_to_proposal_v1_esp(proposal, transform);
+ break;
+ default:
+ break;
+ }
+ /* TODO-IKEv1: We currently accept the first set of transforms
+ * in a substructure only. We need to return multiple proposals,
+ * but this messes up proposal numbering, as we don't support
+ * transform numbering. */
+ break;
+ }
}
enumerator->destroy(enumerator);
switch (this->spi.len)
{
case 4:
- spi = *((u_int32_t*)this->spi.ptr);
+ proposal->set_spi(proposal, *((u_int32_t*)this->spi.ptr));
break;
case 8:
- spi = *((u_int64_t*)this->spi.ptr);
+ proposal->set_spi(proposal, *((u_int64_t*)this->spi.ptr));
break;
default:
- spi = 0;
+ break;
}
- proposal->set_spi(proposal, spi);
return proposal;
}
private_proposal_substructure_t *this)
{
this->transforms->destroy_offset(this->transforms,
- offsetof(transform_substructure_t, destroy));
+ offsetof(payload_t, destroy));
chunk_free(&this->spi);
free(this);
}
/*
* Described in header.
*/
-proposal_substructure_t *proposal_substructure_create()
+proposal_substructure_t *proposal_substructure_create(payload_type_t type)
{
private_proposal_substructure_t *this;
.next_payload = NO_PAYLOAD,
.proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH,
.transforms = linked_list_create(),
+ .type = type,
);
return &this->public;
* Described in header.
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(
- proposal_t *proposal)
+ payload_type_t type, 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)
+ {
+ /* TODO-IKEv1: IKEv1 specific proposal encoding */
+ subtype = TRANSFORM_SUBSTRUCTURE_V1;
+ }
- this = (private_proposal_substructure_t*)proposal_substructure_create();
+ this = (private_proposal_substructure_t*)proposal_substructure_create(type);
/* 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(ENCRYPTION_ALGORITHM,
- alg, key_size);
+ transform = transform_substructure_create_type(subtype,
+ ENCRYPTION_ALGORITHM, alg, key_size);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
while (enumerator->enumerate(enumerator, &alg, &key_size))
{
- transform = transform_substructure_create_type(INTEGRITY_ALGORITHM,
- alg, key_size);
+ transform = transform_substructure_create_type(subtype,
+ INTEGRITY_ALGORITHM, alg, key_size);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
while (enumerator->enumerate(enumerator, &alg, &key_size))
{
- transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION,
- alg, key_size);
+ transform = transform_substructure_create_type(subtype,
+ PSEUDO_RANDOM_FUNCTION, alg, key_size);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
while (enumerator->enumerate(enumerator, &alg, NULL))
{
- transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP,
- alg, 0);
+ transform = transform_substructure_create_type(subtype,
+ DIFFIE_HELLMAN_GROUP, alg, 0);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
while (enumerator->enumerate(enumerator, &alg, NULL))
{
- transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS,
- alg, 0);
+ transform = transform_substructure_create_type(subtype,
+ EXTENDED_SEQUENCE_NUMBERS, alg, 0);
add_transform_substructure(this, transform);
}
enumerator->destroy(enumerator);
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
/**
- * Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
- *
- * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
+ * Class representing an IKEv1/IKEv2 proposal substructure.
*/
struct proposal_substructure_t {
/**
* Creates an empty proposal_substructure_t object
*
- * @return proposal_substructure_t object
+ * @param type PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+ * @return proposal_substructure_t object
*/
-proposal_substructure_t *proposal_substructure_create(void);
+proposal_substructure_t *proposal_substructure_create(payload_type_t type);
/**
* Creates a proposal_substructure_t from a proposal_t.
*
+ * @param type PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
* @param proposal proposal to build a substruct out of it
* @return proposal_substructure_t object
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(
- proposal_t *proposal);
+ payload_type_t type, proposal_t *proposal);
#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
METHOD(payload_t, verify, status_t,
private_sa_payload_t *this)
{
- int expected_number = 1, current_number;
+ int expected_number = 0, current_number;
status_t status = SUCCESS;
enumerator_t *enumerator;
proposal_substructure_t *substruct;
+ if (this->type == SECURITY_ASSOCIATION)
+ {
+ expected_number = 1;
+ }
+
/* check proposal numbering */
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void**)&substruct))
private_sa_payload_t *this, proposal_t *proposal)
{
proposal_substructure_t *substruct, *last;
+ payload_type_t subtype = PROPOSAL_SUBSTRUCTURE;
u_int count;
count = this->proposals->get_count(this->proposals);
- substruct = proposal_substructure_create_from_proposal(proposal);
+ if (this->type == SECURITY_ASSOCIATION_V1)
+ {
+ subtype = PROPOSAL_SUBSTRUCTURE_V1;
+ }
+ substruct = proposal_substructure_create_from_proposal(subtype, proposal);
if (count > 0)
{
this->proposals->get_last(this->proposals, (void**)&last);
linked_list_t *list;
proposal_t *proposal;
+ if (this->type == SECURITY_ASSOCIATION_V1)
+ { /* IKEv1 proposals start with 0 */
+ struct_number = ignore_struct_number = -1;
+ }
+
list = linked_list_create();
/* we do not support proposals split up to two proposal substructures, as
* AH+ESP bundles are not supported in RFC4301 anymore.
#include <encoding/payloads/encodings.h>
#include <library.h>
+ENUM(tattr_ph1_names, TATTR_PH1_ENCRYPTION_ALGORITHM, TATTR_PH1_GROUP_ORDER,
+ "ENCRYPTION_ALGORITHM",
+ "HASH_ALGORITHM",
+ "AUTH_METHOD",
+ "GROUP",
+ "GROUP_TYPE",
+ "GROUP_PRIME",
+ "GROUP_GENONE",
+ "GROUP_GENTWO",
+ "GROUP_CURVE_A",
+ "GROUP_CURVE_B",
+ "LIFE_TYPE",
+ "LIFE_DURATION",
+ "PRF",
+ "KEY_LENGTH",
+ "FIELD_SIZE",
+ "GROUP_ORDER",
+);
+
+ENUM(tattr_ph2_names, TATTR_PH2_SA_LIFE_TYPE, TATTR_PH2_EXT_SEQ_NUMBER,
+ "SA_LIFE_TYPE",
+ "SA_LIFE_DURATION",
+ "GROUP",
+ "ENCAP_MODE",
+ "AUTH_ALGORITHM",
+ "KEY_LENGTH",
+ "KEY_ROUNDS",
+ "COMP_DICT_SIZE",
+ "COMP_PRIV_ALGORITHM",
+ "ECN_TUNNEL",
+ "EXT_SEQ_NUMBER",
+);
+
+ENUM(tattr_ikev2_names, TATTR_IKEV2_KEY_LENGTH, TATTR_IKEV2_KEY_LENGTH,
+ "KEY_LENGTH",
+);
+
+
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
-};
-
-ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
- "ATTRIBUTE_UNDEFINED");
-ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
- "KEY_LENGTH");
-ENUM_END(transform_attribute_type_name, KEY_LENGTH);
+ /**
+ * Payload type, TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+ */
+ payload_type_t type;
+};
/**
- * Encoding rules to parse or generate a Transform attribute.
- *
- * The defined offsets are the positions in a object of type
- * private_transform_attribute_t.
+ * Encoding rules for IKEv1/IKEv2 transform attributes
*/
-encoding_rule_t transform_attribute_encodings[] = {
+static encoding_rule_t encodings[] = {
/* Flag defining the format of this payload */
{ ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
private_transform_attribute_t *this, encoding_rule_t **rules,
size_t *rule_count)
{
- *rules = transform_attribute_encodings;
- *rule_count = countof(transform_attribute_encodings);
+ *rules = encodings;
+ *rule_count = countof(encodings);
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_attribute_t *this)
{
- return TRANSFORM_ATTRIBUTE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
METHOD(transform_attribute_t, clone_, transform_attribute_t*,
private_transform_attribute_t *this)
{
- private_transform_attribute_t *new_clone;
+ private_transform_attribute_t *new;
- new_clone = (private_transform_attribute_t *)transform_attribute_create();
+ new = (private_transform_attribute_t*)transform_attribute_create(this->type);
- new_clone->attribute_format = this->attribute_format;
- new_clone->attribute_type = this->attribute_type;
- new_clone->attribute_length_or_value = this->attribute_length_or_value;
+ new->attribute_format = this->attribute_format;
+ new->attribute_type = this->attribute_type;
+ new->attribute_length_or_value = this->attribute_length_or_value;
- if (!new_clone->attribute_format)
+ if (!new->attribute_format)
{
- new_clone->attribute_value = chunk_clone(this->attribute_value);
+ new->attribute_value = chunk_clone(this->attribute_value);
}
- return &new_clone->public;
+ return &new->public;
}
METHOD2(payload_t, transform_attribute_t, destroy, void,
/*
* Described in header.
*/
-transform_attribute_t *transform_attribute_create()
+transform_attribute_t *transform_attribute_create(payload_type_t type)
{
private_transform_attribute_t *this;
.destroy = _destroy,
},
.attribute_format = TRUE,
+ .type = type,
);
return &this->public;
}
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
{
- transform_attribute_t *attribute = transform_attribute_create();
- attribute->set_attribute_type(attribute, KEY_LENGTH);
+ 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);
+
return attribute;
}
#include <library.h>
#include <encoding/payloads/payload.h>
-
/**
- * Type of the attribute, as in IKEv2 RFC 3.3.5.
+ * Type of the attribute.
*/
enum transform_attribute_type_t {
- ATTRIBUTE_UNDEFINED = 16384,
- KEY_LENGTH = 14
+ /** IKEv1 Phase 1 attributes */
+ TATTR_PH1_ENCRYPTION_ALGORITHM = 1,
+ TATTR_PH1_HASH_ALGORITHM = 2,
+ TATTR_PH1_AUTH_METHOD = 3,
+ TATTR_PH1_GROUP = 4,
+ TATTR_PH1_GROUP_TYPE = 5,
+ TATTR_PH1_GROUP_PRIME = 6,
+ TATTR_PH1_GROUP_GENONE = 7,
+ TATTR_PH1_GROUP_GENTWO = 8,
+ TATTR_PH1_GROUP_CURVE_A = 9,
+ TATTR_PH1_GROUP_CURVE_B = 10,
+ TATTR_PH1_LIFE_TYPE = 11,
+ TATTR_PH1_LIFE_DURATION = 12,
+ TATTR_PH1_PRF = 13,
+ TATTR_PH1_KEY_LENGTH = 14,
+ TATTR_PH1_FIELD_SIZE = 15,
+ TATTR_PH1_GROUP_ORDER = 16,
+ /** IKEv1 Phase 2 attributes */
+ TATTR_PH2_SA_LIFE_TYPE = 1,
+ TATTR_PH2_SA_LIFE_DURATION = 2,
+ TATTR_PH2_GROUP = 3,
+ TATTR_PH2_ENCAP_MODE = 4,
+ TATTR_PH2_AUTH_ALGORITHM = 5,
+ TATTR_PH2_KEY_LENGTH = 6,
+ TATTR_PH2_KEY_ROUNDS = 7,
+ TATTR_PH2_COMP_DICT_SIZE = 8,
+ TATTR_PH2_COMP_PRIV_ALGORITHM = 9,
+ TATTR_PH2_ECN_TUNNEL = 10,
+ TATTR_PH2_EXT_SEQ_NUMBER = 11,
+ /* IKEv2 key length attribute */
+ TATTR_IKEV2_KEY_LENGTH = 14,
+ /* undefined, private use attribute */
+ TATTR_UNDEFINED = 16384,
};
/**
- * enum name for transform_attribute_type_t.
+ * Enum names for IKEv1 Phase 1 transform_attribute_type_t.
*/
-extern enum_name_t *transform_attribute_type_names;
+extern enum_name_t *tattr_ph1_names;
/**
- * Class representing an IKEv2- TRANSFORM Attribute.
- *
- * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
+ * Enum names for IKEv1 Phase 2 transform_attribute_type_t.
+ */
+extern enum_name_t *tattr_ph2_names;
+
+/**
+ * Enum names for IKEv2 transform_attribute_type_t.
+ */
+extern enum_name_t *tattr_ikev2_names;
+
+
+/**
+ * Class representing an IKEv1/IKEv2 TRANSFORM Attribute.
*/
struct transform_attribute_t {
+
/**
* The payload_t interface.
*/
/**
* Creates an empty transform_attribute_t object.
*
+ * @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
* @return transform_attribute_t object
*/
-transform_attribute_t *transform_attribute_create(void);
+transform_attribute_t *transform_attribute_create(payload_type_t type);
/**
* Creates an transform_attribute_t of type KEY_LENGTH.
* Next payload type.
*/
u_int8_t next_payload;
+
/**
- * Reserved bytes
+ * Reserved byte
*/
- u_int8_t reserved[2];
+ u_int8_t reserved[3];
/**
* Length of this payload.
u_int16_t transform_length;
/**
- * Type of the transform.
+ * Type or number, Type of the transform in IKEv2, number in IKEv2.
*/
- u_int8_t transform_type;
+ u_int8_t transform_ton;
/**
- * Transform ID.
+ * Transform ID, as encoded in IKEv1.
*/
- u_int16_t transform_id;
+ u_int8_t transform_id_v1;
+
+ /**
+ * Transform ID, as encoded in IKEv2.
+ */
+ u_int16_t transform_id_v2;
/**
* Transforms Attributes are stored in a linked_list_t.
*/
linked_list_t *attributes;
+
+ /**
+ * Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+ */
+ payload_type_t type;
};
/**
- * Encoding rules to parse or generate a Transform substructure.
- *
- * The defined offsets are the positions in a object of type
- * private_transform_substructure_t.
+ * Encoding rules for TRANSFORM_SUBSTRUCTURE
*/
-encoding_rule_t transform_substructure_encodings[] = {
+static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
- { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
/* Length of the whole transform substructure*/
- { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
- /* transform type is a number of 8 bit */
- { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
+ /* transform type */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_ton) },
+ /* transform identifier, as used by IKEv1 */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
+ /* transform identifier, as used by IKEv2 */
+ { U_INT_16, offsetof(private_transform_substructure_t, transform_id_v2) },
+ /* Attributes in a transform attribute list */
+ { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
+};
+
+/**
+ * Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
- { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
- /* transform ID is a number of 8 bit */
- { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
- /* Attributes are stored in a transform attribute,
- offset points to a linked_list_t pointer */
- { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
+ /* Length of the whole transform substructure*/
+ { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
+ /* transform number */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_ton)},
+ /* transform identifier, as used by IKEv1 */
+ { U_INT_8, offsetof(private_transform_substructure_t, transform_id_v1) },
+ /* transform identifier, as used by IKEv2 */
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
+ { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[2]) },
+ /* Attributes in a transform attribute list */
+ { TRANSFORM_ATTRIBUTES_V1, offsetof(private_transform_substructure_t, attributes) }
};
/*
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- !Transform Type ! RESERVED ! Transform ID !
+ ! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
return FAILED;
}
- switch (this->transform_type)
- {
- case ENCRYPTION_ALGORITHM:
- case PSEUDO_RANDOM_FUNCTION:
- case INTEGRITY_ALGORITHM:
- case DIFFIE_HELLMAN_GROUP:
- case EXTENDED_SEQUENCE_NUMBERS:
- /* we don't check transform ID, we want to reply
- * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
- break;
- default:
- {
- DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
- return FAILED;
- }
- }
-
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
private_transform_substructure_t *this, encoding_rule_t **rules,
size_t *rule_count)
{
- *rules = transform_substructure_encodings;
- *rule_count = countof(transform_substructure_encodings);
+ if (this->type == TRANSFORM_ATTRIBUTE)
+ {
+ *rules = encodings_v2;
+ *rule_count = countof(encodings_v2);
+ }
+ else
+ {
+ *rules = encodings_v1;
+ *rule_count = countof(encodings_v1);
+ }
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_substructure_t *this)
{
- return TRANSFORM_SUBSTRUCTURE;
+ return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
/**
* recompute the length of the payload.
*/
-static void compute_length (private_transform_substructure_t *this)
+static void compute_length(private_transform_substructure_t *this)
{
enumerator_t *enumerator;
payload_t *attribute;
{
}
-METHOD(transform_substructure_t, get_transform_type, u_int8_t,
+METHOD(transform_substructure_t, get_transform_type_or_number, u_int8_t,
private_transform_substructure_t *this)
{
- return this->transform_type;
+ return this->transform_ton;
}
METHOD(transform_substructure_t, get_transform_id, u_int16_t,
private_transform_substructure_t *this)
{
- return this->transform_id;
+ if (this->type == TRANSFORM_SUBSTRUCTURE)
+ {
+ return this->transform_id_v2;
+ }
+ return this->transform_id_v1;
}
-METHOD(transform_substructure_t, get_key_length, status_t,
- private_transform_substructure_t *this, u_int16_t *key_length)
+METHOD(transform_substructure_t, create_attribute_enumerator, enumerator_t*,
+ private_transform_substructure_t *this)
{
- enumerator_t *enumerator;
- transform_attribute_t *attribute;
-
- enumerator = this->attributes->create_enumerator(this->attributes);
- while (enumerator->enumerate(enumerator, &attribute))
- {
- if (attribute->get_attribute_type(attribute) == KEY_LENGTH)
- {
- *key_length = attribute->get_value(attribute);
- enumerator->destroy(enumerator);
- return SUCCESS;
- }
- }
- enumerator->destroy(enumerator);
- return FAILED;
+ return this->attributes->create_enumerator(this->attributes);
}
METHOD2(payload_t, transform_substructure_t, destroy, void,
private_transform_substructure_t *this)
{
this->attributes->destroy_offset(this->attributes,
- offsetof(transform_attribute_t, destroy));
+ offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
-transform_substructure_t *transform_substructure_create()
+transform_substructure_t *transform_substructure_create(payload_type_t type)
{
private_transform_substructure_t *this;
.destroy = _destroy,
},
.set_is_last_transform = _set_is_last_transform,
- .get_transform_type = _get_transform_type,
+ .get_transform_type_or_number = _get_transform_type_or_number,
.get_transform_id = _get_transform_id,
- .get_key_length = _get_key_length,
+ .create_attribute_enumerator = _create_attribute_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH,
.attributes = linked_list_create(),
+ .type = type,
);
return &this->public;
}
/*
* Described in header
*/
-transform_substructure_t *transform_substructure_create_type(
- transform_type_t type, u_int16_t id, u_int16_t key_length)
+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)
{
private_transform_substructure_t *this;
- this = (private_transform_substructure_t*)transform_substructure_create();
+ this = (private_transform_substructure_t*)transform_substructure_create(type);
- this->transform_type = type;
- this->transform_id = id;
+ this->transform_ton = type_or_number;
+ if (type == TRANSFORM_SUBSTRUCTURE)
+ {
+ this->transform_id_v2 = id;
+ }
+ else
+ {
+ this->transform_id_v1 = id;
+ }
if (key_length)
{
this->attributes->insert_last(this->attributes,
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
/**
- * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
- *
- * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
+ * Class representing an IKEv1/IKEv2 transform substructure.
*/
struct transform_substructure_t {
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
- * get transform type of the current transform.
+ * Get transform type (IKEv2) or the transform number (IKEv1).
*
* @return Transform type of current transform substructure.
*/
- u_int8_t (*get_transform_type) (transform_substructure_t *this);
+ u_int8_t (*get_transform_type_or_number) (transform_substructure_t *this);
/**
* Get transform id of the current transform.
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
- * Get transform id of the current transform.
+ * Create an enumerator over transform attributes.
*
- * @param key_length The key length is written to this location
- * @return
- * - SUCCESS if a key length attribute is contained
- * - FAILED if no key length attribute is part of this
- * transform or key length uses more then 16 bit!
+ * @return enumerator over transform_attribute_t*
*/
- status_t (*get_key_length) (transform_substructure_t *this,
- u_int16_t *key_length);
+ enumerator_t* (*create_attribute_enumerator)(transform_substructure_t *this);
/**
* Destroys an transform_substructure_t object.
/**
* Creates an empty transform_substructure_t object.
*
+ * @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
* @return created transform_substructure_t object
*/
-transform_substructure_t *transform_substructure_create(void);
+transform_substructure_t *transform_substructure_create(payload_type_t type);
/**
* Creates an empty transform_substructure_t object.
*
- * @param type type of transform to create
- * @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
+ * @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(
- transform_type_t type, u_int16_t id, u_int16_t key_length);
+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);
#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/