diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg_aes.c libreswan-3.29/lib/libswan/ike_alg_aes.c --- libreswan-3.29-orig/lib/libswan/ike_alg_aes.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/lib/libswan/ike_alg_aes.c 2019-08-11 13:31:13.849294693 -0400 @@ -23,14 +23,21 @@ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" + #include "ike_alg.h" +#include "ike_alg_encrypt.h" +#include "ike_alg_integ.h" +#include "ike_alg_prf.h" + #include "ike_alg_encrypt_nss_cbc_ops.h" #include "ike_alg_encrypt_nss_ctr_ops.h" #include "ike_alg_encrypt_nss_gcm_ops.h" +#ifdef CKM_AES_XCBC_MAC +#include "ike_alg_prf_nss_ops.h" +#else #include "ike_alg_prf_nss_xcbc_ops.h" -#include "ike_alg_encrypt.h" -#include "ike_alg_integ.h" -#include "ike_alg_prf.h" +#endif + #include "sadb.h" const struct encrypt_desc ike_alg_encrypt_aes_cbc = { @@ -313,6 +320,7 @@ .encrypt_kernel_audit_name = "AES_CCM_C", }; +#ifdef USE_PRF_AES_XCBC const struct prf_desc ike_alg_prf_aes_xcbc = { .common = { .name = "aes_xcbc", @@ -326,14 +334,23 @@ }, .fips = false, }, +#ifdef CKM_AES_XCBC_MAC + .nss = { + .mechanism = CKM_AES_XCBC_MAC, + }, + .prf_ops = &ike_alg_prf_nss_ops, +#else + /* XXX: NSS encryption algorithm used by custom XCBC */ .nss = { .mechanism = CKM_AES_ECB, }, + .prf_ops = &ike_alg_prf_nss_xcbc_ops, +#endif .prf_key_size = BYTES_FOR_BITS(128), .prf_output_size = BYTES_FOR_BITS(128), - .prf_ops = &ike_alg_prf_nss_xcbc_ops, .prf_ike_audit_name = "aes_xcbc", }; +#endif const struct integ_desc ike_alg_integ_aes_xcbc = { .common = { @@ -351,7 +368,7 @@ .integ_keymat_size = AES_XCBC_DIGEST_SIZE, .integ_output_size = AES_XCBC_DIGEST_SIZE_TRUNC, /* XXX 96 */ .integ_ikev1_ah_transform = AH_AES_XCBC_MAC, -#ifdef USE_XCBC +#ifdef USE_PRF_AES_XCBC .prf = &ike_alg_prf_aes_xcbc, #endif #ifdef SADB_X_AALG_AES_XCBC_MAC diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg.c libreswan-3.29/lib/libswan/ike_alg.c --- libreswan-3.29-orig/lib/libswan/ike_alg.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/lib/libswan/ike_alg.c 2019-08-11 13:31:13.850294706 -0400 @@ -478,7 +478,7 @@ &ike_alg_prf_sha2_384, &ike_alg_prf_sha2_512, #endif -#ifdef USE_XCBC +#ifdef USE_PRF_AES_XCBC &ike_alg_prf_aes_xcbc, #endif }; diff -Naur libreswan-3.29-orig/lib/libswan/ike_alg_md5.c libreswan-3.29/lib/libswan/ike_alg_md5.c --- libreswan-3.29-orig/lib/libswan/ike_alg_md5.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/lib/libswan/ike_alg_md5.c 2019-08-11 13:31:13.851294720 -0400 @@ -26,7 +26,7 @@ #include "ike_alg_hash.h" #include "ike_alg_prf.h" #include "ike_alg_hash_nss_ops.h" -#include "ike_alg_prf_hmac_ops.h" +#include "ike_alg_prf_nss_ops.h" #include "sadb.h" const struct hash_desc ike_alg_hash_md5 = { @@ -63,10 +63,13 @@ [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_MD5, }, }, + .nss = { + .mechanism = CKM_MD5_HMAC, + }, .prf_key_size = MD5_DIGEST_SIZE, .prf_output_size = MD5_DIGEST_SIZE, .hasher = &ike_alg_hash_md5, - .prf_ops = &ike_alg_prf_hmac_ops, + .prf_ops = &ike_alg_prf_nss_ops, .prf_ike_audit_name = "md5", }; diff -Naur libreswan-3.29-orig/mk/config.mk libreswan-3.29/mk/config.mk --- libreswan-3.29-orig/mk/config.mk 2019-08-11 13:30:45.756906229 -0400 +++ libreswan-3.29/mk/config.mk 2019-08-11 13:31:13.852294734 -0400 @@ -239,6 +239,18 @@ NSS_UTIL_LDFLAGS ?= -lnssutil3 NSPR_LDFLAGS ?= -lnspr4 +# Use the NSS Key Derivation Function (KDF) instead of using the NSS +# secure hash functions to build our own PRF. With this enabled, +# libreswan itself no longer needs to be FIPS validated. +# Requires NSS >= 3.44 +USE_NSS_PRF?=false +ifeq ($(USE_NSS_PRF),true) +NSSFLAGS+=-DUSE_NSS_PRF +USE_NSS_AVA_COPY=false +endif + +# +# # Use local copy of nss function CERT_CompareAVA # See https://bugzilla.mozilla.org/show_bug.cgi?id=1336487 # This work-around is needed with nss versions before 3.30. diff -Naur libreswan-3.29-orig/mk/userland-cflags.mk libreswan-3.29/mk/userland-cflags.mk --- libreswan-3.29-orig/mk/userland-cflags.mk 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/mk/userland-cflags.mk 2019-08-11 13:31:13.853294748 -0400 @@ -269,9 +269,10 @@ LIBTWOFISH= ${OBJDIRTOP}/lib/libcrypto/libtwofish/libtwofish.a endif -USE_XCBC ?= true -ifeq ($(USE_XCBC),true) -USERLAND_CFLAGS += -DUSE_XCBC +# Requires NSS >= 3.44 or backport +USE_PRF_AES_XCBC ?= true +ifeq ($(USE_PRF_AES_XCBC),true) +USERLAND_CFLAGS += -DUSE_PRF_AES_XCBC endif # diff -Naur libreswan-3.29-orig/programs/pluto/crypt_symkey.c libreswan-3.29/programs/pluto/crypt_symkey.c --- libreswan-3.29-orig/programs/pluto/crypt_symkey.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/crypt_symkey.c 2019-08-11 13:31:13.854294762 -0400 @@ -15,7 +15,6 @@ * for more details. */ -#include "libreswan.h" #include "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" @@ -23,6 +22,7 @@ #include "crypto.h" #include "lswfips.h" #include "lswnss.h" +#include "crypt_prf.h" /* hack */ #define SPACES " " @@ -590,9 +590,51 @@ PK11SymKey *prf_key_from_symkey_bytes(const char *name, const struct prf_desc *prf, - size_t symkey_start_byte, size_t sizeof_symkey, + size_t symkey_start_byte, size_t symkey_size, PK11SymKey *source_key) { +#ifdef CKM_AES_XCBC_MAC + if (prf->nss.mechanism == CKM_AES_XCBC_MAC && + symkey_size != prf->prf_key_size) { + PK11SymKey *tmp = symkey_from_symkey("tmp", source_key, + CKM_VENDOR_DEFINED, /*flags*/0, + symkey_start_byte, symkey_size); + /* + * code lifted from ike_alg_prf_nss_xcbc_ops.c + */ + size_t dkey_sz = sizeof_symkey(tmp); + if (dkey_sz < prf->prf_key_size) { + DBGF(DBG_CRYPT, "XCBC: Key %zd<%zd too small, padding with zeros", + dkey_sz, prf->prf_key_size); + /* + * right pad with zeros + */ + chunk_t zeros = alloc_chunk(prf->prf_key_size - dkey_sz, "zeros"); + append_symkey_chunk(&tmp, zeros); + freeanychunk(zeros); + } else { + pexpect(dkey_sz > prf->prf_key_size); + DBGF(DBG_CRYPT, "XCBC: Key %zd>%zd too big, rehashing to size", + dkey_sz, prf->prf_key_size); + /* + * put the key through the mac with a zero + * key; recursive + */ + chunk_t zeros = alloc_chunk(prf->prf_key_size, "zeros"); + PK11SymKey *zero_key = prf_key_from_bytes("zeros", prf, zeros.ptr, zeros.len); + freeanychunk(zeros); + struct crypt_prf *xmac = crypt_prf_init_symkey("xmac", prf, "zero", zero_key); + crypt_prf_update_symkey(xmac, "tmp", tmp); + PK11SymKey *tmp2 = crypt_prf_final_symkey(&xmac); + release_symkey(name, "tmp2", &tmp); + tmp = tmp2; + } + PK11SymKey *key = symkey_from_symkey(name, tmp, CKM_AES_XCBC_MAC, CKF_SIGN, + 0, prf->prf_key_size); + release_symkey(name, "tmp", &tmp); + return key; + } +#endif /* * NSS expects a key's mechanism to match the NSS algorithm * the key is intended for. If this is wrong then the @@ -614,7 +656,7 @@ mechanism = prf->nss.mechanism; } return symkey_from_symkey(name, source_key, mechanism, flags, - symkey_start_byte, sizeof_symkey); + symkey_start_byte, symkey_size); } /* @@ -656,9 +698,13 @@ PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key, size_t next_byte, size_t sizeof_key) { - return symkey_from_symkey("result", source_key, - CKM_EXTRACT_KEY_FROM_KEY, - 0, next_byte, sizeof_key); + if (sizeof_key == 0) { + return NULL; + } else { + return symkey_from_symkey("result", source_key, + CKM_EXTRACT_KEY_FROM_KEY, + 0, next_byte, sizeof_key); + } } /* diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_prf.c libreswan-3.29/programs/pluto/ikev1_prf.c --- libreswan-3.29-orig/programs/pluto/ikev1_prf.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/ikev1_prf.c 2019-08-11 13:31:13.855294776 -0400 @@ -17,8 +17,11 @@ * for more details. */ +#include "lswlog.h" /* for LSWLOG_PEXPECT() */ + #include "ikev1_prf.h" +#include "ike_alg.h" #include "crypt_prf.h" #include "crypt_symkey.h" @@ -32,6 +35,25 @@ const chunk_t Nr, /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */) { +#ifdef USE_NSS_PRF + CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bDataAsKey = CK_TRUE, + .bRekey = CK_FALSE, + .pNi = Ni.ptr, + .ulNiLen = Ni.len, + .pNr = Nr.ptr, + .ulNrLen = Nr.len, + }; + SECItem params = { + .data = (unsigned char *)&ike_prf_params, + .len = sizeof(ike_prf_params), + }; + + return PK11_Derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, + CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, + 0); +#else /* key = Ni|Nr */ chunk_t key = clone_chunk_chunk(Ni, Nr, "key = Ni|Nr"); struct crypt_prf *prf = crypt_prf_init_chunk("SKEYID sig", @@ -42,6 +64,7 @@ crypt_prf_update_symkey(prf, "g^xy", dh_secret); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -51,6 +74,33 @@ chunk_t pre_shared_key, chunk_t Ni, chunk_t Nr) { +#ifdef USE_NSS_PRF + PK11SymKey *psk = prf_key_from_bytes("psk", prf_desc, + pre_shared_key.ptr, pre_shared_key.len); + PK11SymKey *skeyid; + if (psk == NULL) { + return NULL; + } + + CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bDataAsKey = CK_FALSE, + .bRekey = CK_FALSE, + .pNi = Ni.ptr, + .ulNiLen = Ni.len, + .pNr = Nr.ptr, + .ulNrLen = Nr.len, + }; + SECItem params = { + .data = (unsigned char *)&ike_prf_params, + .len = sizeof(ike_prf_params), + }; + skeyid = PK11_Derive(psk, CKM_NSS_IKE_PRF_DERIVE, ¶ms, + CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, + 0 ); + release_symkey("SKEYID psk", "psk", &psk); + return skeyid; +#else /* key = pre-shared-key */ struct crypt_prf *prf = crypt_prf_init_chunk("SKEYID psk", prf_desc, "psk", pre_shared_key); @@ -59,6 +109,7 @@ crypt_prf_update_chunk(prf, "Nr", Nr); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -69,6 +120,26 @@ PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { +#ifdef USE_NSS_PRF + CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bHasPrevKey = CK_FALSE, + .hKeygxy = PK11_GetSymKeyHandle(dh_secret), + .pCKYi = cky_i.ptr, + .ulCKYiLen = cky_i.len, + .pCKYr = cky_r.ptr, + .ulCKYrLen = cky_r.len, + .keyNumber = 0, + }; + SECItem params = { + .data = (unsigned char *)&ike1_prf_params, + .len = sizeof(ike1_prf_params), + }; + + return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, + CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, + 0); +#else /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_d", prf_desc, "SKEYID", skeyid); @@ -79,6 +150,7 @@ crypt_prf_update_byte(prf, "0", 0); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -89,6 +161,27 @@ PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { +#ifdef USE_NSS_PRF + CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bHasPrevKey = CK_TRUE, + .hKeygxy = PK11_GetSymKeyHandle(dh_secret), + .hPrevKey = PK11_GetSymKeyHandle(skeyid_d), + .pCKYi = cky_i.ptr, + .ulCKYiLen = cky_i.len, + .pCKYr = cky_r.ptr, + .ulCKYrLen = cky_r.len, + .keyNumber = 1, + }; + SECItem params = { + .data = (unsigned char *)&ike1_prf_params, + .len = sizeof(ike1_prf_params), + }; + + return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, + CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, + 0); +#else /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_a", prf_desc, "SKEYID", skeyid); @@ -100,6 +193,7 @@ crypt_prf_update_byte(prf, "1", 1); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -110,6 +204,27 @@ PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { +#ifdef USE_NSS_PRF + CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bHasPrevKey = CK_TRUE, + .hKeygxy = PK11_GetSymKeyHandle(dh_secret), + .hPrevKey = PK11_GetSymKeyHandle(skeyid_a), + .pCKYi = cky_i.ptr, + .ulCKYiLen = cky_i.len, + .pCKYr = cky_r.ptr, + .ulCKYrLen = cky_r.len, + .keyNumber = 2, + }; + SECItem params = { + .data = (unsigned char *)&ike1_prf_params, + .len = sizeof(ike1_prf_params), + }; + + return PK11_Derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, + CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, + 0); +#else /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_e", prf_desc, "SKEYID", skeyid); @@ -121,6 +236,7 @@ crypt_prf_update_byte(prf, "2", 2); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } PK11SymKey *appendix_b_keymat_e(const struct prf_desc *prf_desc, @@ -128,6 +244,20 @@ PK11SymKey *skeyid_e, unsigned required_keymat) { +#ifdef USE_NSS_PRF + CK_MECHANISM_TYPE mechanism = prf_desc->nss.mechanism; + CK_MECHANISM_TYPE target = encrypter->nss.mechanism; + SECItem params = { + .data = (unsigned char *)&mechanism, + .len = sizeof(mechanism), + }; + /* for when ENCRYPTER isn't NSS */ + if (target == 0) target = CKM_EXTRACT_KEY_FROM_KEY; + + return PK11_DeriveWithFlags(skeyid_e, CKM_NSS_IKE1_APP_B_PRF_DERIVE, + ¶ms, target, CKA_ENCRYPT, + required_keymat, CKF_DECRYPT); +#else if (sizeof_symkey(skeyid_e) >= required_keymat) { return encrypt_key_from_symkey_bytes("keymat", encrypter, 0, required_keymat, @@ -160,4 +290,5 @@ keymat); release_symkey(__func__, "keymat", &keymat); return cryptkey; +#endif } diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_prf.c libreswan-3.29/programs/pluto/ikev2_prf.c --- libreswan-3.29-orig/programs/pluto/ikev2_prf.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/ikev2_prf.c 2019-08-11 13:33:13.680951735 -0400 @@ -32,12 +32,44 @@ /* * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. */ +#ifdef USE_NSS_PRF +static PK11SymKey *ikev2_prfplus_key_data( + const struct prf_desc *prf_desc, + PK11SymKey *key, + PK11SymKey *seed_key, + chunk_t seed_data, + size_t required_keymat) +{ + CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike_prf_plus_params = { + .pSeedData = seed_data.ptr, + .ulSeedDataLen = seed_data.len, + .prfMechanism = prf_desc->nss.mechanism, + }; + if (seed_key == NULL) { + ike_prf_plus_params.bHasSeedKey = CK_FALSE; + } else { + ike_prf_plus_params.bHasSeedKey = CK_TRUE; + ike_prf_plus_params.hSeedKey = PK11_GetSymKeyHandle(seed_key); + } + SECItem params = { + .data = (unsigned char *)&ike_prf_plus_params, + .len = sizeof(ike_prf_plus_params), + }; + + return PK11_Derive(key, CKM_NSS_IKE_PRF_PLUS_DERIVE, ¶ms, + CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, + required_keymat); +} +#endif PK11SymKey *ikev2_prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat) { +#ifdef USE_NSS_PRF + return ikev2_prfplus_key_data(prf_desc, key, seed, empty_chunk, required_keymat); +#else uint8_t count = 1; /* T1(prfplus) = prf(KEY, SEED|1) */ @@ -66,6 +98,7 @@ } release_symkey(__func__, "old_t[final]", &old_t); return prfplus; +#endif } /* @@ -77,6 +110,33 @@ const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { + +#ifdef USE_NSS_PRF + int is_aes_prf = 0; + switch (prf_desc->common.id[IKEv2_ALG_ID]) { + case IKEv2_PRF_AES128_CMAC: + case IKEv2_PRF_AES128_XCBC: + is_aes_prf = 1; + } + + CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bDataAsKey = CK_TRUE, + .bRekey = CK_FALSE, + .pNi = Ni.ptr, + .ulNiLen = is_aes_prf ? BYTES_FOR_BITS(64) : Ni.len, + .pNr = Nr.ptr, + .ulNrLen = is_aes_prf ? BYTES_FOR_BITS(64) : Nr.len, + }; + SECItem params = { + .data = (unsigned char *)&ike_prf_params, + .len = sizeof(ike_prf_params), + }; + + return PK11_Derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, + CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, + 0); +#else /* * 2.14. Generating Keying Material for the IKE SA * @@ -117,6 +177,7 @@ crypt_prf_update_symkey(prf, "g^ir", dh_secret); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -127,6 +188,26 @@ PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr) { +#ifdef USE_NSS_PRF + CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { + .prfMechanism = prf_desc->nss.mechanism, + .bDataAsKey = CK_FALSE, + .bRekey = CK_TRUE, + .hNewKey = PK11_GetSymKeyHandle(new_dh_secret), + .pNi = Ni.ptr, + .ulNiLen = Ni.len, + .pNr = Nr.ptr, + .ulNrLen = Nr.len, + }; + SECItem params = { + .data = (unsigned char *)&ike_prf_params, + .len = sizeof(ike_prf_params), + }; + + return PK11_Derive(SK_d_old, CKM_NSS_IKE_PRF_DERIVE, ¶ms, + CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, + 0); +#else /* key = SK_d (old) */ struct crypt_prf *prf = crypt_prf_init_symkey("ike sa rekey skeyseed", prf_desc, "SK_d (old)", SK_d_old); @@ -141,6 +222,7 @@ crypt_prf_update_chunk(prf, "Nr", Nr); /* generate */ return crypt_prf_final_symkey(&prf); +#endif } /* @@ -152,6 +234,17 @@ const ike_spis_t *SPIir, size_t required_bytes) { +#ifdef USE_NSS_PRF + chunk_t seed_data; + PK11SymKey *prf_plus; + + seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); + append_chunk_bytes("seed_data = Nir || SPIi", &seed_data, &SPIir->initiator, sizeof(SPIir->initiator)); + append_chunk_bytes("seed_data = Nir || SPIir", &seed_data, &SPIir->responder, sizeof(SPIir->responder)); + prf_plus = ikev2_prfplus_key_data(prf_desc, skeyseed, NULL, seed_data, required_bytes); + freeanychunk(seed_data); + return prf_plus; +#else PK11SymKey *data = symkey_from_chunk("data", Ni); append_symkey_chunk(&data, Nr); append_symkey_bytes(&data, &SPIir->initiator, sizeof(SPIir->initiator)); @@ -161,6 +254,7 @@ required_bytes); release_symkey(__func__, "data", &data); return prfplus; +#endif } /* @@ -172,6 +266,24 @@ const chunk_t Ni, const chunk_t Nr, size_t required_bytes) { + if (required_bytes == 0) { + /* + * For instance esp=null-none. Caller should + * interpret NULL to mean empty (NSS doesn't create + * zero length keys). + */ + dbg("No CHILD SA KEMAT is required"); + return NULL; + } +#ifdef USE_NSS_PRF + chunk_t seed_data; + PK11SymKey *prf_plus; + + seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); + prf_plus = ikev2_prfplus_key_data(prf_desc, SK_d, new_dh_secret, seed_data, required_bytes); + freeanychunk(seed_data); + return prf_plus; +#else PK11SymKey *data; if (new_dh_secret == NULL) { data = symkey_from_chunk("data", Ni); @@ -185,4 +297,5 @@ required_bytes); release_symkey(__func__, "data", &data); return prfplus; +#endif } diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_psk.c libreswan-3.29/programs/pluto/ikev2_psk.c --- libreswan-3.29-orig/programs/pluto/ikev2_psk.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/ikev2_psk.c 2019-08-11 13:31:13.858294817 -0400 @@ -181,6 +181,36 @@ PK11SymKey *prf_psk; { + static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ +#ifdef USE_NSS_PRF + CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params; + SECItem params; + CK_MECHANISM_TYPE prf_mech = st->st_oakley.ta_prf->nss.mechanism; + PK11SymKey *pss_key = prf_key_from_bytes("pss", st->st_oakley.ta_prf, + pss->ptr, pss->len); + if (pss_key == NULL) { + if (libreswan_fipsmode()) { + PASSERT_FAIL("FIPS: failure creating %s PRF context for digesting PSK", + st->st_oakley.ta_prf->common.name); + } + loglog(RC_LOG_SERIOUS, + "failure creating %s PRF context for digesting PSK", + st->st_oakley.ta_prf->common.name); + return FALSE; + } + + ike_prf_params.prfMechanism = prf_mech; + ike_prf_params.bDataAsKey = CK_FALSE; + ike_prf_params.bRekey = CK_FALSE; + ike_prf_params.pNi = (CK_BYTE_PTR) psk_key_pad_str; + ike_prf_params.ulNiLen = sizeof(psk_key_pad_str) - 1; + ike_prf_params.pNr = NULL; + ike_prf_params.ulNrLen = 0; + params.data = (unsigned char *)&ike_prf_params; + params.len = sizeof(ike_prf_params); + prf_psk = PK11_Derive(pss_key, CKM_NSS_IKE_PRF_DERIVE, ¶ms, prf_mech, CKA_SIGN, 0); + release_symkey("psk pss_key", "pss_key", &pss_key); +#else struct crypt_prf *prf = crypt_prf_init_chunk(" = prf(,\"Key Pad for IKEv2\")", st->st_oakley.ta_prf, @@ -196,12 +226,11 @@ return FALSE; } - static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ - crypt_prf_update_bytes(prf, psk_key_pad_str, /* name */ psk_key_pad_str, sizeof(psk_key_pad_str) - 1); prf_psk = crypt_prf_final_symkey(&prf); +#endif } /* calculate outer prf */ diff -Naur libreswan-3.29-orig/programs/pluto/plutomain.c libreswan-3.29/programs/pluto/plutomain.c --- libreswan-3.29-orig/programs/pluto/plutomain.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/plutomain.c 2019-08-11 13:31:13.859294831 -0400 @@ -189,6 +189,11 @@ #ifdef NSS_IPSEC_PROFILE " (IPsec profile)" #endif +#ifdef USE_NSS_PRF + " (NSS-PRF)" +#else + " (native-PRF)" +#endif #ifdef USE_DNSSEC " DNSSEC" #endif diff -Naur libreswan-3.29-orig/programs/pluto/prf_test_vectors.c libreswan-3.29/programs/pluto/prf_test_vectors.c --- libreswan-3.29-orig/programs/pluto/prf_test_vectors.c 2019-06-10 10:22:04.000000000 -0400 +++ libreswan-3.29/programs/pluto/prf_test_vectors.c 2019-08-11 13:31:13.860294845 -0400 @@ -34,6 +34,7 @@ * Ref: https://tools.ietf.org/html/rfc4435: Test Vectors */ +#ifdef USE_PRF_AES_XCBC const struct prf_test_vectors aes_xcbc_prf_tests = { .prf = &ike_alg_prf_aes_xcbc, .tests = { @@ -105,6 +106,10 @@ .message = "0x000102030405060708090a0b0c0d0e0f10111213", .prf_output = "0x47f51b4564966215b8985c63055ed308", }, + /* + * XXX: for some reason NSS explodes when trying to + * create a non-standard AES_XCBC_MAC key. + */ { .description = "Test Case AES-XCBC-PRF-128 with 20-byte input (key length 10)", .key = "0x00010203040506070809", @@ -124,7 +129,9 @@ } }, }; +#endif +/* So far we only have AES_XCBC PRF test vectors :/ */ static bool test_prf_vector(const struct prf_desc *prf, const struct prf_test_vector *test) { @@ -137,7 +144,6 @@ : alloc_chunk(test->message_size, __func__); chunk_t prf_output = decode_to_chunk(__func__, test->prf_output); - /* chunk interface */ struct crypt_prf *chunk_prf = crypt_prf_init_chunk("PRF chunk interface", prf, "key", chunk_key);