From: Tobias Brunner Date: Tue, 10 Jul 2018 14:26:58 +0000 (+0200) Subject: wip: keymat_v2: Cache initial IKE messages for auth octets X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=a5b76e7d0cc3725b762e674e4882d92fb17f199e;p=thirdparty%2Fstrongswan.git wip: keymat_v2: Cache initial IKE messages for auth octets This avoids pre-generating the message to be sent and supports fragments as used for IKE_AUX. In scenarios with IKE_AUX this basically changes the auth octets as follows: InitiatorSignedOctets = RealMessage1(INIT) | RealMessage3(AUX) | ... NonceRData | MACedIDForI and ResponderSignedOctets = RealMessage2(INIT) | RealMessage4(AUX) | ... NonceIData | MACedIDForR wip: Since this requires keeping around quite some data, alternatives would be to hash the message (with some negotiated or fixed hash function) or applying the PRF (if it is QC-safe, e.g. with a zero key or the ones we derived from DH). --- diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index 937bed8d92..3685ac4163 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Tobias Brunner + * Copyright (C) 2015-2018 Tobias Brunner * Copyright (C) 2012 Reto Buerki * Copyright (C) 2012 Adrian-Ken Rueegsegger * HSR Hochschule fuer Technik Rapperswil @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "tkm.h" @@ -77,6 +78,11 @@ struct private_tkm_keymat_t { * Set of hash algorithms supported by peer for signature authentication */ hash_algorithm_set_t *hash_algorithms; + + /** + * Initial packet data + */ + init_packet_cache_t *packets; }; /** @@ -383,6 +389,36 @@ METHOD(keymat_t, get_aead, aead_t*, return in ? this->aead_in : this->aead_out; } +METHOD(keymat_v2_t, add_packet, void, + private_tkm_keymat_t *this, bool sent, uint32_t mid, uint16_t fnr, + chunk_t data) +{ + if (!this->packets) + { + this->packets = init_packet_cache_create(); + } + this->packets->add_packet(this->packets, sent, mid, fnr, data); +} + +METHOD(keymat_v2_t, get_packets, chunk_t, + private_tkm_keymat_t *this, bool sent) +{ + if (this->packets) + { + return this->packets->get_packets(this->packets, sent); + } + return chunk_empty; +} + +METHOD(keymat_v2_t, clear_packets, void, + private_tkm_keymat_t *this) +{ + if (this->packets) + { + this->packets->clear_packets(this->packets); + } +} + METHOD(keymat_v2_t, get_auth_octets, bool, private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3], @@ -473,6 +509,7 @@ METHOD(keymat_t, destroy, void, } } + DESTROY_IF(this->packets); DESTROY_IF(this->hash_algorithms); DESTROY_IF(this->aead_in); DESTROY_IF(this->aead_out); @@ -527,6 +564,9 @@ tkm_keymat_t *tkm_keymat_create(bool initiator) .derive_ike_keys_ppk = (void*)return_false, .derive_child_keys = _derive_child_keys, .get_skd = _get_skd, + .add_packet = _add_packet, + .get_packets = _get_packets, + .clear_packets = _clear_packets, .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, .add_hash_algorithm = _add_hash_algorithm, diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 2c0e6d77cf..5deee2f8ac 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -92,6 +92,7 @@ sa/task.c sa/task.h libcharon_la_SOURCES += \ sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \ sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \ +sa/ikev2/init_packet_cache.c sa/ikev2/init_packet_cache.h \ sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \ sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \ sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \ diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 799a9a0724..404ba3ed01 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -91,6 +91,7 @@ if USE_IKEV2 libcharon_la_SOURCES += \ sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \ sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \ +sa/ikev2/init_packet_cache.c sa/ikev2/init_packet_cache.h \ sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \ sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \ sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \ diff --git a/src/libcharon/sa/ikev2/init_packet_cache.c b/src/libcharon/sa/ikev2/init_packet_cache.c new file mode 100644 index 0000000000..43f2a6c47d --- /dev/null +++ b/src/libcharon/sa/ikev2/init_packet_cache.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * 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 "init_packet_cache.h" + +#include +#include +#include + +typedef struct private_init_packet_cache_t private_init_packet_cache_t; + +/** + * Private data + */ +struct private_init_packet_cache_t { + + /** + * Public interface. + */ + init_packet_cache_t public; + + /** + * Cached packet data + */ + array_t *packets; +}; + +/** + * Data for an initial packet + */ +typedef struct { + /** Message ID */ + uint32_t mid; + /** Fragment number */ + uint16_t fnr; + /** Whether the packet was sent, or received */ + bool sent; + /** Actual data */ + chunk_t data; +} packet_data_t; + +/** + * Destroy cached data + */ +static void packet_destroy(packet_data_t *this) +{ + chunk_free(&this->data); + free(this); +} + +METHOD(init_packet_cache_t, add_packet, void, + private_init_packet_cache_t *this, bool sent, uint32_t mid, uint16_t fnr, + chunk_t data) +{ + packet_data_t *packet; + int i, insert_at = -1; + + for (i = 0; i < array_count(this->packets); i++) + { + array_get(this->packets, i, &packet); + if (packet->sent != sent) + { + continue; + } + if (packet->mid == mid) + { + if (packet->fnr == fnr) + { + /* replace current data */ + chunk_free(&packet->data); + packet->data = chunk_clone(data); + return; + } + if (packet->fnr > fnr) + { + insert_at = i; + break; + } + continue; + } + if (packet->mid > mid) + { + insert_at = i; + break; + } + } + INIT(packet, + .mid = mid, + .fnr = fnr, + .sent = sent, + .data = chunk_clone(data), + ); + array_insert_create(&this->packets, insert_at, packet); +} + +METHOD(init_packet_cache_t, get_packets, chunk_t, + private_init_packet_cache_t *this, bool sent) +{ + packet_data_t *packet; + bio_writer_t *writer; + chunk_t data; + uint32_t len = 0; + int i; + + for (i = 0; i < array_count(this->packets); i++) + { + array_get(this->packets, i, &packet); + if (packet->sent == sent) + { + len += packet->data.len; + } + } + + writer = bio_writer_create(len); + for (i = 0; i < array_count(this->packets); i++) + { + array_get(this->packets, i, &packet); + if (packet->sent == sent) + { + writer->write_data(writer, packet->data); + } + } + data = writer->extract_buf(writer); + writer->destroy(writer); + return data; +} + +METHOD(init_packet_cache_t, clear_packets, void, + private_init_packet_cache_t *this) +{ + array_destroy_function(this->packets, (void*)packet_destroy, NULL); + this->packets = NULL; +} + +METHOD(init_packet_cache_t, destroy, void, + private_init_packet_cache_t *this) +{ + clear_packets(this); + free(this); +} + +/* + * Described in header + */ +init_packet_cache_t *init_packet_cache_create() +{ + private_init_packet_cache_t *this; + + INIT(this, + .public = { + .add_packet = _add_packet, + .get_packets = _get_packets, + .clear_packets = _clear_packets, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/sa/ikev2/init_packet_cache.h b/src/libcharon/sa/ikev2/init_packet_cache.h new file mode 100644 index 0000000000..8a20bf9896 --- /dev/null +++ b/src/libcharon/sa/ikev2/init_packet_cache.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * 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 init_packet_cache init_packet_cache + * @{ @ingroup ikev2 + */ + +#ifndef INIT_PACKET_CACHE_H_ +#define INIT_PACKET_CACHE_H_ + +#include + +typedef struct init_packet_cache_t init_packet_cache_t; + +/** + * Helper class to cache packet data of initial IKE messages for use in auth + * octets. + */ +struct init_packet_cache_t { + + /** + * Cache data of an initial IKE packet (IKE_SA_INIT/IKE_AUX) for use in the + * auth octets. + * + * @param sent TRUE if message was sent, FALSE if received + * @param mid message ID of the packet + * @param fnr fragment number of the packet + * @param data IKE message or fragment data (cloned) + */ + void (*add_packet)(init_packet_cache_t *this, bool sent, uint32_t mid, + uint16_t fnr, chunk_t data); + + /** + * Get cached data of all initial IKE packets for use in the auth octets. + * + * @param sent TRUE for sent packets, FALSE for received packets + * @return concatenated packet data (allocated) + */ + chunk_t (*get_packets)(init_packet_cache_t *this, bool sent); + + /** + * Clear all cached initial IKE packet data. + */ + void (*clear_packets)(init_packet_cache_t *this); + + /** + * Destroy this instance. + */ + void (*destroy)(init_packet_cache_t *this); +}; + +/** + * Create a init_packet_cache_t instance. + * + * @return created instance + */ +init_packet_cache_t *init_packet_cache_create(); + +#endif /** INIT_PACKET_CACHE_H_ @}*/ diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c index 7ac36e7cfe..174e957506 100644 --- a/src/libcharon/sa/ikev2/keymat_v2.c +++ b/src/libcharon/sa/ikev2/keymat_v2.c @@ -17,6 +17,7 @@ #include "keymat_v2.h" #include +#include #include #include @@ -76,6 +77,11 @@ struct private_keymat_v2_t { * Set of hash algorithms supported by peer for signature authentication */ hash_algorithm_set_t *hash_algorithms; + + /** + * Initial packet data + */ + init_packet_cache_t *packets; }; METHOD(keymat_t, get_version, ike_version_t, @@ -741,8 +747,38 @@ METHOD(keymat_t, get_aead, aead_t*, return in ? this->aead_in : this->aead_out; } +METHOD(keymat_v2_t, add_packet, void, + private_keymat_v2_t *this, bool sent, uint32_t mid, uint16_t fnr, + chunk_t data) +{ + if (!this->packets) + { + this->packets = init_packet_cache_create(); + } + this->packets->add_packet(this->packets, sent, mid, fnr, data); +} + +METHOD(keymat_v2_t, get_packets, chunk_t, + private_keymat_v2_t *this, bool sent) +{ + if (this->packets) + { + return this->packets->get_packets(this->packets, sent); + } + return chunk_empty; +} + +METHOD(keymat_v2_t, clear_packets, void, + private_keymat_v2_t *this) +{ + if (this->packets) + { + this->packets->clear_packets(this->packets); + } +} + METHOD(keymat_v2_t, get_auth_octets, bool, - private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init, + private_keymat_v2_t *this, bool verify, chunk_t packets, chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3], chunk_t *octets, array_t *schemes) { @@ -775,7 +811,7 @@ METHOD(keymat_v2_t, get_auth_octets, bool, return FALSE; } chunk_clear(&skp_ppk); - *octets = chunk_cat("ccm", ike_sa_init, nonce, chunk); + *octets = chunk_cat("ccm", packets, nonce, chunk); DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", octets); return TRUE; } @@ -787,7 +823,7 @@ METHOD(keymat_v2_t, get_auth_octets, bool, #define IKEV2_KEY_PAD_LENGTH 17 METHOD(keymat_v2_t, get_psk_sig, bool, - private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, + private_keymat_v2_t *this, bool verify, chunk_t packets, chunk_t nonce, chunk_t secret, chunk_t ppk, identification_t *id, char reserved[3], chunk_t *sig) { @@ -807,7 +843,7 @@ METHOD(keymat_v2_t, get_psk_sig, bool, secret = skp_ppk; } } - if (!get_auth_octets(this, verify, ike_sa_init, nonce, ppk, id, reserved, + if (!get_auth_octets(this, verify, packets, nonce, ppk, id, reserved, &octets, NULL)) { goto failure; @@ -834,7 +870,6 @@ failure: chunk_free(&octets); chunk_free(&key); return success; - } METHOD(keymat_v2_t, hash_algorithm_supported, bool, @@ -867,6 +902,7 @@ METHOD(keymat_t, destroy, void, chunk_clear(&this->skp_verify); chunk_clear(&this->skp_build); DESTROY_IF(this->hash_algorithms); + DESTROY_IF(this->packets); free(this); } @@ -891,6 +927,9 @@ keymat_v2_t *keymat_v2_create(bool initiator) .derive_ike_keys_ppk = _derive_ike_keys_ppk, .derive_child_keys = _derive_child_keys, .get_skd = _get_skd, + .add_packet = _add_packet, + .get_packets = _get_packets, + .clear_packets = _clear_packets, .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, .add_hash_algorithm = _add_hash_algorithm, diff --git a/src/libcharon/sa/ikev2/keymat_v2.h b/src/libcharon/sa/ikev2/keymat_v2.h index a7d0003a65..053f451f55 100644 --- a/src/libcharon/sa/ikev2/keymat_v2.h +++ b/src/libcharon/sa/ikev2/keymat_v2.h @@ -113,6 +113,31 @@ struct keymat_v2_t { */ pseudo_random_function_t (*get_skd)(keymat_v2_t *this, chunk_t *skd); + /** + * Cache data of an initial IKE packet (IKE_SA_INIT/IKE_AUX) for use in the + * auth octets. + * + * @param sent TRUE if message was sent, FALSE if received + * @param mid message ID of the packet + * @param fnr fragment number of the packet + * @param data IKE message or fragment data (cloned) + */ + void (*add_packet)(keymat_v2_t *this, bool sent, uint32_t mid, uint16_t fnr, + chunk_t data); + + /** + * Get cached data of all initial IKE packets for use in the auth octets. + * + * @param sent TRUE for sent packets, FALSE for received packets + * @return concatenated packet data (allocated) + */ + chunk_t (*get_packets)(keymat_v2_t *this, bool sent); + + /** + * Clear all cached initial IKE packets after the authentication succeeded. + */ + void (*clear_packets)(keymat_v2_t *this); + /** * Generate octets to use for authentication procedure (RFC4306 2.15). * @@ -121,21 +146,22 @@ struct keymat_v2_t { * the get_psk_sig() method instead. * * @param verify TRUE to create for verification, FALSE to sign - * @param ike_sa_init encoded ike_sa_init message + * @param packets initial packet data * @param nonce nonce value * @param ppk optional postquantum preshared key * @param id identity * @param reserved reserved bytes of id_payload - * @param octests chunk receiving allocated auth octets + * @param octets chunk receiving allocated auth octets * @param schemes array containing signature schemes * (signature_params_t*) in case they need to be * modified by the keymat implementation * @return TRUE if octets created successfully */ - bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init, + bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t packets, chunk_t nonce, chunk_t ppk, identification_t *id, char reserved[3], chunk_t *octets, array_t *schemes); + /** * Build the shared secret signature used for PSK and EAP authentication. * @@ -144,7 +170,7 @@ struct keymat_v2_t { * used as secret (used for EAP methods without MSK). * * @param verify TRUE to create for verification, FALSE to sign - * @param ike_sa_init encoded ike_sa_init message + * @param packets initial packet data * @param nonce nonce value * @param secret optional secret to include into signature * @param ppk optional postquantum preshared key @@ -153,7 +179,7 @@ struct keymat_v2_t { * @param sign chunk receiving allocated signature octets * @return TRUE if signature created successfully */ - bool (*get_psk_sig)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init, + bool (*get_psk_sig)(keymat_v2_t *this, bool verify, chunk_t packets, chunk_t nonce, chunk_t secret, chunk_t ppk, identification_t *id, char reserved[3], chunk_t *sig); diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 37e7aa5924..a3af9d6279 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +327,63 @@ static bool generate_message(private_task_manager_t *this, message_t *message, return TRUE; } +/** + * Check if the given message has to be cached for authentication + */ +static inline bool cache_required(private_task_manager_t *this, message_t *msg) +{ + /* collect IKE_SA_INIT and IKE_AUX while connecting */ + return msg->get_exchange_type(msg) == IKE_SA_INIT || + (msg->get_exchange_type(msg) == IKE_AUX && + this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING); +} + +/** + * Cache the initial IKE packet data for sent messages/fragments + */ +static void cache_sent_message(private_task_manager_t *this, message_t *msg, + array_t *packets) +{ + keymat_v2_t *keymat; + packet_t *packet; + uint32_t mid; + int i; + + if (!cache_required(this, msg)) + { + return; + } + + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); + mid = msg->get_message_id(msg); + + for (i = 0; i < array_count(packets); i++) + { + array_get(packets, i, &packet); + keymat->add_packet(keymat, TRUE, mid, i+1, packet->get_data(packet)); + } +} + +/** + * Cache the initial IKE packet data for received messages/fragments (fragment + * may be NULL for unfragmented messages) + */ +static void cache_received_message(private_task_manager_t *this, message_t *msg, + encrypted_fragment_payload_t *fragment) +{ + keymat_v2_t *keymat; + + if (!cache_required(this, msg)) + { + return; + } + + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); + keymat->add_packet(keymat, FALSE, msg->get_message_id(msg), + fragment ? fragment->get_fragment_number(fragment) : 1, + msg->get_packet_data(msg)); +} + METHOD(task_manager_t, retransmit, status_t, private_task_manager_t *this, uint32_t message_id) { @@ -674,6 +733,8 @@ METHOD(task_manager_t, initiate, status_t, if (result) { + cache_sent_message(this, message, this->initiating.packets); + enumerator = array_create_enumerator(this->active_tasks); while (enumerator->enumerate(enumerator, &task)) { @@ -947,6 +1008,8 @@ static status_t build_response(private_task_manager_t *this, message_t *request) if (result && !delete) { + cache_sent_message(this, message, this->responding.packets); + enumerator = array_create_enumerator(this->passive_tasks); while (enumerator->enumerate(enumerator, &task)) { @@ -1307,16 +1370,23 @@ METHOD(task_manager_t, get_mid, uint32_t, * * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was * handled properly. Error states are returned if the fragment was invalid or - * the reassembled message could not have been processed properly. + * the reassembled message could not be processed properly. */ static status_t handle_fragment(private_task_manager_t *this, message_t **defrag, message_t *msg) { - message_t *reassembled; + encrypted_fragment_payload_t *fragment; status_t status; - if (!msg->get_payload(msg, PLV2_FRAGMENT)) + fragment = (encrypted_fragment_payload_t*)msg->get_payload(msg, + PLV2_FRAGMENT); + if (!fragment) { + /* ignore reassembled messages, we collected their fragments below */ + if (msg != *defrag) + { + cache_received_message(this, msg, NULL); + } return SUCCESS; } if (!*defrag) @@ -1328,18 +1398,22 @@ static status_t handle_fragment(private_task_manager_t *this, } } status = (*defrag)->add_fragment(*defrag, msg); + + if (status == NEED_MORE || status == SUCCESS) + { + cache_received_message(this, msg, fragment); + } if (status == SUCCESS) { /* reinject the reassembled message */ - reassembled = *defrag; - *defrag = NULL; - status = this->ike_sa->process_message(this->ike_sa, reassembled); + status = this->ike_sa->process_message(this->ike_sa, *defrag); if (status == SUCCESS) { /* avoid processing the last fragment */ status = NEED_MORE; } - reassembled->destroy(reassembled); + (*defrag)->destroy(*defrag); + *defrag = NULL; } return status; } diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c index be553dfb12..e522483791 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_auth.c +++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c @@ -71,14 +71,14 @@ struct private_ike_auth_t { chunk_t ppk; /** - * IKE_SA_INIT message sent by us + * Data of initial packets sent by us */ - packet_t *my_packet; + chunk_t my_packets; /** - * IKE_SA_INIT message sent by peer + * Data of initial packets sent by peer */ - packet_t *other_packet; + chunk_t other_packets; /** * Reserved bytes of ID payload @@ -165,13 +165,6 @@ static status_t collect_my_init_data(private_ike_auth_t *this, return FAILED; } this->my_nonce = nonce->get_nonce(nonce); - - /* pre-generate the message, keep a copy */ - if (this->ike_sa->generate_message(this->ike_sa, message, - &this->my_packet) != SUCCESS) - { - return FAILED; - } return NEED_MORE; } @@ -191,9 +184,6 @@ static status_t collect_other_init_data(private_ike_auth_t *this, return FAILED; } this->other_nonce = nonce->get_nonce(nonce); - - /* keep a copy of the received packet */ - this->other_packet = message->get_packet(message); return NEED_MORE; } @@ -638,6 +628,16 @@ METHOD(task_t, build_i, status_t, return NEED_MORE; } + if (!this->my_packets.ptr) + { + keymat_v2_t *keymat; + + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); + this->my_packets = keymat->get_packets(keymat, TRUE); + this->other_packets = keymat->get_packets(keymat, FALSE); + keymat->clear_packets(keymat); + } + /* check if an authenticator is in progress */ if (!this->my_auth) { @@ -695,10 +695,9 @@ METHOD(task_t, build_i, status_t, /* build authentication data */ this->my_auth = authenticator_create_builder(this->ike_sa, cfg, - this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet), - this->reserved); + this->other_nonce, this->my_nonce, + this->other_packets, this->my_packets, + this->reserved); if (!this->my_auth) { charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); @@ -803,6 +802,16 @@ METHOD(task_t, process_r, status_t, this->first_auth = TRUE; } + if (!this->my_packets.ptr) + { + keymat_v2_t *keymat; + + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); + this->my_packets = keymat->get_packets(keymat, TRUE); + this->other_packets = keymat->get_packets(keymat, FALSE); + keymat->clear_packets(keymat); + } + if (!this->other_auth) { /* handle IDi payload */ @@ -862,10 +871,9 @@ METHOD(task_t, process_r, status_t, /* verify authentication data */ this->other_auth = authenticator_create_verifier(this->ike_sa, - message, this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet), - this->reserved); + message, this->other_nonce, this->my_nonce, + this->other_packets, this->my_packets, + this->reserved); if (!this->other_auth) { this->authentication_failed = TRUE; @@ -1041,10 +1049,9 @@ METHOD(task_t, build_r, status_t, { /* build authentication data */ this->my_auth = authenticator_create_builder(this->ike_sa, cfg, - this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet), - this->reserved); + this->other_nonce, this->my_nonce, + this->other_packets, this->my_packets, + this->reserved); if (!this->my_auth) { goto local_auth_failed; @@ -1343,10 +1350,9 @@ METHOD(task_t, process_i, status_t, { /* verify authentication data */ this->other_auth = authenticator_create_verifier(this->ike_sa, - message, this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet), - this->reserved); + message, this->other_nonce, this->my_nonce, + this->other_packets, this->my_packets, + this->reserved); if (!this->other_auth) { goto peer_auth_failed; @@ -1512,16 +1518,14 @@ METHOD(task_t, migrate, void, clear_ppk(this); chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); - DESTROY_IF(this->my_packet); - DESTROY_IF(this->other_packet); + chunk_free(&this->my_packets); + chunk_free(&this->other_packets); DESTROY_IF(this->peer_cfg); DESTROY_IF(this->my_auth); DESTROY_IF(this->other_auth); DESTROY_IF(this->redirect_to); this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy)); - this->my_packet = NULL; - this->other_packet = NULL; this->ike_sa = ike_sa; this->peer_cfg = NULL; this->my_auth = NULL; @@ -1540,8 +1544,8 @@ METHOD(task_t, destroy, void, clear_ppk(this); chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); - DESTROY_IF(this->my_packet); - DESTROY_IF(this->other_packet); + chunk_free(&this->my_packets); + chunk_free(&this->other_packets); DESTROY_IF(this->my_auth); DESTROY_IF(this->other_auth); DESTROY_IF(this->peer_cfg);