diff options
-rw-r--r-- | src/libcharon/encoding/generator.c | 1 | ||||
-rw-r--r-- | src/libcharon/encoding/parser.c | 11 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encodings.c | 1 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encodings.h | 5 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/ke_payload.c | 66 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/ke_payload.h | 34 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/payload.c | 3 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/child_create.c | 3 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/ike_init.c | 2 |
9 files changed, 96 insertions, 30 deletions
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c index 329b1c15f..662ebf977 100644 --- a/src/libcharon/encoding/generator.c +++ b/src/libcharon/encoding/generator.c @@ -450,6 +450,7 @@ METHOD(generator_t, generate_payload, void, case ADDRESS: case SPI: case KEY_EXCHANGE_DATA: + case KEY_EXCHANGE_DATA_V1: case NOTIFICATION_DATA: case NONCE_DATA: case ID_DATA: diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c index c2c60f06a..86ab212b8 100644 --- a/src/libcharon/encoding/parser.c +++ b/src/libcharon/encoding/parser.c @@ -729,6 +729,17 @@ METHOD(parser_t, parse_payload, status_t, } break; } + case KEY_EXCHANGE_DATA_V1: + { + if (payload_length < KE_PAYLOAD_V1_HEADER_LENGTH || + !parse_chunk(this, rule_number, output + rule->offset, + payload_length - KE_PAYLOAD_V1_HEADER_LENGTH)) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } case NOTIFICATION_DATA: { if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size || diff --git a/src/libcharon/encoding/payloads/encodings.c b/src/libcharon/encoding/payloads/encodings.c index d181d9303..582847048 100644 --- a/src/libcharon/encoding/payloads/encodings.c +++ b/src/libcharon/encoding/payloads/encodings.c @@ -30,6 +30,7 @@ ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA, "SPI_SIZE", "SPI", "KEY_EXCHANGE_DATA", + "KEY_EXCHANGE_DATA_V1", "NOTIFICATION_DATA", "PROPOSALS", "PROPOSALS_V1", diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h index 8c9fb866c..0e9a44e92 100644 --- a/src/libcharon/encoding/payloads/encodings.h +++ b/src/libcharon/encoding/payloads/encodings.h @@ -197,6 +197,11 @@ enum encoding_type_t { KEY_EXCHANGE_DATA, /** + * Same as KEY_EXCHANGE_DATA, but for KEY_EXCHANGE_V1 + */ + KEY_EXCHANGE_DATA_V1, + + /** * Representating a Notification field. * * When generating the content of the chunkt pointing to diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c index 999d73192..53edaf4f4 100644 --- a/src/libcharon/encoding/payloads/ke_payload.c +++ b/src/libcharon/encoding/payloads/ke_payload.c @@ -67,15 +67,17 @@ struct private_ke_payload_t { * Key Exchange Data of this KE payload. */ chunk_t key_exchange_data; + + /** + * Payload type, KEY_EXCHANGE or KEY_EXCHANGE_V1 + */ + payload_type_t type; }; /** - * Encoding rules to parse or generate a IKEv2-KE Payload. - * - * The defined offsets are the positions in a object of type - * private_ke_payload_t. + * Encoding rules for IKEv2 key exchange payload. */ -encoding_rule_t ke_payload_encodings[] = { +static encoding_rule_t encodings_v2[] = { /* 1 Byte next payload type, stored in the field next_payload */ { U_INT_8, offsetof(private_ke_payload_t, next_payload) }, /* the critical bit */ @@ -96,7 +98,7 @@ encoding_rule_t ke_payload_encodings[] = { { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])}, { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])}, /* Key Exchange Data is from variable size */ - { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)} + { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}, }; /* @@ -113,6 +115,30 @@ encoding_rule_t ke_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +static encoding_rule_t encodings_v1[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_ke_payload_t, next_payload) }, + /* Reserved Byte */ + { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])}, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) }, + /* Key Exchange Data is from variable size */ + { KEY_EXCHANGE_DATA_V1, offsetof(private_ke_payload_t, key_exchange_data)}, +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload ! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Key Exchange Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + + METHOD(payload_t, verify, status_t, private_ke_payload_t *this) { @@ -122,14 +148,22 @@ METHOD(payload_t, verify, status_t, METHOD(payload_t, get_encoding_rules, void, private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { - *rules = ke_payload_encodings; - *rule_count = countof(ke_payload_encodings); + if (this->type == KEY_EXCHANGE) + { + *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_ke_payload_t *this) { - return KEY_EXCHANGE; + return this->type; } METHOD(payload_t, get_next_type, payload_type_t, @@ -172,7 +206,7 @@ METHOD2(payload_t, ke_payload_t, destroy, void, /* * Described in header */ -ke_payload_t *ke_payload_create() +ke_payload_t *ke_payload_create(payload_type_t type) { private_ke_payload_t *this; @@ -194,20 +228,26 @@ ke_payload_t *ke_payload_create() .next_payload = NO_PAYLOAD, .payload_length = KE_PAYLOAD_HEADER_LENGTH, .dh_group_number = MODP_NONE, + .type = type, ); + if (type == KEY_EXCHANGE_V1) + { + this->payload_length = KE_PAYLOAD_V1_HEADER_LENGTH; + } return &this->public; } /* * Described in header */ -ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh) +ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type, + diffie_hellman_t *dh) { - private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(); + private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type); dh->get_my_public_value(dh, &this->key_exchange_data); this->dh_group_number = dh->get_dh_group(dh); - this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH; + this->payload_length += this->key_exchange_data.len; return &this->public; } diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h index 65cc11883..c448ceff6 100644 --- a/src/libcharon/encoding/payloads/ke_payload.h +++ b/src/libcharon/encoding/payloads/ke_payload.h @@ -31,16 +31,20 @@ typedef struct ke_payload_t ke_payload_t; #include <crypto/diffie_hellman.h> /** - * KE payload length in bytes without any key exchange data. + * KE payload length in bytes without any key exchange data (IKEv2). */ #define KE_PAYLOAD_HEADER_LENGTH 8 /** - * Class representing an IKEv2-KE Payload. - * - * The KE Payload format is described in RFC section 3.4. + * KE payload length in bytes without any key exchange data (IKEv1). + */ +#define KE_PAYLOAD_V1_HEADER_LENGTH 4 + +/** + * Class representing an IKEv1 or IKEv2 key exchange payload. */ struct ke_payload_t { + /** * The payload_t interface. */ @@ -54,32 +58,34 @@ struct ke_payload_t { chunk_t (*get_key_exchange_data) (ke_payload_t *this); /** - * Gets the Diffie-Hellman Group Number of this KE payload. + * Gets the Diffie-Hellman Group Number of this KE payload (IKEv2 only). * * @return DH Group Number of this payload */ diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this); /** - * Destroys an ke_payload_t object. + * Destroys a ke_payload_t object. */ void (*destroy) (ke_payload_t *this); }; /** - * Creates an empty ke_payload_t object + * Creates an empty ke_payload_t object. * - * @return ke_payload_t object + * @param type KEY_EXCHANGE or KEY_EXCHANGE_V1 + * @return ke_payload_t object */ -ke_payload_t *ke_payload_create(void); +ke_payload_t *ke_payload_create(payload_type_t type); /** - * Creates a ke_payload_t from a diffie_hellman_t + * Creates a ke_payload_t from a diffie_hellman_t. * - * @param diffie_hellman diffie hellman object containing group and key - * @return ke_payload_t object + * @param type KEY_EXCHANGE or KEY_EXCHANGE_V1 + * @param dh diffie hellman object containing group and key + * @return ke_payload_t object */ -ke_payload_t *ke_payload_create_from_diffie_hellman( - diffie_hellman_t *diffie_hellman); +ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type, + diffie_hellman_t *dh); #endif /** KE_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index 56563acef..3e7c390e0 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -201,7 +201,8 @@ payload_t *payload_create(payload_type_t type) case TRAFFIC_SELECTOR_RESPONDER: return (payload_t*)ts_payload_create(FALSE); case KEY_EXCHANGE: - return (payload_t*)ke_payload_create(); + case KEY_EXCHANGE_V1: + return (payload_t*)ke_payload_create(type); case NOTIFY: return (payload_t*)notify_payload_create(); case DELETE: diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c index 587e37aea..46382a2a0 100644 --- a/src/libcharon/sa/tasks/child_create.c +++ b/src/libcharon/sa/tasks/child_create.c @@ -547,7 +547,8 @@ static void build_payloads(private_child_create_t *this, message_t *message) /* diffie hellman exchange, if PFS enabled */ if (this->dh) { - ke_payload = ke_payload_create_from_diffie_hellman(this->dh); + ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE, + this->dh); message->add_payload(message, (payload_t*)ke_payload); } diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c index e6f4237ce..aa514bffc 100644 --- a/src/libcharon/sa/tasks/ike_init.c +++ b/src/libcharon/sa/tasks/ike_init.c @@ -150,7 +150,7 @@ static void build_payloads(private_ike_init_t *this, message_t *message) nonce_payload = nonce_payload_create(NONCE); nonce_payload->set_nonce(nonce_payload, this->my_nonce); - ke_payload = ke_payload_create_from_diffie_hellman(this->dh); + ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE, this->dh); if (this->old_sa) { /* payload order differs if we are rekeying */ |