static void run_ikev2(void) { print_number("COUNT", count); print_chunk("Ni", ni, 0); print_chunk("Nr", nr, 0); print_symkey("g^ir", g_ir, 0); print_symkey("g^ir (new)", g_ir_new, 0); print_chunk("SPIi", spi_i, 0); print_chunk("SPIr", spi_r, 0); if (hasher == NULL) { print_line(hasher_name); return; } /* SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *skeyseed = ikev2_ike_sa_skeyseed(hasher, ni, nr, g_ir); print_symkey("SKEYSEED", skeyseed, 0); /* prf+(SKEYSEED, Ni | Nr | SPIi | SPIr) */ PK11SymKey *dkm = ikev2_ike_sa_keymat(hasher, skeyseed, ni, nr, spi_i, spi_r, dkm_length / 8); print_symkey("DKM", dkm, dkm_length / 8); /* prf+(SK_d, Ni | Nr) */ PK11SymKey *SK_d = key_from_symkey_bytes(dkm, 0, hasher->hash_digest_len); PK11SymKey *child_sa_dkm = ikev2_child_sa_keymat(hasher, SK_d, NULL, ni, nr, child_sa_dkm_length / 8); print_symkey("DKM(Child SA)", child_sa_dkm, child_sa_dkm_length / 8); /* prf+(SK_d, g^ir (new) | Ni | Nr) */ PK11SymKey *child_sa_dkm_dh = ikev2_child_sa_keymat(hasher, SK_d, g_ir_new, ni, nr, child_sa_dkm_length / 8); print_symkey("DKM(Child SA D-H)", child_sa_dkm_dh, child_sa_dkm_length / 8); /* prf(SK_d (old), g^ir (new) | Ni | Nr) */ PK11SymKey *skeyseed_rekey = ikev2_ike_sa_rekey_skeyseed(hasher, SK_d, g_ir_new, ni, nr); print_symkey("SKEYSEED(Rekey)", skeyseed_rekey, 0); free_any_symkey("skeyseed", &skeyseed); free_any_symkey("dkm", &dkm); free_any_symkey("SK_d", &SK_d); free_any_symkey("child_sa_dkm", &child_sa_dkm); free_any_symkey("child_sa_dkm_dh", &child_sa_dkm_dh); free_any_symkey("skeyseed_rekey", &skeyseed_rekey); }
/* MUST BE THREAD-SAFE */ static void calc_skeyseed_v2(struct pcr_skeyid_q *skq, PK11SymKey *shared, const size_t key_size, const size_t salt_size, PK11SymKey **skeyseed_out, PK11SymKey **SK_d_out, PK11SymKey **SK_ai_out, PK11SymKey **SK_ar_out, PK11SymKey **SK_ei_out, PK11SymKey **SK_er_out, PK11SymKey **SK_pi_out, PK11SymKey **SK_pr_out, chunk_t *initiator_salt_out, chunk_t *responder_salt_out, chunk_t *chunk_SK_pi_out, chunk_t *chunk_SK_pr_out) { DBG(DBG_CRYPT, DBG_log("NSS: Started key computation")); PK11SymKey *skeyseed_k, *SK_d_k, *SK_ai_k, *SK_ar_k, *SK_ei_k, *SK_er_k, *SK_pi_k, *SK_pr_k; chunk_t initiator_salt; chunk_t responder_salt; chunk_t chunk_SK_pi; chunk_t chunk_SK_pr; /* this doesn't take any memory, it's just moving pointers around */ chunk_t ni; chunk_t nr; chunk_t spii; chunk_t spir; setchunk_from_wire(ni, skq, &skq->ni); setchunk_from_wire(nr, skq, &skq->nr); setchunk_from_wire(spii, skq, &skq->icookie); setchunk_from_wire(spir, skq, &skq->rcookie); DBG(DBG_CONTROLMORE, DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey-size=%zu salt-size=%zu", enum_name(&ikev2_trans_type_prf_names, skq->prf_hash), enum_name(&ikev2_trans_type_integ_names, skq->integ_hash), key_size, salt_size)); const struct hash_desc *prf_hasher = (struct hash_desc *) ikev2_alg_find(IKE_ALG_HASH, skq->prf_hash); passert(prf_hasher != NULL); const struct encrypt_desc *encrypter = skq->encrypter; passert(encrypter != NULL); /* generate SKEYSEED from key=(Ni|Nr), hash of shared */ skeyseed_k = ikev2_ike_sa_skeyseed(prf_hasher, ni, nr, shared); passert(skeyseed_k != NULL); /* now we have to generate the keys for everything */ /* need to know how many bits to generate */ /* SK_d needs PRF hasher key bytes */ /* SK_p needs PRF hasher*2 key bytes */ /* SK_e needs key_size*2 key bytes */ /* ..._salt needs salt_size*2 bytes */ /* SK_a needs integ's key size*2 bytes */ int skd_bytes = prf_hasher->hash_key_size; int skp_bytes = prf_hasher->hash_key_size; const struct hash_desc *integ_hasher = (struct hash_desc *)ikev2_alg_find(IKE_ALG_INTEG, skq->integ_hash); int integ_size = integ_hasher != NULL ? integ_hasher->hash_key_size : 0; size_t total_keysize = skd_bytes + 2*skp_bytes + 2*key_size + 2*salt_size + 2*integ_size; PK11SymKey *finalkey = ikev2_ike_sa_keymat(prf_hasher, skeyseed_k, ni, nr, spii, spir, total_keysize); size_t next_byte = 0; SK_d_k = key_from_symkey_bytes(finalkey, next_byte, skd_bytes); next_byte += skd_bytes; SK_ai_k = key_from_symkey_bytes(finalkey, next_byte, integ_size); next_byte += integ_size; SK_ar_k = key_from_symkey_bytes(finalkey, next_byte, integ_size); next_byte += integ_size; /* The encryption key and salt are extracted together. */ SK_ei_k = encrypt_key_from_symkey_bytes(finalkey, encrypter, next_byte, key_size); next_byte += key_size; PK11SymKey *initiator_salt_key = key_from_symkey_bytes(finalkey, next_byte, salt_size); initiator_salt = chunk_from_symkey("initiator salt", initiator_salt_key); free_any_symkey("initiator salt key:", &initiator_salt_key); next_byte += salt_size; /* The encryption key and salt are extracted together. */ SK_er_k = encrypt_key_from_symkey_bytes(finalkey, encrypter, next_byte, key_size); next_byte += key_size; PK11SymKey *responder_salt_key = key_from_symkey_bytes(finalkey, next_byte, salt_size); responder_salt = chunk_from_symkey("responder salt", responder_salt_key); free_any_symkey("responder salt key:", &responder_salt_key); next_byte += salt_size; SK_pi_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes); /* store copy of SK_pi_k for later use in authnull */ chunk_SK_pi = chunk_from_symkey("chunk_SK_pi", SK_pi_k); next_byte += skp_bytes; SK_pr_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes); /* store copy of SK_pr_k for later use in authnull */ chunk_SK_pr = chunk_from_symkey("chunk_SK_pr", SK_pr_k); next_byte += skp_bytes; /* next_byte not subsequently used */ DBG(DBG_CRYPT, DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA")); free_any_symkey("finalkey", &finalkey); *skeyseed_out = skeyseed_k; *SK_d_out = SK_d_k; *SK_ai_out = SK_ai_k; *SK_ar_out = SK_ar_k; *SK_ei_out = SK_ei_k; *SK_er_out = SK_er_k; *SK_pi_out = SK_pi_k; *SK_pr_out = SK_pr_k; *initiator_salt_out = initiator_salt; *responder_salt_out = responder_salt; *chunk_SK_pi_out = chunk_SK_pi; *chunk_SK_pr_out = chunk_SK_pr; DBG(DBG_CRYPT, DBG_log("calc_skeyseed_v2 pointers: shared %p, skeyseed %p, SK_d %p, SK_ai %p, SK_ar %p, SK_ei %p, SK_er %p, SK_pi %p, SK_pr %p", shared, skeyseed_k, SK_d_k, SK_ai_k, SK_ar_k, SK_ei_k, SK_er_k, SK_pi_k, SK_pr_k); DBG_dump_chunk("calc_skeyseed_v2 initiator salt", initiator_salt); DBG_dump_chunk("calc_skeyseed_v2 responder salt", responder_salt); DBG_dump_chunk("calc_skeyseed_v2 SK_pi", chunk_SK_pi); DBG_dump_chunk("calc_skeyseed_v2 SK_pr", chunk_SK_pr)); }