static PK11SymKey *ikev2_prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat) { uint8_t count = 1; /* T1(prfplus) = prf(KEY, SEED|1) */ PK11SymKey *prfplus; { struct crypt_prf *prf = crypt_prf_init_symkey("prf+0", DBG_CRYPT, prf_desc, "key", key); crypt_prf_update_symkey("seed", prf, seed); crypt_prf_update_byte("1++", prf, count++); prfplus = crypt_prf_final(prf); } /* make a copy to keep things easy */ PK11SymKey *old_t = key_from_symkey_bytes(prfplus, 0, sizeof_symkey(prfplus)); while (sizeof_symkey(prfplus) < required_keymat) { /* Tn = prf(KEY, Tn-1|SEED|n) */ struct crypt_prf *prf = crypt_prf_init_symkey("prf+N", DBG_CRYPT, prf_desc, "key", key); crypt_prf_update_symkey("old_t", prf, old_t); crypt_prf_update_symkey("seed", prf, seed); crypt_prf_update_byte("N++", prf, count++); PK11SymKey *new_t = crypt_prf_final(prf); append_symkey_symkey(prf_desc->hasher, &prfplus, new_t); free_any_symkey("old_t[N]", &old_t); old_t = new_t; } free_any_symkey("old_t[final]", &old_t); return prfplus; }
/* * SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *ikev2_ike_sa_skeyseed(const struct hash_desc *hasher, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { struct crypt_prf *prf = crypt_prf_init("ike sa SKEYSEED", hasher, dh_secret); /* key = Ni|Nr */ crypt_prf_init_chunk("Ni", prf, Ni); crypt_prf_init_chunk("Nr", prf, Nr); /* seed = g^ir */ crypt_prf_update(prf); /* generate */ crypt_prf_update_symkey("g^ir", prf, dh_secret); return crypt_prf_final(prf); }
/* * SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ PK11SymKey *ikev2_ike_sa_rekey_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *SK_d_old, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr) { /* key = SK_d (old) */ struct crypt_prf *prf = crypt_prf_init_symkey("ike sa rekey skeyseed", DBG_CRYPT, prf_desc, "SK_d (old)", SK_d_old); /* seed: g^ir (new) | Ni | Nr) */ crypt_prf_update_symkey("g^ir (new)", prf, new_dh_secret); crypt_prf_update_chunk("Ni", prf, Ni); crypt_prf_update_chunk("Nr", prf, Nr); /* generate */ return crypt_prf_final(prf); }
/* * SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *ikev2_ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { /* key = Ni|Nr */ chunk_t key = concat_chunk_chunk("key = Ni|Nr", Ni, Nr); struct crypt_prf *prf = crypt_prf_init_chunk("ike sa SKEYSEED", DBG_CRYPT, prf_desc, "Ni|Nr", key); freeanychunk(key); /* seed = g^ir */ crypt_prf_update_symkey("g^ir", prf, dh_secret); /* generate */ return crypt_prf_final(prf); }
static bool ikev2_calculate_psk_sighash(struct state *st, enum original_role role, unsigned char *idhash, chunk_t firstpacket, unsigned char *signed_octets) { const chunk_t *nonce; const char *nonce_name; const struct connection *c = st->st_connection; const chunk_t *pss = &empty_chunk; const size_t hash_len = st->st_oakley.prf_hasher->hash_digest_len; if (!(c->policy & POLICY_AUTH_NULL)) { pss = get_preshared_secret(c); if (pss == NULL) { libreswan_log("No matching PSK found for connection:%s", st->st_connection->name); return FALSE; /* failure: no PSK to use */ } DBG(DBG_PRIVATE, DBG_dump_chunk("User PSK:", *pss)); } else { /* * draft-ietf-ipsecme-ikev2-null-auth-02 * * When using the NULL Authentication Method, the * content of the AUTH payload is computed using the * syntax of pre-shared secret authentication, * described in Section 2.15 of [RFC7296]. The values * SK_pi and SK_pr are used as shared secrets for the * content of the AUTH payloads generated by the * initiator and the responder respectively. * * We have SK_pi/SK_pr as PK11SymKey in st_skey_pi_nss * and st_skey_pr_nss */ passert(st->hidden_variables.st_skeyid_calculated); /* * This is wrong as role - we need to role for THIS exchange * But verify calls this routine with the role inverted, so we * cannot juse st->st_state either. */ if (role == ORIGINAL_INITIATOR) { /* we are sending initiator, or verifying responder */ pss = &st->st_skey_chunk_SK_pi; } else { /* we are verifying initiator, or sending responder */ pss = &st->st_skey_chunk_SK_pr; } DBG(DBG_PRIVATE, DBG_dump_chunk("AUTH_NULL PSK:", *pss)); } /* * RFC 4306 2.15: * AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */ /* calculate inner prf */ PK11SymKey *prf_psk; { struct crypt_prf *prf = crypt_prf_init(("<prf-psk>" " = prf(<psk>,\"Key Pad for IKEv2\")"), st->st_oakley.prf_hasher, st->st_shared_nss/*scratch*/); crypt_prf_init_chunk("shared secret", prf, *pss); crypt_prf_update(prf); crypt_prf_update_bytes(psk_key_pad_str/*name*/, prf, psk_key_pad_str, psk_key_pad_str_len); prf_psk = crypt_prf_final(prf); } /* decide nonce based on the role */ if (role == ORIGINAL_INITIATOR) { /* on initiator, we need to hash responders nonce */ nonce = &st->st_nr; nonce_name = "inputs to hash2 (responder nonce)"; } else { nonce = &st->st_ni; nonce_name = "inputs to hash2 (initiator nonce)"; } /* calculate outer prf */ { struct crypt_prf *prf = crypt_prf_init(("<signed-octets>" " = prf(<prf-psk>, <msg octets>)"), st->st_oakley.prf_hasher, st->st_shared_nss /*scratch*/); crypt_prf_init_symkey("<prf-psk>", prf, prf_psk); /* * For the responder, the octets to be signed start * with the first octet of the first SPI in the header * of the second message and end with the last octet * of the last payload in the second message. * Appended to this (for purposes of computing the * signature) are the initiator's nonce Ni (just the * value, not the payload containing it), and the * value prf(SK_pr,IDr') where IDr' is the responder's * ID payload excluding the fixed header. Note that * neither the nonce Ni nor the value prf(SK_pr,IDr') * are transmitted. */ crypt_prf_update(prf); crypt_prf_update_chunk("first-packet", prf, firstpacket); crypt_prf_update_chunk("nonce", prf, *nonce); crypt_prf_update_bytes("hash", prf, idhash, hash_len); crypt_prf_final_bytes(prf, signed_octets, hash_len); } free_any_symkey("<prf-psk>", &prf_psk); DBG(DBG_CRYPT, DBG_dump_chunk("inputs to hash1 (first packet)", firstpacket); DBG_dump_chunk(nonce_name, *nonce); DBG_dump("idhash", idhash, hash_len)); return TRUE; }