ha: Add support to sync IKE and Child SAs with multiple key exchanges

Synchronization for the additional transforms in the IKE and Child SA
proposals is added.  Details of the IKE_SA synchronization are changed
to support IKE_INTERMEDIATE exchanges that cause multiple HA_IKE_ADD
messages and key derivations.  The cache has been extended to handle
multiple such messages.

Co-authored-by: Thomas Egerer <[email protected]>
This commit is contained in:
Tobias Brunner
2025-02-28 16:02:41 +01:00
co-authored by Thomas Egerer
parent f717bb5249
commit e7848e36fa
8 changed files with 263 additions and 121 deletions
+25 -18
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2015-2024 Tobias Brunner
* Copyright (C) 2010 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -70,9 +71,9 @@ struct private_ha_cache_t {
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;
@@ -83,27 +84,27 @@ typedef struct {
} 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);
@@ -119,12 +120,13 @@ METHOD(ha_cache_t, cache, void,
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);
@@ -305,7 +307,7 @@ static void rekey_segment(private_ha_cache_t *this, u_int segment)
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;
@@ -318,13 +320,18 @@ METHOD(ha_cache_t, resync, void,
{
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);
}
updates->destroy(updates);
messages->destroy(messages);
messages = entry->updates->create_enumerator(entry->updates);
while (messages->enumerate(messages, &message))
{
this->socket->push(this->socket, message);
}
messages->destroy(messages);
if (entry->midi)
{
this->socket->push(this->socket, entry->midi);
+8 -5
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -91,21 +92,23 @@ METHOD(listener_t, child_keys, bool,
{
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();
+139 -64
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2016-2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -23,7 +24,7 @@
#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.
@@ -62,14 +63,14 @@ struct private_ha_dispatcher_t {
};
/**
* 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
@@ -77,49 +78,73 @@ struct ha_diffie_hellman_t {
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);
}
}
}
/**
@@ -133,9 +158,10 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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;
@@ -147,8 +173,13 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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,
@@ -169,6 +200,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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;
@@ -196,11 +230,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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;
}
@@ -210,38 +248,52 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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);
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 (encr)
else
{
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
}
if (prf)
{
proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
}
if (dh_grp)
{
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;
@@ -254,12 +306,12 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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)
@@ -278,8 +330,11 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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);
@@ -287,10 +342,21 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
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)
{
@@ -659,12 +725,13 @@ static void process_child_add(private_ha_dispatcher_t *this,
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);
@@ -709,8 +776,11 @@ static void process_child_add(private_ha_dispatcher_t *this,
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;
@@ -724,6 +794,9 @@ static void process_child_add(private_ha_dispatcher_t *this,
case HA_SECRET:
secret = value.chunk;
break;
case HA_ADD_SECRET:
add_secret = value.chunk;
break;
default:
break;
}
@@ -763,15 +836,18 @@ static void process_child_add(private_ha_dispatcher_t *this,
{
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)
{
@@ -780,7 +856,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
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;
@@ -788,11 +864,10 @@ static void process_child_add(private_ha_dispatcher_t *this,
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");
+26 -22
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -97,8 +98,7 @@ METHOD(listener_t, ike_keys, bool,
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);
@@ -109,7 +109,7 @@ METHOD(listener_t, ike_keys, bool,
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;
@@ -119,32 +119,37 @@ METHOD(listener_t, ike_keys, bool,
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))
@@ -421,4 +426,3 @@ ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
return &this->public;
}
+39 -4
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -231,7 +232,7 @@ METHOD(ha_message_t, add_attribute, void,
break;
}
/* uint16_t */
case HA_ALG_DH:
case HA_ALG_KE:
case HA_ALG_PRF:
case HA_ALG_OLD_PRF:
case HA_ALG_ENCR:
@@ -270,11 +271,13 @@ METHOD(ha_message_t, add_attribute, void,
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;
@@ -318,6 +321,36 @@ METHOD(ha_message_t, add_attribute, void,
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
*/
@@ -455,7 +488,7 @@ METHOD(enumerator_t, attribute_enumerate, bool,
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:
@@ -496,11 +529,13 @@ METHOD(enumerator_t, attribute_enumerate, bool,
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;
@@ -626,7 +661,7 @@ METHOD(ha_message_t, get_encoding, chunk_t,
METHOD(ha_message_t, destroy, void,
private_ha_message_t *this)
{
free(this->buf.ptr);
chunk_clear(&this->buf);
free(this);
}
@@ -639,6 +674,7 @@ static private_ha_message_t *ha_message_create_generic()
.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,
@@ -688,4 +724,3 @@ ha_message_t *ha_message_parse(chunk_t data)
return &this->public;
}
+19 -6
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2024 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
@@ -26,12 +27,13 @@
#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;
@@ -109,8 +111,10 @@ enum ha_message_attribute_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 */
@@ -123,8 +127,10 @@ enum ha_message_attribute_t {
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 */
@@ -149,9 +155,9 @@ enum ha_message_attribute_t {
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,
@@ -197,6 +203,13 @@ struct ha_message_t {
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.
*
+1 -2
View File
@@ -33,8 +33,7 @@
#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;
+6
View File
@@ -52,6 +52,12 @@ enum transform_type_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.
*/