/*
+ * Copyright (C) 2015-2024 Tobias Brunner
* Copyright (C) 2010 Martin Willi
*
* Copyright (C) secunet Security Networks AG
typedef struct {
/* segment this entry is associate to */
u_int segment;
- /* ADD message */
- ha_message_t *add;
- /* list of updates UPDATE message */
+ /* list of ADD messages */
+ linked_list_t *add;
+ /* list of UPDATE messages */
linked_list_t *updates;
/* last initiator mid */
ha_message_t *midi;
} entry_t;
/**
- * Create a entry with an add message
+ * Create a entry
*/
-static entry_t *entry_create(ha_message_t *add)
+static entry_t *entry_create()
{
entry_t *entry;
INIT(entry,
- .add = add,
+ .add = linked_list_create(),
.updates = linked_list_create(),
);
return entry;
}
/**
- * clean up a entry
+ * Clean up a entry
*/
static void entry_destroy(entry_t *entry)
{
entry->updates->destroy_offset(entry->updates,
- offsetof(ha_message_t, destroy));
- entry->add->destroy(entry->add);
+ offsetof(ha_message_t, destroy));
+ entry->add->destroy_offset(entry->add, offsetof(ha_message_t, destroy));
DESTROY_IF(entry->midi);
DESTROY_IF(entry->midr);
DESTROY_IF(entry->iv);
switch (message->get_type(message))
{
case HA_IKE_ADD:
- entry = entry_create(message);
- entry = this->cache->put(this->cache, ike_sa, entry);
- if (entry)
+ entry = this->cache->get(this->cache, ike_sa);
+ if (!entry)
{
- entry_destroy(entry);
+ entry = entry_create();
+ this->cache->put(this->cache, ike_sa, entry);
}
+ entry->add->insert_last(entry->add, message);
break;
case HA_IKE_UPDATE:
entry = this->cache->get(this->cache, ike_sa);
METHOD(ha_cache_t, resync, void,
private_ha_cache_t *this, u_int segment)
{
- enumerator_t *enumerator, *updates;
+ enumerator_t *enumerator, *messages;
ike_sa_t *ike_sa;
entry_t *entry;
ha_message_t *message;
{
if (entry->segment == segment)
{
- this->socket->push(this->socket, entry->add);
- updates = entry->updates->create_enumerator(entry->updates);
- while (updates->enumerate(updates, &message))
+ messages = entry->add->create_enumerator(entry->add);
+ while (messages->enumerate(messages, &message))
+ {
+ this->socket->push(this->socket, message);
+ }
+ messages->destroy(messages);
+ messages = entry->updates->create_enumerator(entry->updates);
+ while (messages->enumerate(messages, &message))
{
this->socket->push(this->socket, message);
}
- updates->destroy(updates);
+ messages->destroy(messages);
if (entry->midi)
{
this->socket->push(this->socket, entry->midi);
/*
+ * Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
{
m->add_attribute(m, HA_ALG_INTEG, alg);
}
- if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
- {
- m->add_attribute(m, HA_ALG_DH, alg);
- }
+ m->add_key_exchange_methods(m, proposal);
if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, &alg, NULL))
{
m->add_attribute(m, HA_ESN, alg);
}
+
m->add_attribute(m, HA_NONCE_I, nonce_i);
m->add_attribute(m, HA_NONCE_R, nonce_r);
if (kes && key_exchange_concat_secrets(kes, &secret, &add_secret))
{
m->add_attribute(m, HA_SECRET, secret);
chunk_clear(&secret);
- chunk_clear(&add_secret);
+ if (add_secret.len)
+ {
+ m->add_attribute(m, HA_ADD_SECRET, add_secret);
+ chunk_clear(&add_secret);
+ }
}
local_ts = linked_list_create();
/*
+ * Copyright (C) 2016-2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
#include <processing/jobs/adopt_children_job.h>
typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
-typedef struct ha_diffie_hellman_t ha_diffie_hellman_t;
+typedef struct ha_key_exchange_t ha_key_exchange_t;
/**
* Private data of an ha_dispatcher_t object.
};
/**
- * DH implementation for HA synced DH values
+ * KE implementation for HA synced KE shared secrets
*/
-struct ha_diffie_hellman_t {
+struct ha_key_exchange_t {
/**
- * Implements key_exchange_t
+ * Public interface
*/
- key_exchange_t dh;
+ key_exchange_t ke;
/**
* Shared secret
chunk_t secret;
/**
- * Own public value
+ * Own public value (IKEv1 only)
*/
chunk_t pub;
};
-METHOD(key_exchange_t, dh_get_shared_secret, bool,
- ha_diffie_hellman_t *this, chunk_t *secret)
+METHOD(key_exchange_t, ke_get_shared_secret, bool,
+ ha_key_exchange_t *this, chunk_t *secret)
{
*secret = chunk_clone(this->secret);
return TRUE;
}
-METHOD(key_exchange_t, dh_get_public_key, bool,
- ha_diffie_hellman_t *this, chunk_t *value)
+METHOD(key_exchange_t, ke_get_public_key, bool,
+ ha_key_exchange_t *this, chunk_t *value)
{
*value = chunk_clone(this->pub);
return TRUE;
}
-METHOD(key_exchange_t, dh_destroy, void,
- ha_diffie_hellman_t *this)
+METHOD(key_exchange_t, ke_destroy, void,
+ ha_key_exchange_t *this)
{
free(this);
}
/**
- * Create a HA synced DH implementation
+ * Create a HA synced KE implementation
*/
-static key_exchange_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub)
+static key_exchange_t *ha_key_exchange_create(chunk_t secret, chunk_t pub)
{
- ha_diffie_hellman_t *this;
+ ha_key_exchange_t *this;
INIT(this,
- .dh = {
- .get_shared_secret = _dh_get_shared_secret,
- .get_public_key = _dh_get_public_key,
- .destroy = _dh_destroy,
+ .ke = {
+ .get_shared_secret = _ke_get_shared_secret,
+ .get_public_key = _ke_get_public_key,
+ .destroy = _ke_destroy,
},
.secret = secret,
.pub = pub,
);
- return &this->dh;
+ return &this->ke;
+}
+
+/**
+ * Add the given KE methods to a proposal
+ */
+static void add_ke_methods_to_proposal(proposal_t *proposal, uint16_t ke_alg,
+ chunk_t add_kes)
+{
+ int i, count;
+
+ if (ke_alg)
+ {
+ proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, ke_alg, 0);
+ }
+ count = min(add_kes.len / sizeof(uint16_t), MAX_ADDITIONAL_KEY_EXCHANGES);
+ for (i = 0; i < count; i++)
+ {
+ ke_alg = ntohs(((uint16_t*)add_kes.ptr)[i]);
+ if (ke_alg)
+ {
+ proposal->add_algorithm(proposal, i + ADDITIONAL_KEY_EXCHANGE_1,
+ ke_alg, 0);
+ }
+ }
}
/**
ike_sa_t *ike_sa = NULL, *old_sa = NULL;
ike_version_t version = IKEV2;
uint16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
- uint16_t dh_grp = 0;
+ uint16_t ke_alg = 0;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
chunk_t secret = chunk_empty, old_skd = chunk_empty;
+ chunk_t add_secret = chunk_empty, add_kes = chunk_empty;
chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
host_t *other = NULL;
bool ok = FALSE;
switch (attribute)
{
case HA_IKE_ID:
- ike_sa = ike_sa_create(value.ike_sa_id,
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ if (!ike_sa)
+ {
+ ike_sa = ike_sa_create(value.ike_sa_id,
value.ike_sa_id->is_initiator(value.ike_sa_id), version);
+ }
break;
case HA_IKE_REKEY_ID:
old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
case HA_SECRET:
secret = value.chunk;
break;
+ case HA_ADD_SECRET:
+ add_secret = value.chunk;
+ break;
case HA_LOCAL_DH:
dh_local = value.chunk;
break;
case HA_ALG_OLD_PRF:
old_prf = value.u16;
break;
- case HA_ALG_DH:
- dh_grp = value.u16;
+ case HA_ALG_KE:
+ ke_alg = value.u16;
+ break;
+ case HA_ALG_ADD_KES:
+ add_kes = value.chunk;
break;
case HA_AUTH_METHOD:
method = value.u16;
+ break;
default:
break;
}
if (ike_sa)
{
proposal_t *proposal;
- key_exchange_t *dh;
+ key_exchange_t *ke;
+ array_t *kes = NULL;
+ bool key_update = FALSE;
- proposal = proposal_create(PROTO_IKE, 0);
- if (integ)
+ proposal = ike_sa->get_proposal(ike_sa);
+ if (!proposal)
{
- proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
- }
- if (encr)
- {
- proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
- }
- if (prf)
- {
- proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ proposal = proposal_create(PROTO_IKE, 0);
+ if (integ)
+ {
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
+ }
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
+ }
+ if (prf)
+ {
+ proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ }
+ add_ke_methods_to_proposal(proposal, ke_alg, add_kes);
}
- if (dh_grp)
+ else
{
- proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, dh_grp, 0);
+ key_update = TRUE;
}
charon->bus->set_sa(charon->bus, ike_sa);
- dh = ha_diffie_hellman_create(secret, dh_local);
+ ke = ha_key_exchange_create(secret, dh_local);
+ array_insert_create(&kes, ARRAY_HEAD, ke);
if (ike_sa->get_version(ike_sa) == IKEV2)
{
keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
- array_t *kes = NULL;
- array_insert_create(&kes, ARRAY_HEAD, dh);
+ if (add_secret.len)
+ {
+ ke = ha_key_exchange_create(add_secret, chunk_empty);
+ array_insert_create(&kes, ARRAY_TAIL, ke);
+ }
+ if (key_update)
+ {
+ old_prf = keymat_v2->get_skd(keymat_v2, &old_skd);
+ }
ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, kes, nonce_i,
nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd);
- array_destroy(kes);
}
- if (ike_sa->get_version(ike_sa) == IKEV1)
+ else if (ike_sa->get_version(ike_sa) == IKEV1)
{
keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
shared_key_t *shared = NULL;
if (keymat_v1->create_hasher(keymat_v1, proposal))
{
ok = keymat_v1->derive_ike_keys(keymat_v1, proposal,
- dh, dh_remote, nonce_i, nonce_r,
+ ke, dh_remote, nonce_i, nonce_r,
ike_sa->get_id(ike_sa), method, shared);
}
DESTROY_IF(shared);
}
- dh->destroy(dh);
+ array_destroy_offset(kes, offsetof(key_exchange_t, destroy));
if (ok)
{
if (old_sa)
ike_sa->set_other_host(ike_sa, other);
other = NULL;
}
- ike_sa->set_state(ike_sa, IKE_CONNECTING);
- ike_sa->set_proposal(ike_sa, proposal);
+ if (!key_update)
+ {
+ ike_sa->set_state(ike_sa, IKE_CONNECTING);
+ ike_sa->set_proposal(ike_sa, proposal);
+ }
this->cache->cache(this->cache, ike_sa, message);
message = NULL;
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
else
{
DBG1(DBG_IKE, "HA keymat derivation failed");
- ike_sa->destroy(ike_sa);
+ if (key_update)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ }
+ else
+ {
+ ike_sa->destroy(ike_sa);
+ charon->bus->set_sa(charon->bus, NULL);
+ }
+ }
+ if (!key_update)
+ {
+ proposal->destroy(proposal);
}
- charon->bus->set_sa(charon->bus, NULL);
- proposal->destroy(proposal);
}
if (old_sa)
{
uint32_t inbound_spi = 0, outbound_spi = 0;
uint16_t inbound_cpi = 0, outbound_cpi = 0;
uint8_t mode = MODE_TUNNEL, ipcomp = 0;
- uint16_t encr = 0, integ = 0, len = 0, dh_grp = 0;
+ uint16_t encr = 0, integ = 0, len = 0, ke_alg = 0;
uint16_t esn = NO_EXT_SEQ_NUMBERS;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
+ chunk_t add_secret = chunk_empty, add_kes = chunk_empty;
chunk_t encr_i, integ_i, encr_r, integ_r;
linked_list_t *local_ts, *remote_ts;
- key_exchange_t *dh = NULL;
+ key_exchange_t *ke = NULL;
array_t *kes = NULL;
enumerator = message->create_attribute_enumerator(message);
case HA_ALG_INTEG:
integ = value.u16;
break;
- case HA_ALG_DH:
- dh_grp = value.u16;
+ case HA_ALG_KE:
+ ke_alg = value.u16;
+ break;
+ case HA_ALG_ADD_KES:
+ add_kes = value.chunk;
break;
case HA_ESN:
esn = value.u16;
case HA_SECRET:
secret = value.chunk;
break;
+ case HA_ADD_SECRET:
+ add_secret = value.chunk;
+ break;
default:
break;
}
{
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
}
- if (dh_grp)
- {
- proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, dh_grp, 0);
- }
+ add_ke_methods_to_proposal(proposal, ke_alg, add_kes);
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
+
if (secret.len)
{
- dh = ha_diffie_hellman_create(secret, chunk_empty);
- array_insert_create(&kes, ARRAY_HEAD, dh);
+ ke = ha_key_exchange_create(secret, chunk_empty);
+ array_insert_create(&kes, ARRAY_HEAD, ke);
+ }
+ if (add_secret.len)
+ {
+ ke = ha_key_exchange_create(add_secret, chunk_empty);
+ array_insert_create(&kes, ARRAY_TAIL, ke);
}
if (ike_sa->get_version(ike_sa) == IKEV2)
{
ok = keymat_v2->derive_child_keys(keymat_v2, proposal, kes,
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
}
- if (ike_sa->get_version(ike_sa) == IKEV1)
+ else if (ike_sa->get_version(ike_sa) == IKEV1)
{
keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
uint32_t spi_i, spi_r;
spi_i = initiator ? inbound_spi : outbound_spi;
spi_r = initiator ? outbound_spi : inbound_spi;
- ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r,
+ ok = keymat_v1->derive_child_keys(keymat_v1, proposal, ke, spi_i, spi_r,
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
}
- array_destroy(kes);
- DESTROY_IF(dh);
+ array_destroy_offset(kes, offsetof(key_exchange_t, destroy));
if (!ok)
{
DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
/*
+ * Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
return TRUE;
}
if (!key_exchange_concat_secrets(kes, &secret, &add_secret) ||
- !array_get(kes, ARRAY_HEAD, &ke) ||
- add_secret.len > 0)
+ !array_get(kes, ARRAY_HEAD, &ke))
{
chunk_clear(&secret);
chunk_clear(&add_secret);
m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa));
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- if (rekey && rekey->get_version(rekey) == IKEV2)
+ if (rekey && rekey != ike_sa && rekey->get_version(rekey) == IKEV2)
{
chunk_t skd;
keymat_v2_t *keymat;
m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd));
m->add_attribute(m, HA_OLD_SKD, skd);
}
-
- proposal = ike_sa->get_proposal(ike_sa);
- if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
+ if (rekey != ike_sa)
{
- m->add_attribute(m, HA_ALG_ENCR, alg);
- if (len)
+ /* only sync the proposal for initial key derivation and rekeyings */
+ proposal = ike_sa->get_proposal(ike_sa);
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len))
{
- m->add_attribute(m, HA_ALG_ENCR_LEN, len);
+ m->add_attribute(m, HA_ALG_ENCR, alg);
+ if (len)
+ {
+ m->add_attribute(m, HA_ALG_ENCR_LEN, len);
+ }
}
- }
- if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
- {
- m->add_attribute(m, HA_ALG_INTEG, alg);
- }
- if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
- {
- m->add_attribute(m, HA_ALG_PRF, alg);
- }
- if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
- {
- m->add_attribute(m, HA_ALG_DH, alg);
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ m->add_attribute(m, HA_ALG_INTEG, alg);
+ }
+ if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ m->add_attribute(m, HA_ALG_PRF, alg);
+ }
+ m->add_key_exchange_methods(m, proposal);
}
m->add_attribute(m, HA_NONCE_I, nonce_i);
m->add_attribute(m, HA_NONCE_R, nonce_r);
m->add_attribute(m, HA_SECRET, secret);
chunk_clear(&secret);
+ if (add_secret.len)
+ {
+ m->add_attribute(m, HA_ADD_SECRET, add_secret);
+ chunk_clear(&add_secret);
+ }
if (ike_sa->get_version(ike_sa) == IKEV1)
{
if (ke->get_public_key(ke, &secret))
return &this->public;
}
-
/*
+ * Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
break;
}
/* uint16_t */
- case HA_ALG_DH:
+ case HA_ALG_KE:
case HA_ALG_PRF:
case HA_ALG_OLD_PRF:
case HA_ALG_ENCR:
case HA_NONCE_I:
case HA_NONCE_R:
case HA_SECRET:
+ case HA_ADD_SECRET:
case HA_LOCAL_DH:
case HA_REMOTE_DH:
case HA_PSK:
case HA_IV:
case HA_OLD_SKD:
+ case HA_ALG_ADD_KES:
{
chunk_t chunk;
va_end(args);
}
+METHOD(ha_message_t, add_key_exchange_methods, void,
+ private_ha_message_t *this, proposal_t *proposal)
+{
+ uint16_t algs[MAX_ADDITIONAL_KEY_EXCHANGES] = {};
+ int i, count = 0;
+
+ if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &algs[0], NULL))
+ {
+ add_attribute(this, HA_ALG_KE, algs[0]);
+ algs[0] = 0;
+ }
+ for (i = 0; i < countof(algs); i++)
+ {
+ if (proposal->get_algorithm(proposal, i + ADDITIONAL_KEY_EXCHANGE_1,
+ &algs[i], NULL))
+ {
+ count = i+1;
+ }
+ }
+ if (count)
+ {
+ for (i = 0; i < count; i++)
+ {
+ algs[i] = htons(algs[i]);
+ }
+ add_attribute(this, HA_ALG_ADD_KES,
+ chunk_create((u_char*)algs, count * sizeof(uint16_t)));
+ }
+}
+
/**
* Attribute enumerator implementation
*/
return TRUE;
}
/** uint16_t */
- case HA_ALG_DH:
+ case HA_ALG_KE:
case HA_ALG_PRF:
case HA_ALG_OLD_PRF:
case HA_ALG_ENCR:
case HA_NONCE_I:
case HA_NONCE_R:
case HA_SECRET:
+ case HA_ADD_SECRET:
case HA_LOCAL_DH:
case HA_REMOTE_DH:
case HA_PSK:
case HA_IV:
case HA_OLD_SKD:
+ case HA_ALG_ADD_KES:
{
size_t len;
METHOD(ha_message_t, destroy, void,
private_ha_message_t *this)
{
- free(this->buf.ptr);
+ chunk_clear(&this->buf);
free(this);
}
.public = {
.get_type = _get_type,
.add_attribute = _add_attribute,
+ .add_key_exchange_methods = _add_key_exchange_methods,
.create_attribute_enumerator = _create_attribute_enumerator,
.get_encoding = _get_encoding,
.destroy = _destroy,
return &this->public;
}
-
/*
+ * Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
#include <networking/host.h>
#include <utils/identification.h>
#include <sa/ike_sa_id.h>
+#include <crypto/proposal/proposal.h>
#include <selectors/traffic_selector.h>
/**
* Protocol version of this implementation
*/
-#define HA_MESSAGE_VERSION 3
+#define HA_MESSAGE_VERSION 4
typedef struct ha_message_t ha_message_t;
typedef enum ha_message_type_t ha_message_type_t;
HA_NONCE_I,
/** chunk_t, responders nonce */
HA_NONCE_R,
- /** chunk_t, diffie hellman shared secret */
+ /** chunk_t, KE shared secret */
HA_SECRET,
+ /** chunk_t, optional additional KE shared secret(s) */
+ HA_ADD_SECRET,
/** chunk_t, SKd of old SA if rekeying */
HA_OLD_SKD,
/** uint16_t, pseudo random function */
HA_ALG_ENCR_LEN,
/** uint16_t, integrity protection algorithm */
HA_ALG_INTEG,
- /** uint16_t, DH group */
- HA_ALG_DH,
+ /** uint16_t, KE method */
+ HA_ALG_KE,
+ /** chunk_t of uint16_t[], optional additional KE methods (IKEv2 only) */
+ HA_ALG_ADD_KES,
/** uint8_t, IPsec mode, TUNNEL|TRANSPORT|... */
HA_IPSEC_MODE,
/** uint8_t, IPComp protocol */
HA_ESN,
/** uint8_t, IKE version */
HA_IKE_VERSION,
- /** chunk_t, own DH public value */
+ /** chunk_t, own DH public value (IKEv1 only) */
HA_LOCAL_DH,
- /** chunk_t, remote DH public value */
+ /** chunk_t, remote DH public value (IKEv1 only) */
HA_REMOTE_DH,
/** chunk_t, shared secret for IKEv1 key derivation */
HA_PSK,
void (*add_attribute)(ha_message_t *this,
ha_message_attribute_t attribute, ...);
+ /**
+ * Add attributes for key exchange methods in the given proposal.
+ *
+ * @param proposal proposal from which to get key exchange methods
+ */
+ void (*add_key_exchange_methods)(ha_message_t *this, proposal_t *proposal);
+
/**
* Create an enumerator over all attributes in a message.
*
#include <processing/jobs/initiate_tasks_job.h>
/** Maximum number of key exchanges (including the initial one, if any) */
-#define MAX_KEY_EXCHANGES (ADDITIONAL_KEY_EXCHANGE_7 - \
- ADDITIONAL_KEY_EXCHANGE_1 + 2)
+#define MAX_KEY_EXCHANGES (MAX_ADDITIONAL_KEY_EXCHANGES + 1)
typedef struct private_child_create_t private_child_create_t;
KEY_DERIVATION_FUNCTION = 262,
};
+/**
+ * Maximum number of additional key exchanges.
+ */
+#define MAX_ADDITIONAL_KEY_EXCHANGES (ADDITIONAL_KEY_EXCHANGE_7 - \
+ ADDITIONAL_KEY_EXCHANGE_1 + 1)
+
/**
* enum names for transform_type_t.
*/