diff options
Diffstat (limited to 'src/charon/sa/keymat.c')
-rw-r--r-- | src/charon/sa/keymat.c | 113 |
1 files changed, 57 insertions, 56 deletions
diff --git a/src/charon/sa/keymat.c b/src/charon/sa/keymat.c index 46fb79587..e49626354 100644 --- a/src/charon/sa/keymat.c +++ b/src/charon/sa/keymat.c @@ -24,52 +24,52 @@ typedef struct private_keymat_t private_keymat_t; * Private data of an keymat_t object. */ struct private_keymat_t { - + /** * Public keymat_t interface. */ keymat_t public; - + /** - * IKE_SA Role, initiator or responder - */ - bool initiator; - + * IKE_SA Role, initiator or responder + */ + bool initiator; + /** * inbound signer (verify) */ signer_t *signer_in; - + /** * outbound signer (sign) */ signer_t *signer_out; - + /** * inbound crypter (decrypt) */ crypter_t *crypter_in; - + /** * outbound crypter (encrypt) */ crypter_t *crypter_out; - + /** * General purpose PRF */ prf_t *prf; - + /** * Negotiated PRF algorithm */ pseudo_random_function_t prf_alg; - + /** * Key to derive key material from for CHILD_SAs, rekeying */ chunk_t skd; - + /** * Key to build outging authentication data (SKp) */ @@ -110,6 +110,7 @@ keylen_entry_t keylen_enc[] = { keylen_entry_t keylen_int[] = { {AUTH_HMAC_MD5_96, 128}, {AUTH_HMAC_SHA1_96, 160}, + {AUTH_HMAC_SHA2_256_96, 256}, {AUTH_HMAC_SHA2_256_128, 256}, {AUTH_HMAC_SHA2_384_192, 384}, {AUTH_HMAC_SHA2_512_256, 512}, @@ -158,15 +159,15 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, prf_plus_t *prf_plus; u_int16_t alg, key_size; prf_t *rekey_prf = NULL; - + spi_i = chunk_alloca(sizeof(u_int64_t)); spi_r = chunk_alloca(sizeof(u_int64_t)); - + if (dh->get_shared_secret(dh, &secret) != SUCCESS) { return FALSE; } - + /* Create SAs general purpose PRF first, we may use it here */ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL)) { @@ -206,8 +207,8 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id); *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id); prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r); - - /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) + + /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) * * if we are rekeying, SKEYSEED is built on another way */ @@ -221,7 +222,7 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, } else { - /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) + /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) * use OLD SAs PRF functions for both prf_plus and prf */ rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function); if (!rekey_prf) @@ -240,20 +241,20 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, prf_plus = prf_plus_create(rekey_prf, prf_plus_seed); } DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); - + chunk_clear(&skeyseed); chunk_clear(&secret); chunk_free(&full_nonce); chunk_free(&fixed_nonce); chunk_clear(&prf_plus_seed); - + /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */ - + /* SK_d is used for generating CHILD_SA key mat => store for later use */ key_size = this->prf->get_key_size(this->prf); prf_plus->allocate_bytes(prf_plus, key_size, &this->skd); DBG4(DBG_IKE, "Sk_d secret %B", &this->skd); - + /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) { @@ -275,17 +276,17 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, return FALSE; } key_size = signer_i->get_key_size(signer_i); - + prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_ai secret %B", &key); signer_i->set_key(signer_i, key); chunk_clear(&key); - + prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_ar secret %B", &key); signer_r->set_key(signer_r, key); chunk_clear(&key); - + if (this->initiator) { this->signer_in = signer_r; @@ -296,7 +297,7 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, this->signer_in = signer_i; this->signer_out = signer_r; } - + /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size)) { @@ -318,17 +319,17 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, return FALSE; } key_size = crypter_i->get_key_size(crypter_i); - + prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_ei secret %B", &key); crypter_i->set_key(crypter_i, key); chunk_clear(&key); - + prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_er secret %B", &key); crypter_r->set_key(crypter_r, key); chunk_clear(&key); - + if (this->initiator) { this->crypter_in = crypter_r; @@ -339,8 +340,8 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, this->crypter_in = crypter_i; this->crypter_out = crypter_r; } - - /* SK_pi/SK_pr used for authentication => stored for later */ + + /* SK_pi/SK_pr used for authentication => stored for later */ key_size = this->prf->get_key_size(this->prf); prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_pi secret %B", &key); @@ -362,11 +363,11 @@ static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, { this->skp_build = key; } - + /* all done, prf_plus not needed anymore */ prf_plus->destroy(prf_plus); DESTROY_IF(rekey_prf); - + return TRUE; } @@ -382,7 +383,7 @@ static bool derive_child_keys(private_keymat_t *this, u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0; chunk_t seed, secret = chunk_empty; prf_plus_t *prf_plus; - + if (dh) { if (dh->get_shared_secret(dh, &secret) != SUCCESS) @@ -393,13 +394,13 @@ static bool derive_child_keys(private_keymat_t *this, } seed = chunk_cata("mcc", secret, nonce_i, nonce_r); DBG4(DBG_CHD, "seed %B", &seed); - + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &enc_size)) { - DBG2(DBG_CHD, " using %N for encryption", + DBG2(DBG_CHD, " using %N for encryption", encryption_algorithm_names, enc_alg); - + if (!enc_size) { enc_size = lookup_keylen(keylen_enc, enc_alg); @@ -412,7 +413,7 @@ static bool derive_child_keys(private_keymat_t *this, } /* to bytes */ enc_size /= 8; - + /* CCM/GCM/CTR needs additional bytes */ switch (enc_alg) { @@ -434,13 +435,13 @@ static bool derive_child_keys(private_keymat_t *this, break; } } - + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &int_size)) { DBG2(DBG_CHD, " using %N for integrity", integrity_algorithm_names, int_alg); - + if (!int_size) { int_size = lookup_keylen(keylen_int, int_alg); @@ -454,17 +455,17 @@ static bool derive_child_keys(private_keymat_t *this, /* to bytes */ int_size /= 8; } - + this->prf->set_key(this->prf, this->skd); prf_plus = prf_plus_create(this->prf, seed); - + prf_plus->allocate_bytes(prf_plus, enc_size, encr_i); prf_plus->allocate_bytes(prf_plus, int_size, integ_i); prf_plus->allocate_bytes(prf_plus, enc_size, encr_r); prf_plus->allocate_bytes(prf_plus, int_size, integ_r); - + prf_plus->destroy(prf_plus); - + if (enc_size) { DBG4(DBG_CHD, "encryption initiator key %B", encr_i); @@ -512,19 +513,19 @@ static chunk_t get_auth_octets(private_keymat_t *this, bool verify, { chunk_t chunk, idx, octets; chunk_t skp; - + skp = verify ? this->skp_verify : this->skp_build; - + chunk = chunk_alloca(4); memset(chunk.ptr, 0, chunk.len); chunk.ptr[0] = id->get_type(id); idx = chunk_cata("cc", chunk, id->get_encoding(id)); - + DBG3(DBG_IKE, "IDx' %B", &idx); DBG3(DBG_IKE, "SK_p %B", &skp); this->prf->set_key(this->prf, skp); this->prf->allocate_bytes(this->prf, idx, &chunk); - + octets = chunk_cat("ccm", ike_sa_init, nonce, chunk); DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets); return octets; @@ -539,12 +540,12 @@ static chunk_t get_auth_octets(private_keymat_t *this, bool verify, /** * Implementation of keymat_t.get_psk_sig */ -static chunk_t get_psk_sig(private_keymat_t *this, bool verify, +static chunk_t get_psk_sig(private_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id) { chunk_t key_pad, key, sig, octets; - + if (!secret.len) { /* EAP uses SK_p if no MSK has been established */ secret = verify ? this->skp_verify : this->skp_build; @@ -561,7 +562,7 @@ static chunk_t get_psk_sig(private_keymat_t *this, bool verify, DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig); chunk_free(&octets); chunk_free(&key); - + return sig; } @@ -587,7 +588,7 @@ static void destroy(private_keymat_t *this) keymat_t *keymat_create(bool initiator) { private_keymat_t *this = malloc_thing(private_keymat_t); - + this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh; this->public.derive_ike_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t,chunk_t))derive_ike_keys; this->public.derive_child_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_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))derive_child_keys; @@ -597,9 +598,9 @@ keymat_t *keymat_create(bool initiator) this->public.get_auth_octets = (chunk_t(*)(keymat_t *, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id))get_auth_octets; this->public.get_psk_sig = (chunk_t(*)(keymat_t*, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id))get_psk_sig; this->public.destroy = (void(*)(keymat_t*))destroy; - + this->initiator = initiator; - + this->signer_in = NULL; this->signer_out = NULL; this->crypter_in = NULL; @@ -609,7 +610,7 @@ keymat_t *keymat_create(bool initiator) this->skd = chunk_empty; this->skp_verify = chunk_empty; this->skp_build = chunk_empty; - + return &this->public; } |