/*
- * Copyright (C) 2015-2019 Tobias Brunner
+ * Copyright (C) 2015-2020 Tobias Brunner
* Copyright (C) 2012 Reto Buerki
* Copyright (C) 2012 Adrian-Ken Rueegsegger
*
}
METHOD(keymat_v2_t, derive_ike_keys, bool,
- private_tkm_keymat_t *this, proposal_t *proposal, key_exchange_t *ke,
+ private_tkm_keymat_t *this, proposal_t *proposal, array_t *kes,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
pseudo_random_function_t rekey_function, chunk_t rekey_skd)
{
uint64_t nc_id, spi_loc, spi_rem;
chunk_t *nonce;
tkm_diffie_hellman_t *tkm_dh;
+ key_exchange_t *ke;
dh_id_type dh_id;
nonce_type nonce_rem;
result_type res;
icv_len_type icv_len;
iv_len_type iv_len;
+ if (array_count(kes) != 1)
+ {
+ DBG1(DBG_IKE, "the TKM currently only supports a single key exchange");
+ return FALSE;
+ }
+
/* Acquire nonce context id */
nonce = this->initiator ? &nonce_i : &nonce_r;
nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce);
}
/* Get DH context id */
+ array_get(kes, ARRAY_HEAD, &ke);
tkm_dh = (tkm_diffie_hellman_t *)ke;
dh_id = tkm_dh->get_id(tkm_dh);
}
METHOD(keymat_v2_t, derive_child_keys, bool,
- private_tkm_keymat_t *this, proposal_t *proposal, key_exchange_t *ke,
+ private_tkm_keymat_t *this, proposal_t *proposal, array_t *kes,
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;
+ key_exchange_t *ke;
- if (ke)
+ if (kes && array_get(kes, ARRAY_HEAD, &ke))
{
dh_id = ((tkm_diffie_hellman_t *)ke)->get_id((tkm_diffie_hellman_t *)ke);
}
ck_assert(dh->ke.get_public_key(&dh->ke, &pubvalue));
ck_assert(dh->ke.set_public_key(&dh->ke, pubvalue));
+ array_t *kes = NULL;
+ array_insert_create(&kes, ARRAY_TAIL, dh);
fail_unless(keymat->keymat_v2.derive_ike_keys(&keymat->keymat_v2, proposal,
- &dh->ke, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty),
+ kes, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty),
"Key derivation failed");
+ array_destroy(kes);
chunk_free(&nonce);
aead_t * const aead = keymat->keymat_v2.keymat.get_aead(&keymat->keymat_v2.keymat, TRUE);
chunk_t encr_i, encr_r, integ_i, integ_r;
chunk_t nonce = chunk_from_chars("test chunk");
+ array_t *kes = NULL;
+ array_insert_create(&kes, ARRAY_TAIL, dh);
fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal,
- &dh->ke,
- nonce, nonce, &encr_i,
+ kes, nonce, nonce, &encr_i,
&integ_i, &encr_r, &integ_r),
"Child key derivation failed");
+ array_destroy(kes);
esa_info_t *info = (esa_info_t *)encr_i.ptr;
fail_if(!info, "encr_i does not contain esa information");
if (ike_sa->get_version(ike_sa) == IKEV2)
{
keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
+ array_t *kes = NULL;
- ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i,
+ array_insert_create(&kes, ARRAY_HEAD, dh);
+ ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, kes, nonce_i,
nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd);
+ array_destroy(kes);
}
if (ike_sa->get_version(ike_sa) == IKEV1)
{
chunk_t encr_i, integ_i, encr_r, integ_r;
linked_list_t *local_ts, *remote_ts;
key_exchange_t *dh = NULL;
+ array_t *kes = NULL;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
if (secret.len)
{
dh = ha_diffie_hellman_create(secret, chunk_empty);
+ array_insert_create(&kes, ARRAY_HEAD, dh);
}
if (ike_sa->get_version(ike_sa) == IKEV2)
{
keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
- ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh,
+ ok = keymat_v2->derive_child_keys(keymat_v2, proposal, kes,
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
}
if (ike_sa->get_version(ike_sa) == IKEV1)
ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r,
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
}
+ array_destroy(kes);
DESTROY_IF(dh);
if (!ok)
{
/*
- * Copyright (C) 2015-2019 Tobias Brunner
+ * Copyright (C) 2015-2020 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
}
METHOD(keymat_v2_t, derive_ike_keys, bool,
- private_keymat_v2_t *this, proposal_t *proposal, key_exchange_t *dh,
+ private_keymat_v2_t *this, proposal_t *proposal, array_t *kes,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
pseudo_random_function_t rekey_function, chunk_t rekey_skd)
{
- chunk_t skeyseed = chunk_empty, secret, full_nonce, fixed_nonce;
- chunk_t prf_plus_seed, spi_i, spi_r, keymat = chunk_empty;
- chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
+ chunk_t skeyseed = chunk_empty, secret, add_secret = chunk_empty;
+ chunk_t full_nonce, fixed_nonce, prf_plus_seed, spi_i, spi_r;
+ chunk_t keymat = chunk_empty, sk_ei = chunk_empty, sk_er = chunk_empty;
chunk_t sk_ai = chunk_empty, sk_ar = chunk_empty, sk_pi, sk_pr;
kdf_t *prf = NULL, *prf_plus = NULL;
uint16_t prf_alg, key_size, enc_alg, enc_size, int_alg;
return FALSE;
}
- if (!dh->get_shared_secret(dh, &secret))
+ if (!key_exchange_concat_secrets(kes, &secret, &add_secret))
{
return FALSE;
}
- DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
+ DBG4(DBG_IKE, "key exchange secret %B", &secret);
+ DBG4(DBG_IKE, "additional key exchange secret %B", &add_secret);
/* full nonce is used as seed for PRF+ ... */
full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ DBG4(DBG_IKE, "nonces %B", &full_nonce);
/* but the PRF may need a fixed key which only uses the first bytes of
* the nonces. */
switch (prf_alg)
key_derivation_function_names, KDF_PRF,
pseudo_random_function_names, this->prf_alg);
chunk_clear(&secret);
+ chunk_clear(&add_secret);
chunk_free(&full_nonce);
chunk_free(&fixed_nonce);
return FALSE;
key_derivation_function_names, KDF_PRF,
pseudo_random_function_names, rekey_function);
chunk_clear(&secret);
+ chunk_clear(&add_secret);
chunk_free(&full_nonce);
chunk_free(&fixed_nonce);
return FALSE;
}
- secret = chunk_cat("sc", secret, full_nonce);
+ secret = chunk_cat("scc", secret, full_nonce, add_secret);
if (prf->set_param(prf, KDF_PARAM_KEY, secret) &&
prf->set_param(prf, KDF_PARAM_SALT, rekey_skd) &&
prf->allocate_bytes(prf, 0, &skeyseed))
}
DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
chunk_clear(&secret);
+ chunk_clear(&add_secret);
chunk_free(&fixed_nonce);
DESTROY_IF(prf);
}
METHOD(keymat_v2_t, derive_child_keys, bool,
- private_keymat_v2_t *this, proposal_t *proposal, key_exchange_t *dh,
+ private_keymat_v2_t *this, proposal_t *proposal, array_t *kes,
chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
chunk_t *encr_r, chunk_t *integ_r)
{
uint16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
- chunk_t seed, secret = chunk_empty, keymat = chunk_empty;
+ chunk_t seed, secret = chunk_empty, add_secret = chunk_empty;
+ chunk_t keymat = chunk_empty;
kdf_t *prf_plus;
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
int_size /= 8;
}
- if (dh)
+ if (kes)
{
- if (!dh->get_shared_secret(dh, &secret))
+ if (!key_exchange_concat_secrets(kes, &secret, &add_secret))
{
return FALSE;
}
- DBG4(DBG_CHD, "DH secret %B", &secret);
+ DBG4(DBG_CHD, "key exchange secret %B", &secret);
+ DBG4(DBG_CHD, "additional key exchange secret %B", &add_secret);
}
- seed = chunk_cata("scc", secret, nonce_i, nonce_r);
+ seed = chunk_cata("sccs", secret, nonce_i, nonce_r, add_secret);
DBG4(DBG_CHD, "seed %B", &seed);
prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS, this->prf_alg);
/*
- * Copyright (C) 2011-2019 Tobias Brunner
+ * Copyright (C) 2011-2020 Tobias Brunner
*
* Copyright (C) secunet Security Networks AG
*
* crypters and authentication functions.
*
* @param proposal selected algorithms
- * @param dh diffie hellman key allocated by create_ke()
+ * @param kes array of key_exchange_t* created by create_ke()
* @param nonce_i initiators nonce value
* @param nonce_r responders nonce value
* @param id IKE_SA identifier
* @return TRUE on success
*/
bool (*derive_ike_keys)(keymat_v2_t *this, proposal_t *proposal,
- key_exchange_t *dh, chunk_t nonce_i,
+ array_t *kes, chunk_t nonce_i,
chunk_t nonce_r, ike_sa_id_t *id,
pseudo_random_function_t rekey_function,
chunk_t rekey_skd);
* 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_ke(), or NULL
+ * @param kes array of key_exchange_t* created 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
* @return TRUE on success
*/
bool (*derive_child_keys)(keymat_v2_t *this,
- proposal_t *proposal, key_exchange_t *dh,
+ proposal_t *proposal, array_t *kes,
chunk_t nonce_i, chunk_t nonce_r,
chunk_t *encr_i, chunk_t *integ_i,
chunk_t *encr_r, chunk_t *integ_r);
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
linked_list_t *my_ts, *other_ts;
host_t *me, *other;
+ array_t *kes = NULL;
proposal_selection_flag_t flags = 0;
if (this->proposals == NULL)
this->ipcomp = IPCOMP_NONE;
}
status_i = status_o = FAILED;
+ if (this->dh)
+ {
+ array_insert_create(&kes, ARRAY_HEAD, this->dh);
+ }
if (this->keymat->derive_child_keys(this->keymat, this->proposal,
- this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ kes, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
{
if (this->initiator)
{
chunk_clear(&integ_r);
chunk_clear(&encr_i);
chunk_clear(&encr_r);
+ array_destroy(kes);
if (status != SUCCESS)
{
pseudo_random_function_t prf_alg = PRF_UNDEFINED;
chunk_t skd = chunk_empty;
ike_sa_id_t *id;
+ array_t *kes;
id = this->ike_sa->get_id(this->ike_sa);
if (this->old_sa)
old_keymat = (keymat_v2_t*)this->old_sa->get_keymat(this->old_sa);
prf_alg = old_keymat->get_skd(old_keymat, &skd);
}
- if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ array_insert_create(&kes, ARRAY_HEAD, this->dh);
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, kes,
nonce_i, nonce_r, id, prf_alg, skd))
{
+ array_destroy(kes);
return FALSE;
}
+ array_destroy(kes);
charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, chunk_empty,
nonce_i, nonce_r, this->old_sa, NULL, AUTH_NONE);
return TRUE;