Blame SOURCES/libreswan-3.29-1714331-nss-kdf.patch

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