Merge branch 'multi-ke-backport'
This merge includes changes that were created for the upcoming IKEv2 extension for multiple key exchanges over the last four years, but which are not directly related to the actual protocol changes. Changes include renaming diffie_hellman_t to the more generic key_exchange_t (also renamed are some of the interface's methods), making utility functions that deal with DH groups more generic, and let tasks handle the first IKE_AUTH message more reliably by not depending on e.g. specific message IDs. One significant change is delaying the IKEv2 key derivation until the keys are actually needed to process or send the next message. So instead of deriving the keys directly while processing an IKE_SA_INIT request (which could come from a spoofed address), this is delayed until the corresponding IKE_AUTH request is received. Implementations of the key_exchange_t interface are now expected to do the key derivation and any costly public key validation in get_shared_secret() and not set_public_key(). Sent IKE_SA_INIT messages are now also not pre-generated anymore to collect their encoding for the authentication. Instead, a new post_build() hook allows the ike-auth task to do so after the actual message has been built, which allows later tasks and plugins (via message() hook) to modify the message (e.g. add notifies) after the ike-auth task's build() method already ran. Also changed is how inbound requests are processed and retransmits are detected. Instead of parsing all inbound messages right away (which might trigger a key derivation or require keys we don't have anymore in the multi-KE use case), we now first check a request's message ID and compare its hash to that of the previous request to decide if it's a valid retransmit. For fragmented messages, we only keep track of the first fragment so we can send the corresponding response immediately if a retransmit of it is received, instead of waiting for all fragments and reconstructing the message, which we did before.
This commit is contained in:
+13
-13
@@ -19,7 +19,7 @@
|
||||
#include <assert.h>
|
||||
#include <library.h>
|
||||
#include <utils/debug.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
static void usage()
|
||||
{
|
||||
@@ -29,7 +29,7 @@ static void usage()
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
} groups[] = {
|
||||
{"modp768", MODP_768_BIT},
|
||||
{"modp1024", MODP_1024_BIT},
|
||||
@@ -65,43 +65,43 @@ static double end_timing(struct timespec *start)
|
||||
(end.tv_sec - start->tv_sec) * 1.0;
|
||||
}
|
||||
|
||||
static void run_test(diffie_hellman_group_t group, int rounds)
|
||||
static void run_test(key_exchange_method_t group, int rounds)
|
||||
{
|
||||
diffie_hellman_t *l[rounds], *r;
|
||||
key_exchange_t *l[rounds], *r;
|
||||
chunk_t chunk, chunks[rounds], lsecrets[rounds], rsecrets[rounds];
|
||||
struct timespec timing;
|
||||
int round;
|
||||
|
||||
r = lib->crypto->create_dh(lib->crypto, group);
|
||||
r = lib->crypto->create_ke(lib->crypto, group);
|
||||
if (!r)
|
||||
{
|
||||
printf("skipping %N, not supported\n",
|
||||
diffie_hellman_group_names, group);
|
||||
printf("skipping %N, not supported\n", key_exchange_method_names,
|
||||
group);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%N:\t", diffie_hellman_group_names, group);
|
||||
printf("%N:\t", key_exchange_method_names, group);
|
||||
|
||||
start_timing(&timing);
|
||||
for (round = 0; round < rounds; round++)
|
||||
{
|
||||
l[round] = lib->crypto->create_dh(lib->crypto, group);
|
||||
assert(l[round]->get_my_public_value(l[round], &chunks[round]));
|
||||
l[round] = lib->crypto->create_ke(lib->crypto, group);
|
||||
assert(l[round]->get_public_key(l[round], &chunks[round]));
|
||||
}
|
||||
printf("A = g^a/s: %8.1f", rounds / end_timing(&timing));
|
||||
|
||||
for (round = 0; round < rounds; round++)
|
||||
{
|
||||
assert(r->set_other_public_value(r, chunks[round]));
|
||||
assert(r->set_public_key(r, chunks[round]));
|
||||
assert(r->get_shared_secret(r, &rsecrets[round]));
|
||||
chunk_free(&chunks[round]);
|
||||
}
|
||||
|
||||
assert(r->get_my_public_value(r, &chunk));
|
||||
assert(r->get_public_key(r, &chunk));
|
||||
start_timing(&timing);
|
||||
for (round = 0; round < rounds; round++)
|
||||
{
|
||||
assert(l[round]->set_other_public_value(l[round], chunk));
|
||||
assert(l[round]->set_public_key(l[round], chunk));
|
||||
assert(l[round]->get_shared_secret(l[round], &lsecrets[round]));
|
||||
}
|
||||
printf(" | S = B^a/s: %8.1f\n", rounds / end_timing(&timing));
|
||||
|
||||
@@ -40,12 +40,12 @@ struct private_tkm_diffie_hellman_t {
|
||||
tkm_diffie_hellman_t public;
|
||||
|
||||
/**
|
||||
* Diffie Hellman group number.
|
||||
* Diffie-Hellman group number.
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
|
||||
/**
|
||||
* Diffie Hellman public value.
|
||||
* Diffie-Hellman public value.
|
||||
*/
|
||||
dh_pubvalue_type pubvalue;
|
||||
|
||||
@@ -56,14 +56,14 @@ struct private_tkm_diffie_hellman_t {
|
||||
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_tkm_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
sequence_to_chunk(this->pubvalue.data, this->pubvalue.size, value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_tkm_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_empty;
|
||||
@@ -71,7 +71,7 @@ METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
}
|
||||
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_tkm_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
dh_pubvalue_type othervalue;
|
||||
@@ -81,13 +81,13 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
return ike_dh_generate_key(this->context_id, othervalue) == TKM_OK;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_tkm_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_tkm_diffie_hellman_t *this)
|
||||
{
|
||||
if (ike_dh_reset(this->context_id) != TKM_OK)
|
||||
@@ -107,13 +107,13 @@ METHOD(tkm_diffie_hellman_t, get_id, dh_id_type,
|
||||
|
||||
static u_int hash(void *key)
|
||||
{
|
||||
diffie_hellman_group_t k = *(diffie_hellman_group_t*)key;
|
||||
key_exchange_method_t k = *(key_exchange_method_t*)key;
|
||||
return chunk_hash(chunk_from_thing(k));
|
||||
}
|
||||
|
||||
static bool equals(void *key, void *other_key)
|
||||
{
|
||||
return *(diffie_hellman_group_t*)key == *(diffie_hellman_group_t*)other_key;
|
||||
return *(key_exchange_method_t*)key == *(key_exchange_method_t*)other_key;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -123,7 +123,7 @@ int register_dh_mapping()
|
||||
{
|
||||
int count, i;
|
||||
char *iana_id_str, *tkm_id_str;
|
||||
diffie_hellman_group_t *iana_id;
|
||||
key_exchange_method_t *iana_id;
|
||||
uint64_t *tkm_id;
|
||||
hashtable_t *map;
|
||||
enumerator_t *enumerator;
|
||||
@@ -137,7 +137,7 @@ int register_dh_mapping()
|
||||
|
||||
while (enumerator->enumerate(enumerator, &iana_id_str, &tkm_id_str))
|
||||
{
|
||||
iana_id = malloc_thing(diffie_hellman_group_t);
|
||||
iana_id = malloc_thing(key_exchange_method_t);
|
||||
*iana_id = settings_value_as_int(iana_id_str, 0);
|
||||
tkm_id = malloc_thing(uint64_t);
|
||||
*tkm_id = settings_value_as_int(tkm_id_str, 0);
|
||||
@@ -148,13 +148,13 @@ int register_dh_mapping()
|
||||
|
||||
count = map->get_count(map);
|
||||
plugin_feature_t f[count + 1];
|
||||
f[0] = PLUGIN_REGISTER(DH, tkm_diffie_hellman_create);
|
||||
f[0] = PLUGIN_REGISTER(KE, tkm_diffie_hellman_create);
|
||||
|
||||
i = 1;
|
||||
enumerator = map->create_enumerator(map);
|
||||
while (enumerator->enumerate(enumerator, &iana_id, &tkm_id))
|
||||
{
|
||||
f[i] = PLUGIN_PROVIDE(DH, *iana_id);
|
||||
f[i] = PLUGIN_PROVIDE(KE, *iana_id);
|
||||
i++;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
@@ -198,7 +198,7 @@ void destroy_dh_mapping()
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group)
|
||||
tkm_diffie_hellman_t *tkm_diffie_hellman_create(key_exchange_method_t group)
|
||||
{
|
||||
private_tkm_diffie_hellman_t *this;
|
||||
|
||||
@@ -209,11 +209,11 @@ tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group)
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_id = _get_id,
|
||||
|
||||
@@ -29,14 +29,14 @@ typedef struct tkm_diffie_hellman_t tkm_diffie_hellman_t;
|
||||
#include <tkm/types.h>
|
||||
|
||||
/**
|
||||
* diffie_hellman_t implementation using the trusted key manager.
|
||||
* key_exchange_t implementation using the trusted key manager.
|
||||
*/
|
||||
struct tkm_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
|
||||
/**
|
||||
* Get Diffie-Hellman context id.
|
||||
@@ -66,6 +66,6 @@ void destroy_dh_mapping();
|
||||
* @param group Diffie Hellman group number to use
|
||||
* @return tkm_diffie_hellman_t object, NULL if not supported
|
||||
*/
|
||||
tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group);
|
||||
tkm_diffie_hellman_t *tkm_diffie_hellman_create(key_exchange_method_t group);
|
||||
|
||||
#endif /** TKM_DIFFIE_HELLMAN_H_ @}*/
|
||||
|
||||
@@ -82,10 +82,10 @@ METHOD(keymat_t, get_version, ike_version_t,
|
||||
return IKEV2;
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_dh, diffie_hellman_t*,
|
||||
private_tkm_keymat_t *this, diffie_hellman_group_t group)
|
||||
METHOD(keymat_t, create_ke, key_exchange_t*,
|
||||
private_tkm_keymat_t *this, key_exchange_method_t ke)
|
||||
{
|
||||
return lib->crypto->create_dh(lib->crypto, group);
|
||||
return lib->crypto->create_ke(lib->crypto, ke);
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
|
||||
@@ -95,7 +95,7 @@ METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
|
||||
}
|
||||
|
||||
METHOD(keymat_v2_t, derive_ike_keys, bool,
|
||||
private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_tkm_keymat_t *this, proposal_t *proposal, key_exchange_t *ke,
|
||||
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
|
||||
pseudo_random_function_t rekey_function, chunk_t rekey_skd)
|
||||
{
|
||||
@@ -119,7 +119,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
|
||||
}
|
||||
|
||||
/* Get DH context id */
|
||||
tkm_dh = (tkm_diffie_hellman_t *)dh;
|
||||
tkm_dh = (tkm_diffie_hellman_t *)ke;
|
||||
dh_id = tkm_dh->get_id(tkm_dh);
|
||||
|
||||
if (this->initiator)
|
||||
@@ -198,16 +198,16 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
|
||||
}
|
||||
|
||||
METHOD(keymat_v2_t, derive_child_keys, bool,
|
||||
private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_tkm_keymat_t *this, proposal_t *proposal, key_exchange_t *ke,
|
||||
chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
|
||||
chunk_t *encr_r, chunk_t *integ_r)
|
||||
{
|
||||
esa_info_t *esa_info_i, *esa_info_r;
|
||||
dh_id_type dh_id = 0;
|
||||
|
||||
if (dh)
|
||||
if (ke)
|
||||
{
|
||||
dh_id = ((tkm_diffie_hellman_t *)dh)->get_id((tkm_diffie_hellman_t *)dh);
|
||||
dh_id = ((tkm_diffie_hellman_t *)ke)->get_id((tkm_diffie_hellman_t *)ke);
|
||||
}
|
||||
|
||||
INIT(esa_info_i,
|
||||
@@ -379,7 +379,7 @@ tkm_keymat_t *tkm_keymat_create(bool initiator)
|
||||
.keymat_v2 = {
|
||||
.keymat = {
|
||||
.get_version = _get_version,
|
||||
.create_dh = _create_dh,
|
||||
.create_ke = _create_ke,
|
||||
.create_nonce_gen = _create_nonce_gen,
|
||||
.get_aead = _get_aead,
|
||||
.destroy = _destroy,
|
||||
|
||||
@@ -31,7 +31,7 @@ START_TEST(test_dh_creation)
|
||||
fail_if(!dh, "MODP_4096 not created");
|
||||
fail_if(!dh->get_id(dh), "Invalid context id (0)");
|
||||
|
||||
dh->dh.destroy(&dh->dh);
|
||||
dh->ke.destroy(&dh->ke);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -41,8 +41,8 @@ START_TEST(test_dh_get_my_pubvalue)
|
||||
fail_if(!dh, "Unable to create DH");
|
||||
|
||||
chunk_t value;
|
||||
ck_assert(dh->dh.get_my_public_value(&dh->dh, &value));
|
||||
dh->dh.destroy(&dh->dh);
|
||||
ck_assert(dh->ke.get_public_key(&dh->ke, &value));
|
||||
dh->ke.destroy(&dh->ke);
|
||||
|
||||
fail_if(value.ptr == NULL, "Pubvalue is NULL");
|
||||
fail_if(value.len != 512, "Pubvalue size mismatch");
|
||||
|
||||
@@ -52,11 +52,11 @@ START_TEST(test_derive_ike_keys)
|
||||
|
||||
/* Use the same pubvalue for both sides */
|
||||
chunk_t pubvalue;
|
||||
ck_assert(dh->dh.get_my_public_value(&dh->dh, &pubvalue));
|
||||
ck_assert(dh->dh.set_other_public_value(&dh->dh, pubvalue));
|
||||
ck_assert(dh->ke.get_public_key(&dh->ke, &pubvalue));
|
||||
ck_assert(dh->ke.set_public_key(&dh->ke, pubvalue));
|
||||
|
||||
fail_unless(keymat->keymat_v2.derive_ike_keys(&keymat->keymat_v2, proposal,
|
||||
&dh->dh, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty),
|
||||
&dh->ke, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty),
|
||||
"Key derivation failed");
|
||||
chunk_free(&nonce);
|
||||
|
||||
@@ -70,7 +70,7 @@ START_TEST(test_derive_ike_keys)
|
||||
|
||||
ng->nonce_gen.destroy(&ng->nonce_gen);
|
||||
proposal->destroy(proposal);
|
||||
dh->dh.destroy(&dh->dh);
|
||||
dh->ke.destroy(&dh->ke);
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat);
|
||||
chunk_free(&pubvalue);
|
||||
@@ -93,7 +93,7 @@ START_TEST(test_derive_child_keys)
|
||||
chunk_t nonce = chunk_from_chars("test chunk");
|
||||
|
||||
fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal,
|
||||
(diffie_hellman_t *)dh,
|
||||
&dh->ke,
|
||||
nonce, nonce, &encr_i,
|
||||
&integ_i, &encr_r, &integ_r),
|
||||
"Child key derivation failed");
|
||||
@@ -133,7 +133,7 @@ START_TEST(test_derive_child_keys)
|
||||
chunk_free(&info->nonce_r);
|
||||
|
||||
proposal->destroy(proposal);
|
||||
dh->dh.destroy(&dh->dh);
|
||||
dh->ke.destroy(&dh->ke);
|
||||
keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat);
|
||||
chunk_free(&encr_i);
|
||||
chunk_free(&encr_r);
|
||||
|
||||
@@ -48,7 +48,7 @@ METHOD(listener_t, message, bool,
|
||||
{
|
||||
ke = (ke_payload_t*)payload;
|
||||
DBG1(DBG_CFG, "received DH group %N",
|
||||
diffie_hellman_group_names, ke->get_dh_group_number(ke));
|
||||
key_exchange_method_names, ke->get_key_exchange_method(ke));
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
@@ -110,7 +110,7 @@ METHOD(listener_t, message, bool,
|
||||
copy_proposal_algs(proposal, new, ENCRYPTION_ALGORITHM);
|
||||
copy_proposal_algs(proposal, new, INTEGRITY_ALGORITHM);
|
||||
copy_proposal_algs(proposal, new, PSEUDO_RANDOM_FUNCTION);
|
||||
copy_proposal_algs(proposal, new, DIFFIE_HELLMAN_GROUP);
|
||||
copy_proposal_algs(proposal, new, KEY_EXCHANGE_METHOD);
|
||||
copy_proposal_algs(proposal, new, EXTENDED_SEQUENCE_NUMBERS);
|
||||
updated->insert_last(updated, new);
|
||||
}
|
||||
|
||||
@@ -574,7 +574,7 @@ METHOD(bus_t, message, void,
|
||||
}
|
||||
|
||||
METHOD(bus_t, ike_keys, void,
|
||||
private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
|
||||
private_bus_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
||||
ike_sa_t *rekey, shared_key_t *shared, auth_method_t method)
|
||||
{
|
||||
@@ -639,7 +639,7 @@ METHOD(bus_t, ike_derived_keys, void,
|
||||
|
||||
METHOD(bus_t, child_keys, void,
|
||||
private_bus_t *this, child_sa_t *child_sa, bool initiator,
|
||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||
key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
@@ -356,7 +356,7 @@ struct bus_t {
|
||||
* @param shared shared key used for key derivation (IKEv1-PSK only)
|
||||
* @param method auth method for key derivation (IKEv1-non-PSK only)
|
||||
*/
|
||||
void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
|
||||
void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
||||
ike_sa_t *rekey, shared_key_t *shared,
|
||||
auth_method_t method);
|
||||
@@ -386,7 +386,7 @@ struct bus_t {
|
||||
* @param nonce_r responder's nonce
|
||||
*/
|
||||
void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
|
||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
|
||||
key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r);
|
||||
|
||||
/**
|
||||
* CHILD_SA derived keys hook.
|
||||
|
||||
@@ -92,7 +92,7 @@ struct listener_t {
|
||||
* @param method auth method for key derivation (IKEv1-non-PSK only)
|
||||
* @return TRUE to stay registered, FALSE to unregister
|
||||
*/
|
||||
bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
|
||||
bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
||||
ike_sa_t *rekey, shared_key_t *shared,
|
||||
auth_method_t method);
|
||||
@@ -125,7 +125,7 @@ struct listener_t {
|
||||
* @return TRUE to stay registered, FALSE to unregister
|
||||
*/
|
||||
bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t nonce_i, chunk_t nonce_r);
|
||||
|
||||
/**
|
||||
|
||||
@@ -216,16 +216,16 @@ CALLBACK(match_proposal, bool,
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_proposals, linked_list_t*,
|
||||
private_child_cfg_t *this, bool strip_dh)
|
||||
private_child_cfg_t *this, bool strip_ke)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
proposal_t *current;
|
||||
proposal_selection_flag_t flags = 0;
|
||||
linked_list_t *proposals = linked_list_create();
|
||||
|
||||
if (strip_dh)
|
||||
if (strip_ke)
|
||||
{
|
||||
flags |= PROPOSAL_SKIP_DH;
|
||||
flags |= PROPOSAL_SKIP_KE;
|
||||
}
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
@@ -484,23 +484,23 @@ METHOD(child_cfg_t, get_close_action, action_t,
|
||||
return this->close_action;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_dh_group, diffie_hellman_group_t,
|
||||
private_child_cfg_t *this)
|
||||
METHOD(child_cfg_t, get_algorithm, uint16_t,
|
||||
private_child_cfg_t *this, transform_type_t type)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
proposal_t *proposal;
|
||||
uint16_t dh_group = MODP_NONE;
|
||||
uint16_t alg = 0;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
while (enumerator->enumerate(enumerator, &proposal))
|
||||
{
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
|
||||
if (proposal->get_algorithm(proposal, type, &alg, NULL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return dh_group;
|
||||
return alg;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_inactivity, uint32_t,
|
||||
@@ -758,7 +758,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
|
||||
.get_dpd_action = _get_dpd_action,
|
||||
.get_close_action = _get_close_action,
|
||||
.get_lifetime = _get_lifetime,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.get_algorithm = _get_algorithm,
|
||||
.get_inactivity = _get_inactivity,
|
||||
.get_reqid = _get_reqid,
|
||||
.get_if_id = _get_if_id,
|
||||
|
||||
@@ -89,10 +89,10 @@ struct child_cfg_t {
|
||||
*
|
||||
* Resulting list and all of its proposals must be freed after use.
|
||||
*
|
||||
* @param strip_dh TRUE strip out diffie hellman groups
|
||||
* @param strip_ke TRUE strip out key exchange methods
|
||||
* @return list of proposals
|
||||
*/
|
||||
linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_dh);
|
||||
linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_ke);
|
||||
|
||||
/**
|
||||
* Select a proposal from a supplied list.
|
||||
@@ -204,11 +204,16 @@ struct child_cfg_t {
|
||||
action_t (*get_close_action) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get the DH group to use for CHILD_SA setup.
|
||||
* Get the first algorithm of a certain transform type that's contained in
|
||||
* any of the configured proposals.
|
||||
*
|
||||
* @return dh group to use
|
||||
* For instance, use with KEY_EXCHANGE_METHOD to get the KE method to use
|
||||
* for the CHILD_SA initiation.
|
||||
*
|
||||
* @param type transform type to look for
|
||||
* @return algorithm identifier (0 for none)
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this);
|
||||
uint16_t (*get_algorithm)(child_cfg_t *this, transform_type_t type);
|
||||
|
||||
/**
|
||||
* Get the inactivity timeout value.
|
||||
|
||||
@@ -348,23 +348,23 @@ METHOD(ike_cfg_t, select_proposal, proposal_t*,
|
||||
return proposal_select(this->proposals, proposals, flags);
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
|
||||
private_ike_cfg_t *this)
|
||||
METHOD(ike_cfg_t, get_algorithm, uint16_t,
|
||||
private_ike_cfg_t *this, transform_type_t type)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
proposal_t *proposal;
|
||||
uint16_t dh_group = MODP_NONE;
|
||||
uint16_t alg = 0;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
while (enumerator->enumerate(enumerator, &proposal))
|
||||
{
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
|
||||
if (proposal->get_algorithm(proposal, type, &alg, NULL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return dh_group;
|
||||
return alg;
|
||||
}
|
||||
|
||||
METHOD(ike_cfg_t, equals, bool,
|
||||
@@ -603,7 +603,7 @@ ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
|
||||
.get_proposals = _get_proposals,
|
||||
.select_proposal = _select_proposal,
|
||||
.has_proposal = _has_proposal,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.get_algorithm = _get_algorithm,
|
||||
.equals = _equals,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
|
||||
@@ -35,7 +35,6 @@ typedef struct ike_cfg_create_t ike_cfg_create_t;
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
#include <crypto/proposal/proposal.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
/**
|
||||
* IKE version.
|
||||
@@ -231,11 +230,16 @@ struct ike_cfg_t {
|
||||
childless_t (*childless)(ike_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get the DH group to use for IKE_SA setup.
|
||||
* Get the first algorithm of a certain transform type that's contained in
|
||||
* any of the configured proposals.
|
||||
*
|
||||
* @return dh group to use for initialization
|
||||
* For instance, use with KEY_EXCHANGE_METHOD to get the KE metho to use
|
||||
* for the IKE_SA initiation.
|
||||
*
|
||||
* @param type transform type to look for
|
||||
* @return algorithm identifier (0 for none)
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this);
|
||||
uint16_t (*get_algorithm)(ike_cfg_t *this, transform_type_t type);
|
||||
|
||||
/**
|
||||
* Check if two IKE configs are equal.
|
||||
|
||||
@@ -1565,7 +1565,7 @@ static encrypted_payload_t* wrap_payloads(private_message_t *this)
|
||||
}
|
||||
}
|
||||
if (encrypted)
|
||||
{ /* simply adopt all the unencrypted payloads */
|
||||
{ /* simply adopt all the unprotected payloads */
|
||||
this->payloads->destroy(this->payloads);
|
||||
this->payloads = payloads;
|
||||
return encrypted;
|
||||
@@ -1655,7 +1655,7 @@ static ike_header_t *create_header(private_message_t *this)
|
||||
*
|
||||
* The generator and the possible encrypted payload are returned. The latter
|
||||
* is not yet encrypted (but the transform is set). It is also not added to
|
||||
* the payload list (so unless there are unencrypted payloads that list will
|
||||
* the payload list (so unless there are unprotected payloads that list will
|
||||
* be empty afterwards).
|
||||
*/
|
||||
static status_t generate_message(private_message_t *this, keymat_t *keymat,
|
||||
@@ -1943,7 +1943,7 @@ static message_t *create_fragment(private_message_t *this, payload_type_t next,
|
||||
/* only in the first fragment is this set to the type of the first
|
||||
* payload in the encrypted payload */
|
||||
fragment->set_next_type(fragment, next);
|
||||
/* move unencrypted payloads to the first fragment */
|
||||
/* move unprotected payloads to the first fragment */
|
||||
enumerator = this->payloads->create_enumerator(this->payloads);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
{
|
||||
@@ -2096,7 +2096,7 @@ METHOD(message_t, fragment, status_t,
|
||||
/* padding and padding length */
|
||||
frag_len = round_down(frag_len, aead->get_block_size(aead));
|
||||
REDUCE_FRAG_LEN(frag_len, 1);
|
||||
/* TODO-FRAG: if there are unencrypted payloads, should we account for
|
||||
/* TODO-FRAG: if there are unprotected payloads, should we account for
|
||||
* their length in the first fragment? we still would have to add
|
||||
* an encrypted fragment payload (albeit empty), even so we couldn't
|
||||
* prevent IP fragmentation in every case */
|
||||
@@ -2894,7 +2894,7 @@ METHOD(message_t, add_fragment_v2, status_t,
|
||||
/* the first fragment denotes the payload type of the first payload in
|
||||
* the original encrypted payload, cache that */
|
||||
this->first_payload = payload->get_next_type(payload);
|
||||
/* move all unencrypted payloads contained in the first fragment */
|
||||
/* move all unprotected payloads contained in the first fragment */
|
||||
enumerator = message->create_payload_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
{
|
||||
@@ -2920,10 +2920,18 @@ METHOD(message_t, add_fragment_v2, status_t,
|
||||
|
||||
data = merge_fragments(this, message);
|
||||
|
||||
/* use the cached next payload type from the SKF of the first fragment */
|
||||
encrypted = encrypted_payload_create_from_plain(this->first_payload, data);
|
||||
encrypted->set_transform(encrypted, aead);
|
||||
|
||||
if (this->payloads->get_last(this->payloads, (void**)&payload) == SUCCESS)
|
||||
{ /* if there are any unprotected payloads, update the last one's next
|
||||
* payload type (it points to an SKF instead of an SK) */
|
||||
payload->set_next_type(payload, encrypted->payload_interface.get_type(
|
||||
&encrypted->payload_interface));
|
||||
}
|
||||
this->payloads->insert_last(this->payloads, encrypted);
|
||||
/* update next payload type (could be an unencrypted payload) */
|
||||
/* update payload type in the header (could be an unprotected payload) */
|
||||
this->payloads->get_first(this->payloads, (void**)&payload);
|
||||
this->first_payload = payload->get_type(payload);
|
||||
|
||||
|
||||
@@ -59,9 +59,9 @@ struct private_ke_payload_t {
|
||||
uint16_t payload_length;
|
||||
|
||||
/**
|
||||
* DH Group Number.
|
||||
* Key exchange method number.
|
||||
*/
|
||||
uint16_t dh_group_number;
|
||||
uint16_t ke_method;
|
||||
|
||||
/**
|
||||
* Key Exchange Data of this KE payload.
|
||||
@@ -92,8 +92,8 @@ static encoding_rule_t encodings_v2[] = {
|
||||
{ RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[6]) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
|
||||
/* DH Group number as 16 bit field*/
|
||||
{ U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
|
||||
/* Key exchange method number as 16 bit field*/
|
||||
{ U_INT_16, offsetof(private_ke_payload_t, ke_method) },
|
||||
/* 2 reserved bytes */
|
||||
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
|
||||
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])},
|
||||
@@ -107,7 +107,7 @@ static encoding_rule_t encodings_v2[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Next Payload !C! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! DH Group # ! RESERVED !
|
||||
! KE method # ! RESERVED !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Key Exchange Data ~
|
||||
@@ -197,10 +197,10 @@ METHOD(ke_payload_t, get_key_exchange_data, chunk_t,
|
||||
return this->key_exchange_data;
|
||||
}
|
||||
|
||||
METHOD(ke_payload_t, get_dh_group_number, diffie_hellman_group_t,
|
||||
METHOD(ke_payload_t, get_key_exchange_method, key_exchange_method_t,
|
||||
private_ke_payload_t *this)
|
||||
{
|
||||
return this->dh_group_number;
|
||||
return this->ke_method;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, ke_payload_t, destroy, void,
|
||||
@@ -230,11 +230,11 @@ ke_payload_t *ke_payload_create(payload_type_t type)
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_key_exchange_data = _get_key_exchange_data,
|
||||
.get_dh_group_number = _get_dh_group_number,
|
||||
.get_key_exchange_method = _get_key_exchange_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = PL_NONE,
|
||||
.dh_group_number = MODP_NONE,
|
||||
.ke_method = KE_NONE,
|
||||
.type = type,
|
||||
);
|
||||
this->payload_length = get_header_length(this);
|
||||
@@ -244,19 +244,19 @@ ke_payload_t *ke_payload_create(payload_type_t type)
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
|
||||
diffie_hellman_t *dh)
|
||||
ke_payload_t *ke_payload_create_from_key_exchange(payload_type_t type,
|
||||
key_exchange_t *ke)
|
||||
{
|
||||
private_ke_payload_t *this;
|
||||
chunk_t value;
|
||||
|
||||
if (!dh->get_my_public_value(dh, &value))
|
||||
if (!ke->get_public_key(ke, &value))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
this = (private_ke_payload_t*)ke_payload_create(type);
|
||||
this->key_exchange_data = value;
|
||||
this->dh_group_number = dh->get_dh_group(dh);
|
||||
this->ke_method = ke->get_method(ke);
|
||||
this->payload_length += this->key_exchange_data.len;
|
||||
|
||||
return &this->public;
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct ke_payload_t ke_payload_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <encoding/payloads/transform_substructure.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
/**
|
||||
* Class representing an IKEv1 or IKEv2 key exchange payload.
|
||||
@@ -49,11 +49,11 @@ struct ke_payload_t {
|
||||
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
|
||||
|
||||
/**
|
||||
* Gets the Diffie-Hellman Group Number of this KE payload (IKEv2 only).
|
||||
* Gets the key exchange method of this KE payload (IKEv2 only).
|
||||
*
|
||||
* @return DH Group Number of this payload
|
||||
* @return key exchange method of this payload
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
|
||||
key_exchange_method_t (*get_key_exchange_method)(ke_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a ke_payload_t object.
|
||||
@@ -70,13 +70,13 @@ struct ke_payload_t {
|
||||
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 key_exchange_t.
|
||||
*
|
||||
* @param type PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE
|
||||
* @param dh diffie hellman object containing group and key
|
||||
* @param ke key exchange object containing method and public key
|
||||
* @return ke_payload_t object, NULL on error
|
||||
*/
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
|
||||
diffie_hellman_t *dh);
|
||||
ke_payload_t *ke_payload_create_from_key_exchange(payload_type_t type,
|
||||
key_exchange_t *ke);
|
||||
|
||||
#endif /** KE_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -904,7 +904,7 @@ static void add_to_proposal_v1_ike(proposal_t *proposal,
|
||||
get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION, value), 0);
|
||||
break;
|
||||
case TATTR_PH1_GROUP:
|
||||
proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
value, 0);
|
||||
break;
|
||||
default:
|
||||
@@ -951,7 +951,7 @@ static void add_to_proposal_v1(proposal_t *proposal,
|
||||
get_alg_from_ikev1_auth(value), 0);
|
||||
break;
|
||||
case TATTR_PH2_GROUP:
|
||||
proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
value, 0);
|
||||
break;
|
||||
case TATTR_PH2_EXT_SEQ_NUMBER:
|
||||
@@ -1318,7 +1318,7 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
|
||||
enumerator = proposal->create_enumerator(proposal, KEY_EXCHANGE_METHOD);
|
||||
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
||||
{
|
||||
transform->add_transform_attribute(transform,
|
||||
@@ -1396,7 +1396,7 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
|
||||
return;
|
||||
}
|
||||
|
||||
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
|
||||
enumerator = proposal->create_enumerator(proposal, KEY_EXCHANGE_METHOD);
|
||||
if (enumerator->enumerate(enumerator, &alg, &key_size))
|
||||
{
|
||||
transform->add_transform_attribute(transform,
|
||||
@@ -1489,11 +1489,11 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* dh groups */
|
||||
enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
|
||||
enumerator = proposal->create_enumerator(proposal, KEY_EXCHANGE_METHOD);
|
||||
while (enumerator->enumerate(enumerator, &alg, NULL))
|
||||
{
|
||||
transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
|
||||
DIFFIE_HELLMAN_GROUP, alg);
|
||||
KEY_EXCHANGE_METHOD, alg);
|
||||
add_transform_substructure(this, transform);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct transform_substructure_t transform_substructure_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <encoding/payloads/transform_attribute.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
#include <crypto/signers/signer.h>
|
||||
#include <crypto/prfs/prf.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
@@ -51,7 +51,7 @@ struct private_ha_child_t {
|
||||
|
||||
METHOD(listener_t, child_keys, bool,
|
||||
private_ha_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
||||
bool initiator, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||
bool initiator, key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||
{
|
||||
ha_message_t *m;
|
||||
chunk_t secret;
|
||||
@@ -92,7 +92,7 @@ METHOD(listener_t, child_keys, bool,
|
||||
{
|
||||
m->add_attribute(m, HA_ALG_INTEG, alg);
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
|
||||
{
|
||||
m->add_attribute(m, HA_ALG_DH, alg);
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ struct private_ha_dispatcher_t {
|
||||
struct ha_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t
|
||||
* Implements key_exchange_t
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t dh;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
@@ -82,21 +82,21 @@ struct ha_diffie_hellman_t {
|
||||
chunk_t pub;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, dh_get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, dh_get_shared_secret, bool,
|
||||
ha_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_clone(this->secret);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, dh_get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, dh_get_public_key, bool,
|
||||
ha_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_clone(this->pub);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, dh_destroy, void,
|
||||
METHOD(key_exchange_t, dh_destroy, void,
|
||||
ha_diffie_hellman_t *this)
|
||||
{
|
||||
free(this);
|
||||
@@ -105,14 +105,14 @@ METHOD(diffie_hellman_t, dh_destroy, void,
|
||||
/**
|
||||
* Create a HA synced DH implementation
|
||||
*/
|
||||
static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub)
|
||||
static key_exchange_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub)
|
||||
{
|
||||
ha_diffie_hellman_t *this;
|
||||
|
||||
INIT(this,
|
||||
.dh = {
|
||||
.get_shared_secret = _dh_get_shared_secret,
|
||||
.get_my_public_value = _dh_get_my_public_value,
|
||||
.get_public_key = _dh_get_public_key,
|
||||
.destroy = _dh_destroy,
|
||||
},
|
||||
.secret = secret,
|
||||
@@ -210,7 +210,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
if (ike_sa)
|
||||
{
|
||||
proposal_t *proposal;
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
proposal = proposal_create(PROTO_IKE, 0);
|
||||
if (integ)
|
||||
@@ -227,7 +227,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
}
|
||||
if (dh_grp)
|
||||
{
|
||||
proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0);
|
||||
proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, dh_grp, 0);
|
||||
}
|
||||
charon->bus->set_sa(charon->bus, ike_sa);
|
||||
dh = ha_diffie_hellman_create(secret, dh_local);
|
||||
@@ -662,7 +662,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
||||
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
|
||||
chunk_t encr_i, integ_i, encr_r, integ_r;
|
||||
linked_list_t *local_ts, *remote_ts;
|
||||
diffie_hellman_t *dh = NULL;
|
||||
key_exchange_t *dh = NULL;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
@@ -762,7 +762,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
||||
}
|
||||
if (dh_grp)
|
||||
{
|
||||
proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0);
|
||||
proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, dh_grp, 0);
|
||||
}
|
||||
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
|
||||
if (secret.len)
|
||||
|
||||
@@ -82,7 +82,7 @@ static void copy_extensions(ha_message_t *m, ike_sa_t *ike_sa)
|
||||
}
|
||||
|
||||
METHOD(listener_t, ike_keys, bool,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey,
|
||||
shared_key_t *shared, auth_method_t method)
|
||||
{
|
||||
@@ -132,7 +132,7 @@ METHOD(listener_t, ike_keys, bool,
|
||||
{
|
||||
m->add_attribute(m, HA_ALG_PRF, alg);
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
|
||||
{
|
||||
m->add_attribute(m, HA_ALG_DH, alg);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ METHOD(listener_t, ike_keys, bool,
|
||||
chunk_clear(&secret);
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
if (dh->get_my_public_value(dh, &secret))
|
||||
if (dh->get_public_key(dh, &secret))
|
||||
{
|
||||
m->add_attribute(m, HA_LOCAL_DH, secret);
|
||||
chunk_free(&secret);
|
||||
|
||||
@@ -16,33 +16,33 @@
|
||||
|
||||
#include "load_tester_diffie_hellman.h"
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
load_tester_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_empty;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
load_tester_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
load_tester_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_empty;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
load_tester_diffie_hellman_t *this)
|
||||
{
|
||||
return MODP_NULL;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
load_tester_diffie_hellman_t *this)
|
||||
{
|
||||
free(this);
|
||||
@@ -52,7 +52,7 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
* See header
|
||||
*/
|
||||
load_tester_diffie_hellman_t *load_tester_diffie_hellman_create(
|
||||
diffie_hellman_group_t group)
|
||||
key_exchange_method_t group)
|
||||
{
|
||||
load_tester_diffie_hellman_t *this;
|
||||
|
||||
@@ -62,11 +62,11 @@ load_tester_diffie_hellman_t *load_tester_diffie_hellman_create(
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifndef LOAD_TESTER_DIFFIE_HELLMAN_H_
|
||||
#define LOAD_TESTER_DIFFIE_HELLMAN_H_
|
||||
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
typedef struct load_tester_diffie_hellman_t load_tester_diffie_hellman_t;
|
||||
|
||||
@@ -32,18 +32,18 @@ typedef struct load_tester_diffie_hellman_t load_tester_diffie_hellman_t;
|
||||
struct load_tester_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new gmp_diffie_hellman_t object.
|
||||
* Creates a new load_tester_diffie_hellman_t object.
|
||||
*
|
||||
* @param group Diffie Hellman group, supports MODP_NULL only
|
||||
* @return gmp_diffie_hellman_t object
|
||||
* @return load_tester_diffie_hellman_t object
|
||||
*/
|
||||
load_tester_diffie_hellman_t *load_tester_diffie_hellman_create(
|
||||
diffie_hellman_group_t group);
|
||||
key_exchange_method_t group);
|
||||
|
||||
#endif /** LOAD_TESTER_DIFFIE_HELLMAN_H_ @}*/
|
||||
|
||||
@@ -231,8 +231,8 @@ METHOD(plugin_t, get_features, int,
|
||||
private_load_tester_plugin_t *this, plugin_feature_t *features[])
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
PLUGIN_REGISTER(DH, load_tester_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(DH, MODP_NULL),
|
||||
PLUGIN_REGISTER(KE, load_tester_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(KE, MODP_NULL),
|
||||
PLUGIN_DEPENDS(CUSTOM, "load-tester"),
|
||||
PLUGIN_CALLBACK((plugin_feature_callback_t)register_load_tester, NULL),
|
||||
PLUGIN_PROVIDE(CUSTOM, "load-tester"),
|
||||
|
||||
@@ -266,10 +266,10 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
|
||||
fprintf(out, "_%u", ks);
|
||||
}
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
&alg, NULL))
|
||||
{
|
||||
fprintf(out, "/%N", diffie_hellman_group_names, alg);
|
||||
fprintf(out, "/%N", key_exchange_method_names, alg);
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
|
||||
&alg, NULL) && alg == EXT_SEQ_NUMBERS)
|
||||
@@ -855,7 +855,7 @@ static void list_algs(FILE *out)
|
||||
ext_out_function_t xof;
|
||||
key_derivation_function_t kdf;
|
||||
drbg_type_t drbg;
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
rng_quality_t quality;
|
||||
const char *plugin_name;
|
||||
int len;
|
||||
@@ -928,10 +928,10 @@ static void list_algs(FILE *out)
|
||||
enumerator->destroy(enumerator);
|
||||
fprintf(out, "\n dh-group: ");
|
||||
len = 13;
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &group, &plugin_name))
|
||||
{
|
||||
print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
|
||||
print_alg(out, &len, key_exchange_method_names, group, plugin_name);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
fprintf(out, "\n random-gen:");
|
||||
|
||||
@@ -230,10 +230,10 @@ static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
|
||||
b->add_kv(b, "integ-keysize", "%u", ks);
|
||||
}
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
&alg, NULL))
|
||||
{
|
||||
b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
|
||||
b->add_kv(b, "dh-group", "%N", key_exchange_method_names, alg);
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
|
||||
&alg, NULL) && alg == EXT_SEQ_NUMBERS)
|
||||
@@ -489,9 +489,9 @@ static void list_ike(private_vici_query_t *this, vici_builder_t *b,
|
||||
{
|
||||
b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
|
||||
}
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
|
||||
{
|
||||
b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
|
||||
b->add_kv(b, "dh-group", "%N", key_exchange_method_names, alg);
|
||||
}
|
||||
}
|
||||
add_condition(b, ike_sa, "ppk", COND_PPK);
|
||||
@@ -1304,7 +1304,7 @@ CALLBACK(get_algorithms, vici_message_t*,
|
||||
ext_out_function_t xof;
|
||||
key_derivation_function_t kdf;
|
||||
drbg_type_t drbg;
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
rng_quality_t quality;
|
||||
const char *plugin_name;
|
||||
|
||||
@@ -1383,10 +1383,10 @@ CALLBACK(get_algorithms, vici_message_t*,
|
||||
b->end_section(b);
|
||||
|
||||
b->begin_section(b, "dh");
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &group, &plugin_name))
|
||||
{
|
||||
add_algorithm(b, diffie_hellman_group_names, group, plugin_name);
|
||||
add_algorithm(b, key_exchange_method_names, group, plugin_name);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
b->end_section(b);
|
||||
|
||||
@@ -121,7 +121,7 @@ authenticator_t *authenticator_create_verifier(
|
||||
* Described in header.
|
||||
*/
|
||||
authenticator_t *authenticator_create_v1(ike_sa_t *ike_sa, bool initiator,
|
||||
auth_method_t auth_method, diffie_hellman_t *dh,
|
||||
auth_method_t auth_method, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload)
|
||||
{
|
||||
|
||||
@@ -238,7 +238,7 @@ authenticator_t *authenticator_create_verifier(
|
||||
* @return authenticator, NULL if not supported
|
||||
*/
|
||||
authenticator_t *authenticator_create_v1(ike_sa_t *ike_sa, bool initiator,
|
||||
auth_method_t auth_method, diffie_hellman_t *dh,
|
||||
auth_method_t auth_method, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload);
|
||||
|
||||
|
||||
@@ -110,6 +110,11 @@ struct private_child_sa_t {
|
||||
*/
|
||||
chunk_t integ_r;
|
||||
|
||||
/**
|
||||
* Whether the registered outbound SA was created as initiator
|
||||
*/
|
||||
bool initiator;
|
||||
|
||||
/**
|
||||
* Whether the outbound SA has only been registered yet during a rekeying
|
||||
*/
|
||||
@@ -1420,13 +1425,13 @@ static bool install_outbound_immediately(private_child_sa_t *this)
|
||||
|
||||
METHOD(child_sa_t, register_outbound, status_t,
|
||||
private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
|
||||
uint16_t cpi, bool tfcv3)
|
||||
uint16_t cpi, bool initiator, bool tfcv3)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
if (install_outbound_immediately(this))
|
||||
{
|
||||
status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
|
||||
status = install_internal(this, encr, integ, spi, cpi, initiator, FALSE,
|
||||
tfcv3);
|
||||
}
|
||||
else
|
||||
@@ -1440,6 +1445,7 @@ METHOD(child_sa_t, register_outbound, status_t,
|
||||
this->other_cpi = cpi;
|
||||
this->encr_r = chunk_clone(encr);
|
||||
this->integ_r = chunk_clone(integ);
|
||||
this->initiator = initiator;
|
||||
this->tfcv3 = tfcv3;
|
||||
status = SUCCESS;
|
||||
}
|
||||
@@ -1457,8 +1463,8 @@ METHOD(child_sa_t, install_outbound, status_t,
|
||||
if (!(this->outbound_state & CHILD_OUTBOUND_SA))
|
||||
{
|
||||
status = install_internal(this, this->encr_r, this->integ_r,
|
||||
this->other_spi, this->other_cpi, FALSE,
|
||||
FALSE, this->tfcv3);
|
||||
this->other_spi, this->other_cpi,
|
||||
this->initiator, FALSE, this->tfcv3);
|
||||
chunk_clear(&this->encr_r);
|
||||
chunk_clear(&this->integ_r);
|
||||
}
|
||||
|
||||
@@ -442,11 +442,13 @@ struct child_sa_t {
|
||||
* @param integ integrity key (cloned)
|
||||
* @param spi SPI to use, allocated for inbound
|
||||
* @param cpi CPI to use, allocated for outbound
|
||||
* @param initiator TRUE if initiator of exchange resulting in this SA
|
||||
* @param tfcv3 TRUE if peer supports ESPv3 TFC
|
||||
* @return SUCCESS or FAILED
|
||||
*/
|
||||
status_t (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
|
||||
uint32_t spi, uint16_t cpi, bool tfcv3);
|
||||
uint32_t spi, uint16_t cpi, bool initiator,
|
||||
bool tfcv3);
|
||||
|
||||
/**
|
||||
* Install the outbound policies and, if not already done, the outbound SA
|
||||
|
||||
@@ -1883,6 +1883,7 @@ METHOD(ike_sa_t, delete_, status_t,
|
||||
{
|
||||
case IKE_ESTABLISHED:
|
||||
case IKE_REKEYING:
|
||||
case IKE_REKEYED:
|
||||
if (time_monotonic(NULL) >= this->stats[STAT_DELETE] &&
|
||||
!(this->version == IKEV1 && this->state == IKE_REKEYING))
|
||||
{ /* IKE_SA hard lifetime hit, ignored for reauthenticated
|
||||
|
||||
@@ -1879,8 +1879,12 @@ METHOD(ike_sa_manager_t, checkin, void,
|
||||
other_id = ike_sa->get_other_eap_id(ike_sa);
|
||||
other = ike_sa->get_other_host(ike_sa);
|
||||
|
||||
DBG2(DBG_MGR, "checkin IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
|
||||
ike_sa->get_unique_id(ike_sa));
|
||||
DBG2(DBG_MGR, "checkin %N SA %s[%u] with SPIs %.16"PRIx64"_i "
|
||||
"%.16"PRIx64"_r", ike_version_names,
|
||||
ike_sa_id->get_ike_version(ike_sa_id), ike_sa->get_name(ike_sa),
|
||||
ike_sa->get_unique_id(ike_sa),
|
||||
be64toh(ike_sa_id->get_initiator_spi(ike_sa_id)),
|
||||
be64toh(ike_sa_id->get_responder_spi(ike_sa_id)));
|
||||
|
||||
/* look for the entry */
|
||||
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
|
||||
|
||||
@@ -78,7 +78,7 @@ METHOD(authenticator_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
hybrid_authenticator_t *hybrid_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ struct hybrid_authenticator_t {
|
||||
* @return hybrid authenticator
|
||||
*/
|
||||
hybrid_authenticator_t *hybrid_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct private_psk_v1_authenticator_t {
|
||||
/**
|
||||
* DH key exchange
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Others DH public value
|
||||
@@ -75,7 +75,7 @@ METHOD(authenticator_t, build, status_t,
|
||||
keymat_v1_t *keymat;
|
||||
chunk_t hash, dh;
|
||||
|
||||
if (!this->dh->get_my_public_value(this->dh, &dh))
|
||||
if (!this->dh->get_public_key(this->dh, &dh))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ METHOD(authenticator_t, process, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (!this->dh->get_my_public_value(this->dh, &dh))
|
||||
if (!this->dh->get_public_key(this->dh, &dh))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ METHOD(authenticator_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
psk_v1_authenticator_t *psk_v1_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload, bool hybrid)
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ struct psk_v1_authenticator_t {
|
||||
* @return PSK authenticator
|
||||
*/
|
||||
psk_v1_authenticator_t *psk_v1_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload, bool hybrid);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ struct private_pubkey_v1_authenticator_t {
|
||||
/**
|
||||
* DH key exchange
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Others DH public value
|
||||
@@ -96,7 +96,7 @@ METHOD(authenticator_t, build, status_t,
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!this->dh->get_my_public_value(this->dh, &dh))
|
||||
if (!this->dh->get_public_key(this->dh, &dh))
|
||||
{
|
||||
private->destroy(private);
|
||||
return FAILED;
|
||||
@@ -181,7 +181,7 @@ METHOD(authenticator_t, process, status_t,
|
||||
}
|
||||
|
||||
id = this->ike_sa->get_other_id(this->ike_sa);
|
||||
if (!this->dh->get_my_public_value(this->dh, &dh))
|
||||
if (!this->dh->get_public_key(this->dh, &dh))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
@@ -238,7 +238,7 @@ METHOD(authenticator_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
pubkey_v1_authenticator_t *pubkey_v1_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload, key_type_t type)
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ struct pubkey_v1_authenticator_t {
|
||||
* @return pubkey authenticator
|
||||
*/
|
||||
pubkey_v1_authenticator_t *pubkey_v1_authenticator_create(ike_sa_t *ike_sa,
|
||||
bool initiator, diffie_hellman_t *dh,
|
||||
bool initiator, key_exchange_t *dh,
|
||||
chunk_t dh_value, chunk_t sa_payload,
|
||||
chunk_t id_payload, key_type_t type);
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ static void adjust_keylen(uint16_t alg, chunk_t *key)
|
||||
}
|
||||
|
||||
METHOD(keymat_v1_t, derive_ike_keys, bool,
|
||||
private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_keymat_v1_t *this, proposal_t *proposal, key_exchange_t *dh,
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
|
||||
auth_method_t auth, shared_key_t *shared_key)
|
||||
{
|
||||
@@ -494,7 +494,7 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dh->get_my_public_value(dh, &dh_me))
|
||||
if (!dh->get_public_key(dh, &dh_me))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -539,7 +539,7 @@ static bool derive_child_keymat(private_keymat_v1_t *this, chunk_t seed,
|
||||
}
|
||||
|
||||
METHOD(keymat_v1_t, derive_child_keys, bool,
|
||||
private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_keymat_v1_t *this, proposal_t *proposal, key_exchange_t *dh,
|
||||
uint32_t spi_i, uint32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
|
||||
chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
|
||||
{
|
||||
@@ -914,10 +914,10 @@ METHOD(keymat_t, get_version, ike_version_t,
|
||||
return IKEV1;
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_dh, diffie_hellman_t*,
|
||||
private_keymat_v1_t *this, diffie_hellman_group_t group)
|
||||
METHOD(keymat_t, create_ke, key_exchange_t*,
|
||||
private_keymat_v1_t *this, key_exchange_method_t method)
|
||||
{
|
||||
return lib->crypto->create_dh(lib->crypto, group);
|
||||
return lib->crypto->create_ke(lib->crypto, method);
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
|
||||
@@ -956,7 +956,7 @@ keymat_v1_t *keymat_v1_create(bool initiator)
|
||||
.public = {
|
||||
.keymat = {
|
||||
.get_version = _get_version,
|
||||
.create_dh = _create_dh,
|
||||
.create_ke = _create_ke,
|
||||
.create_nonce_gen = _create_nonce_gen,
|
||||
.get_aead = _get_aead,
|
||||
.destroy = _destroy,
|
||||
|
||||
@@ -44,7 +44,7 @@ struct keymat_v1_t {
|
||||
* crypters and authentication functions.
|
||||
*
|
||||
* @param proposal selected algorithms
|
||||
* @param dh diffie hellman key allocated by create_dh()
|
||||
* @param dh diffie hellman key allocated by create_ke()
|
||||
* @param dh_other public DH value from other peer
|
||||
* @param nonce_i initiators nonce value
|
||||
* @param nonce_r responders nonce value
|
||||
@@ -54,7 +54,7 @@ struct keymat_v1_t {
|
||||
* @return TRUE on success
|
||||
*/
|
||||
bool (*derive_ike_keys)(keymat_v1_t *this, proposal_t *proposal,
|
||||
diffie_hellman_t *dh, chunk_t dh_other,
|
||||
key_exchange_t *dh, chunk_t dh_other,
|
||||
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
|
||||
auth_method_t auth, shared_key_t *shared_key);
|
||||
|
||||
@@ -73,7 +73,7 @@ struct keymat_v1_t {
|
||||
* @param integ_r allocated responders integrity key
|
||||
*/
|
||||
bool (*derive_child_keys)(keymat_v1_t *this, proposal_t *proposal,
|
||||
diffie_hellman_t *dh, uint32_t spi_i, uint32_t spi_r,
|
||||
key_exchange_t *dh, uint32_t spi_i, uint32_t spi_r,
|
||||
chunk_t nonce_i, chunk_t nonce_r,
|
||||
chunk_t *encr_i, chunk_t *integ_i,
|
||||
chunk_t *encr_r, chunk_t *integ_r);
|
||||
|
||||
@@ -63,7 +63,7 @@ struct private_phase1_t {
|
||||
/**
|
||||
* DH exchange
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Keymat derivation (from SA)
|
||||
@@ -210,9 +210,9 @@ METHOD(phase1_t, create_hasher, bool,
|
||||
}
|
||||
|
||||
METHOD(phase1_t, create_dh, bool,
|
||||
private_phase1_t *this, diffie_hellman_group_t group)
|
||||
private_phase1_t *this, key_exchange_method_t group)
|
||||
{
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat, group);
|
||||
return this->dh != NULL;
|
||||
}
|
||||
|
||||
@@ -705,8 +705,8 @@ METHOD(phase1_t, add_nonce_ke, bool,
|
||||
nonce_gen_t *nonceg;
|
||||
chunk_t nonce;
|
||||
|
||||
ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
ke_payload = ke_payload_create_from_key_exchange(PLV1_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
if (!ke_payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "creating KE payload failed");
|
||||
@@ -756,7 +756,7 @@ METHOD(phase1_t, get_nonce_ke, bool,
|
||||
return FALSE;
|
||||
}
|
||||
this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
|
||||
if (!this->dh->set_other_public_value(this->dh, this->dh_value))
|
||||
if (!this->dh->set_public_key(this->dh, this->dh_value))
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to apply received KE value");
|
||||
return FALSE;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
typedef struct phase1_t phase1_t;
|
||||
|
||||
#include <sa/ike_sa.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
/**
|
||||
* Common phase 1 helper for main and aggressive mode.
|
||||
@@ -45,7 +45,7 @@ struct phase1_t {
|
||||
* @param group negotiated DH group
|
||||
* @return TRUE if group supported
|
||||
*/
|
||||
bool (*create_dh)(phase1_t *this, diffie_hellman_group_t group);
|
||||
bool (*create_dh)(phase1_t *this, key_exchange_method_t group);
|
||||
|
||||
/**
|
||||
* Derive key material.
|
||||
|
||||
@@ -252,8 +252,9 @@ METHOD(task_t, build_i, status_t,
|
||||
|
||||
message->add_payload(message, &sa_payload->payload_interface);
|
||||
|
||||
group = this->ike_cfg->get_dh_group(this->ike_cfg);
|
||||
if (group == MODP_NONE)
|
||||
group = this->ike_cfg->get_algorithm(this->ike_cfg,
|
||||
KEY_EXCHANGE_METHOD);
|
||||
if (!group)
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group selection failed");
|
||||
return FAILED;
|
||||
@@ -261,7 +262,7 @@ METHOD(task_t, build_i, status_t,
|
||||
if (!this->ph1->create_dh(this->ph1, group))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group %N not supported",
|
||||
diffie_hellman_group_names, group);
|
||||
key_exchange_method_names, group);
|
||||
return FAILED;
|
||||
}
|
||||
if (!this->ph1->add_nonce_ke(this->ph1, message))
|
||||
@@ -438,7 +439,7 @@ METHOD(task_t, process_r, status_t,
|
||||
}
|
||||
|
||||
if (!this->proposal->get_algorithm(this->proposal,
|
||||
DIFFIE_HELLMAN_GROUP, &group, NULL))
|
||||
KEY_EXCHANGE_METHOD, &group, NULL))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group selection failed");
|
||||
return send_notify(this, INVALID_KEY_INFORMATION);
|
||||
|
||||
@@ -314,7 +314,7 @@ METHOD(task_t, build_i, status_t,
|
||||
return send_notify(this, NO_PROPOSAL_CHOSEN);
|
||||
}
|
||||
if (!this->proposal->get_algorithm(this->proposal,
|
||||
DIFFIE_HELLMAN_GROUP, &group, NULL))
|
||||
KEY_EXCHANGE_METHOD, &group, NULL))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group selection failed");
|
||||
return send_notify(this, NO_PROPOSAL_CHOSEN);
|
||||
@@ -428,7 +428,7 @@ METHOD(task_t, process_r, status_t,
|
||||
return send_notify(this, INVALID_KEY_INFORMATION);
|
||||
}
|
||||
if (!this->proposal->get_algorithm(this->proposal,
|
||||
DIFFIE_HELLMAN_GROUP, &group, NULL))
|
||||
KEY_EXCHANGE_METHOD, &group, NULL))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group selection failed");
|
||||
return send_notify(this, INVALID_KEY_INFORMATION);
|
||||
|
||||
@@ -137,7 +137,7 @@ struct private_quick_mode_t {
|
||||
/**
|
||||
* DH exchange, when PFS is in use
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Negotiated lifetime of new SA
|
||||
@@ -486,8 +486,8 @@ static bool add_ke(private_quick_mode_t *this, message_t *message)
|
||||
{
|
||||
ke_payload_t *ke_payload;
|
||||
|
||||
ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
ke_payload = ke_payload_create_from_key_exchange(PLV1_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
if (!ke_payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "creating KE payload failed");
|
||||
@@ -510,7 +510,7 @@ static bool get_ke(private_quick_mode_t *this, message_t *message)
|
||||
DBG1(DBG_IKE, "KE payload missing");
|
||||
return FALSE;
|
||||
}
|
||||
if (!this->dh->set_other_public_value(this->dh,
|
||||
if (!this->dh->set_public_key(this->dh,
|
||||
ke_payload->get_key_exchange_data(ke_payload)))
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to apply received KE value");
|
||||
@@ -782,10 +782,10 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
|
||||
|
||||
/**
|
||||
* Prepare a list of proposals from child_config containing only the specified
|
||||
* DH group, unless it is set to MODP_NONE.
|
||||
* DH group, unless it is set to KE_NONE.
|
||||
*/
|
||||
static linked_list_t *get_proposals(private_quick_mode_t *this,
|
||||
diffie_hellman_group_t group)
|
||||
key_exchange_method_t group)
|
||||
{
|
||||
linked_list_t *list;
|
||||
proposal_t *proposal;
|
||||
@@ -795,15 +795,15 @@ static linked_list_t *get_proposals(private_quick_mode_t *this,
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &proposal))
|
||||
{
|
||||
if (group != MODP_NONE)
|
||||
if (group != KE_NONE)
|
||||
{
|
||||
if (!proposal->has_dh_group(proposal, group))
|
||||
if (!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD, group))
|
||||
{
|
||||
list->remove_at(list, enumerator);
|
||||
proposal->destroy(proposal);
|
||||
continue;
|
||||
}
|
||||
proposal->promote_dh_group(proposal, group);
|
||||
proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD, group);
|
||||
}
|
||||
proposal->set_spi(proposal, this->spi_i);
|
||||
}
|
||||
@@ -822,7 +822,7 @@ METHOD(task_t, build_i, status_t,
|
||||
sa_payload_t *sa_payload;
|
||||
linked_list_t *list, *tsi, *tsr;
|
||||
proposal_t *proposal;
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
encap_t encap;
|
||||
|
||||
this->mode = this->config->get_mode(this->config);
|
||||
@@ -866,14 +866,15 @@ METHOD(task_t, build_i, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
group = this->config->get_dh_group(this->config);
|
||||
if (group != MODP_NONE)
|
||||
group = this->config->get_algorithm(this->config,
|
||||
KEY_EXCHANGE_METHOD);
|
||||
if (group != KE_NONE)
|
||||
{
|
||||
proposal_t *proposal;
|
||||
uint16_t preferred_group;
|
||||
|
||||
proposal = this->ike_sa->get_proposal(this->ike_sa);
|
||||
proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
&preferred_group, NULL);
|
||||
/* try the negotiated DH group from IKE_SA */
|
||||
list = get_proposals(this, preferred_group);
|
||||
@@ -888,19 +889,19 @@ METHOD(task_t, build_i, status_t,
|
||||
list = get_proposals(this, group);
|
||||
}
|
||||
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat,
|
||||
group);
|
||||
if (!this->dh)
|
||||
{
|
||||
DBG1(DBG_IKE, "configured DH group %N not supported",
|
||||
diffie_hellman_group_names, group);
|
||||
key_exchange_method_names, group);
|
||||
list->destroy_offset(list, offsetof(proposal_t, destroy));
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list = get_proposals(this, MODP_NONE);
|
||||
list = get_proposals(this, KE_NONE);
|
||||
}
|
||||
|
||||
get_lifetimes(this);
|
||||
@@ -915,7 +916,7 @@ METHOD(task_t, build_i, status_t,
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (group != MODP_NONE)
|
||||
if (group != KE_NONE)
|
||||
{
|
||||
if (!add_ke(this, message))
|
||||
{
|
||||
@@ -1165,14 +1166,14 @@ METHOD(task_t, process_r, status_t,
|
||||
}
|
||||
|
||||
if (this->proposal->get_algorithm(this->proposal,
|
||||
DIFFIE_HELLMAN_GROUP, &group, NULL))
|
||||
KEY_EXCHANGE_METHOD, &group, NULL))
|
||||
{
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat,
|
||||
group);
|
||||
if (!this->dh)
|
||||
{
|
||||
DBG1(DBG_IKE, "negotiated DH group %N not supported",
|
||||
diffie_hellman_group_names, group);
|
||||
key_exchange_method_names, group);
|
||||
return send_notify(this, INVALID_KEY_INFORMATION);
|
||||
}
|
||||
if (!get_ke(this, message))
|
||||
|
||||
@@ -84,10 +84,10 @@ METHOD(keymat_t, get_version, ike_version_t,
|
||||
return IKEV2;
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_dh, diffie_hellman_t*,
|
||||
private_keymat_v2_t *this, diffie_hellman_group_t group)
|
||||
METHOD(keymat_t, create_ke, key_exchange_t*,
|
||||
private_keymat_v2_t *this, key_exchange_method_t method)
|
||||
{
|
||||
return lib->crypto->create_dh(lib->crypto, group);
|
||||
return lib->crypto->create_ke(lib->crypto, method);
|
||||
}
|
||||
|
||||
METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
|
||||
@@ -237,7 +237,7 @@ static bool set_aead_keys(private_keymat_v2_t *this, uint16_t enc_alg,
|
||||
}
|
||||
|
||||
METHOD(keymat_v2_t, derive_ike_keys, bool,
|
||||
private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_keymat_v2_t *this, proposal_t *proposal, key_exchange_t *dh,
|
||||
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
|
||||
pseudo_random_function_t rekey_function, chunk_t rekey_skd)
|
||||
{
|
||||
@@ -523,7 +523,7 @@ METHOD(keymat_v2_t, derive_ike_keys_ppk, bool,
|
||||
}
|
||||
|
||||
METHOD(keymat_v2_t, derive_child_keys, bool,
|
||||
private_keymat_v2_t *this, proposal_t *proposal, diffie_hellman_t *dh,
|
||||
private_keymat_v2_t *this, proposal_t *proposal, key_exchange_t *dh,
|
||||
chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
|
||||
chunk_t *encr_r, chunk_t *integ_r)
|
||||
{
|
||||
@@ -796,7 +796,7 @@ keymat_v2_t *keymat_v2_create(bool initiator)
|
||||
.public = {
|
||||
.keymat = {
|
||||
.get_version = _get_version,
|
||||
.create_dh = _create_dh,
|
||||
.create_ke = _create_ke,
|
||||
.create_nonce_gen = _create_nonce_gen,
|
||||
.get_aead = _get_aead,
|
||||
.destroy = _destroy,
|
||||
|
||||
@@ -44,7 +44,7 @@ struct keymat_v2_t {
|
||||
* crypters and authentication functions.
|
||||
*
|
||||
* @param proposal selected algorithms
|
||||
* @param dh diffie hellman key allocated by create_dh()
|
||||
* @param dh diffie hellman key allocated by create_ke()
|
||||
* @param nonce_i initiators nonce value
|
||||
* @param nonce_r responders nonce value
|
||||
* @param id IKE_SA identifier
|
||||
@@ -53,7 +53,7 @@ struct keymat_v2_t {
|
||||
* @return TRUE on success
|
||||
*/
|
||||
bool (*derive_ike_keys)(keymat_v2_t *this, proposal_t *proposal,
|
||||
diffie_hellman_t *dh, chunk_t nonce_i,
|
||||
key_exchange_t *dh, chunk_t nonce_i,
|
||||
chunk_t nonce_r, ike_sa_id_t *id,
|
||||
pseudo_random_function_t rekey_function,
|
||||
chunk_t rekey_skd);
|
||||
@@ -77,7 +77,7 @@ struct keymat_v2_t {
|
||||
* If no PFS is used for the CHILD_SA, dh can be NULL.
|
||||
*
|
||||
* @param proposal selected algorithms
|
||||
* @param dh diffie hellman key allocated by create_dh(), or NULL
|
||||
* @param dh diffie hellman key allocated by create_ke(), or NULL
|
||||
* @param nonce_i initiators nonce value
|
||||
* @param nonce_r responders nonce value
|
||||
* @param encr_i chunk to write initiators encryption key to
|
||||
@@ -87,7 +87,7 @@ struct keymat_v2_t {
|
||||
* @return TRUE on success
|
||||
*/
|
||||
bool (*derive_child_keys)(keymat_v2_t *this,
|
||||
proposal_t *proposal, diffie_hellman_t *dh,
|
||||
proposal_t *proposal, key_exchange_t *dh,
|
||||
chunk_t nonce_i, chunk_t nonce_r,
|
||||
chunk_t *encr_i, chunk_t *integ_i,
|
||||
chunk_t *encr_r, chunk_t *integ_r);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2018 Tobias Brunner
|
||||
* Copyright (C) 2007-2019 Tobias Brunner
|
||||
* Copyright (C) 2007-2010 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <sa/ikev2/tasks/child_create.h>
|
||||
#include <sa/ikev2/tasks/child_rekey.h>
|
||||
#include <sa/ikev2/tasks/child_delete.h>
|
||||
#include <encoding/payloads/encrypted_fragment_payload.h>
|
||||
#include <encoding/payloads/delete_payload.h>
|
||||
#include <encoding/payloads/unknown_payload.h>
|
||||
#include <processing/jobs/retransmit_job.h>
|
||||
@@ -79,14 +80,24 @@ struct private_task_manager_t {
|
||||
uint32_t mid;
|
||||
|
||||
/**
|
||||
* packet(s) for retransmission
|
||||
* Helper to defragment the request
|
||||
*/
|
||||
message_t *defrag;
|
||||
|
||||
/**
|
||||
* Hash of the current message, or its first fragment
|
||||
*/
|
||||
uint8_t hash[HASH_SIZE_SHA1];
|
||||
|
||||
/**
|
||||
* Packet(s) for retransmissions (mid-1)
|
||||
*/
|
||||
array_t *packets;
|
||||
|
||||
/**
|
||||
* Helper to defragment the request
|
||||
* Hash of the previously received message, or its first fragment
|
||||
*/
|
||||
message_t *defrag;
|
||||
uint8_t prev_hash[HASH_SIZE_SHA1];
|
||||
|
||||
} responding;
|
||||
|
||||
@@ -464,6 +475,40 @@ METHOD(task_manager_t, retransmit, status_t,
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive IKE keys if necessary
|
||||
*/
|
||||
static bool derive_keys(private_task_manager_t *this, array_t *tasks)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
task_t *task;
|
||||
|
||||
enumerator = array_create_enumerator(tasks);
|
||||
while (enumerator->enumerate(enumerator, (void*)&task))
|
||||
{
|
||||
if (task->get_type(task) == TASK_IKE_INIT)
|
||||
{
|
||||
ike_init_t *ike_init = (ike_init_t*)task;
|
||||
|
||||
switch (ike_init->derive_keys(ike_init))
|
||||
{
|
||||
case SUCCESS:
|
||||
array_remove_at(tasks, enumerator);
|
||||
task->destroy(task);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
enumerator->destroy(enumerator);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(task_manager_t, initiate, status_t,
|
||||
private_task_manager_t *this)
|
||||
{
|
||||
@@ -472,6 +517,7 @@ METHOD(task_manager_t, initiate, status_t,
|
||||
message_t *message;
|
||||
host_t *me, *other;
|
||||
exchange_type_t exchange = 0;
|
||||
bool result;
|
||||
|
||||
if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
|
||||
{
|
||||
@@ -597,6 +643,11 @@ METHOD(task_manager_t, initiate, status_t,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!derive_keys(this, this->active_tasks))
|
||||
{
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
DBG2(DBG_IKE, "reinitiating already active tasks");
|
||||
enumerator = array_create_enumerator(this->active_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
@@ -686,17 +737,47 @@ METHOD(task_manager_t, initiate, status_t,
|
||||
return initiate(this);
|
||||
}
|
||||
|
||||
if (!generate_message(this, message, &this->initiating.packets))
|
||||
result = generate_message(this, message, &this->initiating.packets);
|
||||
|
||||
if (result)
|
||||
{
|
||||
/* message generation failed. There is nothing more to do than to
|
||||
* close the SA */
|
||||
message->destroy(message);
|
||||
flush(this);
|
||||
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
|
||||
return DESTROY_ME;
|
||||
enumerator = array_create_enumerator(this->active_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
{
|
||||
if (!task->post_build)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (task->post_build(task, message))
|
||||
{
|
||||
case SUCCESS:
|
||||
array_remove_at(this->active_tasks, enumerator);
|
||||
task->destroy(task);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
/* critical failure, destroy IKE_SA */
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
message->destroy(message);
|
||||
|
||||
if (!result)
|
||||
{ /* message generation failed. There is nothing more to do than to
|
||||
* close the SA */
|
||||
flush(this);
|
||||
if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
|
||||
this->ike_sa->get_state(this->ike_sa) != IKE_REKEYED)
|
||||
{
|
||||
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
array_compress(this->active_tasks);
|
||||
array_compress(this->queued_tasks);
|
||||
|
||||
@@ -806,6 +887,31 @@ static status_t process_response(private_task_manager_t *this,
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
enumerator = array_create_enumerator(this->active_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
{
|
||||
if (!task->post_process)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (task->post_process(task, message))
|
||||
{
|
||||
case SUCCESS:
|
||||
array_remove_at(this->active_tasks, enumerator);
|
||||
task->destroy(task);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
/* critical failure, destroy IKE_SA */
|
||||
array_remove_at(this->active_tasks, enumerator);
|
||||
enumerator->destroy(enumerator);
|
||||
task->destroy(task);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->initiating.mid++;
|
||||
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
|
||||
clear_packets(this->initiating.packets);
|
||||
@@ -816,13 +922,15 @@ static status_t process_response(private_task_manager_t *this,
|
||||
}
|
||||
|
||||
/**
|
||||
* handle exchange collisions
|
||||
* Handle exchange collisions, returns TRUE if the given passive task was
|
||||
* adopted by the active task and the task manager lost control over it.
|
||||
*/
|
||||
static bool handle_collisions(private_task_manager_t *this, task_t *task)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
task_t *active;
|
||||
task_type_t type;
|
||||
bool adopted = FALSE;
|
||||
|
||||
type = task->get_type(task);
|
||||
|
||||
@@ -840,7 +948,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
|
||||
if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE)
|
||||
{
|
||||
ike_rekey_t *rekey = (ike_rekey_t*)active;
|
||||
rekey->collide(rekey, task);
|
||||
adopted = rekey->collide(rekey, task);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -848,7 +956,7 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
|
||||
if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
|
||||
{
|
||||
child_rekey_t *rekey = (child_rekey_t*)active;
|
||||
rekey->collide(rekey, task);
|
||||
adopted = rekey->collide(rekey, task);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -856,11 +964,11 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task)
|
||||
continue;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return TRUE;
|
||||
return adopted;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
return FALSE;
|
||||
return adopted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -947,7 +1055,34 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
|
||||
/* message complete, send it */
|
||||
clear_packets(this->responding.packets);
|
||||
result = generate_message(this, message, &this->responding.packets);
|
||||
|
||||
if (result && !delete)
|
||||
{
|
||||
enumerator = array_create_enumerator(this->passive_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
{
|
||||
if (!task->post_build)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (task->post_build(task, message))
|
||||
{
|
||||
case SUCCESS:
|
||||
array_remove_at(this->passive_tasks, enumerator);
|
||||
task->destroy(task);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
/* critical failure, destroy IKE_SA */
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
message->destroy(message);
|
||||
|
||||
if (id)
|
||||
{
|
||||
id->set_responder_spi(id, responder_spi);
|
||||
@@ -1256,6 +1391,31 @@ static status_t process_request(private_task_manager_t *this,
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
enumerator = array_create_enumerator(this->passive_tasks);
|
||||
while (enumerator->enumerate(enumerator, &task))
|
||||
{
|
||||
if (!task->post_process)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (task->post_process(task, message))
|
||||
{
|
||||
case SUCCESS:
|
||||
array_remove_at(this->passive_tasks, enumerator);
|
||||
task->destroy(task);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
/* critical failure, destroy IKE_SA */
|
||||
array_remove_at(this->passive_tasks, enumerator);
|
||||
enumerator->destroy(enumerator);
|
||||
task->destroy(task);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return build_response(this, message);
|
||||
}
|
||||
|
||||
@@ -1278,27 +1438,46 @@ METHOD(task_manager_t, get_mid, uint32_t,
|
||||
return initiate ? this->initiating.mid : this->responding.mid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the given message with SHA-1
|
||||
*/
|
||||
static bool hash_message(message_t *msg, uint8_t hash[HASH_SIZE_SHA1])
|
||||
{
|
||||
hasher_t *hasher;
|
||||
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
||||
if (!hasher ||
|
||||
!hasher->get_hash(hasher, msg->get_packet_data(msg), hash))
|
||||
{
|
||||
DESTROY_IF(hasher);
|
||||
return FALSE;
|
||||
}
|
||||
hasher->destroy(hasher);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given IKE fragment, if it is one.
|
||||
*
|
||||
* 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 (*defrag && (*defrag)->get_message_id(*defrag) < msg->get_message_id(msg))
|
||||
{
|
||||
/* clear fragments of an incompletely received retransmitted message */
|
||||
(*defrag)->destroy(*defrag);
|
||||
*defrag = NULL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
hash_message(msg, this->responding.hash);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
if (!*defrag)
|
||||
@@ -1310,18 +1489,26 @@ static status_t handle_fragment(private_task_manager_t *this,
|
||||
}
|
||||
}
|
||||
status = (*defrag)->add_fragment(*defrag, msg);
|
||||
|
||||
if (status == NEED_MORE || status == SUCCESS)
|
||||
{
|
||||
/* to detect retransmissions we only hash the first fragment */
|
||||
if (fragment->get_fragment_number(fragment) == 1)
|
||||
{
|
||||
hash_message(msg, this->responding.hash);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -1383,6 +1570,36 @@ static status_t send_invalid_syntax(private_task_manager_t *this,
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for unsupported critical payloads
|
||||
*/
|
||||
static status_t has_unsupported_critical_payload(message_t *msg, uint8_t *type)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
unknown_payload_t *unknown;
|
||||
payload_t *payload;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
enumerator = msg->create_payload_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
{
|
||||
if (payload->get_type(payload) == PL_UNKNOWN)
|
||||
{
|
||||
unknown = (unknown_payload_t*)payload;
|
||||
if (unknown->is_critical(unknown))
|
||||
{
|
||||
*type = unknown->get_type(unknown);
|
||||
DBG1(DBG_ENC, "payload type %N is not supported, "
|
||||
"but payload is critical!", payload_type_names, *type);
|
||||
status = NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given message and verify that it is valid.
|
||||
*/
|
||||
@@ -1391,34 +1608,22 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg)
|
||||
status_t parse_status, status;
|
||||
uint8_t type = 0;
|
||||
|
||||
parse_status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
|
||||
if (derive_keys(this, this->passive_tasks))
|
||||
{
|
||||
parse_status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
|
||||
|
||||
if (parse_status == SUCCESS)
|
||||
{ /* check for unsupported critical payloads */
|
||||
enumerator_t *enumerator;
|
||||
unknown_payload_t *unknown;
|
||||
payload_t *payload;
|
||||
|
||||
enumerator = msg->create_payload_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
if (parse_status == SUCCESS)
|
||||
{
|
||||
if (payload->get_type(payload) == PL_UNKNOWN)
|
||||
{
|
||||
unknown = (unknown_payload_t*)payload;
|
||||
if (unknown->is_critical(unknown))
|
||||
{
|
||||
type = unknown->get_type(unknown);
|
||||
DBG1(DBG_ENC, "payload type %N is not supported, "
|
||||
"but payload is critical!", payload_type_names, type);
|
||||
parse_status = NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parse_status = has_unsupported_critical_payload(msg, &type);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
status = parse_status;
|
||||
status = parse_status;
|
||||
}
|
||||
else
|
||||
{ /* there is no point in trying again */
|
||||
parse_status = INVALID_STATE;
|
||||
status = DESTROY_ME;
|
||||
}
|
||||
|
||||
if (parse_status != SUCCESS)
|
||||
{
|
||||
@@ -1488,47 +1693,6 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg)
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a message with message ID 0 looks like it is used to synchronize
|
||||
* the message IDs.
|
||||
*/
|
||||
static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg,
|
||||
bool strict)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
notify_payload_t *notify;
|
||||
payload_t *payload;
|
||||
bool found = FALSE, other = FALSE;
|
||||
|
||||
if (msg->get_exchange_type(msg) == INFORMATIONAL)
|
||||
{
|
||||
enumerator = msg->create_payload_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
{
|
||||
if (payload->get_type(payload) == PLV2_NOTIFY)
|
||||
{
|
||||
notify = (notify_payload_t*)payload;
|
||||
switch (notify->get_notify_type(notify))
|
||||
{
|
||||
case IKEV2_MESSAGE_ID_SYNC:
|
||||
case IPSEC_REPLAY_COUNTER_SYNC:
|
||||
found = TRUE;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strict)
|
||||
{
|
||||
other = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
return found && !other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we should reject the given request message
|
||||
*/
|
||||
@@ -1582,22 +1746,90 @@ static inline bool reject_request(private_task_manager_t *this,
|
||||
}
|
||||
return reject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a message with message ID 0 looks like it is used to synchronize
|
||||
* the message IDs and we are prepared to process it.
|
||||
* the message IDs.
|
||||
*
|
||||
* Note: This is not called if the responder never sent a message before (i.e.
|
||||
* we expect MID 0).
|
||||
* Call this after checking the message with is_potential_mid_sync() first.
|
||||
*/
|
||||
static bool is_mid_sync(private_task_manager_t *this, message_t *msg)
|
||||
{
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED &&
|
||||
this->ike_sa->supports_extension(this->ike_sa,
|
||||
EXT_IKE_MESSAGE_ID_SYNC))
|
||||
enumerator_t *enumerator;
|
||||
notify_payload_t *notify;
|
||||
payload_t *payload;
|
||||
bool found = FALSE, other = FALSE;
|
||||
|
||||
enumerator = msg->create_payload_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &payload))
|
||||
{
|
||||
return looks_like_mid_sync(this, msg, TRUE);
|
||||
if (payload->get_type(payload) == PLV2_NOTIFY)
|
||||
{
|
||||
notify = (notify_payload_t*)payload;
|
||||
switch (notify->get_notify_type(notify))
|
||||
{
|
||||
case IKEV2_MESSAGE_ID_SYNC:
|
||||
case IPSEC_REPLAY_COUNTER_SYNC:
|
||||
found = TRUE;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
other = TRUE;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
enumerator->destroy(enumerator);
|
||||
return found && !other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a message with message ID 0 looks like it could potentially be used
|
||||
* to synchronize the message IDs and if we are prepared to process it.
|
||||
*
|
||||
* This may be called before the message body is parsed.
|
||||
*/
|
||||
static bool is_potential_mid_sync(private_task_manager_t *this, message_t *msg)
|
||||
{
|
||||
return msg->get_exchange_type(msg) == INFORMATIONAL &&
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED &&
|
||||
this->ike_sa->supports_extension(this->ike_sa,
|
||||
EXT_IKE_MESSAGE_ID_SYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given message is a retransmitted request
|
||||
*/
|
||||
static status_t is_retransmit(private_task_manager_t *this, message_t *msg)
|
||||
{
|
||||
uint8_t hash[HASH_SIZE_SHA1];
|
||||
uint32_t mid;
|
||||
|
||||
mid = msg->get_message_id(msg);
|
||||
|
||||
if (mid == this->responding.mid)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (mid == this->responding.mid - 1 &&
|
||||
array_count(this->responding.packets))
|
||||
{
|
||||
if (!hash_message(msg, hash))
|
||||
{
|
||||
DBG1(DBG_IKE, "failed to hash message, ignored");
|
||||
return FAILED;
|
||||
}
|
||||
if (memeq_const(hash, this->responding.prev_hash, sizeof(hash)))
|
||||
{
|
||||
return ALREADY_DONE;
|
||||
}
|
||||
}
|
||||
/* this includes fragments with fragment number > 1 (we only hash the first
|
||||
* fragment), for which RFC 7383, section 2.6.1 explicitly does not allow
|
||||
* retransmitting responses. we don't parse/verify these messages to check,
|
||||
* we just ignore them. also included are MID sync messages with MID 0 */
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
METHOD(task_manager_t, process_message, status_t,
|
||||
@@ -1605,27 +1837,85 @@ METHOD(task_manager_t, process_message, status_t,
|
||||
{
|
||||
host_t *me, *other;
|
||||
status_t status;
|
||||
uint32_t mid;
|
||||
uint32_t mid, *expected_mid = NULL;
|
||||
bool schedule_delete_job = FALSE;
|
||||
|
||||
me = msg->get_destination(msg);
|
||||
other = msg->get_source(msg);
|
||||
mid = msg->get_message_id(msg);
|
||||
|
||||
charon->bus->message(charon->bus, msg, TRUE, FALSE);
|
||||
status = parse_message(this, msg);
|
||||
if (status != SUCCESS)
|
||||
|
||||
if (msg->get_request(msg))
|
||||
{
|
||||
bool potential_mid_sync = FALSE;
|
||||
|
||||
switch (is_retransmit(this, msg))
|
||||
{
|
||||
case ALREADY_DONE:
|
||||
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
|
||||
"retransmitting response", mid);
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
|
||||
send_packets(this, this->responding.packets,
|
||||
msg->get_destination(msg), msg->get_source(msg));
|
||||
return SUCCESS;
|
||||
case INVALID_ARG:
|
||||
if (mid == 0 && is_potential_mid_sync(this, msg))
|
||||
{
|
||||
potential_mid_sync = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_mid = &this->responding.mid;
|
||||
break;
|
||||
}
|
||||
/* check if it's actually an MID sync message */
|
||||
case NEED_MORE:
|
||||
status = parse_message(this, msg);
|
||||
if (potential_mid_sync && status == SUCCESS &&
|
||||
!is_mid_sync(this, msg))
|
||||
{
|
||||
expected_mid = &this->responding.mid;
|
||||
}
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mid == this->initiating.mid)
|
||||
{
|
||||
status = parse_message(this, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_mid = &this->initiating.mid;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_mid)
|
||||
{
|
||||
DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
|
||||
mid, *expected_mid);
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
me = msg->get_destination(msg);
|
||||
other = msg->get_source(msg);
|
||||
|
||||
/* if this IKE_SA is virgin, we check for a config */
|
||||
if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
|
||||
if (!this->ike_sa->get_ike_cfg(this->ike_sa))
|
||||
{
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
ike_cfg = charon->backends->get_ike_cfg(charon->backends,
|
||||
me, other, IKEV2);
|
||||
if (ike_cfg == NULL)
|
||||
if (!ike_cfg)
|
||||
{
|
||||
/* no config found for these hosts, destroy */
|
||||
DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
|
||||
@@ -1640,123 +1930,88 @@ METHOD(task_manager_t, process_message, status_t,
|
||||
schedule_delete_job = TRUE;
|
||||
}
|
||||
|
||||
mid = msg->get_message_id(msg);
|
||||
if (msg->get_request(msg))
|
||||
{
|
||||
if (mid == this->responding.mid || (mid == 0 && is_mid_sync(this, msg)))
|
||||
/* special handling for requests happens in is_retransmit()
|
||||
* reject initial messages if not received in specific states,
|
||||
* after rekeying we only expect a DELETE in an INFORMATIONAL */
|
||||
if (reject_request(this, msg))
|
||||
{
|
||||
if (reject_request(this, msg))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||
{ /* only do implicit updates without MOBIKE, and only force
|
||||
* updates for IKE_AUTH (ports might change due to NAT-T) */
|
||||
this->ike_sa->update_hosts(this->ike_sa, me, other,
|
||||
mid == 1 ? UPDATE_HOSTS_FORCE_ADDRS : 0);
|
||||
}
|
||||
status = handle_fragment(this, &this->responding.defrag, msg);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
if (status == NEED_MORE)
|
||||
{
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
charon->bus->message(charon->bus, msg, TRUE, TRUE);
|
||||
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
|
||||
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
|
||||
return SUCCESS;
|
||||
}
|
||||
switch (process_request(this, msg))
|
||||
{
|
||||
case SUCCESS:
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
this->responding.mid++;
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
flush(this);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
else if ((mid == this->responding.mid - 1) &&
|
||||
array_count(this->responding.packets) &&
|
||||
!(mid == 0 && looks_like_mid_sync(this, msg, FALSE)))
|
||||
{
|
||||
status = handle_fragment(this, &this->responding.defrag, msg);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
if (status == NEED_MORE)
|
||||
{
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
|
||||
"retransmitting response", mid);
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
|
||||
send_packets(this, this->responding.packets,
|
||||
msg->get_destination(msg), msg->get_source(msg));
|
||||
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||
{ /* only do implicit updates without MOBIKE, and only force
|
||||
* updates for IKE_AUTH (ports might change due to NAT-T) */
|
||||
this->ike_sa->update_hosts(this->ike_sa, me, other,
|
||||
mid == 1 ? UPDATE_HOSTS_FORCE_ADDRS : 0);
|
||||
}
|
||||
else
|
||||
status = handle_fragment(this, &this->responding.defrag, msg);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
|
||||
mid, this->responding.mid);
|
||||
if (status == NEED_MORE)
|
||||
{
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
charon->bus->message(charon->bus, msg, TRUE, TRUE);
|
||||
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
|
||||
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
|
||||
return SUCCESS;
|
||||
}
|
||||
switch (process_request(this, msg))
|
||||
{
|
||||
case SUCCESS:
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
this->responding.mid++;
|
||||
memcpy(this->responding.prev_hash, this->responding.hash,
|
||||
sizeof(this->responding.prev_hash));
|
||||
break;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
flush(this);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mid == this->initiating.mid)
|
||||
{
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
|
||||
msg->get_exchange_type(msg) != IKE_SA_INIT)
|
||||
{ /* only do updates based on verified messages (or initial ones) */
|
||||
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||
{ /* only do implicit updates without MOBIKE, we force an
|
||||
* update of the local address on IKE_SA_INIT as we might
|
||||
* not know it yet, but never for the remote address */
|
||||
this->ike_sa->update_hosts(this->ike_sa, me, other,
|
||||
mid == 0 ? UPDATE_HOSTS_FORCE_LOCAL : 0);
|
||||
}
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
|
||||
msg->get_exchange_type(msg) != IKE_SA_INIT)
|
||||
{ /* only do updates based on verified messages (or initial ones) */
|
||||
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||
{ /* only do implicit updates without MOBIKE, we force an
|
||||
* update of the local address on IKE_SA_INIT as we might
|
||||
* not know it yet, but never for the remote address */
|
||||
this->ike_sa->update_hosts(this->ike_sa, me, other,
|
||||
mid == 0 ? UPDATE_HOSTS_FORCE_LOCAL : 0);
|
||||
}
|
||||
status = handle_fragment(this, &this->initiating.defrag, msg);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
if (status == NEED_MORE)
|
||||
{
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
charon->bus->message(charon->bus, msg, TRUE, TRUE);
|
||||
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
|
||||
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
|
||||
return SUCCESS;
|
||||
}
|
||||
if (process_response(this, msg) != SUCCESS)
|
||||
{
|
||||
flush(this);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
else
|
||||
status = handle_fragment(this, &this->initiating.defrag, msg);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
|
||||
mid, this->initiating.mid);
|
||||
if (status == NEED_MORE)
|
||||
{
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
charon->bus->message(charon->bus, msg, TRUE, TRUE);
|
||||
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
|
||||
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
|
||||
return SUCCESS;
|
||||
}
|
||||
if (process_response(this, msg) != SUCCESS)
|
||||
{
|
||||
flush(this);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
|
||||
time_monotonic(NULL));
|
||||
}
|
||||
|
||||
if (schedule_delete_job)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include <daemon.h>
|
||||
#include <sa/ikev2/keymat_v2.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
#include <encoding/payloads/ke_payload.h>
|
||||
@@ -117,7 +117,7 @@ struct private_child_create_t {
|
||||
/**
|
||||
* optional diffie hellman exchange
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Applying DH public value failed?
|
||||
@@ -127,7 +127,7 @@ struct private_child_create_t {
|
||||
/**
|
||||
* group used for DH exchange
|
||||
*/
|
||||
diffie_hellman_group_t dh_group;
|
||||
key_exchange_method_t dh_group;
|
||||
|
||||
/**
|
||||
* IKE_SAs keymat
|
||||
@@ -325,10 +325,11 @@ static bool update_and_check_proposals(private_child_create_t *this)
|
||||
proposal->set_spi(proposal, this->my_spi);
|
||||
|
||||
/* move the selected DH group to the front, if any */
|
||||
if (this->dh_group != MODP_NONE)
|
||||
if (this->dh_group != KE_NONE)
|
||||
{ /* proposals that don't contain the selected group are
|
||||
* moved to the back */
|
||||
if (!proposal->promote_dh_group(proposal, this->dh_group))
|
||||
if (!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{
|
||||
this->proposals->remove_at(this->proposals, enumerator);
|
||||
other_dh_groups->insert_last(other_dh_groups, proposal);
|
||||
@@ -348,7 +349,7 @@ static bool update_and_check_proposals(private_child_create_t *this)
|
||||
enumerator->destroy(enumerator);
|
||||
other_dh_groups->destroy(other_dh_groups);
|
||||
|
||||
return this->dh_group == MODP_NONE || found;
|
||||
return this->dh_group == KE_NONE || found;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -518,7 +519,7 @@ static status_t select_and_install(private_child_create_t *this,
|
||||
|
||||
if (no_dh)
|
||||
{
|
||||
flags |= PROPOSAL_SKIP_DH;
|
||||
flags |= PROPOSAL_SKIP_KE;
|
||||
}
|
||||
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN) &&
|
||||
!lib->settings->get_bool(lib->settings, "%s.accept_private_algs",
|
||||
@@ -554,16 +555,17 @@ static status_t select_and_install(private_child_create_t *this,
|
||||
}
|
||||
this->child_sa->set_proposal(this->child_sa, this->proposal);
|
||||
|
||||
if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
|
||||
if (!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{
|
||||
uint16_t group;
|
||||
|
||||
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (this->proposal->get_algorithm(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
&group, NULL))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
|
||||
diffie_hellman_group_names, this->dh_group,
|
||||
diffie_hellman_group_names, group);
|
||||
key_exchange_method_names, this->dh_group,
|
||||
key_exchange_method_names, group);
|
||||
this->dh_group = group;
|
||||
return INVALID_ARG;
|
||||
}
|
||||
@@ -571,7 +573,7 @@ static status_t select_and_install(private_child_create_t *this,
|
||||
DBG1(DBG_IKE, "ignoring KE exchange, agreed on a non-PFS proposal");
|
||||
DESTROY_IF(this->dh);
|
||||
this->dh = NULL;
|
||||
this->dh_group = MODP_NONE;
|
||||
this->dh_group = KE_NONE;
|
||||
}
|
||||
|
||||
if (this->initiator)
|
||||
@@ -713,13 +715,13 @@ static status_t select_and_install(private_child_create_t *this,
|
||||
{
|
||||
status_o = this->child_sa->register_outbound(this->child_sa,
|
||||
encr_i, integ_i, this->other_spi, this->other_cpi,
|
||||
this->tfcv3);
|
||||
this->initiator, this->tfcv3);
|
||||
}
|
||||
else
|
||||
{
|
||||
status_o = this->child_sa->register_outbound(this->child_sa,
|
||||
encr_r, integ_r, this->other_spi, this->other_cpi,
|
||||
this->tfcv3);
|
||||
this->initiator, this->tfcv3);
|
||||
}
|
||||
}
|
||||
else if (this->initiator)
|
||||
@@ -836,8 +838,8 @@ static bool 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(PLV2_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
ke_payload = ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
if (!ke_payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "creating KE payload failed");
|
||||
@@ -979,18 +981,19 @@ static void process_payloads(private_child_create_t *this, message_t *message)
|
||||
ke_payload = (ke_payload_t*)payload;
|
||||
if (!this->initiator)
|
||||
{
|
||||
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
|
||||
this->dh = this->keymat->keymat.create_dh(
|
||||
this->dh_group = ke_payload->get_key_exchange_method(
|
||||
ke_payload);
|
||||
this->dh = this->keymat->keymat.create_ke(
|
||||
&this->keymat->keymat, this->dh_group);
|
||||
}
|
||||
else if (this->dh)
|
||||
{
|
||||
this->dh_failed = this->dh->get_dh_group(this->dh) !=
|
||||
ke_payload->get_dh_group_number(ke_payload);
|
||||
this->dh_failed = this->dh->get_method(this->dh) !=
|
||||
ke_payload->get_key_exchange_method(ke_payload);
|
||||
}
|
||||
if (this->dh && !this->dh_failed)
|
||||
{
|
||||
this->dh_failed = !this->dh->set_other_public_value(this->dh,
|
||||
this->dh_failed = !this->dh->set_public_key(this->dh,
|
||||
ke_payload->get_key_exchange_data(ke_payload));
|
||||
}
|
||||
break;
|
||||
@@ -1155,17 +1158,13 @@ METHOD(task_t, build_i, status_t,
|
||||
message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
|
||||
return SUCCESS;
|
||||
}
|
||||
if (!this->retry && this->dh_group == MODP_NONE)
|
||||
if (!this->retry && this->dh_group == KE_NONE)
|
||||
{ /* during a rekeying the group might already be set */
|
||||
this->dh_group = this->config->get_dh_group(this->config);
|
||||
this->dh_group = this->config->get_algorithm(this->config,
|
||||
KEY_EXCHANGE_METHOD);
|
||||
}
|
||||
break;
|
||||
case IKE_AUTH:
|
||||
if (message->get_message_id(message) != 1)
|
||||
{
|
||||
/* send only in the first request, not in subsequent rounds */
|
||||
return NEED_MORE;
|
||||
}
|
||||
switch (defer_child_sa(this))
|
||||
{
|
||||
case DESTROY_ME:
|
||||
@@ -1179,9 +1178,11 @@ METHOD(task_t, build_i, status_t,
|
||||
/* just continue to establish the CHILD_SA */
|
||||
break;
|
||||
}
|
||||
/* send only in the first request, not in subsequent rounds */
|
||||
this->public.task.build = (void*)return_need_more;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
/* check if we want a virtual IP, but don't have one */
|
||||
@@ -1244,7 +1245,7 @@ METHOD(task_t, build_i, status_t,
|
||||
}
|
||||
|
||||
this->proposals = this->config->get_proposals(this->config,
|
||||
this->dh_group == MODP_NONE);
|
||||
this->dh_group == KE_NONE);
|
||||
this->mode = this->config->get_mode(this->config);
|
||||
|
||||
this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, TRUE);
|
||||
@@ -1287,13 +1288,13 @@ METHOD(task_t, build_i, status_t,
|
||||
{
|
||||
DBG1(DBG_IKE, "requested DH group %N not contained in any of our "
|
||||
"proposals",
|
||||
diffie_hellman_group_names, this->dh_group);
|
||||
key_exchange_method_names, this->dh_group);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (this->dh_group != MODP_NONE)
|
||||
if (this->dh_group != KE_NONE)
|
||||
{
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat,
|
||||
this->dh_group);
|
||||
}
|
||||
|
||||
@@ -1340,13 +1341,11 @@ METHOD(task_t, process_r, status_t,
|
||||
get_nonce(message, &this->other_nonce);
|
||||
break;
|
||||
case IKE_AUTH:
|
||||
if (message->get_message_id(message) != 1)
|
||||
{
|
||||
/* only handle first AUTH payload, not additional rounds */
|
||||
return NEED_MORE;
|
||||
}
|
||||
default:
|
||||
/* only handle first AUTH payload, not additional rounds */
|
||||
this->public.task.process = (void*)return_need_more;
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
process_payloads(this, message);
|
||||
@@ -1575,8 +1574,9 @@ METHOD(task_t, build_r, status_t,
|
||||
break;
|
||||
}
|
||||
ike_auth = TRUE;
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
|
||||
@@ -1772,8 +1772,9 @@ METHOD(task_t, process_i, status_t,
|
||||
return NEED_MORE;
|
||||
}
|
||||
ike_auth = TRUE;
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
/* check for erroneous notifies */
|
||||
@@ -1818,7 +1819,7 @@ METHOD(task_t, process_i, status_t,
|
||||
case INVALID_KE_PAYLOAD:
|
||||
{
|
||||
chunk_t data;
|
||||
uint16_t group = MODP_NONE;
|
||||
uint16_t group = KE_NONE;
|
||||
|
||||
data = notify->get_notification_data(notify);
|
||||
if (data.len == sizeof(group))
|
||||
@@ -1829,15 +1830,15 @@ METHOD(task_t, process_i, status_t,
|
||||
if (this->retry)
|
||||
{
|
||||
DBG1(DBG_IKE, "already retried with DH group %N, "
|
||||
"ignore requested %N", diffie_hellman_group_names,
|
||||
this->dh_group, diffie_hellman_group_names, group);
|
||||
"ignore requested %N", key_exchange_method_names,
|
||||
this->dh_group, key_exchange_method_names, group);
|
||||
handle_child_sa_failure(this, message);
|
||||
/* an error in CHILD_SA creation is not critical */
|
||||
return SUCCESS;
|
||||
}
|
||||
DBG1(DBG_IKE, "peer didn't accept DH group %N, "
|
||||
"it requested %N", diffie_hellman_group_names,
|
||||
this->dh_group, diffie_hellman_group_names, group);
|
||||
"it requested %N", key_exchange_method_names,
|
||||
this->dh_group, key_exchange_method_names, group);
|
||||
this->retry = TRUE;
|
||||
this->dh_group = group;
|
||||
this->child_sa->set_state(this->child_sa, CHILD_RETRYING);
|
||||
@@ -1945,7 +1946,7 @@ METHOD(child_create_t, use_label, void,
|
||||
}
|
||||
|
||||
METHOD(child_create_t, use_dh_group, void,
|
||||
private_child_create_t *this, diffie_hellman_group_t dh_group)
|
||||
private_child_create_t *this, key_exchange_method_t dh_group)
|
||||
{
|
||||
this->dh_group = dh_group;
|
||||
}
|
||||
@@ -2015,7 +2016,7 @@ METHOD(task_t, migrate, void,
|
||||
}
|
||||
if (!this->rekey && !this->retry)
|
||||
{
|
||||
this->dh_group = MODP_NONE;
|
||||
this->dh_group = KE_NONE;
|
||||
}
|
||||
this->ike_sa = ike_sa;
|
||||
this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
|
||||
@@ -2031,6 +2032,7 @@ METHOD(task_t, migrate, void,
|
||||
this->ipcomp_received = IPCOMP_NONE;
|
||||
this->other_cpi = 0;
|
||||
this->established = FALSE;
|
||||
this->public.task.build = _build_i;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
@@ -2101,7 +2103,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
|
||||
.config = config,
|
||||
.packet_tsi = tsi ? tsi->clone(tsi) : NULL,
|
||||
.packet_tsr = tsr ? tsr->clone(tsr) : NULL,
|
||||
.dh_group = MODP_NONE,
|
||||
.dh_group = KE_NONE,
|
||||
.keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
|
||||
.mode = MODE_TUNNEL,
|
||||
.tfcv3 = TRUE,
|
||||
|
||||
@@ -83,7 +83,7 @@ struct child_create_t {
|
||||
*
|
||||
* @param dh_group DH group to use
|
||||
*/
|
||||
void (*use_dh_group)(child_create_t *this, diffie_hellman_group_t dh_group);
|
||||
void (*use_dh_group)(child_create_t *this, key_exchange_method_t dh_group);
|
||||
|
||||
/**
|
||||
* Get the lower of the two nonces, used for rekey collisions.
|
||||
|
||||
@@ -197,7 +197,7 @@ METHOD(task_t, build_i, status_t,
|
||||
config->get_ref(config), TRUE, NULL, NULL);
|
||||
|
||||
proposal = this->child_sa->get_proposal(this->child_sa);
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
&dh_group, NULL))
|
||||
{ /* reuse the DH group negotiated previously */
|
||||
this->child_create->use_dh_group(this->child_create, dh_group);
|
||||
@@ -528,7 +528,7 @@ METHOD(child_rekey_t, is_redundant, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(child_rekey_t, collide, void,
|
||||
METHOD(child_rekey_t, collide, bool,
|
||||
private_child_rekey_t *this, task_t *other)
|
||||
{
|
||||
/* the task manager only detects exchange collision, but not if
|
||||
@@ -540,16 +540,14 @@ METHOD(child_rekey_t, collide, void,
|
||||
|
||||
if (rekey->child_sa != this->child_sa)
|
||||
{ /* not the same child => no collision */
|
||||
other->destroy(other);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
/* ignore passive tasks that did not successfully create a CHILD_SA */
|
||||
other_child = rekey->child_create->get_child(rekey->child_create);
|
||||
if (!other_child ||
|
||||
other_child->get_state(other_child) != CHILD_INSTALLED)
|
||||
{
|
||||
other->destroy(other);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (other->get_type(other) == TASK_CHILD_DELETE)
|
||||
@@ -558,26 +556,24 @@ METHOD(child_rekey_t, collide, void,
|
||||
if (is_redundant(this, del->get_child(del)))
|
||||
{
|
||||
this->other_child_destroyed = TRUE;
|
||||
other->destroy(other);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
if (del->get_child(del) != this->child_sa)
|
||||
{
|
||||
/* not the same child => no collision */
|
||||
other->destroy(other);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* any other task is not critical for collisions, ignore */
|
||||
other->destroy(other);
|
||||
return;
|
||||
/* shouldn't happen */
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
|
||||
TASK_CHILD_REKEY, task_type_names, other->get_type(other));
|
||||
DESTROY_IF(this->collision);
|
||||
this->collision = other;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(task_t, migrate, void,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Tobias Brunner
|
||||
* Copyright (C) 2016-2020 Tobias Brunner
|
||||
* Copyright (C) 2007 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -59,9 +59,11 @@ struct child_rekey_t {
|
||||
* be handled gracefully. The task manager is aware of what exchanges
|
||||
* are going on and notifies the active task by passing the passive.
|
||||
*
|
||||
* @param other passive task (adopted)
|
||||
* @param other passive task
|
||||
* @return whether the task was adopted and should be removed from
|
||||
* the task manager's control
|
||||
*/
|
||||
void (*collide)(child_rekey_t* this, task_t *other);
|
||||
bool (*collide)(child_rekey_t* this, task_t *other);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2018 Tobias Brunner
|
||||
* Copyright (C) 2012-2019 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@@ -131,6 +131,11 @@ struct private_ike_auth_t {
|
||||
*/
|
||||
bool eap_acceptable;
|
||||
|
||||
/**
|
||||
* Whether we already handled the first IKE_AUTH message
|
||||
*/
|
||||
bool first_auth;
|
||||
|
||||
/**
|
||||
* Gateway ID if redirected
|
||||
*/
|
||||
@@ -154,20 +159,15 @@ static status_t collect_my_init_data(private_ike_auth_t *this,
|
||||
{
|
||||
nonce_payload_t *nonce;
|
||||
|
||||
/* get the nonce that was generated in ike_init */
|
||||
/* get the nonce that was generated in ike_init and a copy of the complete
|
||||
* packet */
|
||||
nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
|
||||
if (!nonce)
|
||||
if (!nonce || !message->is_encoded(message))
|
||||
{
|
||||
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;
|
||||
}
|
||||
this->my_packet = message->get_packet(message);
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
@@ -588,10 +588,18 @@ METHOD(task_t, build_i, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
auth_cfg_t *cfg;
|
||||
bool first_auth = FALSE;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
return collect_my_init_data(this, message);
|
||||
case IKE_AUTH:
|
||||
if (!this->first_auth)
|
||||
{ /* some special handling for the first IKE_AUTH message below */
|
||||
first_auth = this->first_auth = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (!this->peer_cfg)
|
||||
@@ -600,7 +608,7 @@ METHOD(task_t, build_i, status_t,
|
||||
this->peer_cfg->get_ref(this->peer_cfg);
|
||||
}
|
||||
|
||||
if (message->get_message_id(message) == 1)
|
||||
if (first_auth)
|
||||
{ /* in the first IKE_AUTH ... */
|
||||
if (this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
|
||||
{ /* indicate support for multiple authentication */
|
||||
@@ -668,8 +676,7 @@ METHOD(task_t, build_i, status_t,
|
||||
get_reserved_id_bytes(this, id_payload);
|
||||
message->add_payload(message, (payload_t*)id_payload);
|
||||
|
||||
if (idr && !idr->contains_wildcards(idr) &&
|
||||
message->get_message_id(message) == 1 &&
|
||||
if (idr && !idr->contains_wildcards(idr) && first_auth &&
|
||||
this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER)
|
||||
{
|
||||
host_t *host;
|
||||
@@ -737,6 +744,18 @@ METHOD(task_t, build_i, status_t,
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(task_t, post_build_i, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
case IKE_SA_INIT:
|
||||
return collect_my_init_data(this, message);
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(task_t, process_r, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
@@ -744,9 +763,14 @@ METHOD(task_t, process_r, status_t,
|
||||
id_payload_t *id_payload;
|
||||
identification_t *id;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
return collect_other_init_data(this, message);
|
||||
case IKE_SA_INIT:
|
||||
return collect_other_init_data(this, message);
|
||||
case IKE_AUTH:
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (!this->my_auth && this->do_another_auth)
|
||||
@@ -769,7 +793,7 @@ METHOD(task_t, process_r, status_t,
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (message->get_message_id(message) == 1)
|
||||
if (!this->first_auth)
|
||||
{ /* check for extensions in the first IKE_AUTH */
|
||||
if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
|
||||
{
|
||||
@@ -784,6 +808,7 @@ METHOD(task_t, process_r, status_t,
|
||||
{
|
||||
this->initial_contact = TRUE;
|
||||
}
|
||||
this->first_auth = TRUE;
|
||||
}
|
||||
|
||||
if (!this->other_auth)
|
||||
@@ -950,14 +975,19 @@ METHOD(task_t, build_r, status_t,
|
||||
identification_t *gateway;
|
||||
auth_cfg_t *cfg;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
if (multiple_auth_enabled())
|
||||
{
|
||||
message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
|
||||
chunk_empty);
|
||||
}
|
||||
return collect_my_init_data(this, message);
|
||||
case IKE_SA_INIT:
|
||||
if (multiple_auth_enabled())
|
||||
{
|
||||
message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
|
||||
chunk_empty);
|
||||
}
|
||||
return NEED_MORE;
|
||||
case IKE_AUTH:
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (this->authentication_failed || !this->peer_cfg)
|
||||
@@ -1159,6 +1189,18 @@ local_auth_failed:
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(task_t, post_build_r, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
case IKE_SA_INIT:
|
||||
return collect_my_init_data(this, message);
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an INFORMATIONAL message with an AUTH_FAILED before closing IKE_SA
|
||||
*/
|
||||
@@ -1225,14 +1267,19 @@ METHOD(task_t, process_i, status_t,
|
||||
auth_cfg_t *cfg;
|
||||
bool mutual_eap = FALSE, ppk_id_received = FALSE;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
|
||||
multiple_auth_enabled())
|
||||
{
|
||||
this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
|
||||
}
|
||||
return collect_other_init_data(this, message);
|
||||
case IKE_SA_INIT:
|
||||
if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
|
||||
multiple_auth_enabled())
|
||||
{
|
||||
this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
|
||||
}
|
||||
return collect_other_init_data(this, message);
|
||||
case IKE_AUTH:
|
||||
break;
|
||||
default:
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
enumerator = message->create_payload_enumerator(message);
|
||||
@@ -1514,6 +1561,7 @@ METHOD(task_t, migrate, void,
|
||||
this->expect_another_auth = TRUE;
|
||||
this->authentication_failed = FALSE;
|
||||
this->candidates = linked_list_create();
|
||||
this->first_auth = FALSE;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
@@ -1545,6 +1593,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
|
||||
.get_type = _get_type,
|
||||
.migrate = _migrate,
|
||||
.build = _build_r,
|
||||
.post_build = _post_build_r,
|
||||
.process = _process_r,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
@@ -1558,6 +1607,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
|
||||
if (initiator)
|
||||
{
|
||||
this->public.task.build = _build_i;
|
||||
this->public.task.post_build = _post_build_i;
|
||||
this->public.task.process = _process_i;
|
||||
}
|
||||
return &this->public;
|
||||
|
||||
@@ -255,8 +255,10 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_ike_cert_post_t *this, message_t *message)
|
||||
{
|
||||
build_certs(this, message);
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
build_certs(this, message);
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
@@ -269,8 +271,10 @@ METHOD(task_t, process_r, status_t,
|
||||
METHOD(task_t, build_r, status_t,
|
||||
private_ike_cert_post_t *this, message_t *message)
|
||||
{
|
||||
build_certs(this, message);
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
build_certs(this, message);
|
||||
}
|
||||
if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
|
||||
{ /* stay alive, we might have additional rounds with certs */
|
||||
return NEED_MORE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tobias Brunner
|
||||
* Copyright (C) 2008-2018 Tobias Brunner
|
||||
* Copyright (C) 2006-2009 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -50,11 +50,6 @@ struct private_ike_cert_pre_t {
|
||||
* Do we accept HTTP certificate lookup requests
|
||||
*/
|
||||
bool do_http_lookup;
|
||||
|
||||
/**
|
||||
* whether this is the final authentication round
|
||||
*/
|
||||
bool final;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -469,24 +464,17 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
|
||||
*/
|
||||
static bool final_auth(message_t *message)
|
||||
{
|
||||
/* we check for an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify */
|
||||
if (message->get_payload(message, PLV2_AUTH) == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
return message->get_payload(message, PLV2_AUTH) != NULL &&
|
||||
!message->get_notify(message, ANOTHER_AUTH_FOLLOWS);
|
||||
}
|
||||
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_ike_cert_pre_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_message_id(message) == 1)
|
||||
{ /* initiator sends CERTREQs in first IKE_AUTH */
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{ /* initiator sends CERTREQs in first IKE_AUTH only */
|
||||
build_certreqs(this, message);
|
||||
this->public.task.build = (void*)return_need_more;
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
@@ -494,12 +482,15 @@ METHOD(task_t, build_i, status_t,
|
||||
METHOD(task_t, process_r, status_t,
|
||||
private_ike_cert_pre_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_exchange_type(message) != IKE_SA_INIT)
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{ /* handle certreqs/certs in any IKE_AUTH, just in case */
|
||||
process_certreqs(this, message);
|
||||
process_certs(this, message);
|
||||
if (final_auth(message))
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
this->final = final_auth(message);
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
@@ -510,25 +501,26 @@ METHOD(task_t, build_r, status_t,
|
||||
{
|
||||
build_certreqs(this, message);
|
||||
}
|
||||
if (this->final)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(task_t, process_i, status_t,
|
||||
private_ike_cert_pre_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
switch (message->get_exchange_type(message))
|
||||
{
|
||||
process_certreqs(this, message);
|
||||
}
|
||||
process_certs(this, message);
|
||||
|
||||
if (final_auth(message))
|
||||
{
|
||||
return SUCCESS;
|
||||
case IKE_SA_INIT:
|
||||
process_certreqs(this, message);
|
||||
break;
|
||||
case IKE_AUTH:
|
||||
process_certs(this, message);
|
||||
if (final_auth(message))
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
@@ -543,6 +535,7 @@ METHOD(task_t, migrate, void,
|
||||
private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
|
||||
{
|
||||
this->ike_sa = ike_sa;
|
||||
this->public.task.build = _build_i;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2018 Tobias Brunner
|
||||
* Copyright (C) 2007 Martin Willi
|
||||
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
|
||||
*
|
||||
@@ -240,8 +241,8 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_ike_config_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_message_id(message) == 1)
|
||||
{ /* in first IKE_AUTH only */
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
cp_payload_t *cp = NULL;
|
||||
enumerator_t *enumerator;
|
||||
attribute_handler_t *handler;
|
||||
@@ -251,6 +252,10 @@ METHOD(task_t, build_i, status_t,
|
||||
linked_list_t *vips;
|
||||
host_t *host;
|
||||
|
||||
/* add attributes to first IKE_AUTH only, keep registered until
|
||||
* attributes are received in the last IKE_AUTH */
|
||||
this->public.task.build = (void*)return_need_more;
|
||||
|
||||
vips = linked_list_create();
|
||||
|
||||
/* reuse virtual IP if we already have one */
|
||||
@@ -329,9 +334,11 @@ METHOD(task_t, build_i, status_t,
|
||||
METHOD(task_t, process_r, status_t,
|
||||
private_ike_config_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_message_id(message) == 1)
|
||||
{ /* in first IKE_AUTH only */
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
process_payloads(this, message);
|
||||
/* process attributes in first IKE_AUTH only */
|
||||
this->public.task.process = (void*)return_need_more;
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
@@ -486,6 +493,7 @@ METHOD(task_t, migrate, void,
|
||||
this->vips = linked_list_create();
|
||||
this->requested->destroy_function(this->requested, free);
|
||||
this->requested = linked_list_create();
|
||||
this->public.task.build = _build_i;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
|
||||
@@ -65,9 +65,8 @@ METHOD(task_t, build_i, status_t,
|
||||
delete_payload = delete_payload_create(PLV2_DELETE, PROTO_IKE);
|
||||
message->add_payload(message, (payload_t*)delete_payload);
|
||||
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_REKEYED)
|
||||
{
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYED)
|
||||
{ /* suppress events when deleting old or redundant SAs */
|
||||
this->rekeyed = TRUE;
|
||||
}
|
||||
this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
|
||||
|
||||
@@ -32,12 +32,6 @@ struct private_ike_dpd_t {
|
||||
ike_dpd_t public;
|
||||
};
|
||||
|
||||
METHOD(task_t, return_need_more, status_t,
|
||||
private_ike_dpd_t *this, message_t *message)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(task_t, get_type, task_type_t,
|
||||
private_ike_dpd_t *this)
|
||||
{
|
||||
@@ -48,7 +42,6 @@ METHOD(task_t, get_type, task_type_t,
|
||||
METHOD(task_t, migrate, void,
|
||||
private_ike_dpd_t *this, ike_sa_t *ike_sa)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
@@ -76,13 +69,13 @@ ike_dpd_t *ike_dpd_create(bool initiator)
|
||||
|
||||
if (initiator)
|
||||
{
|
||||
this->public.task.build = _return_need_more;
|
||||
this->public.task.build = (void*)return_need_more;
|
||||
this->public.task.process = (void*)return_success;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->public.task.build = (void*)return_success;
|
||||
this->public.task.process = _return_need_more;
|
||||
this->public.task.process = (void*)return_need_more;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <bio/bio_reader.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <sa/ikev2/keymat_v2.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
#include <crypto/hashers/hash_algorithm_set.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
#include <encoding/payloads/ke_payload.h>
|
||||
@@ -55,15 +55,25 @@ struct private_ike_init_t {
|
||||
*/
|
||||
bool initiator;
|
||||
|
||||
/**
|
||||
* Whether the key exchange is done
|
||||
*/
|
||||
bool ke_done;
|
||||
|
||||
/**
|
||||
* Whether keys have already been derived
|
||||
*/
|
||||
bool ke_derived;
|
||||
|
||||
/**
|
||||
* diffie hellman group to use
|
||||
*/
|
||||
diffie_hellman_group_t dh_group;
|
||||
key_exchange_method_t dh_group;
|
||||
|
||||
/**
|
||||
* diffie hellman key exchange
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* Applying DH public value failed?
|
||||
@@ -333,7 +343,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
|
||||
proposal->set_spi(proposal, id->get_initiator_spi(id));
|
||||
}
|
||||
/* move the selected DH group to the front of the proposal */
|
||||
if (!proposal->promote_dh_group(proposal, this->dh_group))
|
||||
if (!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{ /* the proposal does not include the group, move to the back */
|
||||
proposal_list->remove_at(proposal_list, enumerator);
|
||||
other_dh_groups->insert_last(other_dh_groups, proposal);
|
||||
@@ -363,8 +374,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
|
||||
}
|
||||
message->add_payload(message, (payload_t*)sa_payload);
|
||||
|
||||
ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
ke_payload = ke_payload_create_from_key_exchange(PLV2_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
if (!ke_payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "creating KE payload failed");
|
||||
@@ -519,6 +530,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
payload_t *payload;
|
||||
ike_sa_id_t *id;
|
||||
ke_payload_t *ke_payload = NULL;
|
||||
|
||||
enumerator = message->create_payload_enumerator(message);
|
||||
@@ -535,7 +547,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
|
||||
{
|
||||
ke_payload = (ke_payload_t*)payload;
|
||||
|
||||
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
|
||||
this->dh_group = ke_payload->get_key_exchange_method(ke_payload);
|
||||
break;
|
||||
}
|
||||
case PLV2_NONCE:
|
||||
@@ -614,23 +626,39 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
|
||||
if (this->proposal)
|
||||
{
|
||||
this->ike_sa->set_proposal(this->ike_sa, this->proposal);
|
||||
|
||||
if (this->old_sa)
|
||||
{ /* retrieve SPI of new IKE_SA when rekeying */
|
||||
id = this->ike_sa->get_id(this->ike_sa);
|
||||
if (this->initiator)
|
||||
{
|
||||
id->set_responder_spi(id,
|
||||
this->proposal->get_spi(this->proposal));
|
||||
}
|
||||
else
|
||||
{
|
||||
id->set_initiator_spi(id,
|
||||
this->proposal->get_spi(this->proposal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ke_payload && this->proposal &&
|
||||
this->proposal->has_dh_group(this->proposal, this->dh_group))
|
||||
this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{
|
||||
if (!this->initiator)
|
||||
{
|
||||
this->dh = this->keymat->keymat.create_dh(
|
||||
this->dh = this->keymat->keymat.create_ke(
|
||||
&this->keymat->keymat, this->dh_group);
|
||||
}
|
||||
else if (this->dh)
|
||||
{
|
||||
this->dh_failed = this->dh->get_dh_group(this->dh) != this->dh_group;
|
||||
this->dh_failed = this->dh->get_method(this->dh) != this->dh_group;
|
||||
}
|
||||
if (this->dh && !this->dh_failed)
|
||||
{
|
||||
this->dh_failed = !this->dh->set_other_public_value(this->dh,
|
||||
this->dh_failed = !this->dh->set_public_key(this->dh,
|
||||
ke_payload->get_key_exchange_data(ke_payload));
|
||||
}
|
||||
}
|
||||
@@ -665,38 +693,40 @@ METHOD(task_t, build_i, status_t,
|
||||
uint16_t dh_group;
|
||||
|
||||
proposal = this->old_sa->get_proposal(this->old_sa);
|
||||
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
|
||||
&dh_group, NULL))
|
||||
{
|
||||
this->dh_group = dh_group;
|
||||
}
|
||||
else
|
||||
{ /* this shouldn't happen, but let's be safe */
|
||||
this->dh_group = ike_cfg->get_dh_group(ike_cfg);
|
||||
this->dh_group = ike_cfg->get_algorithm(ike_cfg,
|
||||
KEY_EXCHANGE_METHOD);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->dh_group = ike_cfg->get_dh_group(ike_cfg);
|
||||
this->dh_group = ike_cfg->get_algorithm(ike_cfg,
|
||||
KEY_EXCHANGE_METHOD);
|
||||
}
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat,
|
||||
this->dh_group);
|
||||
if (!this->dh)
|
||||
{
|
||||
DBG1(DBG_IKE, "configured DH group %N not supported",
|
||||
diffie_hellman_group_names, this->dh_group);
|
||||
key_exchange_method_names, this->dh_group);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else if (this->dh->get_dh_group(this->dh) != this->dh_group)
|
||||
else if (this->dh->get_method(this->dh) != this->dh_group)
|
||||
{ /* reset DH instance if group changed (INVALID_KE_PAYLOAD) */
|
||||
this->dh->destroy(this->dh);
|
||||
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
|
||||
this->dh = this->keymat->keymat.create_ke(&this->keymat->keymat,
|
||||
this->dh_group);
|
||||
if (!this->dh)
|
||||
{
|
||||
DBG1(DBG_IKE, "requested DH group %N not supported",
|
||||
diffie_hellman_group_names, this->dh_group);
|
||||
key_exchange_method_names, this->dh_group);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
@@ -765,8 +795,8 @@ METHOD(task_t, process_r, status_t,
|
||||
/**
|
||||
* Derive the keymat for the IKE_SA
|
||||
*/
|
||||
static bool derive_keys(private_ike_init_t *this,
|
||||
chunk_t nonce_i, chunk_t nonce_r)
|
||||
static bool derive_keys_internal(private_ike_init_t *this, chunk_t nonce_i,
|
||||
chunk_t nonce_r)
|
||||
{
|
||||
keymat_v2_t *old_keymat;
|
||||
pseudo_random_function_t prf_alg = PRF_UNDEFINED;
|
||||
@@ -779,14 +809,6 @@ static bool derive_keys(private_ike_init_t *this,
|
||||
/* rekeying: Include old SKd, use old PRF, apply SPI */
|
||||
old_keymat = (keymat_v2_t*)this->old_sa->get_keymat(this->old_sa);
|
||||
prf_alg = old_keymat->get_skd(old_keymat, &skd);
|
||||
if (this->initiator)
|
||||
{
|
||||
id->set_responder_spi(id, this->proposal->get_spi(this->proposal));
|
||||
}
|
||||
else
|
||||
{
|
||||
id->set_initiator_spi(id, this->proposal->get_spi(this->proposal));
|
||||
}
|
||||
}
|
||||
if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
|
||||
nonce_i, nonce_r, id, prf_alg, skd))
|
||||
@@ -798,6 +820,35 @@ static bool derive_keys(private_ike_init_t *this,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(ike_init_t, derive_keys, status_t,
|
||||
private_ike_init_t *this)
|
||||
{
|
||||
bool success;
|
||||
|
||||
if (!this->ke_done || this->ke_derived)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
if (this->initiator)
|
||||
{
|
||||
success = derive_keys_internal(this, this->my_nonce, this->other_nonce);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = derive_keys_internal(this, this->other_nonce, this->my_nonce);
|
||||
}
|
||||
|
||||
this->ke_derived = TRUE;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
DBG1(DBG_IKE, "key derivation failed");
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(task_t, build_r, status_t,
|
||||
private_ike_init_t *this, message_t *message)
|
||||
{
|
||||
@@ -829,16 +880,17 @@ METHOD(task_t, build_r, status_t,
|
||||
}
|
||||
|
||||
if (this->dh == NULL ||
|
||||
!this->proposal->has_dh_group(this->proposal, this->dh_group))
|
||||
!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{
|
||||
uint16_t group;
|
||||
|
||||
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
|
||||
if (this->proposal->get_algorithm(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
&group, NULL))
|
||||
{
|
||||
DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
|
||||
diffie_hellman_group_names, this->dh_group,
|
||||
diffie_hellman_group_names, group);
|
||||
key_exchange_method_names, this->dh_group,
|
||||
key_exchange_method_names, group);
|
||||
this->dh_group = group;
|
||||
group = htons(group);
|
||||
message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
|
||||
@@ -859,18 +911,25 @@ METHOD(task_t, build_r, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (!derive_keys(this, this->other_nonce, this->my_nonce))
|
||||
{
|
||||
DBG1(DBG_IKE, "key derivation failed");
|
||||
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
|
||||
return FAILED;
|
||||
}
|
||||
if (!build_payloads(this, message))
|
||||
{
|
||||
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
this->ke_done = TRUE;
|
||||
|
||||
if (this->old_sa)
|
||||
{
|
||||
/* during rekeying, we derive keys here directly */
|
||||
if (derive_keys(this) != SUCCESS)
|
||||
{
|
||||
message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* key derivation is done before the next request is processed */
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -976,14 +1035,14 @@ METHOD(task_t, process_i, status_t,
|
||||
case INVALID_KE_PAYLOAD:
|
||||
{
|
||||
chunk_t data;
|
||||
diffie_hellman_group_t bad_group;
|
||||
key_exchange_method_t bad_group;
|
||||
|
||||
bad_group = this->dh_group;
|
||||
data = notify->get_notification_data(notify);
|
||||
this->dh_group = ntohs(*((uint16_t*)data.ptr));
|
||||
DBG1(DBG_IKE, "peer didn't accept DH group %N, "
|
||||
"it requested %N", diffie_hellman_group_names,
|
||||
bad_group, diffie_hellman_group_names, this->dh_group);
|
||||
"it requested %N", key_exchange_method_names,
|
||||
bad_group, key_exchange_method_names, this->dh_group);
|
||||
|
||||
if (this->old_sa == NULL)
|
||||
{ /* reset the IKE_SA if we are not rekeying */
|
||||
@@ -1003,6 +1062,12 @@ METHOD(task_t, process_i, status_t,
|
||||
break;
|
||||
case COOKIE:
|
||||
{
|
||||
if (this->old_sa)
|
||||
{
|
||||
DBG1(DBG_IKE, "received COOKIE notify during rekeying"
|
||||
", ignored");
|
||||
break;
|
||||
}
|
||||
chunk_free(&this->cookie);
|
||||
this->cookie = chunk_clone(notify->get_notification_data(notify));
|
||||
this->ike_sa->reset(this->ike_sa, FALSE);
|
||||
@@ -1064,7 +1129,8 @@ METHOD(task_t, process_i, status_t,
|
||||
}
|
||||
|
||||
if (this->dh == NULL ||
|
||||
!this->proposal->has_dh_group(this->proposal, this->dh_group))
|
||||
!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
|
||||
this->dh_group))
|
||||
{
|
||||
DBG1(DBG_IKE, "peer DH group selection invalid");
|
||||
return FAILED;
|
||||
@@ -1075,13 +1141,15 @@ METHOD(task_t, process_i, status_t,
|
||||
DBG1(DBG_IKE, "applying DH public value failed");
|
||||
return FAILED;
|
||||
}
|
||||
this->ke_done = TRUE;
|
||||
|
||||
if (!derive_keys(this, this->my_nonce, this->other_nonce))
|
||||
if (this->old_sa)
|
||||
{
|
||||
DBG1(DBG_IKE, "key derivation failed");
|
||||
return FAILED;
|
||||
/* during rekeying, we derive keys here directly */
|
||||
return derive_keys(this);
|
||||
}
|
||||
return SUCCESS;
|
||||
/* key derivation is done before we send the next message */
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(task_t, get_type, task_type_t,
|
||||
@@ -1095,6 +1163,8 @@ METHOD(task_t, migrate, void,
|
||||
{
|
||||
DESTROY_IF(this->proposal);
|
||||
chunk_free(&this->other_nonce);
|
||||
this->ke_done = FALSE;
|
||||
this->ke_derived = FALSE;
|
||||
|
||||
this->ike_sa = ike_sa;
|
||||
this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
|
||||
@@ -1142,11 +1212,12 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
|
||||
.migrate = _migrate,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.derive_keys = _derive_keys,
|
||||
.get_lower_nonce = _get_lower_nonce,
|
||||
},
|
||||
.ike_sa = ike_sa,
|
||||
.initiator = initiator,
|
||||
.dh_group = MODP_NONE,
|
||||
.dh_group = KE_NONE,
|
||||
.keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
|
||||
.old_sa = old_sa,
|
||||
.signature_authentication = lib->settings->get_bool(lib->settings,
|
||||
|
||||
@@ -40,6 +40,18 @@ struct ike_init_t {
|
||||
*/
|
||||
task_t task;
|
||||
|
||||
/**
|
||||
* Derive the keys for this IKE_SA when not used during a rekeying.
|
||||
*
|
||||
* @return
|
||||
* - FAILED if key derivation failed
|
||||
* - NEED_MORE if key drivation was successful but more
|
||||
* key exchanges are necessary
|
||||
* - SUCCESS if key derivation was successful and the task
|
||||
* can be removed from the queue
|
||||
*/
|
||||
status_t (*derive_keys)(ike_init_t *this);
|
||||
|
||||
/**
|
||||
* Get the lower of the two nonces, used for rekey collisions.
|
||||
*
|
||||
|
||||
@@ -366,11 +366,12 @@ METHOD(ike_mobike_t, transmit, bool,
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_ike_mobike_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||
message->get_message_id(message) == 1)
|
||||
{ /* only in first IKE_AUTH */
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
|
||||
build_address_list(this, message);
|
||||
/* only in first IKE_AUTH */
|
||||
this->public.task.build = (void*)return_need_more;
|
||||
}
|
||||
else if (message->get_exchange_type(message) == INFORMATIONAL)
|
||||
{
|
||||
@@ -424,10 +425,11 @@ METHOD(task_t, build_i, status_t,
|
||||
METHOD(task_t, process_r, status_t,
|
||||
private_ike_mobike_t *this, message_t *message)
|
||||
{
|
||||
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||
message->get_message_id(message) == 1)
|
||||
{ /* only first IKE_AUTH */
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
process_payloads(this, message);
|
||||
/* only first IKE_AUTH */
|
||||
this->public.task.process = (void*)return_need_more;
|
||||
}
|
||||
else if (message->get_exchange_type(message) == INFORMATIONAL)
|
||||
{
|
||||
@@ -473,7 +475,7 @@ METHOD(task_t, build_r, status_t,
|
||||
{
|
||||
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
|
||||
{
|
||||
{ /* in last IKE_AUTH only */
|
||||
if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||
{
|
||||
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
|
||||
@@ -502,7 +504,7 @@ METHOD(task_t, process_i, status_t,
|
||||
{
|
||||
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
|
||||
{
|
||||
{ /* in last IKE_AUTH only */
|
||||
process_payloads(this, message);
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -642,6 +644,7 @@ METHOD(task_t, migrate, void,
|
||||
{
|
||||
this->natd->task.migrate(&this->natd->task, ike_sa);
|
||||
}
|
||||
this->public.task.build = _build_i;
|
||||
}
|
||||
|
||||
METHOD(task_t, destroy, void,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Tobias Brunner
|
||||
* Copyright (C) 2015-2018 Tobias Brunner
|
||||
* Copyright (C) 2005-2008 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@@ -67,7 +67,7 @@ struct private_ike_rekey_t {
|
||||
/**
|
||||
* colliding task detected by the task manager
|
||||
*/
|
||||
task_t *collision;
|
||||
private_ike_rekey_t *collision;
|
||||
|
||||
/**
|
||||
* TRUE if rekeying can't be handled temporarily
|
||||
@@ -167,8 +167,16 @@ METHOD(task_t, build_i, status_t,
|
||||
ike_version_t version;
|
||||
|
||||
/* create new SA only on first try */
|
||||
if (this->new_sa == NULL)
|
||||
if (!this->new_sa)
|
||||
{
|
||||
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
|
||||
this->ike_sa->get_state(this->ike_sa) == IKE_REKEYED)
|
||||
{
|
||||
/* ignore SAs that have or are currently being rekeyed passively */
|
||||
message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
version = this->ike_sa->get_version(this->ike_sa);
|
||||
this->new_sa = charon->ike_sa_manager->create_new(
|
||||
charon->ike_sa_manager, version, TRUE);
|
||||
@@ -254,7 +262,7 @@ METHOD(task_t, process_r, status_t,
|
||||
this->new_sa->inherit_pre(this->new_sa, this->ike_sa);
|
||||
this->ike_init = ike_init_create(this->new_sa, FALSE, this->ike_sa);
|
||||
this->ike_init->task.process(&this->ike_init->task, message);
|
||||
|
||||
charon->bus->set_sa(charon->bus, this->ike_sa);
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
@@ -266,12 +274,14 @@ METHOD(task_t, build_r, status_t,
|
||||
message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
|
||||
return SUCCESS;
|
||||
}
|
||||
if (this->new_sa == NULL)
|
||||
if (!this->new_sa)
|
||||
{
|
||||
/* IKE_SA/a CHILD_SA is in an unacceptable state, deny rekeying */
|
||||
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
charon->bus->set_sa(charon->bus, this->new_sa);
|
||||
if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
|
||||
{
|
||||
this->ike_init->task.destroy(&this->ike_init->task);
|
||||
@@ -303,12 +313,11 @@ METHOD(task_t, build_r, status_t,
|
||||
*/
|
||||
static bool conclude_undetected_collision(private_ike_rekey_t *this)
|
||||
{
|
||||
if (this->collision &&
|
||||
this->collision->get_type(this->collision) == TASK_IKE_REKEY)
|
||||
if (this->collision)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer did not notice IKE_SA rekey collision, abort "
|
||||
"active rekeying");
|
||||
establish_new((private_ike_rekey_t*)this->collision);
|
||||
establish_new(this->collision);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -338,26 +347,24 @@ METHOD(task_t, process_i, status_t,
|
||||
}
|
||||
return SUCCESS;
|
||||
case NEED_MORE:
|
||||
/* bad dh group, try again */
|
||||
/* bad KE method, try again */
|
||||
this->ike_init->task.migrate(&this->ike_init->task, this->new_sa);
|
||||
return NEED_MORE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for collisions */
|
||||
if (this->collision &&
|
||||
this->collision->get_type(this->collision) == TASK_IKE_REKEY)
|
||||
if (this->collision)
|
||||
{
|
||||
private_ike_rekey_t *other = (private_ike_rekey_t*)this->collision;
|
||||
private_ike_rekey_t *other = this->collision;
|
||||
host_t *host;
|
||||
chunk_t this_nonce, other_nonce;
|
||||
|
||||
this_nonce = this->ike_init->get_lower_nonce(this->ike_init);
|
||||
other_nonce = other->ike_init->get_lower_nonce(other->ike_init);
|
||||
|
||||
/* if we have the lower nonce, delete rekeyed SA. If not, delete
|
||||
* the redundant. */
|
||||
/* the SA with the lowest nonce should be deleted, check if we or
|
||||
* the peer created that */
|
||||
if (memcmp(this_nonce.ptr, other_nonce.ptr,
|
||||
min(this_nonce.len, other_nonce.len)) < 0)
|
||||
{
|
||||
@@ -369,9 +376,7 @@ METHOD(task_t, process_i, status_t,
|
||||
this->new_sa->set_my_host(this->new_sa, host->clone(host));
|
||||
host = this->ike_sa->get_other_host(this->ike_sa);
|
||||
this->new_sa->set_other_host(this->new_sa, host->clone(host));
|
||||
/* IKE_SAs in state IKE_REKEYED are silently deleted, so we use
|
||||
* IKE_REKEYING */
|
||||
this->new_sa->set_state(this->new_sa, IKE_REKEYING);
|
||||
this->new_sa->set_state(this->new_sa, IKE_REKEYED);
|
||||
if (this->new_sa->delete(this->new_sa, FALSE) == DESTROY_ME)
|
||||
{
|
||||
this->new_sa->destroy(this->new_sa);
|
||||
@@ -386,7 +391,8 @@ METHOD(task_t, process_i, status_t,
|
||||
establish_new(other);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* peer should delete this SA. Add a timeout just in case. */
|
||||
|
||||
/* peer should delete the SA it created, add a timeout just in case */
|
||||
job_t *job = (job_t*)delete_ike_sa_job_create(
|
||||
other->new_sa->get_id(other->new_sa), TRUE);
|
||||
lib->scheduler->schedule_job(lib->scheduler, job,
|
||||
@@ -402,7 +408,7 @@ METHOD(task_t, process_i, status_t,
|
||||
|
||||
establish_new(this);
|
||||
|
||||
/* rekeying successful, delete the IKE_SA using a subtask */
|
||||
/* rekeying successful, delete this IKE_SA using a subtask */
|
||||
this->ike_delete = ike_delete_create(this->ike_sa, TRUE);
|
||||
this->public.task.build = _build_i_delete;
|
||||
this->public.task.process = _process_i_delete;
|
||||
@@ -419,11 +425,10 @@ METHOD(task_t, get_type, task_type_t,
|
||||
METHOD(ike_rekey_t, did_collide, bool,
|
||||
private_ike_rekey_t *this)
|
||||
{
|
||||
return this->collision &&
|
||||
this->collision->get_type(this->collision) == TASK_IKE_REKEY;
|
||||
return this->collision != NULL;
|
||||
}
|
||||
|
||||
METHOD(ike_rekey_t, collide, void,
|
||||
METHOD(ike_rekey_t, collide, bool,
|
||||
private_ike_rekey_t* this, task_t *other)
|
||||
{
|
||||
DBG1(DBG_IKE, "detected %N collision with %N", task_type_names,
|
||||
@@ -433,8 +438,7 @@ METHOD(ike_rekey_t, collide, void,
|
||||
{
|
||||
case TASK_IKE_DELETE:
|
||||
conclude_undetected_collision(this);
|
||||
other->destroy(other);
|
||||
return;
|
||||
break;
|
||||
case TASK_IKE_REKEY:
|
||||
{
|
||||
private_ike_rekey_t *rekey = (private_ike_rekey_t*)other;
|
||||
@@ -443,16 +447,17 @@ METHOD(ike_rekey_t, collide, void,
|
||||
{
|
||||
DBG1(DBG_IKE, "colliding exchange did not result in an IKE_SA, "
|
||||
"ignore");
|
||||
other->destroy(other);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
DESTROY_IF(&this->collision->public.task);
|
||||
this->collision = rekey;
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
/* shouldn't happen */
|
||||
break;
|
||||
}
|
||||
DESTROY_IF(this->collision);
|
||||
this->collision = other;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,7 +478,7 @@ static void cleanup(private_ike_rekey_t *this)
|
||||
cur_sa = charon->bus->get_sa(charon->bus);
|
||||
DESTROY_IF(this->new_sa);
|
||||
charon->bus->set_sa(charon->bus, cur_sa);
|
||||
DESTROY_IF(this->collision);
|
||||
DESTROY_IF(&this->collision->public.task);
|
||||
}
|
||||
|
||||
METHOD(task_t, migrate, void,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Tobias Brunner
|
||||
* Copyright (C) 2016-2020 Tobias Brunner
|
||||
* Copyright (C) 2007 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -47,15 +47,17 @@ struct ike_rekey_t {
|
||||
bool (*did_collide)(ike_rekey_t *this);
|
||||
|
||||
/**
|
||||
* Register a rekeying task which collides with this one.
|
||||
* Register a rekeying/delete task which collides with this one.
|
||||
*
|
||||
* If two peers initiate rekeying at the same time, the collision must
|
||||
* be handled gracefully. The task manager is aware of what exchanges
|
||||
* are going on and notifies the outgoing task by passing the incoming.
|
||||
* are going on and notifies the active task by passing the passive.
|
||||
*
|
||||
* @param other incoming task
|
||||
* @param other passive task
|
||||
* @return whether the task was adopted and should be removed from
|
||||
* the task manager's control
|
||||
*/
|
||||
void (*collide)(ike_rekey_t* this, task_t *other);
|
||||
bool (*collide)(ike_rekey_t* this, task_t *other);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+10
-11
@@ -53,22 +53,21 @@ struct keymat_t {
|
||||
ike_version_t (*get_version)(keymat_t *this);
|
||||
|
||||
/**
|
||||
* Create a diffie hellman object for key agreement.
|
||||
* Create a key exchange object for key agreement.
|
||||
*
|
||||
* The diffie hellman is either for IKE negotiation/rekeying or
|
||||
* CHILD_SA rekeying (using PFS). The resulting DH object must be passed
|
||||
* to derive_keys or to derive_child_keys and destroyed after use.
|
||||
* The key exchange is either for IKE negotiation/rekeying or
|
||||
* CHILD_SA rekeying (using PFS). The resulting object must be passed
|
||||
* to derive_ike_keys() or to derive_child_keys() and destroyed after use.
|
||||
*
|
||||
* Only DH objects allocated through this method are passed to other
|
||||
* keymat_t methods, allowing private DH implementations. In some cases
|
||||
* (such as retrying with a COOKIE), a DH object allocated from a different
|
||||
* Only objects allocated through this method are passed to other
|
||||
* keymat_t methods, allowing private KE implementations. In some cases
|
||||
* (such as retrying with a COOKIE), a KE object allocated from a different
|
||||
* keymat_t instance may be passed to other methods.
|
||||
*
|
||||
* @param group diffie hellman group
|
||||
* @return DH object, NULL if group not supported
|
||||
* @param method key exchange method
|
||||
* @return key exchange object, NULL if method not supported
|
||||
*/
|
||||
diffie_hellman_t* (*create_dh)(keymat_t *this,
|
||||
diffie_hellman_group_t group);
|
||||
key_exchange_t* (*create_ke)(keymat_t *this, key_exchange_method_t method);
|
||||
|
||||
/**
|
||||
* Create a nonce generator object.
|
||||
|
||||
+25
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2015 Tobias Brunner
|
||||
* Copyright (C) 2007-2019 Tobias Brunner
|
||||
* Copyright (C) 2006 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -147,6 +147,18 @@ struct task_t {
|
||||
*/
|
||||
status_t (*build) (task_t *this, message_t *message);
|
||||
|
||||
/**
|
||||
* Called after a message has been built (optional to implement by tasks).
|
||||
*
|
||||
* @param message generated message, can't be modified anymore
|
||||
* @return
|
||||
* - SUCCESS if task completed
|
||||
* - NEED_MORE if another call to build/process needed
|
||||
* - Anything else will result in the destruction of
|
||||
* the IKE_SA
|
||||
*/
|
||||
status_t (*post_build) (task_t *this, message_t *message);
|
||||
|
||||
/**
|
||||
* Process a request or response message for this task.
|
||||
*
|
||||
@@ -172,6 +184,18 @@ struct task_t {
|
||||
*/
|
||||
status_t (*pre_process) (task_t *this, message_t *message);
|
||||
|
||||
/**
|
||||
* Called after a message has been processed (optional to implement).
|
||||
*
|
||||
* @param message processed message
|
||||
* @return
|
||||
* - SUCCESS if task completed
|
||||
* - NEED_MORE if another call to build/process needed
|
||||
* - Anything else will result in the destruction of
|
||||
* the IKE_SA
|
||||
*/
|
||||
status_t (*post_process) (task_t *this, message_t *message);
|
||||
|
||||
/**
|
||||
* Get the type of the task implementation.
|
||||
*/
|
||||
|
||||
@@ -74,7 +74,7 @@ START_TEST(test_chacha20poly1305)
|
||||
chunk_t chunk, exp;
|
||||
keymat_t keymat = {
|
||||
.get_version = _get_version,
|
||||
.create_dh = (void*)return_null,
|
||||
.create_ke = (void*)return_null,
|
||||
.create_nonce_gen = (void*)return_null,
|
||||
.get_aead = _get_aead,
|
||||
};
|
||||
|
||||
@@ -300,17 +300,33 @@ METHOD(exchange_test_helper_t, add_listener, void,
|
||||
*/
|
||||
static void initialize_logging()
|
||||
{
|
||||
int level = LEVEL_SILENT;
|
||||
char *verbosity;
|
||||
char buf[BUF_LEN], *verbosity;
|
||||
level_t level;
|
||||
debug_t group;
|
||||
|
||||
lib->settings->set_default_str(lib->settings, "%s.filelog.stderr.default",
|
||||
"-1", lib->ns);
|
||||
|
||||
verbosity = getenv("TESTS_VERBOSITY");
|
||||
if (verbosity)
|
||||
{
|
||||
level = atoi(verbosity);
|
||||
lib->settings->set_int(lib->settings, "%s.filelog.stderr.default",
|
||||
level, lib->ns);
|
||||
}
|
||||
|
||||
for (group = 0; group < DBG_MAX; group++)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "TESTS_VERBOSITY_%s",
|
||||
enum_to_name(debug_names, group));
|
||||
verbosity = getenv(buf);
|
||||
if (verbosity)
|
||||
{
|
||||
level = atoi(verbosity);
|
||||
lib->settings->set_int(lib->settings, "%s.filelog.stderr.%N",
|
||||
level, lib->ns, debug_lower_names, group);
|
||||
}
|
||||
}
|
||||
lib->settings->set_int(lib->settings, "%s.filelog.stderr.default",
|
||||
lib->settings->get_int(lib->settings, "%s.filelog.stderr.default",
|
||||
level, lib->ns), lib->ns);
|
||||
lib->settings->set_bool(lib->settings, "%s.filelog.stderr.ike_name", TRUE,
|
||||
lib->ns);
|
||||
charon->load_loggers(charon);
|
||||
@@ -332,11 +348,11 @@ void exchange_test_helper_init(char *plugins)
|
||||
private_exchange_test_helper_t *this;
|
||||
private_backend_t *backend;
|
||||
plugin_feature_t features[] = {
|
||||
PLUGIN_REGISTER(DH, mock_dh_create),
|
||||
PLUGIN_REGISTER(KE, mock_dh_create),
|
||||
/* we only need to support a limited number of DH groups */
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_256_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(KE, ECP_256_BIT),
|
||||
PLUGIN_REGISTER(NONCE_GEN, create_nonce_gen),
|
||||
PLUGIN_PROVIDE(NONCE_GEN),
|
||||
PLUGIN_DEPENDS(RNG, RNG_WEAK),
|
||||
|
||||
@@ -34,41 +34,41 @@ struct private_diffie_hellman_t {
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
diffie_hellman_t public;
|
||||
key_exchange_t public;
|
||||
|
||||
/**
|
||||
* Instantiated DH group
|
||||
* Instantiated key exchagne method
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t method;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_clone(mock_key);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_clone(mock_key);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
return this->method;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
free(this);
|
||||
@@ -77,19 +77,19 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
diffie_hellman_t *mock_dh_create(diffie_hellman_group_t group)
|
||||
key_exchange_t *mock_dh_create(key_exchange_method_t method)
|
||||
{
|
||||
private_diffie_hellman_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.group = group,
|
||||
.method = method,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
#ifndef MOCK_DH_H_
|
||||
#define MOCK_DH_H_
|
||||
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
/**
|
||||
* Creates a diffie_hellman_t object.
|
||||
* Creates a key_exchange_t object.
|
||||
*
|
||||
* @param group Diffie Hellman group, supports MODP_NULL only
|
||||
* @param method key_exchange method, supports MODP_NULL only
|
||||
* @return created object
|
||||
*/
|
||||
diffie_hellman_t *mock_dh_create(diffie_hellman_group_t group);
|
||||
key_exchange_t *mock_dh_create(key_exchange_method_t method);
|
||||
|
||||
#endif /** MOCK_DH_H_ @}*/
|
||||
|
||||
@@ -70,7 +70,7 @@ struct private_pts_t {
|
||||
/**
|
||||
* PTS Diffie-Hellman Secret
|
||||
*/
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *dh;
|
||||
|
||||
/**
|
||||
* PTS Diffie-Hellman Initiator Nonce
|
||||
@@ -200,15 +200,15 @@ METHOD(pts_t, set_dh_hash_algorithm, void,
|
||||
METHOD(pts_t, create_dh_nonce, bool,
|
||||
private_pts_t *this, pts_dh_group_t group, int nonce_len)
|
||||
{
|
||||
diffie_hellman_group_t dh_group;
|
||||
key_exchange_method_t dh_group;
|
||||
chunk_t *nonce;
|
||||
rng_t *rng;
|
||||
|
||||
dh_group = pts_dh_group_to_ike(group);
|
||||
DBG2(DBG_PTS, "selected PTS DH group is %N",
|
||||
diffie_hellman_group_names, dh_group);
|
||||
key_exchange_method_names, dh_group);
|
||||
DESTROY_IF(this->dh);
|
||||
this->dh = lib->crypto->create_dh(lib->crypto, dh_group);
|
||||
this->dh = lib->crypto->create_ke(lib->crypto, dh_group);
|
||||
|
||||
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
|
||||
if (!rng)
|
||||
@@ -232,7 +232,7 @@ METHOD(pts_t, create_dh_nonce, bool,
|
||||
METHOD(pts_t, get_my_public_value, bool,
|
||||
private_pts_t *this, chunk_t *value, chunk_t *nonce)
|
||||
{
|
||||
if (!this->dh->get_my_public_value(this->dh, value))
|
||||
if (!this->dh->get_public_key(this->dh, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -243,7 +243,7 @@ METHOD(pts_t, get_my_public_value, bool,
|
||||
METHOD(pts_t, set_peer_public_value, bool,
|
||||
private_pts_t *this, chunk_t value, chunk_t nonce)
|
||||
{
|
||||
if (!this->dh->set_other_public_value(this->dh, value))
|
||||
if (!this->dh->set_public_key(this->dh, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -24,44 +24,44 @@
|
||||
bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
diffie_hellman_group_t dh_group;
|
||||
key_exchange_method_t dh_group;
|
||||
const char *plugin_name;
|
||||
char format1[] = " %s PTS DH group %N[%s] available";
|
||||
char format2[] = " %s PTS DH group %N not available";
|
||||
|
||||
*dh_groups = PTS_DH_GROUP_NONE;
|
||||
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
|
||||
{
|
||||
if (dh_group == MODP_1024_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE2;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
DBG2(DBG_PTS, format1, "optional ", key_exchange_method_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == MODP_1536_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE5;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
DBG2(DBG_PTS, format1, "optional ", key_exchange_method_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == MODP_2048_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE14;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
DBG2(DBG_PTS, format1, "optional ", key_exchange_method_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == ECP_256_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE19;
|
||||
DBG2(DBG_PTS, format1, "mandatory", diffie_hellman_group_names,
|
||||
DBG2(DBG_PTS, format1, "mandatory", key_exchange_method_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == ECP_384_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE20;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
DBG2(DBG_PTS, format1, "optional ", key_exchange_method_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups)
|
||||
}
|
||||
if (mandatory_dh_groups)
|
||||
{
|
||||
DBG1(DBG_PTS, format2, "mandatory", diffie_hellman_group_names,
|
||||
DBG1(DBG_PTS, format2, "mandatory", key_exchange_method_names,
|
||||
ECP_256_BIT);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups,
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
|
||||
key_exchange_method_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
|
||||
{
|
||||
switch (dh_group)
|
||||
{
|
||||
@@ -180,6 +180,6 @@ diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
|
||||
case PTS_DH_GROUP_IKE20:
|
||||
return ECP_384_BIT;
|
||||
default:
|
||||
return MODP_NONE;
|
||||
return KE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define PTS_DH_GROUP_H_
|
||||
|
||||
#include <library.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
typedef enum pts_dh_group_t pts_dh_group_t;
|
||||
|
||||
@@ -98,11 +98,11 @@ pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_groups,
|
||||
pts_dh_group_t offered_groups);
|
||||
|
||||
/**
|
||||
* Convert pts_dh_group_t to diffie_hellman_group_t
|
||||
* Convert pts_dh_group_t to key_exchange_method_t
|
||||
*
|
||||
* @param dh_group PTS DH group type
|
||||
* @return IKE DH group type
|
||||
*/
|
||||
diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group);
|
||||
key_exchange_method_t pts_dh_group_to_ike(pts_dh_group_t dh_group);
|
||||
|
||||
#endif /** PTS_DH_GROUP_H_ @}*/
|
||||
|
||||
@@ -15,7 +15,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
|
||||
crypto/rngs/rng.c crypto/rngs/rng_tester.c \
|
||||
crypto/signers/signer.c \
|
||||
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
|
||||
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
|
||||
crypto/key_exchange.c crypto/aead.c crypto/transform.c \
|
||||
crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
|
||||
crypto/iv/iv_gen_null.c crypto/kdfs/kdf.c \
|
||||
crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
|
||||
|
||||
@@ -13,7 +13,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
|
||||
crypto/rngs/rng.c crypto/rngs/rng_tester.c \
|
||||
crypto/signers/signer.c \
|
||||
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
|
||||
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
|
||||
crypto/key_exchange.c crypto/aead.c crypto/transform.c \
|
||||
crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
|
||||
crypto/iv/iv_gen_null.c crypto/kdfs/kdf.c \
|
||||
crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
|
||||
@@ -79,7 +79,7 @@ crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
|
||||
crypto/rngs/rng.h crypto/rngs/rng_tester.h \
|
||||
crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/nonce_gen.h \
|
||||
crypto/signers/signer.h crypto/signers/mac_signer.h \
|
||||
crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
|
||||
crypto/crypto_factory.h crypto/crypto_tester.h crypto/key_exchange.h \
|
||||
crypto/aead.h crypto/transform.h crypto/pkcs5.h crypto/iv/iv_gen.h \
|
||||
crypto/iv/iv_gen_rand.h crypto/iv/iv_gen_seq.h crypto/iv/iv_gen_null.h \
|
||||
crypto/xofs/xof.h crypto/xofs/xof_bitspender.h crypto/xofs/mgf1.h \
|
||||
|
||||
@@ -56,7 +56,7 @@ struct entry_t {
|
||||
drbg_constructor_t create_drbg;
|
||||
rng_constructor_t create_rng;
|
||||
nonce_gen_constructor_t create_nonce_gen;
|
||||
dh_constructor_t create_dh;
|
||||
ke_constructor_t create_ke;
|
||||
void *create;
|
||||
};
|
||||
};
|
||||
@@ -124,9 +124,9 @@ struct private_crypto_factory_t {
|
||||
linked_list_t *nonce_gens;
|
||||
|
||||
/**
|
||||
* registered diffie hellman, as entry_t
|
||||
* registered key exchange methods, as entry_t
|
||||
*/
|
||||
linked_list_t *dhs;
|
||||
linked_list_t *kes;
|
||||
|
||||
/**
|
||||
* test manager to test crypto algorithms
|
||||
@@ -484,37 +484,33 @@ METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
|
||||
return nonce_gen;
|
||||
}
|
||||
|
||||
METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
|
||||
private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
|
||||
METHOD(crypto_factory_t, create_ke, key_exchange_t*,
|
||||
private_crypto_factory_t *this, key_exchange_method_t method, ...)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
entry_t *entry;
|
||||
va_list args;
|
||||
chunk_t g = chunk_empty, p = chunk_empty;
|
||||
diffie_hellman_t *diffie_hellman = NULL;
|
||||
key_exchange_t *ke = NULL;
|
||||
|
||||
if (group == MODP_CUSTOM)
|
||||
if (method == MODP_CUSTOM)
|
||||
{
|
||||
va_start(args, group);
|
||||
g = va_arg(args, chunk_t);
|
||||
p = va_arg(args, chunk_t);
|
||||
va_end(args);
|
||||
VA_ARGS_GET(method, g, p);
|
||||
}
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
enumerator = this->dhs->create_enumerator(this->dhs);
|
||||
enumerator = this->kes->create_enumerator(this->kes);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->algo == group)
|
||||
if (entry->algo == method)
|
||||
{
|
||||
if (this->test_on_create && group != MODP_CUSTOM &&
|
||||
!this->tester->test_dh(this->tester, group,
|
||||
entry->create_dh, NULL, entry->plugin_name))
|
||||
if (this->test_on_create && method != MODP_CUSTOM &&
|
||||
!this->tester->test_ke(this->tester, method,
|
||||
entry->create_ke, NULL, entry->plugin_name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
diffie_hellman = entry->create_dh(group, g, p);
|
||||
if (diffie_hellman)
|
||||
ke = entry->create_ke(method, g, p);
|
||||
if (ke)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -522,7 +518,7 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
return diffie_hellman;
|
||||
return ke;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -935,36 +931,36 @@ METHOD(crypto_factory_t, remove_nonce_gen, void,
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
METHOD(crypto_factory_t, add_dh, bool,
|
||||
private_crypto_factory_t *this, diffie_hellman_group_t group,
|
||||
const char *plugin_name, dh_constructor_t create)
|
||||
METHOD(crypto_factory_t, add_ke, bool,
|
||||
private_crypto_factory_t *this, key_exchange_method_t group,
|
||||
const char *plugin_name, ke_constructor_t create)
|
||||
{
|
||||
u_int speed = 0;
|
||||
|
||||
if (!this->test_on_add ||
|
||||
this->tester->test_dh(this->tester, group, create,
|
||||
this->tester->test_ke(this->tester, group, create,
|
||||
this->bench ? &speed : NULL, plugin_name))
|
||||
{
|
||||
add_entry(this, this->dhs, group, plugin_name, 0, create);
|
||||
add_entry(this, this->kes, group, plugin_name, 0, create);
|
||||
return TRUE;
|
||||
}
|
||||
this->test_failures++;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(crypto_factory_t, remove_dh, void,
|
||||
private_crypto_factory_t *this, dh_constructor_t create)
|
||||
METHOD(crypto_factory_t, remove_ke, void,
|
||||
private_crypto_factory_t *this, ke_constructor_t create)
|
||||
{
|
||||
entry_t *entry;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
enumerator = this->dhs->create_enumerator(this->dhs);
|
||||
enumerator = this->kes->create_enumerator(this->kes);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->create_dh == create)
|
||||
if (entry->create_ke == create)
|
||||
{
|
||||
this->dhs->remove_at(this->dhs, enumerator);
|
||||
this->kes->remove_at(this->kes, enumerator);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
@@ -1190,11 +1186,11 @@ METHOD(crypto_factory_t, create_drbg_enumerator, enumerator_t*,
|
||||
return create_enumerator(this, this->drbgs, drbg_filter);
|
||||
}
|
||||
|
||||
CALLBACK(dh_filter, bool,
|
||||
CALLBACK(ke_filter, bool,
|
||||
void *n, enumerator_t *orig, va_list args)
|
||||
{
|
||||
entry_t *entry;
|
||||
diffie_hellman_group_t *algo;
|
||||
key_exchange_method_t *algo;
|
||||
const char **plugin_name;
|
||||
|
||||
VA_ARGS_VGET(args, algo, plugin_name);
|
||||
@@ -1208,10 +1204,10 @@ CALLBACK(dh_filter, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
|
||||
METHOD(crypto_factory_t, create_ke_enumerator, enumerator_t*,
|
||||
private_crypto_factory_t *this)
|
||||
{
|
||||
return create_enumerator(this, this->dhs, dh_filter);
|
||||
return create_enumerator(this, this->kes, ke_filter);
|
||||
}
|
||||
|
||||
CALLBACK(rng_filter, bool,
|
||||
@@ -1283,8 +1279,8 @@ METHOD(crypto_factory_t, add_test_vector, void,
|
||||
return this->tester->add_drbg_vector(this->tester, vector);
|
||||
case RANDOM_NUMBER_GENERATOR:
|
||||
return this->tester->add_rng_vector(this->tester, vector);
|
||||
case DIFFIE_HELLMAN_GROUP:
|
||||
return this->tester->add_dh_vector(this->tester, vector);
|
||||
case KEY_EXCHANGE_METHOD:
|
||||
return this->tester->add_ke_vector(this->tester, vector);
|
||||
default:
|
||||
DBG1(DBG_LIB, "%N test vectors not supported, ignored",
|
||||
transform_type_names, type);
|
||||
@@ -1354,9 +1350,9 @@ METHOD(enumerator_t, verify_enumerate, bool,
|
||||
*valid = this->tester->test_rng(this->tester, entry->algo,
|
||||
entry->create_rng, NULL, entry->plugin_name);
|
||||
break;
|
||||
case DIFFIE_HELLMAN_GROUP:
|
||||
*valid = this->tester->test_dh(this->tester, entry->algo,
|
||||
entry->create_dh, NULL, entry->plugin_name);
|
||||
case KEY_EXCHANGE_METHOD:
|
||||
*valid = this->tester->test_ke(this->tester, entry->algo,
|
||||
entry->create_ke, NULL, entry->plugin_name);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
@@ -1410,8 +1406,8 @@ METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
|
||||
case RANDOM_NUMBER_GENERATOR:
|
||||
inner = this->rngs->create_enumerator(this->rngs);
|
||||
break;
|
||||
case DIFFIE_HELLMAN_GROUP:
|
||||
inner = this->dhs->create_enumerator(this->dhs);
|
||||
case KEY_EXCHANGE_METHOD:
|
||||
inner = this->kes->create_enumerator(this->kes);
|
||||
break;
|
||||
default:
|
||||
this->lock->unlock(this->lock);
|
||||
@@ -1444,7 +1440,7 @@ METHOD(crypto_factory_t, destroy, void,
|
||||
this->drbgs->destroy(this->drbgs);
|
||||
this->rngs->destroy(this->rngs);
|
||||
this->nonce_gens->destroy(this->nonce_gens);
|
||||
this->dhs->destroy(this->dhs);
|
||||
this->kes->destroy(this->kes);
|
||||
this->tester->destroy(this->tester);
|
||||
this->lock->destroy(this->lock);
|
||||
free(this);
|
||||
@@ -1469,7 +1465,7 @@ crypto_factory_t *crypto_factory_create()
|
||||
.create_drbg = _create_drbg,
|
||||
.create_rng = _create_rng,
|
||||
.create_nonce_gen = _create_nonce_gen,
|
||||
.create_dh = _create_dh,
|
||||
.create_ke = _create_ke,
|
||||
.add_crypter = _add_crypter,
|
||||
.remove_crypter = _remove_crypter,
|
||||
.add_aead = _add_aead,
|
||||
@@ -1490,8 +1486,8 @@ crypto_factory_t *crypto_factory_create()
|
||||
.remove_rng = _remove_rng,
|
||||
.add_nonce_gen = _add_nonce_gen,
|
||||
.remove_nonce_gen = _remove_nonce_gen,
|
||||
.add_dh = _add_dh,
|
||||
.remove_dh = _remove_dh,
|
||||
.add_ke = _add_ke,
|
||||
.remove_ke = _remove_ke,
|
||||
.create_crypter_enumerator = _create_crypter_enumerator,
|
||||
.create_aead_enumerator = _create_aead_enumerator,
|
||||
.create_signer_enumerator = _create_signer_enumerator,
|
||||
@@ -1500,7 +1496,7 @@ crypto_factory_t *crypto_factory_create()
|
||||
.create_xof_enumerator = _create_xof_enumerator,
|
||||
.create_kdf_enumerator = _create_kdf_enumerator,
|
||||
.create_drbg_enumerator = _create_drbg_enumerator,
|
||||
.create_dh_enumerator = _create_dh_enumerator,
|
||||
.create_ke_enumerator = _create_ke_enumerator,
|
||||
.create_rng_enumerator = _create_rng_enumerator,
|
||||
.create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
|
||||
.add_test_vector = _add_test_vector,
|
||||
@@ -1517,7 +1513,7 @@ crypto_factory_t *crypto_factory_create()
|
||||
.drbgs = linked_list_create(),
|
||||
.rngs = linked_list_create(),
|
||||
.nonce_gens = linked_list_create(),
|
||||
.dhs = linked_list_create(),
|
||||
.kes = linked_list_create(),
|
||||
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
||||
.tester = crypto_tester_create(),
|
||||
.test_on_add = lib->settings->get_bool(lib->settings,
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef struct crypto_factory_t crypto_factory_t;
|
||||
#include <crypto/kdfs/kdf.h>
|
||||
#include <crypto/drbgs/drbg.h>
|
||||
#include <crypto/nonce_gen.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
#include <crypto/transform.h>
|
||||
|
||||
#define CRYPTO_MAX_ALG_LINE 120 /* characters */
|
||||
@@ -97,12 +97,12 @@ typedef rng_t* (*rng_constructor_t)(rng_quality_t quality);
|
||||
typedef nonce_gen_t* (*nonce_gen_constructor_t)();
|
||||
|
||||
/**
|
||||
* Constructor function for diffie hellman
|
||||
* Constructor function for key exchange methods
|
||||
*
|
||||
* The DH constructor accepts additional arguments for:
|
||||
* The key exchange method constructor accepts additional arguments for:
|
||||
* - MODP_CUSTOM: chunk_t generator, chunk_t prime
|
||||
*/
|
||||
typedef diffie_hellman_t* (*dh_constructor_t)(diffie_hellman_group_t group, ...);
|
||||
typedef key_exchange_t* (*ke_constructor_t)(key_exchange_method_t method, ...);
|
||||
|
||||
/**
|
||||
* Handles crypto modules and creates instances.
|
||||
@@ -207,15 +207,15 @@ struct crypto_factory_t {
|
||||
nonce_gen_t* (*create_nonce_gen)(crypto_factory_t *this);
|
||||
|
||||
/**
|
||||
* Create a diffie hellman instance.
|
||||
* Create a key exchange method instance.
|
||||
*
|
||||
* Additional arguments are passed to the DH constructor.
|
||||
* Additional arguments are passed to the key exchange method constructor.
|
||||
*
|
||||
* @param group diffie hellman group
|
||||
* @return diffie_hellman_t instance, NULL if not supported
|
||||
* @param method key exchange method
|
||||
* @return key_exchange_t instance, NULL if not supported
|
||||
*/
|
||||
diffie_hellman_t* (*create_dh)(crypto_factory_t *this,
|
||||
diffie_hellman_group_t group, ...);
|
||||
key_exchange_t* (*create_ke)(crypto_factory_t *this,
|
||||
key_exchange_method_t method, ...);
|
||||
|
||||
/**
|
||||
* Register a crypter constructor.
|
||||
@@ -402,22 +402,22 @@ struct crypto_factory_t {
|
||||
nonce_gen_constructor_t create);
|
||||
|
||||
/**
|
||||
* Register a diffie hellman constructor.
|
||||
* Register a key exchange method constructor.
|
||||
*
|
||||
* @param group dh group to constructor
|
||||
* @param method key exchange method to constructor
|
||||
* @param plugin_name plugin that registered this algorithm
|
||||
* @param create constructor function for that algorithm
|
||||
* @return TRUE if registered, FALSE if test vector failed
|
||||
*/
|
||||
bool (*add_dh)(crypto_factory_t *this, diffie_hellman_group_t group,
|
||||
const char *plugin_name, dh_constructor_t create);
|
||||
bool (*add_ke)(crypto_factory_t *this, key_exchange_method_t method,
|
||||
const char *plugin_name, ke_constructor_t create);
|
||||
|
||||
/**
|
||||
* Unregister a diffie hellman constructor.
|
||||
* Unregister a key exchange method constructor.
|
||||
*
|
||||
* @param create constructor function to unregister
|
||||
*/
|
||||
void (*remove_dh)(crypto_factory_t *this, dh_constructor_t create);
|
||||
void (*remove_ke)(crypto_factory_t *this, ke_constructor_t create);
|
||||
|
||||
/**
|
||||
* Create an enumerator over all registered crypter algorithms.
|
||||
@@ -476,11 +476,11 @@ struct crypto_factory_t {
|
||||
enumerator_t* (*create_drbg_enumerator)(crypto_factory_t *this);
|
||||
|
||||
/**
|
||||
* Create an enumerator over all registered diffie hellman groups.
|
||||
* Create an enumerator over all registered key exchange method.
|
||||
*
|
||||
* @return enumerator over diffie_hellman_group_t, plugin
|
||||
* @return enumerator over key_exchange_method_t, plugin
|
||||
*/
|
||||
enumerator_t* (*create_dh_enumerator)(crypto_factory_t *this);
|
||||
enumerator_t* (*create_ke_enumerator)(crypto_factory_t *this);
|
||||
|
||||
/**
|
||||
* Create an enumerator over all registered random generators.
|
||||
|
||||
@@ -85,9 +85,9 @@ struct private_crypto_tester_t {
|
||||
linked_list_t *rng;
|
||||
|
||||
/**
|
||||
* List of Diffie-Hellman test vectors
|
||||
* List of key exchange method test vectors
|
||||
*/
|
||||
linked_list_t *dh;
|
||||
linked_list_t *ke;
|
||||
|
||||
/**
|
||||
* Is a test vector required to pass a test?
|
||||
@@ -1649,13 +1649,13 @@ failure:
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark a DH backend
|
||||
* Benchmark a key exchange backend
|
||||
*/
|
||||
static u_int bench_dh(private_crypto_tester_t *this,
|
||||
diffie_hellman_group_t group, dh_constructor_t create)
|
||||
static u_int bench_ke(private_crypto_tester_t *this,
|
||||
key_exchange_method_t method, ke_constructor_t create)
|
||||
{
|
||||
chunk_t pub = chunk_empty, shared = chunk_empty;
|
||||
diffie_hellman_t *dh;
|
||||
key_exchange_t *ke;
|
||||
struct timespec start;
|
||||
u_int runs;
|
||||
|
||||
@@ -1663,46 +1663,46 @@ static u_int bench_dh(private_crypto_tester_t *this,
|
||||
start_timing(&start);
|
||||
while (end_timing(&start) < this->bench_time)
|
||||
{
|
||||
dh = create(group);
|
||||
if (!dh)
|
||||
ke = create(method);
|
||||
if (!ke)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (dh->get_my_public_value(dh, &pub) &&
|
||||
dh->set_other_public_value(dh, pub) &&
|
||||
dh->get_shared_secret(dh, &shared))
|
||||
if (ke->get_public_key(ke, &pub) &&
|
||||
ke->set_public_key(ke, pub) &&
|
||||
ke->get_shared_secret(ke, &shared))
|
||||
{
|
||||
runs++;
|
||||
}
|
||||
chunk_free(&pub);
|
||||
chunk_free(&shared);
|
||||
dh->destroy(dh);
|
||||
ke->destroy(ke);
|
||||
}
|
||||
return runs;
|
||||
}
|
||||
|
||||
METHOD(crypto_tester_t, test_dh, bool,
|
||||
private_crypto_tester_t *this, diffie_hellman_group_t group,
|
||||
dh_constructor_t create, u_int *speed, const char *plugin_name)
|
||||
METHOD(crypto_tester_t, test_ke, bool,
|
||||
private_crypto_tester_t *this, key_exchange_method_t method,
|
||||
ke_constructor_t create, u_int *speed, const char *plugin_name)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
dh_test_vector_t *v;
|
||||
ke_test_vector_t *v;
|
||||
bool failed = FALSE;
|
||||
u_int tested = 0;
|
||||
|
||||
enumerator = this->dh->create_enumerator(this->dh);
|
||||
enumerator = this->ke->create_enumerator(this->ke);
|
||||
while (enumerator->enumerate(enumerator, &v))
|
||||
{
|
||||
diffie_hellman_t *a, *b;
|
||||
key_exchange_t *a, *b;
|
||||
chunk_t apub, bpub, asec, bsec;
|
||||
|
||||
if (v->group != group)
|
||||
if (v->method != method)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
a = create(group);
|
||||
b = create(group);
|
||||
a = create(method);
|
||||
b = create(method);
|
||||
if (!a || !b)
|
||||
{
|
||||
DESTROY_IF(a);
|
||||
@@ -1710,11 +1710,11 @@ METHOD(crypto_tester_t, test_dh, bool,
|
||||
failed = TRUE;
|
||||
tested++;
|
||||
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
|
||||
diffie_hellman_group_names, group, plugin_name);
|
||||
key_exchange_method_names, method, plugin_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!a->set_private_value || !b->set_private_value)
|
||||
if (!a->set_private_key || !b->set_private_key)
|
||||
{ /* does not support testing */
|
||||
a->destroy(a);
|
||||
b->destroy(b);
|
||||
@@ -1725,23 +1725,23 @@ METHOD(crypto_tester_t, test_dh, bool,
|
||||
|
||||
apub = bpub = asec = bsec = chunk_empty;
|
||||
|
||||
if (!a->set_private_value(a, chunk_create(v->priv_a, v->priv_len)) ||
|
||||
!b->set_private_value(b, chunk_create(v->priv_b, v->priv_len)))
|
||||
if (!a->set_private_key(a, chunk_create(v->priv_a, v->priv_len)) ||
|
||||
!b->set_private_key(b, chunk_create(v->priv_b, v->priv_len)))
|
||||
{
|
||||
goto failure;
|
||||
}
|
||||
if (!a->get_my_public_value(a, &apub) ||
|
||||
if (!a->get_public_key(a, &apub) ||
|
||||
!chunk_equals(apub, chunk_create(v->pub_a, v->pub_len)))
|
||||
{
|
||||
goto failure;
|
||||
}
|
||||
if (!b->get_my_public_value(b, &bpub) ||
|
||||
if (!b->get_public_key(b, &bpub) ||
|
||||
!chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len)))
|
||||
{
|
||||
goto failure;
|
||||
}
|
||||
if (!a->set_other_public_value(a, bpub) ||
|
||||
!b->set_other_public_value(b, apub))
|
||||
if (!a->set_public_key(a, bpub) ||
|
||||
!b->set_public_key(b, apub))
|
||||
{
|
||||
goto failure;
|
||||
}
|
||||
@@ -1767,7 +1767,7 @@ failure:
|
||||
if (failed)
|
||||
{
|
||||
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
|
||||
diffie_hellman_group_names, group, plugin_name, get_name(v));
|
||||
key_exchange_method_names, method, plugin_name, get_name(v));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1776,21 +1776,21 @@ failure:
|
||||
{
|
||||
DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
|
||||
this->required ? "disabled" : "enabled ",
|
||||
diffie_hellman_group_names, group, plugin_name);
|
||||
key_exchange_method_names, method, plugin_name);
|
||||
return !this->required;
|
||||
}
|
||||
if (!failed)
|
||||
{
|
||||
if (speed)
|
||||
{
|
||||
*speed = bench_dh(this, group, create);
|
||||
*speed = bench_ke(this, method, create);
|
||||
DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
|
||||
diffie_hellman_group_names, group, plugin_name, tested, *speed);
|
||||
key_exchange_method_names, method, plugin_name, tested, *speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
|
||||
diffie_hellman_group_names, group, plugin_name, tested);
|
||||
key_exchange_method_names, method, plugin_name, tested);
|
||||
}
|
||||
}
|
||||
return !failed;
|
||||
@@ -1850,10 +1850,10 @@ METHOD(crypto_tester_t, add_rng_vector, void,
|
||||
this->rng->insert_last(this->rng, vector);
|
||||
}
|
||||
|
||||
METHOD(crypto_tester_t, add_dh_vector, void,
|
||||
private_crypto_tester_t *this, dh_test_vector_t *vector)
|
||||
METHOD(crypto_tester_t, add_ke_vector, void,
|
||||
private_crypto_tester_t *this, ke_test_vector_t *vector)
|
||||
{
|
||||
this->dh->insert_last(this->dh, vector);
|
||||
this->ke->insert_last(this->ke, vector);
|
||||
}
|
||||
|
||||
METHOD(crypto_tester_t, destroy, void,
|
||||
@@ -1868,7 +1868,7 @@ METHOD(crypto_tester_t, destroy, void,
|
||||
this->kdf->destroy(this->kdf);
|
||||
this->drbg->destroy(this->drbg);
|
||||
this->rng->destroy(this->rng);
|
||||
this->dh->destroy(this->dh);
|
||||
this->ke->destroy(this->ke);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -1890,7 +1890,7 @@ crypto_tester_t *crypto_tester_create()
|
||||
.test_kdf = _test_kdf,
|
||||
.test_drbg = _test_drbg,
|
||||
.test_rng = _test_rng,
|
||||
.test_dh = _test_dh,
|
||||
.test_ke = _test_ke,
|
||||
.add_crypter_vector = _add_crypter_vector,
|
||||
.add_aead_vector = _add_aead_vector,
|
||||
.add_signer_vector = _add_signer_vector,
|
||||
@@ -1900,7 +1900,7 @@ crypto_tester_t *crypto_tester_create()
|
||||
.add_kdf_vector = _add_kdf_vector,
|
||||
.add_drbg_vector = _add_drbg_vector,
|
||||
.add_rng_vector = _add_rng_vector,
|
||||
.add_dh_vector = _add_dh_vector,
|
||||
.add_ke_vector = _add_ke_vector,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.crypter = linked_list_create(),
|
||||
@@ -1912,7 +1912,7 @@ crypto_tester_t *crypto_tester_create()
|
||||
.kdf = linked_list_create(),
|
||||
.drbg = linked_list_create(),
|
||||
.rng = linked_list_create(),
|
||||
.dh = linked_list_create(),
|
||||
.ke = linked_list_create(),
|
||||
|
||||
.required = lib->settings->get_bool(lib->settings,
|
||||
"%s.crypto_test.required", FALSE, lib->ns),
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef struct kdf_test_vector_t kdf_test_vector_t;
|
||||
typedef struct kdf_test_args_t kdf_test_args_t;
|
||||
typedef struct drbg_test_vector_t drbg_test_vector_t;
|
||||
typedef struct rng_test_vector_t rng_test_vector_t;
|
||||
typedef struct dh_test_vector_t dh_test_vector_t;
|
||||
typedef struct ke_test_vector_t ke_test_vector_t;
|
||||
|
||||
struct crypter_test_vector_t {
|
||||
/** encryption algorithm this vector tests */
|
||||
@@ -182,20 +182,20 @@ struct rng_test_vector_t {
|
||||
void *user;
|
||||
};
|
||||
|
||||
struct dh_test_vector_t {
|
||||
/** diffie hellman group to test */
|
||||
diffie_hellman_group_t group;
|
||||
/** private value of alice */
|
||||
struct ke_test_vector_t {
|
||||
/** key exchange method to test */
|
||||
key_exchange_method_t method;
|
||||
/** private key of alice */
|
||||
u_char *priv_a;
|
||||
/** private value of bob */
|
||||
/** private key of bob */
|
||||
u_char *priv_b;
|
||||
/** length of private values */
|
||||
/** length of private keys */
|
||||
size_t priv_len;
|
||||
/** expected public value of alice */
|
||||
/** expected public key of alice */
|
||||
u_char *pub_a;
|
||||
/** expected public value of bob */
|
||||
/** expected public key of bob */
|
||||
u_char *pub_b;
|
||||
/** size of public values */
|
||||
/** size of public keys */
|
||||
size_t pub_len;
|
||||
/** expected shared secret */
|
||||
u_char *shared;
|
||||
@@ -318,15 +318,15 @@ struct crypto_tester_t {
|
||||
rng_constructor_t create,
|
||||
u_int *speed, const char *plugin_name);
|
||||
/**
|
||||
* Test a Diffie-Hellman implementation.
|
||||
* Test a key exchange implementation.
|
||||
*
|
||||
* @param group group to test
|
||||
* @param create constructor function for the DH backend
|
||||
* @param speed speed test result, NULL to omit
|
||||
* @param ke key exchange method to test
|
||||
* @param create constructor function for the key exchange method
|
||||
* @param speed speeed test result, NULL to omit
|
||||
* @return TRUE if test passed
|
||||
*/
|
||||
bool (*test_dh)(crypto_tester_t *this, diffie_hellman_group_t group,
|
||||
dh_constructor_t create,
|
||||
bool (*test_ke)(crypto_tester_t *this, key_exchange_method_t ke,
|
||||
ke_constructor_t create,
|
||||
u_int *speed, const char *plugin_name);
|
||||
|
||||
/**
|
||||
@@ -397,7 +397,7 @@ struct crypto_tester_t {
|
||||
*
|
||||
* @param vector pointer to test vector
|
||||
*/
|
||||
void (*add_dh_vector)(crypto_tester_t *this, dh_test_vector_t *vector);
|
||||
void (*add_ke_vector)(crypto_tester_t *this, ke_test_vector_t *vector);
|
||||
|
||||
/**
|
||||
* Destroy a crypto_tester_t.
|
||||
|
||||
+42
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Tobias Brunner
|
||||
* Copyright (C) 2010-2019 Tobias Brunner
|
||||
* Copyright (C) 2005-2010 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@@ -16,15 +16,15 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "diffie_hellman.h"
|
||||
#include "key_exchange.h"
|
||||
|
||||
ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT,
|
||||
"MODP_NONE",
|
||||
ENUM_BEGIN(key_exchange_method_names, KE_NONE, MODP_1024_BIT,
|
||||
"KE_NONE",
|
||||
"MODP_768",
|
||||
"MODP_1024");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
|
||||
"MODP_1536");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
|
||||
"MODP_2048",
|
||||
"MODP_3072",
|
||||
"MODP_4096",
|
||||
@@ -33,7 +33,7 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
|
||||
"ECP_256",
|
||||
"ECP_384",
|
||||
"ECP_521");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, CURVE_448, ECP_521_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names, MODP_1024_160, CURVE_448, ECP_521_BIT,
|
||||
"MODP_1024_160",
|
||||
"MODP_2048_224",
|
||||
"MODP_2048_256",
|
||||
@@ -45,26 +45,26 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, CURVE_448, ECP_521_BIT,
|
||||
"ECP_512_BP",
|
||||
"CURVE_25519",
|
||||
"CURVE_448");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_NULL, CURVE_448,
|
||||
ENUM_NEXT(key_exchange_method_names, MODP_NULL, MODP_NULL, CURVE_448,
|
||||
"MODP_NULL");
|
||||
ENUM_NEXT(diffie_hellman_group_names, NTRU_112_BIT, NTRU_256_BIT, MODP_NULL,
|
||||
ENUM_NEXT(key_exchange_method_names, NTRU_112_BIT, NTRU_256_BIT, MODP_NULL,
|
||||
"NTRU_112",
|
||||
"NTRU_128",
|
||||
"NTRU_192",
|
||||
"NTRU_256");
|
||||
ENUM_NEXT(diffie_hellman_group_names, NH_128_BIT, NH_128_BIT, NTRU_256_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names, NH_128_BIT, NH_128_BIT, NTRU_256_BIT,
|
||||
"NEWHOPE_128");
|
||||
ENUM_NEXT(diffie_hellman_group_names, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
|
||||
"MODP_CUSTOM");
|
||||
ENUM_END(diffie_hellman_group_names, MODP_CUSTOM);
|
||||
ENUM_END(key_exchange_method_names, MODP_CUSTOM);
|
||||
|
||||
ENUM_BEGIN(diffie_hellman_group_names_short, MODP_NONE, MODP_1024_BIT,
|
||||
"modpnone",
|
||||
ENUM_BEGIN(key_exchange_method_names_short, KE_NONE, MODP_1024_BIT,
|
||||
"none",
|
||||
"modp768",
|
||||
"modp1024");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names_short, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
|
||||
"modp1536");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names_short, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
|
||||
"modp2048",
|
||||
"modp3072",
|
||||
"modp4096",
|
||||
@@ -73,7 +73,7 @@ ENUM_NEXT(diffie_hellman_group_names_short, MODP_2048_BIT, ECP_521_BIT, MODP_153
|
||||
"ecp256",
|
||||
"ecp384",
|
||||
"ecp521");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, MODP_1024_160, CURVE_448, ECP_521_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names_short, MODP_1024_160, CURVE_448, ECP_521_BIT,
|
||||
"modp1024s160",
|
||||
"modp2048s224",
|
||||
"modp2048s256",
|
||||
@@ -85,27 +85,27 @@ ENUM_NEXT(diffie_hellman_group_names_short, MODP_1024_160, CURVE_448, ECP_521_BI
|
||||
"ecp512bp",
|
||||
"curve25519",
|
||||
"curve448");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, MODP_NULL, MODP_NULL, CURVE_448,
|
||||
ENUM_NEXT(key_exchange_method_names_short, MODP_NULL, MODP_NULL, CURVE_448,
|
||||
"modpnull");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, NTRU_112_BIT, NTRU_256_BIT, MODP_NULL,
|
||||
ENUM_NEXT(key_exchange_method_names_short, NTRU_112_BIT, NTRU_256_BIT, MODP_NULL,
|
||||
"ntru112",
|
||||
"ntru128",
|
||||
"ntru192",
|
||||
"ntru256");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, NH_128_BIT, NH_128_BIT, NTRU_256_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names_short, NH_128_BIT, NH_128_BIT, NTRU_256_BIT,
|
||||
"newhope128");
|
||||
ENUM_NEXT(diffie_hellman_group_names_short, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
|
||||
ENUM_NEXT(key_exchange_method_names_short, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
|
||||
"modpcustom");
|
||||
ENUM_END(diffie_hellman_group_names_short, MODP_CUSTOM);
|
||||
ENUM_END(key_exchange_method_names_short, MODP_CUSTOM);
|
||||
|
||||
/**
|
||||
* List of known diffie hellman group parameters.
|
||||
* List of known Diffie-Hellman group parameters.
|
||||
*/
|
||||
static struct {
|
||||
/* Public part of the struct */
|
||||
diffie_hellman_params_t public;
|
||||
/* The group identifier as specified in IKEv2 */
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
} dh_params[] = {
|
||||
{
|
||||
.group = MODP_768_BIT, .public = {
|
||||
@@ -475,8 +475,8 @@ static struct {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* See header.
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
void diffie_hellman_init()
|
||||
{
|
||||
@@ -500,16 +500,16 @@ void diffie_hellman_init()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
diffie_hellman_params_t *diffie_hellman_get_params(diffie_hellman_group_t group)
|
||||
diffie_hellman_params_t *diffie_hellman_get_params(key_exchange_method_t ke)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < countof(dh_params); i++)
|
||||
{
|
||||
if (dh_params[i].group == group)
|
||||
if (dh_params[i].group == ke)
|
||||
{
|
||||
return &dh_params[i].public;
|
||||
}
|
||||
@@ -517,12 +517,12 @@ diffie_hellman_params_t *diffie_hellman_get_params(diffie_hellman_group_t group)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
bool diffie_hellman_group_is_ec(diffie_hellman_group_t group)
|
||||
bool key_exchange_is_ecdh(key_exchange_method_t ke)
|
||||
{
|
||||
switch (group)
|
||||
switch (ke)
|
||||
{
|
||||
case ECP_256_BIT:
|
||||
case ECP_384_BIT:
|
||||
@@ -541,15 +541,15 @@ bool diffie_hellman_group_is_ec(diffie_hellman_group_t group)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
bool diffie_hellman_verify_value(diffie_hellman_group_t group, chunk_t value)
|
||||
bool key_exchange_verify_pubkey(key_exchange_method_t ke, chunk_t value)
|
||||
{
|
||||
diffie_hellman_params_t *params;
|
||||
bool valid = FALSE;
|
||||
|
||||
switch (group)
|
||||
switch (ke)
|
||||
{
|
||||
case MODP_768_BIT:
|
||||
case MODP_1024_BIT:
|
||||
@@ -562,7 +562,7 @@ bool diffie_hellman_verify_value(diffie_hellman_group_t group, chunk_t value)
|
||||
case MODP_1024_160:
|
||||
case MODP_2048_224:
|
||||
case MODP_2048_256:
|
||||
params = diffie_hellman_get_params(group);
|
||||
params = diffie_hellman_get_params(ke);
|
||||
if (params)
|
||||
{
|
||||
valid = value.len == params->prime.len;
|
||||
@@ -607,15 +607,15 @@ bool diffie_hellman_verify_value(diffie_hellman_group_t group, chunk_t value)
|
||||
case MODP_CUSTOM:
|
||||
valid = TRUE;
|
||||
break;
|
||||
case MODP_NONE:
|
||||
case KE_NONE:
|
||||
/* fail */
|
||||
break;
|
||||
/* compile-warn unhandled groups, fail verification */
|
||||
/* compile-warn unhandled methods, fail verification */
|
||||
}
|
||||
if (!valid)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid DH public value size (%zu bytes) for %N",
|
||||
value.len, diffie_hellman_group_names, group);
|
||||
value.len, key_exchange_method_names, ke);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
+53
-54
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Tobias Brunner
|
||||
* Copyright (C) 2010-2019 Tobias Brunner
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@@ -17,21 +17,21 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup diffie_hellman diffie_hellman
|
||||
* @defgroup key_exchange key_exchange
|
||||
* @{ @ingroup crypto
|
||||
*/
|
||||
|
||||
#ifndef DIFFIE_HELLMAN_H_
|
||||
#define DIFFIE_HELLMAN_H_
|
||||
#ifndef KEY_EXCHANGE_H_
|
||||
#define KEY_EXCHANGE_H_
|
||||
|
||||
typedef enum diffie_hellman_group_t diffie_hellman_group_t;
|
||||
typedef struct diffie_hellman_t diffie_hellman_t;
|
||||
typedef enum key_exchange_method_t key_exchange_method_t;
|
||||
typedef struct key_exchange_t key_exchange_t;
|
||||
typedef struct diffie_hellman_params_t diffie_hellman_params_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Diffie-Hellman group.
|
||||
* Key exchange method.
|
||||
*
|
||||
* The modulus (or group) to use for a Diffie-Hellman calculation.
|
||||
* See IKEv2 RFC 3.3.2 and RFC 3526.
|
||||
@@ -40,8 +40,8 @@ typedef struct diffie_hellman_params_t diffie_hellman_params_t;
|
||||
* ECC Brainpool groups are defined in RFC 6954.
|
||||
* Curve25519 and Curve448 groups are defined in RFC 8031.
|
||||
*/
|
||||
enum diffie_hellman_group_t {
|
||||
MODP_NONE = 0,
|
||||
enum key_exchange_method_t {
|
||||
KE_NONE = 0,
|
||||
MODP_768_BIT = 1,
|
||||
MODP_1024_BIT = 2,
|
||||
MODP_1536_BIT = 5,
|
||||
@@ -79,80 +79,79 @@ enum diffie_hellman_group_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for diffie_hellman_group_t.
|
||||
* enum name for key_exchange_method_t.
|
||||
*/
|
||||
extern enum_name_t *diffie_hellman_group_names;
|
||||
extern enum_name_t *key_exchange_method_names;
|
||||
|
||||
/**
|
||||
* enum names for diffie_hellman_group_t (matching proposal keywords).
|
||||
* enum names for key_exchange_method_t (matching proposal keywords).
|
||||
*/
|
||||
extern enum_name_t *diffie_hellman_group_names_short;
|
||||
extern enum_name_t *key_exchange_method_names_short;
|
||||
|
||||
/**
|
||||
* Implementation of the Diffie-Hellman algorithm, as in RFC2631.
|
||||
* Implementation of a key exchange algorithms (e.g. Diffie-Hellman).
|
||||
*/
|
||||
struct diffie_hellman_t {
|
||||
struct key_exchange_t {
|
||||
|
||||
/**
|
||||
* Returns the shared secret of this diffie hellman exchange.
|
||||
* Returns the shared secret of this key exchange method.
|
||||
*
|
||||
* Space for returned secret is allocated and must be freed by the caller.
|
||||
*
|
||||
* @param secret shared secret will be written into this chunk
|
||||
* @param secret shared secret (allocated)
|
||||
* @return TRUE if shared secret computed successfully
|
||||
*/
|
||||
bool (*get_shared_secret)(diffie_hellman_t *this, chunk_t *secret)
|
||||
bool (*get_shared_secret)(key_exchange_t *this, chunk_t *secret)
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/**
|
||||
* Sets the public value of partner.
|
||||
* Sets the public key from the peer.
|
||||
*
|
||||
* Chunk gets cloned and can be destroyed afterwards.
|
||||
* @note This operation should be relatively quick. Costly public key
|
||||
* validation operations or key derivation should be implemented in
|
||||
* get_shared_secret().
|
||||
*
|
||||
* @param value public value of partner
|
||||
* @return TRUE if other public value verified and set
|
||||
* @param value public key of peer
|
||||
* @return TRUE if other public key verified and set
|
||||
*/
|
||||
bool (*set_other_public_value)(diffie_hellman_t *this, chunk_t value)
|
||||
bool (*set_public_key)(key_exchange_t *this, chunk_t value)
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/**
|
||||
* Gets the own public value to transmit.
|
||||
* Gets the own public key to transmit.
|
||||
*
|
||||
* Space for returned chunk is allocated and must be freed by the caller.
|
||||
*
|
||||
* @param value public value of caller is stored at this location
|
||||
* @return TRUE if public value retrieved
|
||||
* @param value public key (allocated)
|
||||
* @return TRUE if public key retrieved
|
||||
*/
|
||||
bool (*get_my_public_value) (diffie_hellman_t *this, chunk_t *value)
|
||||
bool (*get_public_key)(key_exchange_t *this, chunk_t *value)
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/**
|
||||
* Set an explicit own private value to use.
|
||||
* Set an explicit own private key to use.
|
||||
*
|
||||
* Calling this method is usually not required, as the DH backend generates
|
||||
* an appropriate private value itself. It is optional to implement, and
|
||||
* used mostly for testing purposes.
|
||||
* used mostly for testing purposes. The private key may be the actual key
|
||||
* or a seed for a DRBG.
|
||||
*
|
||||
* @param value private value to set
|
||||
* @param value private key value to set
|
||||
*/
|
||||
bool (*set_private_value)(diffie_hellman_t *this, chunk_t value)
|
||||
bool (*set_private_key)(key_exchange_t *this, chunk_t value)
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/**
|
||||
* Get the DH group used.
|
||||
* Get the key exchange method used.
|
||||
*
|
||||
* @return DH group set in construction
|
||||
* @return key exchange method set in construction
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this);
|
||||
key_exchange_method_t (*get_method)(key_exchange_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a diffie_hellman_t object.
|
||||
* Destroys a key_exchange_t object.
|
||||
*/
|
||||
void (*destroy) (diffie_hellman_t *this);
|
||||
void (*destroy)(key_exchange_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters for a specific diffie hellman group.
|
||||
* Parameters for a specific Diffie-Hellman group.
|
||||
*/
|
||||
struct diffie_hellman_params_t {
|
||||
|
||||
@@ -183,31 +182,31 @@ struct diffie_hellman_params_t {
|
||||
void diffie_hellman_init();
|
||||
|
||||
/**
|
||||
* Get the parameters associated with the specified diffie hellman group.
|
||||
* Get the parameters associated with the specified Diffie-Hellman group.
|
||||
*
|
||||
* Before calling this method, use diffie_hellman_init() to initialize the
|
||||
* DH group table. This is usually done by library_init().
|
||||
*
|
||||
* @param group DH group
|
||||
* @param ke key exchange method (DH group)
|
||||
* @return The parameters or NULL, if the group is not supported
|
||||
*/
|
||||
diffie_hellman_params_t *diffie_hellman_get_params(diffie_hellman_group_t group);
|
||||
diffie_hellman_params_t *diffie_hellman_get_params(key_exchange_method_t ke);
|
||||
|
||||
/**
|
||||
* Check if a given DH group is an ECDH group
|
||||
* Check if a given key exchange method is an ECDH group.
|
||||
*
|
||||
* @param group group to check
|
||||
* @return TRUE if group is an ECP group
|
||||
* @param ke key exchange method to check
|
||||
* @return TRUE if key exchange method is an ECP group
|
||||
*/
|
||||
bool diffie_hellman_group_is_ec(diffie_hellman_group_t group);
|
||||
bool key_exchange_is_ecdh(key_exchange_method_t ke);
|
||||
|
||||
/**
|
||||
* Check if a diffie hellman public value is valid for given group.
|
||||
* Check if a public key is valid for given key exchange method.
|
||||
*
|
||||
* @param group group the value is used in
|
||||
* @param value public DH value to check
|
||||
* @return TRUE if value looks valid for group
|
||||
* @param ke key exchange method
|
||||
* @param value public key to check
|
||||
* @return TRUE if value looks valid
|
||||
*/
|
||||
bool diffie_hellman_verify_value(diffie_hellman_group_t group, chunk_t value);
|
||||
bool key_exchange_verify_pubkey(key_exchange_method_t ke, chunk_t value);
|
||||
|
||||
#endif /** DIFFIE_HELLMAN_H_ @}*/
|
||||
#endif /** KEY_EXCHANGE_H_ @}*/
|
||||
@@ -252,34 +252,37 @@ METHOD(proposal_t, get_algorithm, bool,
|
||||
return found;
|
||||
}
|
||||
|
||||
METHOD(proposal_t, has_dh_group, bool,
|
||||
private_proposal_t *this, diffie_hellman_group_t group)
|
||||
METHOD(proposal_t, has_transform, bool,
|
||||
private_proposal_t *this, transform_type_t type, uint16_t alg)
|
||||
{
|
||||
bool found = FALSE, any = FALSE;
|
||||
enumerator_t *enumerator;
|
||||
uint16_t current;
|
||||
|
||||
enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP);
|
||||
enumerator = create_enumerator(this, type);
|
||||
while (enumerator->enumerate(enumerator, ¤t, NULL))
|
||||
{
|
||||
any = TRUE;
|
||||
if (current == group)
|
||||
if (current)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
any = TRUE;
|
||||
if (alg && current == alg)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!any && group == MODP_NONE)
|
||||
if (!any && !alg)
|
||||
{
|
||||
found = TRUE;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
METHOD(proposal_t, promote_dh_group, bool,
|
||||
private_proposal_t *this, diffie_hellman_group_t group)
|
||||
METHOD(proposal_t, promote_transform, bool,
|
||||
private_proposal_t *this, transform_type_t type, uint16_t alg)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
entry_t *entry;
|
||||
@@ -288,8 +291,8 @@ METHOD(proposal_t, promote_dh_group, bool,
|
||||
enumerator = array_create_enumerator(this->transforms);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->type == DIFFIE_HELLMAN_GROUP &&
|
||||
entry->alg == group)
|
||||
if (entry->type == type &&
|
||||
entry->alg == alg)
|
||||
{
|
||||
array_remove_at(this->transforms, enumerator);
|
||||
found = TRUE;
|
||||
@@ -300,8 +303,8 @@ METHOD(proposal_t, promote_dh_group, bool,
|
||||
if (found)
|
||||
{
|
||||
entry_t entry = {
|
||||
.type = DIFFIE_HELLMAN_GROUP,
|
||||
.alg = group,
|
||||
.type = type,
|
||||
.alg = alg,
|
||||
};
|
||||
array_insert(this->transforms, ARRAY_HEAD, &entry);
|
||||
}
|
||||
@@ -319,7 +322,7 @@ static bool select_algo(private_proposal_t *this, proposal_t *other,
|
||||
uint16_t alg1, alg2, ks1, ks2;
|
||||
bool found = FALSE, optional = FALSE;
|
||||
|
||||
if (type == DIFFIE_HELLMAN_GROUP)
|
||||
if (type == KEY_EXCHANGE_METHOD)
|
||||
{
|
||||
optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH;
|
||||
}
|
||||
@@ -408,7 +411,7 @@ static bool select_algos(private_proposal_t *this, proposal_t *other,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH))
|
||||
if (type == KEY_EXCHANGE_METHOD && (flags & PROPOSAL_SKIP_KE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -601,7 +604,7 @@ METHOD(proposal_t, clone_, proposal_t*,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (entry->type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH))
|
||||
if (entry->type == KEY_EXCHANGE_METHOD && (flags & PROPOSAL_SKIP_KE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -692,17 +695,17 @@ static bool check_proposal(private_proposal_t *this)
|
||||
DBG1(DBG_CFG, "a PRF algorithm is mandatory in IKE proposals");
|
||||
return FALSE;
|
||||
}
|
||||
/* remove MODP_NONE from IKE proposal */
|
||||
/* remove KE_NONE from IKE proposal */
|
||||
e = array_create_enumerator(this->transforms);
|
||||
while (e->enumerate(e, &entry))
|
||||
{
|
||||
if (entry->type == DIFFIE_HELLMAN_GROUP && !entry->alg)
|
||||
if (entry->type == KEY_EXCHANGE_METHOD && !entry->alg)
|
||||
{
|
||||
array_remove_at(this->transforms, e);
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
if (!get_algorithm(this, DIFFIE_HELLMAN_GROUP, NULL, NULL))
|
||||
if (!get_algorithm(this, KEY_EXCHANGE_METHOD, NULL, NULL))
|
||||
{
|
||||
DBG1(DBG_CFG, "a DH group is mandatory in IKE proposals");
|
||||
return FALSE;
|
||||
@@ -943,8 +946,8 @@ proposal_t *proposal_create_v1(protocol_id_t protocol, uint8_t number,
|
||||
.add_algorithm = _add_algorithm,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.get_algorithm = _get_algorithm,
|
||||
.has_dh_group = _has_dh_group,
|
||||
.promote_dh_group = _promote_dh_group,
|
||||
.has_transform = _has_transform,
|
||||
.promote_transform = _promote_transform,
|
||||
.select = _select_proposal,
|
||||
.matches = _matches,
|
||||
.get_protocol = _get_protocol,
|
||||
@@ -983,7 +986,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
encryption_algorithm_t encryption;
|
||||
integrity_algorithm_t integrity;
|
||||
pseudo_random_function_t prf;
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
const char *plugin_name;
|
||||
|
||||
if (aead)
|
||||
@@ -1175,7 +1178,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &group, &plugin_name))
|
||||
{
|
||||
switch (group)
|
||||
@@ -1192,7 +1195,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
case NTRU_192_BIT:
|
||||
case NTRU_256_BIT:
|
||||
case NH_128_BIT:
|
||||
add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
|
||||
add_algorithm(this, KEY_EXCHANGE_METHOD, group, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1201,7 +1204,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* Round 2 adds other algorithms with at least 128 bit security strength */
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &group, &plugin_name))
|
||||
{
|
||||
switch (group)
|
||||
@@ -1210,7 +1213,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
case MODP_4096_BIT:
|
||||
case MODP_6144_BIT:
|
||||
case MODP_8192_BIT:
|
||||
add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
|
||||
add_algorithm(this, KEY_EXCHANGE_METHOD, group, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1219,7 +1222,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* Round 3 adds algorithms with less than 128 bit security strength */
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &group, &plugin_name))
|
||||
{
|
||||
switch (group)
|
||||
@@ -1244,7 +1247,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
|
||||
/* rarely used */
|
||||
break;
|
||||
case MODP_2048_BIT:
|
||||
add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
|
||||
add_algorithm(this, KEY_EXCHANGE_METHOD, group, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef struct proposal_t proposal_t;
|
||||
#include <crypto/transform.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
#include <crypto/signers/signer.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
/**
|
||||
* Protocol ID of a proposal.
|
||||
@@ -61,8 +61,8 @@ enum proposal_selection_flag_t {
|
||||
PROPOSAL_PREFER_SUPPLIED = (1<<0),
|
||||
/** Whether to skip and ignore algorithms from a private range. */
|
||||
PROPOSAL_SKIP_PRIVATE = (1<<1),
|
||||
/** Whether to skip and ignore diffie hellman groups. */
|
||||
PROPOSAL_SKIP_DH = (1<<2),
|
||||
/** Whether to skip and ignore key exchange methods. */
|
||||
PROPOSAL_SKIP_KE = (1<<2),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -110,21 +110,26 @@ struct proposal_t {
|
||||
uint16_t *alg, uint16_t *key_size);
|
||||
|
||||
/**
|
||||
* Check if the proposal has a specific DH group.
|
||||
* Check if the proposal has a specific transform.
|
||||
*
|
||||
* @param group group to check for
|
||||
* @param type kind of algorithm
|
||||
* @param alg algorithm to check for (if 0, TRUE is returned if
|
||||
* no transform of the given type is found)
|
||||
* @return TRUE if algorithm included
|
||||
*/
|
||||
bool (*has_dh_group)(proposal_t *this, diffie_hellman_group_t group);
|
||||
bool (*has_transform)(proposal_t *this, transform_type_t type,
|
||||
uint16_t alg);
|
||||
|
||||
/**
|
||||
* Move the given DH group to the front of the list if it was contained in
|
||||
* Move the given transform to the front of the list if it was contained in
|
||||
* the proposal.
|
||||
*
|
||||
* @param group group to promote
|
||||
* @param type kind of algorithm
|
||||
* @param alg algorithm to promote
|
||||
* @return TRUE if algorithm included
|
||||
*/
|
||||
bool (*promote_dh_group)(proposal_t *this, diffie_hellman_group_t group);
|
||||
bool (*promote_transform)(proposal_t *this, transform_type_t type,
|
||||
uint16_t alg);
|
||||
|
||||
/**
|
||||
* Compare two proposals and select a matching subset.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <crypto/transform.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
#include <crypto/signers/signer.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
%}
|
||||
struct proposal_token {
|
||||
@@ -149,36 +149,37 @@ prfmd5, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0
|
||||
prfaesxcbc, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0
|
||||
prfcamelliaxcbc, PSEUDO_RANDOM_FUNCTION, PRF_CAMELLIA128_XCBC, 0
|
||||
prfaescmac, PSEUDO_RANDOM_FUNCTION, PRF_AES128_CMAC, 0
|
||||
modpnone, DIFFIE_HELLMAN_GROUP, MODP_NONE, 0
|
||||
modpnull, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0
|
||||
modp768, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0
|
||||
modp1024, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0
|
||||
modp1536, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0
|
||||
modp2048, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0
|
||||
modp3072, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0
|
||||
modp4096, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0
|
||||
modp6144, DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0
|
||||
modp8192, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0
|
||||
ecp192, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0
|
||||
ecp224, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0
|
||||
ecp256, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0
|
||||
ecp384, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0
|
||||
ecp521, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0
|
||||
modp1024s160, DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0
|
||||
modp2048s224, DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0
|
||||
modp2048s256, DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0
|
||||
ecp224bp, DIFFIE_HELLMAN_GROUP, ECP_224_BP, 0
|
||||
ecp256bp, DIFFIE_HELLMAN_GROUP, ECP_256_BP, 0
|
||||
ecp384bp, DIFFIE_HELLMAN_GROUP, ECP_384_BP, 0
|
||||
ecp512bp, DIFFIE_HELLMAN_GROUP, ECP_512_BP, 0
|
||||
curve25519, DIFFIE_HELLMAN_GROUP, CURVE_25519, 0
|
||||
x25519, DIFFIE_HELLMAN_GROUP, CURVE_25519, 0
|
||||
curve448, DIFFIE_HELLMAN_GROUP, CURVE_448, 0
|
||||
x448, DIFFIE_HELLMAN_GROUP, CURVE_448, 0
|
||||
ntru112, DIFFIE_HELLMAN_GROUP, NTRU_112_BIT, 0
|
||||
ntru128, DIFFIE_HELLMAN_GROUP, NTRU_128_BIT, 0
|
||||
ntru192, DIFFIE_HELLMAN_GROUP, NTRU_192_BIT, 0
|
||||
ntru256, DIFFIE_HELLMAN_GROUP, NTRU_256_BIT, 0
|
||||
newhope128, DIFFIE_HELLMAN_GROUP, NH_128_BIT, 0
|
||||
none, KEY_EXCHANGE_METHOD, KE_NONE, 0
|
||||
modpnone, KEY_EXCHANGE_METHOD, KE_NONE, 0
|
||||
modpnull, KEY_EXCHANGE_METHOD, MODP_NULL, 0
|
||||
modp768, KEY_EXCHANGE_METHOD, MODP_768_BIT, 0
|
||||
modp1024, KEY_EXCHANGE_METHOD, MODP_1024_BIT, 0
|
||||
modp1536, KEY_EXCHANGE_METHOD, MODP_1536_BIT, 0
|
||||
modp2048, KEY_EXCHANGE_METHOD, MODP_2048_BIT, 0
|
||||
modp3072, KEY_EXCHANGE_METHOD, MODP_3072_BIT, 0
|
||||
modp4096, KEY_EXCHANGE_METHOD, MODP_4096_BIT, 0
|
||||
modp6144, KEY_EXCHANGE_METHOD, MODP_6144_BIT, 0
|
||||
modp8192, KEY_EXCHANGE_METHOD, MODP_8192_BIT, 0
|
||||
ecp192, KEY_EXCHANGE_METHOD, ECP_192_BIT, 0
|
||||
ecp224, KEY_EXCHANGE_METHOD, ECP_224_BIT, 0
|
||||
ecp256, KEY_EXCHANGE_METHOD, ECP_256_BIT, 0
|
||||
ecp384, KEY_EXCHANGE_METHOD, ECP_384_BIT, 0
|
||||
ecp521, KEY_EXCHANGE_METHOD, ECP_521_BIT, 0
|
||||
modp1024s160, KEY_EXCHANGE_METHOD, MODP_1024_160, 0
|
||||
modp2048s224, KEY_EXCHANGE_METHOD, MODP_2048_224, 0
|
||||
modp2048s256, KEY_EXCHANGE_METHOD, MODP_2048_256, 0
|
||||
ecp224bp, KEY_EXCHANGE_METHOD, ECP_224_BP, 0
|
||||
ecp256bp, KEY_EXCHANGE_METHOD, ECP_256_BP, 0
|
||||
ecp384bp, KEY_EXCHANGE_METHOD, ECP_384_BP, 0
|
||||
ecp512bp, KEY_EXCHANGE_METHOD, ECP_512_BP, 0
|
||||
curve25519, KEY_EXCHANGE_METHOD, CURVE_25519, 0
|
||||
x25519, KEY_EXCHANGE_METHOD, CURVE_25519, 0
|
||||
curve448, KEY_EXCHANGE_METHOD, CURVE_448, 0
|
||||
x448, KEY_EXCHANGE_METHOD, CURVE_448, 0
|
||||
ntru112, KEY_EXCHANGE_METHOD, NTRU_112_BIT, 0
|
||||
ntru128, KEY_EXCHANGE_METHOD, NTRU_128_BIT, 0
|
||||
ntru192, KEY_EXCHANGE_METHOD, NTRU_192_BIT, 0
|
||||
ntru256, KEY_EXCHANGE_METHOD, NTRU_256_BIT, 0
|
||||
newhope128, KEY_EXCHANGE_METHOD, NH_128_BIT, 0
|
||||
noesn, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0
|
||||
esn, EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0
|
||||
|
||||
@@ -23,7 +23,7 @@ ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS
|
||||
"ENCRYPTION_ALGORITHM",
|
||||
"PSEUDO_RANDOM_FUNCTION",
|
||||
"INTEGRITY_ALGORITHM",
|
||||
"DIFFIE_HELLMAN_GROUP",
|
||||
"KEY_EXCHANGE_METHOD",
|
||||
"EXTENDED_SEQUENCE_NUMBERS");
|
||||
ENUM_NEXT(transform_type_names, HASH_ALGORITHM, KEY_DERIVATION_FUNCTION,
|
||||
EXTENDED_SEQUENCE_NUMBERS,
|
||||
@@ -59,8 +59,8 @@ enum_name_t* transform_get_enum_names(transform_type_t type)
|
||||
return pseudo_random_function_names;
|
||||
case INTEGRITY_ALGORITHM:
|
||||
return integrity_algorithm_names;
|
||||
case DIFFIE_HELLMAN_GROUP:
|
||||
return diffie_hellman_group_names;
|
||||
case KEY_EXCHANGE_METHOD:
|
||||
return key_exchange_method_names;
|
||||
case EXTENDED_SEQUENCE_NUMBERS:
|
||||
return extended_sequence_numbers_names;
|
||||
case EXTENDED_OUTPUT_FUNCTION:
|
||||
|
||||
@@ -33,7 +33,7 @@ enum transform_type_t {
|
||||
ENCRYPTION_ALGORITHM = 1,
|
||||
PSEUDO_RANDOM_FUNCTION = 2,
|
||||
INTEGRITY_ALGORITHM = 3,
|
||||
DIFFIE_HELLMAN_GROUP = 4,
|
||||
KEY_EXCHANGE_METHOD = 4,
|
||||
EXTENDED_SEQUENCE_NUMBERS = 5,
|
||||
HASH_ALGORITHM = 256,
|
||||
RANDOM_NUMBER_GENERATOR = 257,
|
||||
|
||||
@@ -49,12 +49,17 @@ struct private_botan_diffie_hellman_t {
|
||||
/**
|
||||
* Diffie Hellman group number
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
|
||||
/**
|
||||
* Private key
|
||||
*/
|
||||
botan_privkey_t dh_key;
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* Public key value provided by peer
|
||||
*/
|
||||
chunk_t pubkey;
|
||||
|
||||
/**
|
||||
* Diffie hellman shared secret
|
||||
@@ -84,8 +89,8 @@ bool load_private_key(private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_destroy(this->dh_key) ||
|
||||
botan_privkey_load_dh(&this->dh_key, this->p, this->g, xa))
|
||||
if (botan_privkey_destroy(this->key) ||
|
||||
botan_privkey_load_dh(&this->key, this->p, this->g, xa))
|
||||
{
|
||||
botan_mp_destroy(xa);
|
||||
return FALSE;
|
||||
@@ -94,33 +99,33 @@ bool load_private_key(private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(this->group, value))
|
||||
if (!key_exchange_verify_pubkey(this->group, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
return botan_dh_key_derivation(this->dh_key, value, &this->shared_secret);
|
||||
chunk_clear(&this->pubkey);
|
||||
this->pubkey = chunk_clone(value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_empty;
|
||||
|
||||
/* get key size of public key first */
|
||||
if (botan_pk_op_key_agreement_export_public(this->dh_key, NULL, &value->len)
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, NULL, &value->len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*value = chunk_alloc(value->len);
|
||||
if (botan_pk_op_key_agreement_export_public(this->dh_key, value->ptr,
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, value->ptr,
|
||||
&value->len))
|
||||
{
|
||||
chunk_clear(value);
|
||||
@@ -129,17 +134,18 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
METHOD(key_exchange_t, set_private_key, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
chunk_clear(&this->shared_secret);
|
||||
return load_private_key(this, value);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
if (!this->shared_secret.len &&
|
||||
!botan_dh_key_derivation(this->key, this->pubkey, &this->shared_secret))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -147,26 +153,27 @@ METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_botan_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_botan_diffie_hellman_t *this)
|
||||
{
|
||||
botan_mp_destroy(this->p);
|
||||
botan_mp_destroy(this->g);
|
||||
botan_privkey_destroy(this->dh_key);
|
||||
botan_privkey_destroy(this->key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
chunk_clear(&this->pubkey);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic internal constructor
|
||||
*/
|
||||
static botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
|
||||
static botan_diffie_hellman_t *create_generic(key_exchange_method_t group,
|
||||
chunk_t g, chunk_t p, size_t exp_len)
|
||||
{
|
||||
private_botan_diffie_hellman_t *this;
|
||||
@@ -175,12 +182,12 @@ static botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.set_private_key = _set_private_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
@@ -222,7 +229,7 @@ static botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
|
||||
* Described in header.
|
||||
*/
|
||||
botan_diffie_hellman_t *botan_diffie_hellman_create(
|
||||
diffie_hellman_group_t group, ...)
|
||||
key_exchange_method_t group, ...)
|
||||
{
|
||||
diffie_hellman_params_t *params;
|
||||
chunk_t g, p;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
typedef struct botan_diffie_hellman_t botan_diffie_hellman_t;
|
||||
|
||||
#include <crypto/diffie_hellman.h>
|
||||
#include <crypto/key_exchange.h>
|
||||
|
||||
/**
|
||||
* Implementation of the Diffie-Hellman algorithm using Botan.
|
||||
@@ -40,20 +40,20 @@ typedef struct botan_diffie_hellman_t botan_diffie_hellman_t;
|
||||
struct botan_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new botan_diffie_hellman_t object.
|
||||
*
|
||||
* @param group Diffie Hellman group number to use
|
||||
* @param group Diffie-Hellman group number to use
|
||||
* @param ... expects generator and prime as chunk_t if MODP_CUSTOM
|
||||
* @return botan_diffie_hellman_t object,
|
||||
* NULL if not supported
|
||||
*/
|
||||
botan_diffie_hellman_t *botan_diffie_hellman_create(
|
||||
diffie_hellman_group_t group, ...);
|
||||
key_exchange_method_t group, ...);
|
||||
|
||||
#endif /** BOTAN_DIFFIE_HELLMAN_H_ @}*/
|
||||
|
||||
@@ -48,7 +48,7 @@ struct private_botan_ec_diffie_hellman_t {
|
||||
/**
|
||||
* Diffie Hellman group
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
|
||||
/**
|
||||
* EC curve name
|
||||
@@ -60,29 +60,32 @@ struct private_botan_ec_diffie_hellman_t {
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* Public key value provided by peer
|
||||
*/
|
||||
chunk_t pubkey;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
*/
|
||||
chunk_t shared_secret;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(this->group, value))
|
||||
if (!key_exchange_verify_pubkey(this->group, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
chunk_clear(&this->pubkey);
|
||||
/* prepend 0x04 to indicate uncompressed point format */
|
||||
value = chunk_cata("cc", chunk_from_chars(0x04), value);
|
||||
|
||||
return botan_dh_key_derivation(this->key, value, &this->shared_secret);
|
||||
this->pubkey = chunk_cat("cc", chunk_from_chars(0x04), value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
chunk_t pkey = chunk_empty;
|
||||
@@ -104,7 +107,7 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
METHOD(key_exchange_t, set_private_key, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
botan_mp_t scalar;
|
||||
@@ -132,10 +135,11 @@ METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
if (!this->shared_secret.len &&
|
||||
!botan_dh_key_derivation(this->key, this->pubkey, &this->shared_secret))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -143,17 +147,18 @@ METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_botan_ec_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_botan_ec_diffie_hellman_t *this)
|
||||
{
|
||||
botan_privkey_destroy(this->key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
chunk_clear(&this->pubkey);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -161,19 +166,19 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
|
||||
diffie_hellman_group_t group)
|
||||
key_exchange_method_t group)
|
||||
{
|
||||
private_botan_ec_diffie_hellman_t *this;
|
||||
botan_rng_t rng;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.set_private_key = _set_private_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -39,18 +39,18 @@ typedef struct botan_ec_diffie_hellman_t botan_ec_diffie_hellman_t;
|
||||
struct botan_ec_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new botan_ec_diffie_hellman_t object.
|
||||
*
|
||||
* @param group EC Diffie Hellman group number to use
|
||||
* @param group EC Diffie-Hellman group number to use
|
||||
* @return botan_ec_diffie_hellman_t object, NULL if not supported
|
||||
*/
|
||||
botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
|
||||
diffie_hellman_group_t group);
|
||||
key_exchange_method_t group);
|
||||
|
||||
#endif /** BOTAN_EC_DIFFIE_HELLMAN_H_ @}*/
|
||||
|
||||
@@ -74,33 +74,33 @@ METHOD(plugin_t, get_features, int,
|
||||
|
||||
#ifdef BOTAN_HAS_DIFFIE_HELLMAN
|
||||
/* MODP DH groups */
|
||||
PLUGIN_REGISTER(DH, botan_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(DH, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_4096_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_6144_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_8192_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_224),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_256),
|
||||
PLUGIN_PROVIDE(DH, MODP_1536_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_160),
|
||||
PLUGIN_PROVIDE(DH, MODP_768_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_CUSTOM),
|
||||
PLUGIN_REGISTER(KE, botan_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(KE, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_4096_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_6144_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_8192_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_224),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_256),
|
||||
PLUGIN_PROVIDE(KE, MODP_1536_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_1024_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_1024_160),
|
||||
PLUGIN_PROVIDE(KE, MODP_768_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_CUSTOM),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_ECDH
|
||||
/* EC DH groups */
|
||||
PLUGIN_REGISTER(DH, botan_ec_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(DH, ECP_256_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_384_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_521_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_256_BP),
|
||||
PLUGIN_PROVIDE(DH, ECP_384_BP),
|
||||
PLUGIN_PROVIDE(DH, ECP_512_BP),
|
||||
PLUGIN_REGISTER(KE, botan_ec_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(KE, ECP_256_BIT),
|
||||
PLUGIN_PROVIDE(KE, ECP_384_BIT),
|
||||
PLUGIN_PROVIDE(KE, ECP_521_BIT),
|
||||
PLUGIN_PROVIDE(KE, ECP_256_BP),
|
||||
PLUGIN_PROVIDE(KE, ECP_384_BP),
|
||||
PLUGIN_PROVIDE(KE, ECP_512_BP),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_X25519
|
||||
PLUGIN_REGISTER(DH, botan_x25519_create),
|
||||
PLUGIN_PROVIDE(DH, CURVE_25519),
|
||||
PLUGIN_REGISTER(KE, botan_x25519_create),
|
||||
PLUGIN_PROVIDE(KE, CURVE_25519),
|
||||
#endif
|
||||
|
||||
/* crypters */
|
||||
|
||||
@@ -42,33 +42,38 @@ struct private_diffie_hellman_t {
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
diffie_hellman_t public;
|
||||
key_exchange_t public;
|
||||
|
||||
/**
|
||||
* Private key
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* Public key value provided by peer
|
||||
*/
|
||||
chunk_t pubkey;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
*/
|
||||
chunk_t shared_secret;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(CURVE_25519, value))
|
||||
if (!key_exchange_verify_pubkey(CURVE_25519, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
return botan_dh_key_derivation(this->key, value, &this->shared_secret);
|
||||
chunk_clear(&this->pubkey);
|
||||
this->pubkey = chunk_clone(value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
value->len = 0;
|
||||
@@ -88,7 +93,7 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
METHOD(key_exchange_t, set_private_key, bool,
|
||||
private_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (value.len != 32)
|
||||
@@ -110,10 +115,11 @@ METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
if (!this->shared_secret.len &&
|
||||
!botan_dh_key_derivation(this->key, this->pubkey, &this->shared_secret))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -121,24 +127,25 @@ METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
return CURVE_25519;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
botan_privkey_destroy(this->key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
chunk_clear(&this->pubkey);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
diffie_hellman_t *botan_x25519_create(diffie_hellman_group_t group)
|
||||
key_exchange_t *botan_x25519_create(key_exchange_method_t ke)
|
||||
{
|
||||
private_diffie_hellman_t *this;
|
||||
botan_rng_t rng;
|
||||
@@ -146,10 +153,10 @@ diffie_hellman_t *botan_x25519_create(diffie_hellman_group_t group)
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.set_private_key = _set_private_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
/**
|
||||
* Creates a new X25519 implementation using Botan.
|
||||
*
|
||||
* @param group DH group, must be CURVE_25519
|
||||
* @param ke key exchange method, must be CURVE_25519
|
||||
* @return object, NULL if not supported
|
||||
*/
|
||||
diffie_hellman_t *botan_x25519_create(diffie_hellman_group_t group);
|
||||
key_exchange_t *botan_x25519_create(key_exchange_method_t ke);
|
||||
|
||||
#endif /** BOTAN_X25519_H_ @}*/
|
||||
|
||||
@@ -42,6 +42,11 @@ struct private_curve25519_dh_t {
|
||||
*/
|
||||
bool computed;
|
||||
|
||||
/**
|
||||
* Public key provided by peer
|
||||
*/
|
||||
u_char pubkey[CURVE25519_KEY_SIZE];
|
||||
|
||||
/**
|
||||
* Curve25519 backend
|
||||
*/
|
||||
@@ -73,21 +78,18 @@ static bool generate_key(private_curve25519_dh_t *this)
|
||||
return this->drv->set_key(this->drv, key);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_curve25519_dh_t *this, chunk_t value)
|
||||
{
|
||||
if (value.len == CURVE25519_KEY_SIZE)
|
||||
{
|
||||
if (this->drv->curve25519(this->drv, value.ptr, this->shared))
|
||||
{
|
||||
this->computed = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
memcpy(this->pubkey, value.ptr, value.len);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_curve25519_dh_t *this, chunk_t *value)
|
||||
{
|
||||
u_char basepoint[CURVE25519_KEY_SIZE] = { 9 };
|
||||
@@ -101,7 +103,7 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
METHOD(key_exchange_t, set_private_key, bool,
|
||||
private_curve25519_dh_t *this, chunk_t value)
|
||||
{
|
||||
if (value.len != CURVE25519_KEY_SIZE)
|
||||
@@ -111,24 +113,26 @@ METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
return this->drv->set_key(this->drv, value.ptr);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_curve25519_dh_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->computed)
|
||||
if (!this->computed &&
|
||||
!this->drv->curve25519(this->drv, this->pubkey, this->shared))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->computed = TRUE;
|
||||
*secret = chunk_clone(chunk_from_thing(this->shared));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_curve25519_dh_t *this)
|
||||
{
|
||||
return CURVE_25519;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_curve25519_dh_t *this)
|
||||
{
|
||||
this->drv->destroy(this->drv);
|
||||
@@ -138,7 +142,7 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
curve25519_dh_t *curve25519_dh_create(diffie_hellman_group_t group)
|
||||
curve25519_dh_t *curve25519_dh_create(key_exchange_method_t group)
|
||||
{
|
||||
private_curve25519_dh_t *this;
|
||||
|
||||
@@ -149,12 +153,12 @@ curve25519_dh_t *curve25519_dh_create(diffie_hellman_group_t group)
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.set_private_key = _set_private_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -32,9 +32,9 @@ typedef struct curve25519_dh_t curve25519_dh_t;
|
||||
struct curve25519_dh_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,6 +43,6 @@ struct curve25519_dh_t {
|
||||
* @param group DH group, CURVE_25519
|
||||
* @return curve25519_dh_t object, NULL on error
|
||||
*/
|
||||
curve25519_dh_t *curve25519_dh_create(diffie_hellman_group_t group);
|
||||
curve25519_dh_t *curve25519_dh_create(key_exchange_method_t group);
|
||||
|
||||
#endif /** CURVE25519_DH_H_ @}*/
|
||||
|
||||
@@ -47,8 +47,8 @@ METHOD(plugin_t, get_features, int,
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
/* X25519 DH group */
|
||||
PLUGIN_REGISTER(DH, curve25519_dh_create),
|
||||
PLUGIN_PROVIDE(DH, CURVE_25519),
|
||||
PLUGIN_REGISTER(KE, curve25519_dh_create),
|
||||
PLUGIN_PROVIDE(KE, CURVE_25519),
|
||||
PLUGIN_DEPENDS(RNG, RNG_STRONG),
|
||||
/* Ed25519 private/public keys */
|
||||
PLUGIN_REGISTER(PRIVKEY, curve25519_private_key_load, TRUE),
|
||||
|
||||
@@ -36,7 +36,7 @@ struct private_gcrypt_dh_t {
|
||||
/**
|
||||
* Diffie Hellman group number
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
key_exchange_method_t group;
|
||||
|
||||
/*
|
||||
* Generator value
|
||||
@@ -74,13 +74,13 @@ struct private_gcrypt_dh_t {
|
||||
size_t p_len;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
METHOD(key_exchange_t, set_public_key, bool,
|
||||
private_gcrypt_dh_t *this, chunk_t value)
|
||||
{
|
||||
gcry_mpi_t p_min_1;
|
||||
gcry_error_t err;
|
||||
|
||||
if (!diffie_hellman_verify_value(this->group, value))
|
||||
if (!key_exchange_verify_pubkey(this->group, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -100,25 +100,22 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
p_min_1 = gcry_mpi_new(this->p_len * 8);
|
||||
gcry_mpi_sub_ui(p_min_1, this->p, 1);
|
||||
|
||||
/* check public value:
|
||||
* 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1
|
||||
* 2. a public value larger or equal the modulus is invalid */
|
||||
if (gcry_mpi_cmp_ui(this->yb, 1) > 0 &&
|
||||
gcry_mpi_cmp(this->yb, p_min_1) < 0)
|
||||
/* check that the public value y satisfies 1 < y < p-1.
|
||||
* according to RFC 6989, section 2.1, this is enough for the common safe-
|
||||
* prime DH groups (i.e. with q=(p-1)/2 being prime) and also for those
|
||||
* with small subgroups (22, 23, 24) if private keys are not reused, which
|
||||
* we never do and explicitly prevent by not resetting this->zz when a
|
||||
* different public key is set. */
|
||||
if (gcry_mpi_cmp_ui(this->yb, 1) <= 0 ||
|
||||
gcry_mpi_cmp(this->yb, p_min_1) >= 0)
|
||||
{
|
||||
if (!this->zz)
|
||||
{
|
||||
this->zz = gcry_mpi_new(this->p_len * 8);
|
||||
}
|
||||
gcry_mpi_powm(this->zz, this->yb, this->xa, this->p);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_LIB, "public DH value verification failed:"
|
||||
" y < 2 || y > p - 1 ");
|
||||
DBG1(DBG_LIB, "public DH value verification failed: "
|
||||
"y <= 1 || y >= p - 1");
|
||||
gcry_mpi_release(p_min_1);
|
||||
return FALSE;
|
||||
}
|
||||
gcry_mpi_release(p_min_1);
|
||||
return this->zz != NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,14 +136,14 @@ static chunk_t export_mpi(gcry_mpi_t value, size_t len)
|
||||
return chunk;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
METHOD(key_exchange_t, get_public_key, bool,
|
||||
private_gcrypt_dh_t *this, chunk_t *value)
|
||||
{
|
||||
*value = export_mpi(this->ya, this->p_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
METHOD(key_exchange_t, set_private_key, bool,
|
||||
private_gcrypt_dh_t *this, chunk_t value)
|
||||
{
|
||||
gcry_error_t err;
|
||||
@@ -164,24 +161,25 @@ METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
return !err;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
METHOD(key_exchange_t, get_shared_secret, bool,
|
||||
private_gcrypt_dh_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->zz)
|
||||
{
|
||||
return FALSE;
|
||||
this->zz = gcry_mpi_new(this->p_len * 8);
|
||||
gcry_mpi_powm(this->zz, this->yb, this->xa, this->p);
|
||||
}
|
||||
*secret = export_mpi(this->zz, this->p_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
METHOD(key_exchange_t, get_method, key_exchange_method_t,
|
||||
private_gcrypt_dh_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
METHOD(key_exchange_t, destroy, void,
|
||||
private_gcrypt_dh_t *this)
|
||||
{
|
||||
gcry_mpi_release(this->p);
|
||||
@@ -196,7 +194,7 @@ METHOD(diffie_hellman_t, destroy, void,
|
||||
/*
|
||||
* Generic internal constructor
|
||||
*/
|
||||
static gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
|
||||
static gcrypt_dh_t *create_generic(key_exchange_method_t group, size_t exp_len,
|
||||
chunk_t g, chunk_t p)
|
||||
{
|
||||
private_gcrypt_dh_t *this;
|
||||
@@ -206,12 +204,12 @@ static gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.ke = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.set_public_key = _set_public_key,
|
||||
.get_public_key = _get_public_key,
|
||||
.set_private_key = _set_private_key,
|
||||
.get_method = _get_method,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
@@ -273,7 +271,7 @@ static gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group)
|
||||
gcrypt_dh_t *gcrypt_dh_create(key_exchange_method_t group)
|
||||
{
|
||||
|
||||
diffie_hellman_params_t *params;
|
||||
@@ -290,7 +288,7 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...)
|
||||
gcrypt_dh_t *gcrypt_dh_create_custom(key_exchange_method_t group, ...)
|
||||
{
|
||||
if (group == MODP_CUSTOM)
|
||||
{
|
||||
|
||||
@@ -32,9 +32,9 @@ typedef struct gcrypt_dh_t gcrypt_dh_t;
|
||||
struct gcrypt_dh_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
* Implements key_exchange_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
key_exchange_t ke;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,7 @@ struct gcrypt_dh_t {
|
||||
* @param group Diffie Hellman group number to use
|
||||
* @return gcrypt_dh_t object, NULL if not supported
|
||||
*/
|
||||
gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group);
|
||||
gcrypt_dh_t *gcrypt_dh_create(key_exchange_method_t group);
|
||||
|
||||
/**
|
||||
* Creates a new gcrypt_dh_t object for MODP_CUSTOM.
|
||||
@@ -52,7 +52,7 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group);
|
||||
* @param ... expects generator and prime as chunk_t
|
||||
* @return gcrypt_dh_t object, NULL if not supported
|
||||
*/
|
||||
gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...);
|
||||
gcrypt_dh_t *gcrypt_dh_create_custom(key_exchange_method_t group, ...);
|
||||
|
||||
#endif /** GCRYPT_DH_H_ @}*/
|
||||
|
||||
|
||||
@@ -106,20 +106,20 @@ METHOD(plugin_t, get_features, int,
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA384),
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA512),
|
||||
/* MODP DH groups */
|
||||
PLUGIN_REGISTER(DH, gcrypt_dh_create),
|
||||
PLUGIN_PROVIDE(DH, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_4096_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_6144_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_8192_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_224),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_256),
|
||||
PLUGIN_PROVIDE(DH, MODP_1536_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_160),
|
||||
PLUGIN_PROVIDE(DH, MODP_768_BIT),
|
||||
PLUGIN_REGISTER(DH, gcrypt_dh_create_custom),
|
||||
PLUGIN_PROVIDE(DH, MODP_CUSTOM),
|
||||
PLUGIN_REGISTER(KE, gcrypt_dh_create),
|
||||
PLUGIN_PROVIDE(KE, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_4096_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_6144_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_8192_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_224),
|
||||
PLUGIN_PROVIDE(KE, MODP_2048_256),
|
||||
PLUGIN_PROVIDE(KE, MODP_1536_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_1024_BIT),
|
||||
PLUGIN_PROVIDE(KE, MODP_1024_160),
|
||||
PLUGIN_PROVIDE(KE, MODP_768_BIT),
|
||||
PLUGIN_REGISTER(KE, gcrypt_dh_create_custom),
|
||||
PLUGIN_PROVIDE(KE, MODP_CUSTOM),
|
||||
/* RSA private/public key loading */
|
||||
PLUGIN_REGISTER(PUBKEY, gcrypt_rsa_public_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user