From: Andreas Steffen Date: Mon, 18 Jun 2018 15:48:04 +0000 (+0200) Subject: encoding: Transport of QSKE payload via IKE_AUX X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce6260d4b4a13639d7fe53d78474fa26a03c2451;p=thirdparty%2Fstrongswan.git encoding: Transport of QSKE payload via IKE_AUX --- diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index d1fb33702e..2c0e6d77cf 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -47,6 +47,7 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \ encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \ encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \ +encoding/payloads/qske_payload.c encoding/payloads/qske_payload.h \ kernel/kernel_interface.c kernel/kernel_interface.h \ kernel/kernel_ipsec.c kernel/kernel_ipsec.h \ kernel/kernel_net.c kernel/kernel_net.h \ diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 15ac7a6d1e..799a9a0724 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -45,6 +45,7 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \ encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \ encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \ encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \ +encoding/payloads/qske_payload.c encoding/payloads/qske_payload.h \ kernel/kernel_interface.c kernel/kernel_interface.h \ kernel/kernel_ipsec.c kernel/kernel_ipsec.h \ kernel/kernel_net.c kernel/kernel_net.h \ diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 819f771e56..e7055d98d7 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2006-2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen + * Copyright (C) 2006-2014 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2010 revosec AG * Copyright (C) 2006 Daniel Roethlisberger @@ -400,6 +401,42 @@ static payload_order_t create_child_sa_r_order[] = { {PLV2_FRAGMENT, 0}, }; +/** + * Message rule for IKE_AUX from initiator. + */ +static payload_rule_t ike_aux_i_rules[] = { +/* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, + {PLV2_QSKE, 0, 1, TRUE, TRUE}, +}; + +/** + * payload order for IKE_AUX initiator + */ +static payload_order_t ike_aux_i_order[] = { +/* payload type notify type */ + {PLV2_QSKE, 0}, + {PLV2_FRAGMENT, 0}, +}; + +/** + * Message rule for IKE_AUX from responder. + */ +static payload_rule_t ike_aux_r_rules[] = { +/* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, + {PLV2_QSKE, 0, 1, TRUE, TRUE}, +}; + +/** + * payload order for IKE_AUX responder + */ +static payload_order_t ike_aux_r_order[] = { +/* payload type notify type */ + {PLV2_QSKE, 0}, + {PLV2_FRAGMENT, 0}, +}; + #ifdef ME /** * Message rule for ME_CONNECT from initiator. @@ -767,6 +804,14 @@ static message_rule_t message_rules[] = { countof(create_child_sa_r_rules), create_child_sa_r_rules, countof(create_child_sa_r_order), create_child_sa_r_order, }, + {IKE_AUX, TRUE, TRUE, + countof(ike_aux_i_rules), ike_aux_i_rules, + countof(ike_aux_i_order), ike_aux_i_order, + }, + {IKE_AUX, FALSE, TRUE, + countof(ike_aux_r_rules), ike_aux_r_rules, + countof(ike_aux_r_order), ike_aux_r_order, + }, #ifdef ME {ME_CONNECT, TRUE, TRUE, countof(me_connect_i_rules), me_connect_i_rules, diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c index 6a39dc8921..79bdd61787 100644 --- a/src/libcharon/encoding/payloads/ike_header.c +++ b/src/libcharon/encoding/payloads/ike_header.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Andreas Steffen * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -129,14 +130,17 @@ ENUM_NEXT(exchange_type_names, QUICK_MODE, IKE_SESSION_RESUME, TRANSACTION, "INFORMATIONAL", "IKE_SESSION_RESUME"); #ifdef ME -ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, IKE_SESSION_RESUME, - "ME_CONNECT"); +ENUM_NEXT(exchange_type_names, ME_CONNECT, IKE_AUX, IKE_SESSION_RESUME, + "ME_CONNECT", + "IKE_AUX"); ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, - EXCHANGE_TYPE_UNDEFINED, ME_CONNECT, + EXCHANGE_TYPE_UNDEFINED, IKE_AUX, "EXCHANGE_TYPE_UNDEFINED"); #else +ENUM_NEXT(exchange_type_names, IKE_AUX, IKE_AUX, IKE_SESSION_RESUME, + "IKE_AUX"); ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, - EXCHANGE_TYPE_UNDEFINED, IKE_SESSION_RESUME, + EXCHANGE_TYPE_UNDEFINED, IKE_AUX, "EXCHANGE_TYPE_UNDEFINED"); #endif /* ME */ ENUM_END(exchange_type_names, EXCHANGE_TYPE_UNDEFINED); @@ -218,6 +222,7 @@ METHOD(payload_t, verify, status_t, break; case IKE_SA_INIT: case IKE_AUTH: + case IKE_AUX: case CREATE_CHILD_SA: case INFORMATIONAL: case IKE_SESSION_RESUME: diff --git a/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h index b7694b5cbd..5a74514bf2 100644 --- a/src/libcharon/encoding/payloads/ike_header.h +++ b/src/libcharon/encoding/payloads/ike_header.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Andreas Steffen * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2011 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -128,6 +129,9 @@ enum exchange_type_t{ ME_CONNECT = 240, #endif /* ME */ + /* IKE_AUX (draft-smyslov-ipsecme-ikev2-aux-00) */ + IKE_AUX = 241, + /** * Undefined exchange type, in private space. */ diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index e2a56f9ff0..597a48c398 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Andreas Steffen * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -85,12 +87,14 @@ ENUM_NEXT(payload_type_names, PLV2_SECURITY_ASSOCIATION, PLV2_FRAGMENT, PLV1_NAT #ifdef ME ENUM_NEXT(payload_type_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_FRAGMENT, "ID_PEER"); -ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER, +ENUM_NEXT(payload_type_names, PLV2_QSKE, PLV1_FRAGMENT, PLV2_ID_PEER, + "QUANTUM_SAFE_KEY_EXCHANGE", "NAT_D_DRAFT_V1", "NAT_OA_DRAFT_V1", "FRAGMENT"); #else -ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_FRAGMENT, +ENUM_NEXT(payload_type_names, PLV2_QSKE, PLV1_FRAGMENT, PLV2_FRAGMENT, + "QUANTUM_SAFE_KEY_EXCHANGE", "NAT_D_DRAFT_V1", "NAT_OA_DRAFT_V1", "FRAGMENT"); @@ -156,12 +160,14 @@ ENUM_NEXT(payload_type_short_names, PLV2_SECURITY_ASSOCIATION, PLV2_FRAGMENT, PL #ifdef ME ENUM_NEXT(payload_type_short_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_FRAGMENT, "IDp"); -ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER, +ENUM_NEXT(payload_type_short_names, PLV2_QSKE, PLV1_FRAGMENT, PLV2_ID_PEER, + "QSKE", "NAT-D", "NAT-OA", "FRAG"); #else -ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_FRAGMENT, +ENUM_NEXT(payload_type_short_names, PLV2_QSKE, PLV1_FRAGMENT, PLV2_FRAGMENT, + "QSKE", "NAT-D", "NAT-OA", "FRAG"); @@ -231,6 +237,8 @@ payload_t *payload_create(payload_type_t type) case PLV2_KEY_EXCHANGE: case PLV1_KEY_EXCHANGE: return (payload_t*)ke_payload_create(type); + case PLV2_QSKE: + return (payload_t*)qske_payload_create(); case PLV2_NOTIFY: case PLV1_NOTIFY: return (payload_t*)notify_payload_create(type); @@ -300,6 +308,10 @@ bool payload_is_known(payload_type_t type, uint8_t maj_ver) { return TRUE; } + if (type == PLV2_QSKE) + { + return TRUE; + } if (type == PLV2_FRAGMENT) { return TRUE; diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h index cb3dce0426..911cbf002f 100644 --- a/src/libcharon/encoding/payloads/payload.h +++ b/src/libcharon/encoding/payloads/payload.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Andreas Steffen * Copyright (C) 2007-2015 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -240,6 +241,11 @@ enum payload_type_t { PLV2_ID_PEER = 128, #endif /* ME */ + /** + * Quantum-Safe Key Exchange + */ + PLV2_QSKE = 129, + /** * NAT discovery payload (NAT-D) (drafts). */ diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c index 2d0cb1f829..07d2b7c59c 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.c +++ b/src/libcharon/encoding/payloads/proposal_substructure.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Andreas Steffen * Copyright (C) 2012-2014 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -1486,6 +1487,16 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this, } enumerator->destroy(enumerator); + /* qske mechanisms */ + enumerator = proposal->create_enumerator(proposal, QSKE_MECHANISM); + while (enumerator->enumerate(enumerator, &alg, NULL)) + { + transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE, + QSKE_MECHANISM, alg); + add_transform_substructure(this, transform); + } + enumerator->destroy(enumerator); + /* extended sequence numbers */ enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS); while (enumerator->enumerate(enumerator, &alg, NULL)) diff --git a/src/libcharon/encoding/payloads/qske_payload.c b/src/libcharon/encoding/payloads/qske_payload.c new file mode 100644 index 0000000000..b3a85c6aad --- /dev/null +++ b/src/libcharon/encoding/payloads/qske_payload.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +#include "qske_payload.h" + +#include + +typedef struct private_qske_payload_t private_qske_payload_t; + +/** + * Private data of an qske_payload_t object. + */ +struct private_qske_payload_t { + + /** + * Public qske_payload_t interface. + */ + qske_payload_t public; + + /** + * Next payload type. + */ + uint8_t next_payload; + + /** + * Critical flag. + */ + bool critical; + + /** + * Reserved bits + */ + bool reserved_bit[7]; + + /** + * Reserved bytes + */ + uint8_t reserved_byte[2]; + + /** + * Length of this payload. + */ + uint16_t payload_length; + + /** + * QSKE mechanism nuber + */ + uint16_t qske_mechanism; + + /** + * Quantum-Safe Key Exchange Data of this QSKE payload. + */ + chunk_t qske_data; +}; + +/** + * Encoding rules for IKEv2 quantum-save key exchange payload. + */ +static encoding_rule_t encodings[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_qske_payload_t, next_payload) }, + /* the critical bit */ + { FLAG, offsetof(private_qske_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_qske_payload_t, reserved_bit[6]) }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_qske_payload_t, payload_length) }, + /* QSKE mechanism number as 16 bit field*/ + { U_INT_16, offsetof(private_qske_payload_t, qske_mechanism) }, + /* 2 reserved bytes */ + { RESERVED_BYTE, offsetof(private_qske_payload_t, reserved_byte[0]) }, + { RESERVED_BYTE, offsetof(private_qske_payload_t, reserved_byte[1]) }, + /* Quantum-Safe Key Exchange Data is from variable size */ + { CHUNK_DATA, offsetof(private_qske_payload_t, qske_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 !C! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! QSKE Mechanism # ! RESERVED ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Quantum-Safe Key Exchange Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + + +METHOD(payload_t, verify, status_t, + private_qske_payload_t *this) +{ + return SUCCESS; +} + +METHOD(payload_t, get_encoding_rules, int, + private_qske_payload_t *this, encoding_rule_t **rules) +{ + *rules = encodings; + return countof(encodings); +} + +METHOD(payload_t, get_header_length, int, + private_qske_payload_t *this) +{ + return 8; +} + +METHOD(payload_t, get_type, payload_type_t, + private_qske_payload_t *this) +{ + return PLV2_QSKE; +} + +METHOD(payload_t, get_next_type, payload_type_t, + private_qske_payload_t *this) +{ + return this->next_payload; +} + +METHOD(payload_t, set_next_type, void, + private_qske_payload_t *this,payload_type_t type) +{ + this->next_payload = type; +} + +METHOD(payload_t, get_length, size_t, + private_qske_payload_t *this) +{ + return this->payload_length; +} + +METHOD(qske_payload_t, get_qske_data, chunk_t, + private_qske_payload_t *this) +{ + return this->qske_data; +} + +METHOD(qske_payload_t, get_qske_mechanism, qske_mechanism_t, + private_qske_payload_t *this) +{ + return this->qske_mechanism; +} + +METHOD2(payload_t, qske_payload_t, destroy, void, + private_qske_payload_t *this) +{ + free(this->qske_data.ptr); + free(this); +} + +/* + * Described in header + */ +qske_payload_t *qske_payload_create(void) +{ + private_qske_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_header_length = _get_header_length, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_qske_data = _get_qske_data, + .get_qske_mechanism = _get_qske_mechanism, + .destroy = _destroy, + }, + .next_payload = PL_NONE, + .qske_mechanism = QSKE_NONE, + ); + this->payload_length = get_header_length(this); + return &this->public; +} + +/* + * Described in header + */ +qske_payload_t *qske_payload_create_from_qske(qske_t *qske, bool initiator) +{ + private_qske_payload_t *this; + chunk_t value; + + if (initiator) + { + if (!qske->get_public_key(qske, &value)) + { + return NULL; + } + } + else + { + if (!qske->get_ciphertext(qske, &value)) + { + return NULL; + } + } + + this = (private_qske_payload_t*)qske_payload_create(); + this->qske_data = value; + this->qske_mechanism = qske->get_qske_mechanism(qske); + this->payload_length += this->qske_data.len; + + return &this->public; +} diff --git a/src/libcharon/encoding/payloads/qske_payload.h b/src/libcharon/encoding/payloads/qske_payload.h new file mode 100644 index 0000000000..f25aaa9037 --- /dev/null +++ b/src/libcharon/encoding/payloads/qske_payload.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup qske_payload qske_payload + * @{ @ingroup payloads + */ + +#ifndef QSKE_PAYLOAD_H_ +#define QSKE_PAYLOAD_H_ + +typedef struct qske_payload_t qske_payload_t; + +#include +#include +#include +#include + +/** + * Class representing an IKEv2 quantum-save key exchange payload. + */ +struct qske_payload_t { + + /** + * The payload_t interface. + */ + payload_t payload_interface; + + /** + * Returns the Quantum-Safe Key Exchange data of this QSKE payload. + * + * @return chunk_t pointing to internal data + */ + chunk_t (*get_qske_data) (qske_payload_t *this); + + /** + * Gets the QSKE mmechanism number of this QSKE payload. + * + * @return QSKE mechanism number of this payload + */ + qske_mechanism_t (*get_qske_mechanism) (qske_payload_t *this); + + /** + * Destroys a qske_payload_t object. + */ + void (*destroy) (qske_payload_t *this); +}; + +/** + * Creates an empty qske_payload_t object. + * + * @return qske_payload_t object + */ +qske_payload_t *qske_payload_create(void); + +/** + * Creates a qske_payload_t from a qske_t. + * + * @param qske QSKE object containing mechanism and key + * @param initiator TRUE if initiator, FALSE as responder + * @return qske_payload_t object, NULL on error + */ +qske_payload_t *qske_payload_create_from_qske(qske_t *qske, bool initiator); + +#endif /** QSKE_PAYLOAD_H_ @}*/