From cb9edc54ebcde710ebbfdb7dccdf48507be85741 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 21 May 2008 14:58:03 +0000 Subject: [PATCH] using fixed size keys in key derivation for AES-XCBC PRF --- src/charon/sa/ike_sa.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index eb5e67739..a6b392796 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -1517,7 +1517,7 @@ static status_t derive_keys(private_ike_sa_t *this, bool initiator, prf_t *child_prf, prf_t *old_prf) { prf_plus_t *prf_plus; - chunk_t skeyseed, key, nonces, prf_plus_seed; + chunk_t skeyseed, key, full_nonce, fixed_nonce, prf_plus_seed; u_int16_t alg, key_size; crypter_t *crypter_i, *crypter_r; signer_t *signer_i, *signer_r; @@ -1540,12 +1540,28 @@ static status_t derive_keys(private_ike_sa_t *this, pseudo_random_function_names, alg); return FAILED; } - DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret); - nonces = chunk_cat("cc", nonce_i, nonce_r); + /* full nonce is used as seed for PRF+ ... */ + full_nonce = chunk_cat("cc", nonce_i, nonce_r); + /* but the PRF may need a fixed key which only uses the first bytes of + * the nonces. */ + switch (alg) + { + case PRF_AES128_XCBC: + /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does + * not and therefore fixed key semantics apply to XCBC for key + * derivation. */ + nonce_i.len = min(nonce_i.len, this->prf->get_key_size(this->prf)/2); + nonce_r.len = min(nonce_r.len, this->prf->get_key_size(this->prf)/2); + break; + default: + /* all other algorithms use variable key length, full nonce */ + break; + } + fixed_nonce = chunk_cat("cc", nonce_i, nonce_r); *((u_int64_t*)spi_i.ptr) = this->ike_sa_id->get_initiator_spi(this->ike_sa_id); *((u_int64_t*)spi_r.ptr) = this->ike_sa_id->get_responder_spi(this->ike_sa_id); - prf_plus_seed = chunk_cat("ccc", nonces, spi_i, spi_r); + prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r); /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) * @@ -1554,7 +1570,7 @@ static status_t derive_keys(private_ike_sa_t *this, if (child_prf == NULL) /* not rekeying */ { /* SKEYSEED = prf(Ni | Nr, g^ir) */ - this->prf->set_key(this->prf, nonces); + this->prf->set_key(this->prf, fixed_nonce); this->prf->allocate_bytes(this->prf, secret, &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); this->prf->set_key(this->prf, skeyseed); @@ -1566,7 +1582,7 @@ static status_t derive_keys(private_ike_sa_t *this, { /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) * use OLD SAs PRF functions for both prf_plus and prf */ - secret = chunk_cat("mc", secret, nonces); + secret = chunk_cat("mc", secret, full_nonce); child_prf->allocate_bytes(child_prf, secret, &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); old_prf->set_key(old_prf, skeyseed); @@ -1574,7 +1590,8 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_free(&secret); prf_plus = prf_plus_create(old_prf, prf_plus_seed); } - chunk_free(&nonces); + chunk_free(&full_nonce); + chunk_free(&fixed_nonce); chunk_free(&prf_plus_seed); /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */