diff --git a/.gitignore b/.gitignore
index d372f53..c47bf85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
+SOURCES/ikev1_dsa.fax.bz2
+SOURCES/ikev1_psk.fax.bz2
+SOURCES/ikev2.fax.bz2
SOURCES/libreswan-3.12.tar.gz
diff --git a/.libreswan.metadata b/.libreswan.metadata
index effea6f..3e211e5 100644
--- a/.libreswan.metadata
+++ b/.libreswan.metadata
@@ -1 +1,4 @@
+b35cd50b8bc0a08b9c07713bf19c72d53bfe66bb SOURCES/ikev1_dsa.fax.bz2
+861d97bf488f9e296cad8c43ab72f111a5b1a848 SOURCES/ikev1_psk.fax.bz2
+fcaf77f3deae3d8e99cdb3b1f8abea63167a0633 SOURCES/ikev2.fax.bz2
bca50e25b044df1b9fc4b732be38b28c25216674 SOURCES/libreswan-3.12.tar.gz
diff --git a/SOURCES/libreswan-3.12-1170018-netlink-label.patch b/SOURCES/libreswan-3.12-1170018-netlink-label.patch
new file mode 100644
index 0000000..2b11cae
--- /dev/null
+++ b/SOURCES/libreswan-3.12-1170018-netlink-label.patch
@@ -0,0 +1,124 @@
+diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.c libreswan-3.12/programs/pluto/kernel_netlink.c
+--- libreswan-3.12-orig/programs/pluto/kernel_netlink.c 2015-02-26 22:02:15.641000000 -0600
++++ libreswan-3.12/programs/pluto/kernel_netlink.c 2015-02-26 22:04:29.990000000 -0600
+@@ -426,7 +426,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct nlmsgerr e;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+ size_t len;
+ ssize_t r;
+@@ -547,7 +547,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct nlmsgerr e;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+ int error;
+
+@@ -610,7 +610,7 @@
+ struct xfrm_userpolicy_info p;
+ struct xfrm_userpolicy_id id;
+ } u;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } req;
+ int shift;
+ int dir;
+@@ -907,7 +907,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_info p;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } req;
+ struct rtattr *attr;
+ const struct aead_alg *aead;
+@@ -1233,7 +1233,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_id id;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } req;
+
+ zero(&req);
+@@ -1513,7 +1513,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_userpolicy_info pol;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe))) {
+@@ -1569,7 +1569,7 @@
+ {
+ struct {
+ struct nlmsghdr n;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+ ssize_t r;
+ struct sockaddr_nl addr;
+@@ -1650,7 +1650,7 @@
+ struct nlmsgerr e;
+ struct xfrm_usersa_info sa;
+ } u;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+ static bool get_cpi_bug = FALSE; /* sticky after failure */
+
+@@ -2235,7 +2235,7 @@
+ struct {
+ struct nlmsghdr n;
+ struct xfrm_usersa_info info;
+- char data[1024];
++ char data[MAX_NETLINK_DATA_SIZE];
+ } rsp;
+
+ zero(&req);
+diff -Naur libreswan-3.12-orig/programs/pluto/kernel_netlink.h libreswan-3.12/programs/pluto/kernel_netlink.h
+--- libreswan-3.12-orig/programs/pluto/kernel_netlink.h 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/pluto/kernel_netlink.h 2015-02-26 22:02:44.521000000 -0600
+@@ -15,4 +15,13 @@
+
+ #if defined(linux) && defined(NETKEY_SUPPORT)
+ extern const struct kernel_ops netkey_kernel_ops;
++/*
++ * The socket buffer is used to queue netlink messages between sender and
++ * receiver. The size of these buffers specifies the maximum size you will be
++ * able to write() to a netlink socket, i.e. it will indirectly define the
++ * maximum message size. The default is 32KiB. For now we picked a somewhat
++ * arbitrary maximum of 8192 for the data portion to accomdate large selinux
++ * IPsec labels (see rhbz#1154784)
++ */
++#define MAX_NETLINK_DATA_SIZE 8192
+ #endif
+diff -Naur libreswan-3.12-orig/programs/pluto/state.h libreswan-3.12/programs/pluto/state.h
+--- libreswan-3.12-orig/programs/pluto/state.h 2015-02-26 22:02:15.658000000 -0600
++++ libreswan-3.12/programs/pluto/state.h 2015-02-26 22:02:44.521000000 -0600
+@@ -195,10 +195,16 @@
+ };
+
+ #ifdef HAVE_LABELED_IPSEC
+-/* security label length should not exceed 256 in most cases,
+- * (discussed with kernel and selinux people).
++/*
++ * While security label length usually does not exceed 256,
++ * there have been requests (rhbz#1154784) for using larger
++ * labels. The maximum label size is PAGE_SIZE (4096 on a
++ * x86_64, but 64kb on ppc64). However, this label has to fit
++ * inside a netlink message whose maximum size is 32KiB.
++ * For now we picked the somewhat arbitrary size of 4096.
+ */
+-#define MAX_SECCTX_LEN 257 /* including '\0'*/
++#define MAX_SECCTX_LEN 4096 /* including '\0'*/
++
+ struct xfrm_user_sec_ctx_ike {
+ u_int16_t len;
+ u_int16_t exttype;
diff --git a/SOURCES/libreswan-3.12-1182224-bsi-random.patch b/SOURCES/libreswan-3.12-1182224-bsi-random.patch
new file mode 100644
index 0000000..7810a7b
--- /dev/null
+++ b/SOURCES/libreswan-3.12-1182224-bsi-random.patch
@@ -0,0 +1,571 @@
+diff -Naur libreswan-3.12-orig/include/ipsecconf/keywords.h libreswan-3.12/include/ipsecconf/keywords.h
+--- libreswan-3.12-orig/include/ipsecconf/keywords.h 2015-02-26 21:24:52.037000000 -0600
++++ libreswan-3.12/include/ipsecconf/keywords.h 2015-02-26 21:25:39.297000000 -0600
+@@ -83,6 +83,7 @@
+ KBF_STRICTCRLPOLICY,
+ KBF_SEND_CA,
+ KBF_NATIKEPORT,
++ KBF_SEEDBITS,
+ KBF_KEEPALIVE,
+ KBF_PLUTORESTARTONCRASH,
+ KBF_CRLCHECKINTERVAL,
+diff -Naur libreswan-3.12-orig/lib/libipsecconf/confread.c libreswan-3.12/lib/libipsecconf/confread.c
+--- libreswan-3.12-orig/lib/libipsecconf/confread.c 2015-02-26 21:24:52.038000000 -0600
++++ libreswan-3.12/lib/libipsecconf/confread.c 2015-02-26 21:25:39.297000000 -0600
+@@ -98,6 +98,10 @@
+
+ cfg->setup.options[KBF_KEEPALIVE] = 0; /* config setup */
+ cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT;
++
++ /* Don't inflict BSI requirements on everyone */
++ cfg->setup.options[KBF_SEEDBITS] = 0;
++
+ #ifdef HAVE_LABELED_IPSEC
+ cfg->setup.options[KBF_SECCTX] = SECCTX;
+ #endif
+diff -Naur libreswan-3.12-orig/lib/libipsecconf/keywords.c libreswan-3.12/lib/libipsecconf/keywords.c
+--- libreswan-3.12-orig/lib/libipsecconf/keywords.c 2015-02-26 21:24:52.038000000 -0600
++++ libreswan-3.12/lib/libipsecconf/keywords.c 2015-02-26 21:25:39.298000000 -0600
+@@ -369,6 +369,7 @@
+ { "virtual-private", kv_config, kt_string, KSF_VIRTUALPRIVATE, NOT_ENUM },
+ { "nat_ikeport", kv_config | kv_alias, kt_number, KBF_NATIKEPORT, NOT_ENUM }, /* obsolete _ */
+ { "nat-ikeport", kv_config, kt_number, KBF_NATIKEPORT, NOT_ENUM },
++ { "seedbits", kv_config, kt_number, KBF_SEEDBITS, NOT_ENUM },
+ { "keep_alive", kv_config | kv_alias, kt_number, KBF_KEEPALIVE, NOT_ENUM }, /* obsolete _ */
+ { "keep-alive", kv_config, kt_number, KBF_KEEPALIVE, NOT_ENUM },
+ { "nat_traversal", kv_config, kt_obsolete_quiet, KBF_WARNIGNORE, NOT_ENUM },
+diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/order.txt libreswan-3.12/programs/configs/d.ipsec.conf/order.txt
+--- libreswan-3.12-orig/programs/configs/d.ipsec.conf/order.txt 2015-02-26 21:24:52.040000000 -0600
++++ libreswan-3.12/programs/configs/d.ipsec.conf/order.txt 2015-02-26 21:25:39.298000000 -0600
+@@ -89,6 +89,7 @@
+ d.ipsec.conf/myvendorid.xml
+ d.ipsec.conf/oe.xml
+ d.ipsec.conf/nhelpers.xml
++d.ipsec.conf/seedbits.xml
+ d.ipsec.conf/secctx-attr-value.xml
+ d.ipsec.conf/plutofork.xml
+ d.ipsec.conf/crlcheckinterval.xml
+diff -Naur libreswan-3.12-orig/programs/configs/d.ipsec.conf/seedbits.xml libreswan-3.12/programs/configs/d.ipsec.conf/seedbits.xml
+--- libreswan-3.12-orig/programs/configs/d.ipsec.conf/seedbits.xml 1969-12-31 18:00:00.000000000 -0600
++++ libreswan-3.12/programs/configs/d.ipsec.conf/seedbits.xml 2015-02-26 21:25:39.299000000 -0600
+@@ -0,0 +1,15 @@
++
++ seedbits
++
++
++Pluto uses the NSS crypto library as its random source. Some government
++Three Letter Agencies require that pluto reads additional bits from /dev/random
++and feed these into the NSS RNG before drawing random from the NSS library,
++despite the NSS library itself already seeding its internal state. This
++process can block pluto for an extended time during startup, depending on
++the entropy of the system. Therefor, the default is to not perform this
++redundant seeding. If specifying a value, it is recommended to specify at
++least 460 bits (for FIPS) or 440 bits (for BSI).
++
++
++
+diff -Naur libreswan-3.12-orig/programs/pluto/pluto.8 libreswan-3.12/programs/pluto/pluto.8
+--- libreswan-3.12-orig/programs/pluto/pluto.8 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/pluto/pluto.8 2015-02-26 21:25:39.299000000 -0600
+@@ -2,12 +2,12 @@
+ .\" Title: IPSEC_PLUTO
+ .\" Author: Paul Wouters
+ .\" Generator: DocBook XSL Stylesheets v1.78.1
+-.\" Date: 10/22/2014
++.\" Date: 01/14/2015
+ .\" Manual: Executable programs
+ .\" Source: libreswan
+ .\" Language: English
+ .\"
+-.TH "IPSEC_PLUTO" "8" "10/22/2014" "libreswan" "Executable programs"
++.TH "IPSEC_PLUTO" "8" "01/14/2015" "libreswan" "Executable programs"
+ .\" -----------------------------------------------------------------
+ .\" * Define some portability stuff
+ .\" -----------------------------------------------------------------
+@@ -31,7 +31,7 @@
+ pluto \- ipsec whack : IPsec IKE keying daemon and control interface
+ .SH "SYNOPSIS"
+ .HP \w'\fBipsec\fR\ 'u
+-\fBipsec\fR \fIpluto\fR [\-\-help] [\-\-version] [\-\-leak\-detective] [\-\-config\ \fIfilename\fR] [\-\-vendorid\ \fIVID\fR] [\-\-nofork] [\-\-stderrlog] [\-\-\-\-plutostderrlogtime] [\-\-logfile\ \fIfilename\fR] [\-\-use\-klips] [\-\-use\-mast] [\-\-use\-netkey] [\-\-use\-nostack] [\-\-uniqueids] [\-\-virtual\-private\ \fInetwork_list\fR] [\-\-keep\-alive\ \fIdelay_sec\fR] [\-\-force\-busy] [\-\-nocrsend] [\-\-strictcrlpolicy] [\-\-crlcheckinterval] [\-\-interface\ \fIinterfacename\fR] [\-\-listen\ \fIipaddr\fR] [\-\-ikeport\ \fIportnumber\fR] [\-\-natikeport\ \fIportnumber\fR] [\-\-ctlbase\ \fIpath\fR] [\-\-secretsfile\ \fIsecrets\-file\fR] [\-\-adns\ \fIpathname\fR] [\-\-nhelpers\ \fInumber\fR] [\-\-perpeerlog] [\-\-perpeerlogbase\ \fIdirname\fR] [\-\-ipsecdir\ \fIdirname\fR] [\-\-coredir\ \fIdirname\fR] [\-\-statsbin\ \fIfilename\fR] [\-\-secctx\-attr\-value\ \fInumber\fR]
++\fBipsec\fR \fIpluto\fR [\-\-help] [\-\-version] [\-\-leak\-detective] [\-\-config\ \fIfilename\fR] [\-\-vendorid\ \fIVID\fR] [\-\-nofork] [\-\-stderrlog] [\-\-\-\-plutostderrlogtime] [\-\-logfile\ \fIfilename\fR] [\-\-use\-klips] [\-\-use\-mast] [\-\-use\-netkey] [\-\-use\-nostack] [\-\-uniqueids] [\-\-virtual\-private\ \fInetwork_list\fR] [\-\-keep\-alive\ \fIdelay_sec\fR] [\-\-force\-busy] [\-\-nocrsend] [\-\-strictcrlpolicy] [\-\-crlcheckinterval] [\-\-interface\ \fIinterfacename\fR] [\-\-listen\ \fIipaddr\fR] [\-\-ikeport\ \fIportnumber\fR] [\-\-natikeport\ \fIportnumber\fR] [\-\-ctlbase\ \fIpath\fR] [\-\-secretsfile\ \fIsecrets\-file\fR] [\-\-adns\ \fIpathname\fR] [\-\-nhelpers\ \fInumber\fR] [\-\-seedbits\ \fInumbits\fR] [\-\-perpeerlog] [\-\-perpeerlogbase\ \fIdirname\fR] [\-\-ipsecdir\ \fIdirname\fR] [\-\-coredir\ \fIdirname\fR] [\-\-statsbin\ \fIfilename\fR] [\-\-secctx\-attr\-value\ \fInumber\fR]
+ .HP \w'\fBipsec\fR\ 'u
+ \fBipsec\fR \fIwhack\fR [\-\-help] [\-\-version]
+ .HP \w'\fBipsec\fR\ 'u
+@@ -317,6 +317,10 @@
+ \fI\-1\fR
+ tells pluto to perform the above calculation\&. Any other value forces the number to that amount\&.
+ .PP
++Pluto uses the NSS crypto library as its random source\&. Some government Three Letter Agency requires that pluto reads 440 bits from /dev/random and feed this into the NSS RNG before drawing random from the NSS library, despite the NSS library itself already seeding its internal state\&. As this process can block pluto for an extended time, the default is to not perform this redundant seeding\&. The
++\fB\-\-seedbits\fR
++option can be used to specify the number of bits that will be pulled from /dev/random and seeded into the NSS RNG\&. This can also be accomplished by specifying seedbits in the "config setup" section of ipsec\&.conf\&. This option should not be used by most people\&.
++.PP
+ \fBpluto\fR
+ attempts to create a lockfile with the name
+ /var/run/pluto/pluto\&.pid\&. If the lockfile cannot be created,
+diff -Naur libreswan-3.12-orig/programs/pluto/pluto.8.xml libreswan-3.12/programs/pluto/pluto.8.xml
+--- libreswan-3.12-orig/programs/pluto/pluto.8.xml 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/pluto/pluto.8.xml 2015-02-26 21:25:39.300000000 -0600
+@@ -57,6 +57,7 @@
+ --secretsfile secrets-file
+ --adns pathname
+ --nhelpers number
++ --seedbits numbits
+ --perpeerlog
+ --perpeerlogbase dirname
+ --ipsecdir dirname
+@@ -984,6 +985,18 @@
+ -1 tells pluto to perform the above
+ calculation. Any other value forces the number to that amount.
+
++ Pluto uses the NSS crypto library as its random source. Some
++ government Three Letter Agency requires that pluto reads 440 bits
++ from /dev/random and feed this into the NSS RNG before drawing
++ random from the NSS library, despite the NSS library itself
++ already seeding its internal state. As this process can block
++ pluto for an extended time, the default is to not perform this
++ redundant seeding. The --seedbits
++ option can be used to specify the number of bits that will be
++ pulled from /dev/random and seeded into the NSS RNG. This can
++ also be accomplished by specifying seedbits in the "config setup"
++ section of ipsec.conf. This option should not be used by most people.
++
+ pluto attempts to create a lockfile
+ with the name /var/run/pluto/pluto.pid. If the
+ lockfile cannot be created, pluto exits -
+diff -Naur libreswan-3.12-orig/programs/pluto/plutomain.c libreswan-3.12/programs/pluto/plutomain.c
+--- libreswan-3.12-orig/programs/pluto/plutomain.c 2015-02-26 21:24:52.012000000 -0600
++++ libreswan-3.12/programs/pluto/plutomain.c 2015-02-26 21:25:39.301000000 -0600
+@@ -111,6 +111,7 @@
+ /* pulled from main for show_setup_plutomain() */
+ static const struct lsw_conf_options *oco;
+ static char *coredir;
++static int pluto_nss_seedbits;
+ static int nhelpers = -1;
+
+ libreswan_passert_fail_t libreswan_passert_fail = passert_fail;
+@@ -314,6 +315,49 @@
+ *target = strdup(value);
+ }
+
++/*
++ * This function MUST NOT be used for anything else!
++ * It is used to seed the NSS PRNG based on --seedbits pluto argument
++ * or the seedbits= * config setup option in ipsec.conf.
++ * Everything else that needs random MUST use get_rnd_bytes()
++ * This function MUST NOT be changed to use /dev/urandom.
++ */
++static void get_bsi_random(size_t nbytes, unsigned char *buf)
++{
++ size_t ndone;
++ int dev;
++ ssize_t got;
++ const char *device = "/dev/random";
++
++ dev = open(device, 0);
++ if (dev < 0) {
++ loglog(RC_LOG_SERIOUS, "could not open %s (%s)\n",
++ device, strerror(errno));
++ exit_pluto(6);
++ }
++
++ ndone = 0;
++ DBG(DBG_CONTROL,DBG_log("need %d bits random for extra seeding of the NSS PRNG",
++ (int) nbytes * BITS_PER_BYTE));
++
++ while (ndone < nbytes) {
++ got = read(dev, buf + ndone, nbytes - ndone);
++ if (got < 0) {
++ loglog(RC_LOG_SERIOUS,"read error on %s (%s)\n",
++ device, strerror(errno));
++ exit_pluto(6);
++ }
++ if (got == 0) {
++ loglog(RC_LOG_SERIOUS,"EOF on %s!?!\n", device);
++ exit_pluto(6);
++ }
++ ndone += got;
++ }
++ close(dev);
++ DBG(DBG_CONTROL,DBG_log("read %ld bytes from /dev/random for NSS PRNG",
++ nbytes));
++}
++
+ static void pluto_init_nss(char *confddir)
+ {
+ SECStatus nss_init_status;
+@@ -328,6 +372,23 @@
+ libreswan_log("NSS Initialized");
+ PK11_SetPasswordFunc(getNSSPassword);
+ }
++
++ /*
++ * This exists purely to make the BSI happy.
++ * We do not infliect this on other users
++ */
++ if (pluto_nss_seedbits != 0) {
++ SECStatus rv;
++ int seedbytes = BYTES_FOR_BITS(pluto_nss_seedbits);
++ unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix");
++
++ get_bsi_random(seedbytes, buf); /* much TLA, very blocking */
++ rv = PK11_RandomUpdate(buf, seedbytes);
++ libreswan_log("seeded %d bytes into the NSS PRNG", seedbytes);
++ passert(rv == SECSuccess);
++ zero(&buf);
++ pfree(buf);
++ }
+ }
+
+ /* by default the CRL policy is lenient */
+@@ -417,6 +478,7 @@
+ { "virtual_private\0_", required_argument, NULL, '6' }, /* _ */
+ { "virtual-private\0", required_argument, NULL, '6' },
+ { "nhelpers\0", required_argument, NULL, 'j' },
++ { "seedbits\0", required_argument, NULL, 'c' },
+ #ifdef HAVE_LABELED_IPSEC
+ { "secctx_attr_value\0_", required_argument, NULL, 'w' }, /* _ */
+ { "secctx-attr-value\0", required_argument, NULL, 'w' },
+@@ -692,6 +754,14 @@
+ nhelpers = u;
+ }
+ continue;
++ case 'c': /* --seedbits */
++ pluto_nss_seedbits = atoi(optarg);
++ if (pluto_nss_seedbits == 0) {
++ printf("pluto: seedbits must be an integer > 0");
++ /* not exit_pluto because we are not initialized yet */
++ exit(6);
++ }
++ continue;
+
+ #ifdef HAVE_LABELED_IPSEC
+ case 'w': /* --secctx-attr-value */
+@@ -969,6 +1039,7 @@
+ }
+ }
+
++ pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS];
+ pluto_nat_port =
+ cfg->setup.options[KBF_NATIKEPORT];
+ keep_alive = cfg->setup.options[KBF_KEEPALIVE];
+@@ -1473,3 +1544,4 @@
+ whack_log(RC_COMMENT, "secctx-attr-value=");
+ #endif
+ }
++
+diff -Naur libreswan-3.12-orig/programs/rsasigkey/Makefile libreswan-3.12/programs/rsasigkey/Makefile
+--- libreswan-3.12-orig/programs/rsasigkey/Makefile 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/rsasigkey/Makefile 2015-02-26 21:25:39.301000000 -0600
+@@ -16,7 +16,7 @@
+ include ${LIBRESWANSRCDIR}/Makefile.inc
+
+ PROGRAM=rsasigkey
+-LIBS=${LIBRESWANLIB} -lgmp
++LIBS=${LSWLOGLIB} ${LIBRESWANLIB} -lgmp
+ LIBS+=${NSSLIBS}
+
+ ifeq ($(USE_FIPSCHECK),true)
+diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8 libreswan-3.12/programs/rsasigkey/rsasigkey.8
+--- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/rsasigkey/rsasigkey.8 2015-02-26 21:25:39.302000000 -0600
+@@ -2,12 +2,12 @@
+ .\" Title: IPSEC_RSASIGKEY
+ .\" Author: Paul Wouters
+ .\" Generator: DocBook XSL Stylesheets v1.78.1
+-.\" Date: 09/06/2013
++.\" Date: 01/14/2015
+ .\" Manual: Executable programs
+ .\" Source: libreswan
+ .\" Language: English
+ .\"
+-.TH "IPSEC_RSASIGKEY" "8" "09/06/2013" "libreswan" "Executable programs"
++.TH "IPSEC_RSASIGKEY" "8" "01/14/2015" "libreswan" "Executable programs"
+ .\" -----------------------------------------------------------------
+ .\" * Define some portability stuff
+ .\" -----------------------------------------------------------------
+@@ -31,9 +31,7 @@
+ ipsec_rsasigkey \- generate RSA signature key
+ .SH "SYNOPSIS"
+ .HP \w'\fBipsec\fR\ 'u
+-\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-random\ \fIfilename\fR] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR] [nbits]
+-.HP \w'\fBipsec\fR\ 'u
+-\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR]
++\fBipsec\fR \fIrsasigkey\fR [\-\-verbose] [\-\-random\ \fIdevice\fR] [\-\-seed\ \fInumbits\fR] [\-\-configdir\ \fInssdbdir\fR] [\-\-password\ \fInsspassword\fR] [\-\-hostname\ \fIhostname\fR] [nbits]
+ .SH "DESCRIPTION"
+ .PP
+ \fIRsasigkey\fR
+@@ -50,7 +48,8 @@
+ .PP
+ The
+ \fB\-\-verbose\fR
+-option makes\fIrsasigkey\fR
++option makes
++\fIrsasigkey\fR
+ give a running commentary on standard error\&. By default, it works in silence until it is ready to generate output\&.
+ .PP
+ The
+@@ -58,9 +57,15 @@
+ option specifies a source for random bits used to seed the crypto library\*(Aqs RNG\&. The default is
+ /dev/random
+ (see
+-\fBrandom\fR(4))\&. FreeS/WAN and Openswan without NSS support used this option to specify the random source used to directly create keys\&. Libreswan only uses it to seed the crypto libraries RNG\&. Under Linux with hardware random support, special devices might show up as
++\fBrandom\fR(4))\&. FreeS/WAN and Openswan without NSS support use this option to specify the random source used to directly create keys\&. Libreswan only uses it to seed the NSS crypto libraries RNG\&. Under Linux with hardware random support, special devices might show up as
+ /dev/*rng*
+-devices\&. However, these should never be access directly using this option, as hardware failures could lead to extremely non\-random values (streams of zeroes have been observed in the wild)
++devices\&. However, these should never be accessed directly using this option, as hardware failures could lead to extremely non\-random values (streams of zeroes have been observed in the wild)
++.PP
++The
++\fB\-\-seedbits\fR
++option specifies how many seed bits are pulled from the random device to seed the NSS PRNG\&. The default of 480bit comes from FIPS requirements\&. Seed bits are rounded up to a multiple of 8\&.
++.PP
++The use of a different random device or a reduction of seedbits from the default value is prevented when the system is running in FIPS mode\&.
+ .PP
+ The
+ \fB\-\-configdir\fR
+@@ -69,7 +74,8 @@
+ .PP
+ The
+ \fB\-\-password\fR
+-option specifies the nss cryptographic module authentication password if the NSS module has been configured to require it\&. A password is required by hardware tokens and also by the internal softotken module when configured to run in FIPS mode\&.
++option specifies the nss cryptographic module authentication password if the NSS module has been configured to require it\&. A password is required by hardware tokens and also by the internal software token module when configured to run in FIPS mode\&. If the argument is
++\fIconfigdir\fR/nsspassword, the password comes from that file; otherwise argument is the password\&.
+ .PP
+ The
+ \fB\-\-hostname\fR
+@@ -140,7 +146,7 @@
+ \fBCoefficient\fR
+ line gives the Chinese Remainder Theorem coefficient, which is the inverse of
+ \fIq\fR, mod
+-\fIp\fR\&. These additional numbers (which must all be kept as secret as the private exponent) are precomputed aids to rapid signature generation\&. When NSS is used, these values are not available outside the NSS security database (softtoken or hardware token) and are instead filled in with the CKA_ID\&.
++\fIp\fR\&. These additional numbers (which must all be kept as secret as the private exponent) are precomputed aids to rapid signature generation\&. When NSS is used, these values are not available outside the NSS security database (software token or hardware token) and are instead filled in with the CKA_ID\&.
+ .PP
+ No attempt is made to break long lines\&.
+ .PP
+diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8.xml libreswan-3.12/programs/rsasigkey/rsasigkey.8.xml
+--- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.8.xml 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/rsasigkey/rsasigkey.8.xml 2015-02-26 21:25:39.302000000 -0600
+@@ -23,20 +23,13 @@
+ ipsec
+ rsasigkey
+ --verbose
+- --random filename
++ --random device
++ --seed numbits
+ --configdir nssdbdir
+ --password nsspassword
+ --hostname hostname
+ nbits
+
+-
+- ipsec
+- rsasigkey
+- --verbose
+- --configdir nssdbdir
+- --password nsspassword
+- --hostname hostname
+-
+
+
+
+@@ -61,14 +54,22 @@
+ source for random bits used to seed the crypto library's
+ RNG. The default is /dev/random (see
+ random4).
+-FreeS/WAN and Openswan without NSS support used this option to specify
++FreeS/WAN and Openswan without NSS support use this option to specify
+ the random source used to directly create keys. Libreswan only uses
+-it to seed the crypto libraries RNG. Under Linux with hardware random
++it to seed the NSS crypto libraries RNG. Under Linux with hardware random
+ support, special devices might show up as /dev/*rng*
+-devices. However, these should never be access directly using this option,
++devices. However, these should never be accessed directly using this option,
+ as hardware failures could lead to extremely non-random values (streams
+ of zeroes have been observed in the wild)
+
++The option specifies how many seed bits are pulled from
++the random device to seed the NSS PRNG. The default of 480bit comes from FIPS requirements.
++Seed bits are rounded up to a multiple of 8.
++
++
++The use of a different random device or a reduction of seedbits from the default value is
++prevented when the system is running in FIPS mode.
++
+ The option specifies the nss configuration directory to use.
+ This is the directory where the NSS certificate, key and security modules databases reside. The
+ default value is /etc/ipsec.d.
+diff -Naur libreswan-3.12-orig/programs/rsasigkey/rsasigkey.c libreswan-3.12/programs/rsasigkey/rsasigkey.c
+--- libreswan-3.12-orig/programs/rsasigkey/rsasigkey.c 2014-11-06 21:52:50.000000000 -0600
++++ libreswan-3.12/programs/rsasigkey/rsasigkey.c 2015-02-26 21:25:39.303000000 -0600
+@@ -4,7 +4,7 @@
+ * Copyright (C) 2003-2008 Michael C Richardson
+ * Copyright (C) 2003-2009 Paul Wouters
+ * Copyright (C) 2009 Avesh Agarwal
+- * Copyright (C) 2012-2013 Paul Wouters
++ * Copyright (C) 2012-2015 Paul Wouters
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -64,26 +64,22 @@
+ #define MIN_KEYBIT 2192
+
+ #ifndef DEVICE
+-/* To the openwrt people: Do not change /dev/random to /dev/urandom. The
+- * /dev/random device is ONLY used for generating long term keys, which
+- * should NEVER be done with /dev/urandom. If people use X.509, PSK or
+- * even raw RSA keys generated on other systems, changing this will have
+- * 0 effect. It's better to fail or bail out of generating a key, then
+- * generate a bad one.
+- */
+ # define DEVICE "/dev/random"
+ #endif
+ #ifndef MAXBITS
+ # define MAXBITS 20000
+ #endif
+
++#define DEFAULT_SEED_BITS 60 /* 480 bits of random seed */
++
+ #define E 3 /* standard public exponent */
+ /* #define F4 65537 */ /* possible future public exponent, Fermat's 4th number */
+
+ #define NSSDIR "/etc/ipsec.d"
+
++char *progname;
+ char usage[] =
+- "rsasigkey [--verbose] [--random ] [--configdir ] [--password ] [--hostname host] []";
++ "rsasigkey [--verbose] [--random ] [--configdir ] [--password ] [--hostname host] [--seedbits bits] []";
+ struct option opts[] = {
+ { "rounds", 1, NULL, 'p', }, /* obsoleted */
+ { "noopt", 0, NULL, 'n', }, /* obsoleted */
+@@ -96,6 +92,7 @@
+ { "configdir", 1, NULL, 'c' },
+ { "configdir2", 1, NULL, 'd' }, /* nss tools use -d */
+ { "password", 1, NULL, 'P' },
++ { "seedbits", 1, NULL, 's' },
+ { 0, 0, NULL, 0, }
+ };
+ int verbose = 0; /* narrate the action? */
+@@ -106,14 +103,13 @@
+ char me[] = "ipsec rsasigkey"; /* for messages */
+
+ /* forwards */
+-void rsasigkey(int nbits, char *configdir, char *password);
++void rsasigkey(int nbits, int seedbits, char *configdir, char *password);
+ void getrandom(size_t nbytes, unsigned char *buf);
+ static const unsigned char *bundle(int e, mpz_t n, size_t *sizep);
+ static const char *conv(const unsigned char *bits, size_t nbytes, int format);
+ static const char *hexout(mpz_t var);
+ void report(char *msg);
+
+-#define RAND_BUF_SIZE 60
+
+ /* getModulus - returns modulus of the RSA public key */
+ static SECItem *getModulus(SECKEYPublicKey *pk)
+@@ -163,15 +159,17 @@
+ }
+
+ /* UpdateRNG - Updates NSS's PRNG with user generated entropy. */
+-static void UpdateNSS_RNG(void)
++static void UpdateNSS_RNG(int seedbits)
+ {
+ SECStatus rv;
+- unsigned char buf[RAND_BUF_SIZE];
++ int seedbytes = BYTES_FOR_BITS(seedbits);
++ unsigned char *buf = alloc_bytes(seedbytes,"TLA seedmix");
+
+- getrandom(RAND_BUF_SIZE, buf);
+- rv = PK11_RandomUpdate(buf, sizeof buf);
++ getrandom(seedbytes, buf);
++ rv = PK11_RandomUpdate(buf, seedbytes);
+ assert(rv == SECSuccess);
+ zero(&buf);
++ pfree(buf);
+ }
+
+ /* Returns the password passed in in the text file.
+@@ -303,6 +301,7 @@
+ {
+ int opt;
+ int nbits = 0;
++ int seedbits = DEFAULT_SEED_BITS;
+ char *configdir = NULL; /* where the NSS databases reside */
+ char *password = NULL; /* password for token authentication */
+
+@@ -344,6 +343,16 @@
+ case 'P': /* token authentication password */
+ password = optarg;
+ break;
++ case 's': /* seed bits */
++ seedbits = atoi(optarg);
++ if (PK11_IsFIPS()) {
++ if (seedbits < DEFAULT_SEED_BITS) {
++ fprintf(stderr, "%s: FIPS mode does not allow < %d seed bits\n",
++ me, DEFAULT_SEED_BITS);
++ exit(1);
++ }
++ }
++ break;
+ case '?':
+ default:
+ printf("Usage:\t%s\n", usage);
+@@ -393,7 +402,7 @@
+ exit(1);
+ }
+
+- rsasigkey(nbits, configdir, password);
++ rsasigkey(nbits, seedbits, configdir, password);
+ exit(0);
+ }
+
+@@ -405,7 +414,7 @@
+ * real speed advantages.
+ * See also: https://www.imperialviolet.org/2012/03/16/rsae.html
+ */
+-void rsasigkey(int nbits, char *configdir, char *password)
++void rsasigkey(int nbits, int seedbits, char *configdir, char *password)
+ {
+ SECStatus rv;
+ PK11RSAGenParams rsaparams = { nbits, (long) E };
+@@ -483,7 +492,7 @@
+ #endif /* 0 */
+
+ /* Do some random-number initialization. */
+- UpdateNSS_RNG();
++ UpdateNSS_RNG(seedbits);
+ /* Log in to the token */
+ if (password) {
+ rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
+@@ -553,9 +562,7 @@
+ /*
+ - getrandom - get some random bytes from /dev/random (or wherever)
+ */
+-void getrandom(nbytes, buf)
+-size_t nbytes;
+-unsigned char *buf; /* known to be big enough */
++void getrandom(size_t nbytes, unsigned char *buf)
+ {
+ size_t ndone;
+ int dev;
+@@ -570,8 +577,8 @@
+
+ ndone = 0;
+ if (verbose) {
+- fprintf(stderr, "getting %d random bytes from %s...\n",
+- (int) nbytes,
++ fprintf(stderr, "getting %d random seed bytes for NSS from %s...\n",
++ (int) nbytes * BITS_PER_BYTE,
+ device);
+ }
+ while (ndone < nbytes) {
+@@ -683,3 +690,12 @@
+
+ fprintf(stderr, "%s\n", msg);
+ }
++/* exit_tool() is needed if the library was compiled with DEBUG, even if we are not.
++ * The odd-looking parens are to prevent macro expansion:
++ * lswlog.h without DEBUG define a macro exit_tool().
++ */
++void (exit_tool)(int x)
++{
++ exit(x);
++}
++
diff --git a/SOURCES/libreswan-3.12-1203794-fipstest.patch b/SOURCES/libreswan-3.12-1203794-fipstest.patch
new file mode 100644
index 0000000..dc6a248
--- /dev/null
+++ b/SOURCES/libreswan-3.12-1203794-fipstest.patch
@@ -0,0 +1,57 @@
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c
+--- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2015-04-12 16:52:11.748913102 -0400
++++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2015-04-12 20:19:08.330821771 -0400
+@@ -410,20 +410,24 @@
+
+ void ike_alg_aes_init(void)
+ {
+- if (!test_aes_cbc(&algo_aes_cbc)) {
++ bool fips = libreswan_fipsmode();
++ if (!fips && !test_aes_cbc(&algo_aes_cbc)) {
+ loglog(RC_LOG_SERIOUS, "CKM_AES_CBC: test failure");
++ exit_pluto(6);
+ }
+ if (ike_alg_register_enc(&algo_aes_cbc) != 1)
+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_cbc for IKE");
+
+- if (!test_aes_ctr(&algo_aes_ctr)) {
++ if (!fips && !test_aes_ctr(&algo_aes_ctr)) {
+ loglog(RC_LOG_SERIOUS, "CKM_AES_CTR: test failure");
++ exit_pluto(6);
+ }
+ if (ike_alg_register_enc(&algo_aes_ctr) != 1)
+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_ctr for IKE");
+
+- if (!test_aes_gcm()) {
++ if (!fips && !test_aes_gcm()) {
+ loglog(RC_LOG_SERIOUS, "CKM_AES_GCM: test failure");
++ exit_pluto(6);
+ }
+ if (ike_alg_register_enc(&algo_aes_gcm_8) != 1)
+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_aes_gcm_8 for IKE");
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c libreswan-3.12/programs/pluto/ike_alg_camellia.c
+--- libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c 2015-04-12 16:52:11.705911919 -0400
++++ libreswan-3.12/programs/pluto/ike_alg_camellia.c 2015-04-12 17:41:22.863365586 -0400
+@@ -94,11 +94,20 @@
+
+ void ike_alg_camellia_init(void)
+ {
+- test_camellia_cbc(&algo_camellia_cbc);
++#ifdef FIPS_CHECK
++ bool fips = libreswan_fipsmode();
++#else
++ bool fips = FALSE;
++#endif
++
++ if (!fips && !test_camellia_cbc(&algo_camellia_cbc)) {
++ loglog(RC_LOG_SERIOUS, "CKM_CAMELLIA_CBC: test failure");
++ exit_pluto(6);
++ }
++
+ if (ike_alg_register_enc(&algo_camellia_cbc) != 1)
+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_cbc for IKE");
+
+- // test_camellia_ctr(&algo_camellia_ctr);
+ if (ike_alg_register_enc(&algo_camellia_ctr) != 1)
+ loglog(RC_LOG_SERIOUS, "Warning: failed to register algo_camellia_ctr for IKE");
+ }
diff --git a/SOURCES/libreswan-3.12-1207689-blacklist.patch b/SOURCES/libreswan-3.12-1207689-blacklist.patch
new file mode 100644
index 0000000..2ed01e5
--- /dev/null
+++ b/SOURCES/libreswan-3.12-1207689-blacklist.patch
@@ -0,0 +1,160 @@
+diff -Naur libreswan-3.12-orig/Makefile.inc libreswan-3.12/Makefile.inc
+--- libreswan-3.12-orig/Makefile.inc 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/Makefile.inc 2015-04-28 23:18:45.781649956 -0400
+@@ -176,7 +176,10 @@
+ OSMOD_DESTDIR?=net/ipsec
+
+ # What command to use to load the modules. openwrt does not have modprobe
+-MODPROBE?=modprobe -q
++# Using -b enables blacklisting - this is needed for some known bad
++# versions of crypto acceleration modules.
++MODPROBEBIN?=modprobe
++MODPROBEARGS?=-q -b
+
+ ### misc installation stuff
+
+@@ -521,7 +524,8 @@
+ -e "s:@IPSEC_EXECDIR@:$(FINALLIBEXECDIR):g" \
+ -e "s:@IPSEC_VARDIR@:$(FINALVARDIR):g" \
+ -e "s:@IPSEC_SBINDIR@:$(FINALSBINDIR):g" \
+- -e "s:@MODPROBE@:$(MODPROBE):g" \
++ -e "s:@MODPROBEBIN@:$(MODPROBEBIN):g" \
++ -e "s:@MODPROBEARGS@:$(MODPROBEARGS):g" \
+ -e "s:@USE_DEFAULT_CONNS@:$(USE_DEFAULT_CONNS):g" \
+
+ # For KVM testing setup
+diff -Naur libreswan-3.12-orig/programs/_stackmanager/_stackmanager.in libreswan-3.12/programs/_stackmanager/_stackmanager.in
+--- libreswan-3.12-orig/programs/_stackmanager/_stackmanager.in 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/_stackmanager/_stackmanager.in 2015-04-28 23:16:25.709947026 -0400
+@@ -2,7 +2,7 @@
+ # STACK startup script
+ # Copyright (C) 2007 Ken Bantoft
+ # Copyright (C) 2007-2008 Paul Wouters
+-# Copyright (C) 2008-2014 Tuomo Soini
++# Copyright (C) 2008-2015 Tuomo Soini
+ # Copyright (C) 2012-2014 Paul Wouters
+ #
+ # This program is free software; you can redistribute it and/or modify it
+@@ -24,6 +24,7 @@
+ export PATH
+
+ test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x
++MODPROBE="@MODPROBEBIN@ @MODPROBEARGS@"
+
+ kamepfkey=/proc/net/pfkey
+ ipsecpfkey=/proc/net/ipsec/version
+@@ -119,11 +120,11 @@
+ xfrm4_mode_beet esp4 esp6 ah4 ah6 af_key ip_vti
+ do
+ # echo -n "${mod} " >&2
+- @MODPROBE@ ${mod} 2>/dev/null
++ ${MODPROBE} ${mod} 2>/dev/null
+ done
+
+ # xfrm_user is the old name for xfrm4_tunnel - backwards compatibility
+- @MODPROBE@ xfrm_user 2>/dev/null
++ ${MODPROBE} xfrm_user 2>/dev/null
+
+ fi
+ # Required for Labeled IPsec
+@@ -184,19 +185,19 @@
+ cryptomodules() {
+ # load hardware random and crypto related modules.
+ # some changed names over time
+- @MODPROBE@ hw_random 2>/dev/null
+- @MODPROBE@ hwrng 2>/dev/null
+- @MODPROBE@ virtio-rng 2>/dev/null
+- @MODPROBE@ amd-rng 2>/dev/null
+- @MODPROBE@ intel-rng 2>/dev/null
+- @MODPROBE@ geode-rng 2>/dev/null
+- @MODPROBE@ timeriomem-rng 2>/dev/null
+- @MODPROBE@ tpm-rng 2>/dev/null
++ ${MODPROBE} hw_random 2>/dev/null
++ ${MODPROBE} hwrng 2>/dev/null
++ ${MODPROBE} virtio-rng 2>/dev/null
++ ${MODPROBE} amd-rng 2>/dev/null
++ ${MODPROBE} intel-rng 2>/dev/null
++ ${MODPROBE} geode-rng 2>/dev/null
++ ${MODPROBE} timeriomem-rng 2>/dev/null
++ ${MODPROBE} tpm-rng 2>/dev/null
+
+ # load any OCF and CryptoAPI modules we might need for acceleration
+ # (OCF works for NETKEY and KLIPS/MAST)
+ # OCF cryptosoft is for kernel acceleration (ESP/AH)
+- @MODPROBE@ cryptosoft 2>/dev/null
++ ${MODPROBE} cryptosoft 2>/dev/null
+ # We skip cryptodev.ko because we no longer support /dev/crypto offloading
+ # (the overhead of cryptodev is not worth it even on embedded platforms)
+
+@@ -219,9 +220,9 @@
+ # padlock must load before aes module - though does not exist on newer
+ # kernels
+ # padlock-aes must load before padlock-sha for some reason
+- @MODPROBE@ padlock 2>/dev/null
+- @MODPROBE@ padlock-aes 2>/dev/null
+- @MODPROBE@ padlock-sha 2>/dev/null
++ ${MODPROBE} padlock 2>/dev/null
++ ${MODPROBE} padlock-aes 2>/dev/null
++ ${MODPROBE} padlock-sha 2>/dev/null
+ # load the most common ciphers/algo's
+ # aes-x86_64 has higher priority in via crypto api
+ # kernel directory does not match uname -m on x86_64 :(
+@@ -234,7 +235,7 @@
+ do
+ module=$(basename ${module} | sed "s/\.ko$//")
+ # echo -n "${module} " >&2
+- @MODPROBE@ ${module} 2>/dev/null
++ ${MODPROBE} ${module} 2>/dev/null
+ done
+ }
+
+@@ -264,10 +265,10 @@
+ ;;
+ esac
+ # modprobe does not like specifying .o or .ko, but insmod needs it
+- if [ "$(basename @MODPROBE@)" = "modprobe" ]; then
+- @MODPROBE@ ipsec
++ if [ "$(basename "@MODPROBEBIN@")" = "modprobe" ]; then
++ ${MODPROBE} ipsec
+ else
+- @MODPROBE@ ${modulename}
++ ${MODPROBE} ${modulename}
+ fi
+
+ if [ ! -f ${ipsecpfkey} ]; then
+@@ -418,7 +419,12 @@
+ exit 4
+ fi
+
+-stack="$(ipsec addconn --config ${IPSEC_CONF} --liststack)"
++if [ "$2" = "--netkey" ]; then
++ # manual override for use in docker
++ stack=netkey
++else
++ stack="$(ipsec addconn --config ${IPSEC_CONF} --liststack)"
++fi
+
+ case ${stack} in
+ netkey|klips|mast|none)
+@@ -435,15 +441,18 @@
+
+ case ${action} in
+ stop)
+- # We don't unload NETKEY/XFRM on stop - only when we detect a stack change.
++ # We don't unload NETKEY/XFRM on stop - only when we detect a stack
++ # change.
+ if [ -f ${ipsecpfkey} ]; then
+ ipsec eroute --clear
+- # this clears all IP addresses on ipsecX interfaces by unloading the module
++ # this clears all IP addresses on ipsecX interfaces by
++ # unloading the module
+ stopklips
+ elif [ -f ${kamepfkey} ]; then
+ ip xfrm state flush
+ ip xfrm policy flush
+- # module unloading skipped on purpose - can hang for a long time or fail
++ # module unloading skipped on purpose - can hang for a long
++ # time or fail
+ fi
+ ;;
+ start)
diff --git a/SOURCES/libreswan-3.12-1212121-cavs.patch b/SOURCES/libreswan-3.12-1212121-cavs.patch
new file mode 100644
index 0000000..f1f7743
--- /dev/null
+++ b/SOURCES/libreswan-3.12-1212121-cavs.patch
@@ -0,0 +1,5368 @@
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp.c libreswan-3.12/programs/pluto/cavp.c
+--- libreswan-3.12-orig/programs/pluto/cavp.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp.c 2015-05-06 11:45:32.912301324 -0400
+@@ -0,0 +1,305 @@
++/*
++ * Parse CAVP test vectors, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++/* #include */
++#include
++#include
++
++#include "constants.h"
++#include "lswalloc.h"
++#include "ike_alg.h"
++#include "crypto.h"
++#include "crypt_symkey.h"
++#include "test_buffer.h"
++
++#include "cavp.h"
++#include "cavp_print.h"
++#include "cavp_ikev1.h"
++#include "cavp_ikev2.h"
++
++struct cavp *cavps[] = {
++ &cavp_ikev1_sig,
++ &cavp_ikev1_psk,
++ &cavp_ikev2,
++ NULL
++};
++
++#define BUF_SIZE 4096
++
++static struct cavp_entry *lookup_entry(struct cavp_entry *entries, const char *key)
++{
++ struct cavp_entry *entry;
++ for (entry = entries; entry->op != NULL; entry++) {
++ if (strcmp(entry->key, key) == 0) {
++ return entry;
++ }
++ }
++ return NULL;
++}
++
++enum what { INITIAL, BLANK, CONFIG, DATA, RUN, FINAL } state = INITIAL;
++
++static void error_state(enum what state, enum what what)
++{
++ fprintf(stderr, "bad state %d what %d\n", state, what);
++ exit(1);
++}
++
++static struct cavp *cavp;
++
++static void next_state(enum what what)
++{
++ switch (state) {
++ case INITIAL:
++ switch (what) {
++ case CONFIG:
++ state = CONFIG;
++ break;
++ case BLANK:
++ break;
++ default:
++ error_state(state, what);
++ }
++ break;
++ case CONFIG:
++ switch (what) {
++ case CONFIG:
++ break;
++ case BLANK:
++ cavp->print_config();
++ state = DATA;
++ break;
++ default:
++ error_state(state, what);
++ }
++ break;
++ case DATA:
++ switch (what) {
++ case DATA:
++ break;
++ case BLANK:
++ cavp->run();
++ state = RUN;
++ break;
++ default:
++ error_state(state, what);
++ }
++ break;
++ case RUN:
++ switch (what) {
++ case CONFIG:
++ state = CONFIG;
++ break;
++ case DATA:
++ state = DATA;
++ break;
++ case BLANK:
++ break;
++ default:
++ error_state(state, what);
++ }
++ break;
++ default:
++ error_state(state, what);
++ break;
++ }
++}
++
++struct hash_desc *hasher;
++char hasher_name[BUF_SIZE];
++
++void hash(struct cavp_entry *entry,
++ const char *value UNUSED)
++{
++ strcpy(hasher_name, entry->key);
++ hasher = ike_alg_get_hasher(entry->value);
++ if (hasher == NULL) {
++ fprintf(stderr, "hasher %s not found\n", entry->key);
++ }
++}
++
++void chunk(struct cavp_entry *entry,
++ const char *value)
++{
++ freeanychunk(*(entry->chunk));
++ *(entry->chunk) = decode_hex_to_chunk(entry->key, value);
++}
++
++void symkey(struct cavp_entry *entry,
++ const char *value)
++{
++ free_any_symkey(__func__, entry->symkey);
++ chunk_t chunk = decode_hex_to_chunk(entry->key, value);
++ *(entry->symkey) = chunk_to_key(CKM_DH_PKCS_DERIVE, chunk);
++ freeanychunk(chunk);
++}
++
++void number(struct cavp_entry *entry,
++ const char *value)
++{
++ *(entry->number) = atoi(value);
++}
++
++void ignore(struct cavp_entry *entry UNUSED,
++ const char *value UNUSED)
++{
++}
++
++static void cavp_parser()
++{
++ char line[BUF_SIZE];
++ while (TRUE) {
++ if (fgets(line, sizeof(line), stdin) == NULL) {
++ int error = ferror(stdin);
++ if (error) {
++ fprintf(stderr, "Unexpected error: %s\n",
++ strerror(error));
++ exit(1);
++ }
++ break;
++ }
++ /* trim trailing cr/nl. */
++ int last = strlen(line) - 1;
++ while (last >= 0 && strchr("\r\n", line[last]) != NULL) {
++ last--;
++ }
++ line[last + 1] = '\0';
++ /* break the line up */
++ char *lparen = strchr(line, '[');
++ char *eq = strchr(line, '=');
++ char *rparen = strchr(line, ']');
++ if (line[0] == '\0') {
++ next_state(BLANK);
++ /* blank */
++ print_line(line);
++ } else if (line[0] == '#') {
++ /* # .... comment */
++ if (cavp == NULL) {
++ struct cavp **cavpp;
++ for (cavpp = cavps; *cavpp != NULL; cavpp++) {
++ if (strstr(line, (*cavpp)->description) != NULL) {
++ cavp = *cavpp;
++ fprintf(stderr, "\ntest: %s (guess)\n\n", cavp->description);
++ break;
++ }
++ }
++ }
++ print_line(line);
++ } else if (lparen != NULL && rparen != NULL) {
++ next_state(CONFIG);
++ /* "[" [ " = " ] "]" */
++ *rparen = '\0';
++ char *key = lparen + 1;
++ char *value;
++ if (eq == NULL) {
++ value = NULL;
++ } else {
++ value = eq + 2;
++ *(eq - 1) = '\0';
++ }
++ struct cavp_entry *entry = lookup_entry(cavp->config, key);
++ if (entry == NULL) {
++ fprintf(stderr, "unknown config entry: ['%s' = '%s']\n", key, value);
++ exit(1);
++ }
++ entry->op(entry, value);
++ } else if (eq != NULL) {
++ next_state(DATA);
++ *(eq - 1) = '\0';
++ char *key = line;
++ char *value = eq + 2;
++ struct cavp_entry *entry = lookup_entry(cavp->data, key);
++ if (entry == NULL) {
++ fprintf(stderr, "unknown data entry: '%s' = '%s'\n", key, value);
++ exit(1);
++ }
++ entry->op(entry, value);
++ } else {
++ fprintf(stderr, "bad line: '%s'\n", line);
++ }
++ }
++}
++
++static void usage()
++{
++ fprintf(stderr, "Usage: cavp [ -OPTION ] |-\n");
++ struct cavp **cavpp;
++ for (cavpp = cavps; *cavpp != NULL; cavpp++) {
++ fprintf(stderr, "\t-%s\t%s\n", (*cavpp)->alias, (*cavpp)->description);
++ }
++}
++
++int main(int argc, char *argv[])
++{
++ if (argc <= 1) {
++ usage();
++ exit(1);
++ }
++ char **argp = argv + 1;
++
++ /* a -XXX option? */
++ if ((*argp)[0] == '-' && (*argp)[1] != '\0') {
++ struct cavp **cavpp;
++ for (cavpp = cavps; *cavpp != NULL; cavpp++) {
++ if (strcmp(argv[1]+1, (*cavpp)->alias) == 0) {
++ cavp = *cavpp;
++ fprintf(stderr, "test: %s\n", cavp->description);
++ break;
++ }
++ }
++ if (cavp == NULL) {
++ fprintf(stderr, "Unknown test %s\n", argv[1]);
++ usage();
++ exit(1);
++ }
++ argp++;
++ } else {
++ fprintf(stderr, "Guessing test type ...\n");
++ }
++
++ if (*argp == NULL) {
++ fprintf(stderr, "missing test file\n");
++ usage();
++ exit(1);
++ }
++ if (strcmp(*argp, "-") == 0) {
++ fprintf(stderr, "Reading from stdin\n");
++ } else {
++ fprintf(stderr, "reading from %s\n", *argp);
++ if (freopen(*argp, "r", stdin) == NULL) {
++ perror("freopen");
++ exit(1);
++ }
++ }
++ argp++;
++
++ if (*argp != NULL) {
++ fprintf(stderr, "unexpected %s", *argp);
++ usage();
++ exit(1);
++ }
++
++ setbuf(stdout, NULL);
++
++ NSS_NoDB_Init(".");
++ init_crypto();
++
++ cavp_parser();
++
++ NSS_Shutdown();
++ return 0;
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp.h libreswan-3.12/programs/pluto/cavp.h
+--- libreswan-3.12-orig/programs/pluto/cavp.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp.h 2015-05-06 11:45:32.912301324 -0400
+@@ -0,0 +1,45 @@
++/*
++ * Parse CAVP test vectors, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++struct hash_desc;
++
++struct cavp_entry {
++ const char *key;
++ void (*op)(struct cavp_entry *key, const char *value);
++ chunk_t *chunk;
++ PK11SymKey **symkey;
++ int *number;
++ struct hash_desc **hasher;
++ int value;
++};
++
++struct cavp {
++ const char *alias;
++ const char *description;
++ void (*print_config)(void);
++ void (*run)(void);
++ struct cavp_entry *config;
++ struct cavp_entry *data;
++};
++
++extern struct hash_desc *hasher;
++extern char hasher_name[];
++void hash(struct cavp_entry *entry, const char *value);
++
++void ignore(struct cavp_entry *entry, const char *value);
++void chunk(struct cavp_entry *entry, const char *value);
++void symkey(struct cavp_entry *entry, const char *value);
++void number(struct cavp_entry *entry, const char *value);
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev1.c libreswan-3.12/programs/pluto/cavp_ikev1.c
+--- libreswan-3.12-orig/programs/pluto/cavp_ikev1.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_ikev1.c 2015-05-06 11:45:32.913301336 -0400
+@@ -0,0 +1,174 @@
++/*
++ * Parse IKEv1 CAVP test functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++
++#include "lswalloc.h"
++#include "ike_alg.h"
++
++#include "ikev1_prf.h"
++#include "crypt_symkey.h"
++
++#include "cavp.h"
++#include "cavp_print.h"
++#include "cavp_ikev1.h"
++
++static int ni_length;
++static int nr_length;
++static int psk_length;
++static int g_xy_length;
++
++static struct cavp_entry config_entries[] = {
++ { .key = "SHA-1", .op = hash, .value = OAKLEY_SHA1, },
++ { .key = "SHA-224", .op = hash, .value = 0, },
++ { .key = "SHA-256", .op = hash, .value = OAKLEY_SHA2_256, },
++ { .key = "SHA-384", .op = hash, .value = OAKLEY_SHA2_384, },
++ { .key = "SHA-512", .op = hash, .value = OAKLEY_SHA2_512, },
++ { .key = "Ni length", .op = number, .number = &ni_length },
++ { .key = "Nr length", .op = number, .number = &nr_length },
++ { .key = "pre-shared-key length", .op = number, .number = &psk_length },
++ { .key = "g^xy length", .op = number, .number = &g_xy_length },
++ { .key = NULL }
++};
++
++static int count;
++static chunk_t psk;
++static chunk_t ni;
++static chunk_t nr;
++static chunk_t cky_i;
++static chunk_t cky_r;
++static PK11SymKey *g_xy;
++
++static struct cavp_entry data_entries[] = {
++ { .key = "COUNT", .op = number, .number = &count },
++ { .key = "g^xy", .op = symkey, .symkey = &g_xy },
++ { .key = "Ni", .op = chunk, .chunk = &ni },
++ { .key = "Nr", .op = chunk, .chunk = &nr },
++ { .key = "CKY_I", .op = chunk, .chunk = &cky_i },
++ { .key = "CKY_R", .op = chunk, .chunk = &cky_r },
++ { .key = "pre-shared-key", .op = chunk, .chunk = &psk },
++ { .key = "SKEYID", .op = ignore },
++ { .key = "SKEYID_d", .op = ignore },
++ { .key = "SKEYID_a", .op = ignore },
++ { .key = "SKEYID_e", .op = ignore },
++ { .key = "SKEYID_", .op = ignore },
++ { .op = NULL }
++};
++
++static void ikev1_skeyid_alphabet(PK11SymKey *skeyid)
++{
++ PK11SymKey *skeyid_d =
++ ikev1_skeyid_d(hasher, skeyid,
++ g_xy, cky_i, cky_r);
++ print_symkey("SKEYID_d", skeyid_d, 0);
++
++ PK11SymKey *skeyid_a =
++ ikev1_skeyid_a(hasher, skeyid, skeyid_d,
++ g_xy, cky_i, cky_r);
++ print_symkey("SKEYID_a", skeyid_a, 0);
++
++ PK11SymKey *skeyid_e =
++ ikev1_skeyid_e(hasher, skeyid, skeyid_a,
++ g_xy, cky_i, cky_r);
++ print_symkey("SKEYID_e", skeyid_e, 0);
++
++ free_any_symkey("skeyid_d", &skeyid_d);
++ free_any_symkey("skeyid_e", &skeyid_e);
++ free_any_symkey("skeyid_a", &skeyid_a);
++}
++
++static void print_sig_config()
++{
++ config_number("g^xy length", g_xy_length);
++ config_key(hasher_name);
++ config_number("Ni length", ni_length);
++ config_number("Nr length", nr_length);
++}
++
++static void run_sig(void)
++{
++ print_number("COUNT", count);
++ print_chunk("CKY_I", cky_i, 0);
++ print_chunk("CKY_R", cky_r, 0);
++ print_chunk("Ni", ni, 0);
++ print_chunk("Nr", nr, 0);
++ print_symkey("g^xy", g_xy, 0);
++
++ if (hasher == NULL) {
++ print_line(hasher_name);
++ return;
++ }
++
++ PK11SymKey *skeyid =
++ ikev1_signature_skeyid(hasher,
++ ni, nr,
++ g_xy);
++ print_symkey("SKEYID", skeyid, 0);
++ ikev1_skeyid_alphabet(skeyid);
++ free_any_symkey("skeyid", &skeyid);
++}
++
++struct cavp cavp_ikev1_sig = {
++ .alias = "v1sig",
++ .description = "IKE v1 Digital Signature Authentication",
++ .print_config = print_sig_config,
++ .run = run_sig,
++ .config = config_entries,
++ .data = data_entries,
++};
++
++static void print_psk_config(void)
++{
++ config_number("g^xy length", g_xy_length);
++ config_key(hasher_name);
++ config_number("Ni length", ni_length);
++ config_number("Nr length", nr_length);
++ config_number("pre-shared-key length", psk_length);
++}
++
++static void run_psk(void)
++{
++ print_number("COUNT", count);
++ print_chunk("CKY_I", cky_i, 0);
++ print_chunk("CKY_R", cky_r, 0);
++ print_chunk("Ni", ni, 0);
++ print_chunk("Nr", nr, 0);
++ print_symkey("g^xy", g_xy, 0);
++ print_chunk("pre-shared-key", psk, 0);
++
++ if (hasher == NULL) {
++ print_line(hasher_name);
++ return;
++ }
++
++ PK11SymKey *skeyid =
++ ikev1_pre_shared_key_skeyid(hasher,
++ psk,
++ ni, nr,
++ g_xy);
++ print_symkey("SKEYID", skeyid, 0);
++ ikev1_skeyid_alphabet(skeyid);
++ free_any_symkey("skeyid", &skeyid);
++}
++
++struct cavp cavp_ikev1_psk = {
++ .alias = "v1psk",
++ .description = "IKE v1 Pre-shared Key Authentication",
++ .print_config = print_psk_config,
++ .run = run_psk,
++ .config = config_entries,
++ .data = data_entries,
++};
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev1.h libreswan-3.12/programs/pluto/cavp_ikev1.h
+--- libreswan-3.12-orig/programs/pluto/cavp_ikev1.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_ikev1.h 2015-05-06 11:45:32.913301336 -0400
+@@ -0,0 +1,18 @@
++/*
++ * Parse IKEv1 CAVP test functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++struct cavp cavp_ikev1_sig;
++struct cavp cavp_ikev1_psk;
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev2.c libreswan-3.12/programs/pluto/cavp_ikev2.c
+--- libreswan-3.12-orig/programs/pluto/cavp_ikev2.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_ikev2.c 2015-05-06 11:45:32.913301336 -0400
+@@ -0,0 +1,141 @@
++/*
++ * Parse IKEv1 CAVP test functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++
++#include "lswalloc.h"
++#include "ike_alg.h"
++
++#include "crypt_symkey.h"
++#include "ikev2_prf.h"
++
++#include "cavp.h"
++#include "cavp_print.h"
++#include "cavp_ikev2.h"
++
++static int g_ir_length;
++static int ni_length;
++static int nr_length;
++static int dkm_length;
++static int child_sa_dkm_length;
++
++static struct cavp_entry config_entries[] = {
++ { .key = "g^ir length", .op = number, .number = &g_ir_length },
++ { .key = "SHA-1", .op = hash, .value = OAKLEY_SHA1, },
++ { .key = "SHA-224", .op = hash, .value = 0, },
++ { .key = "SHA-256", .op = hash, .value = OAKLEY_SHA2_256, },
++ { .key = "SHA-384", .op = hash, .value = OAKLEY_SHA2_384, },
++ { .key = "SHA-512", .op = hash, .value = OAKLEY_SHA2_512, },
++ { .key = "Ni length", .op = number, .number = &ni_length },
++ { .key = "Nr length", .op = number, .number = &nr_length },
++ { .key = "DKM length", .op = number, .number = &dkm_length },
++ { .key = "Child SA DKM length", .op = number, .number = &child_sa_dkm_length },
++ { .key = NULL }
++};
++
++static void ikev2_config()
++{
++ config_number("g^ir length", g_ir_length);
++ config_key(hasher_name);
++ config_number("Ni length",ni_length);
++ config_number("Nr length",nr_length);
++ config_number("DKM length",dkm_length);
++ config_number("Child SA DKM length",child_sa_dkm_length);
++}
++
++static int count;
++static chunk_t ni;
++static chunk_t nr;
++static PK11SymKey *g_ir;
++static PK11SymKey *g_ir_new;
++static chunk_t spi_i;
++static chunk_t spi_r;
++
++static struct cavp_entry data_entries[] = {
++ { .key = "COUNT", .op = number, .number = &count },
++ { .key = "g^ir", .op = symkey, .symkey = &g_ir },
++ { .key = "g^ir (new)", .op = symkey, .symkey = &g_ir_new },
++ { .key = "Ni", .op = chunk, .chunk = &ni },
++ { .key = "Nr", .op = chunk, .chunk = &nr },
++ { .key = "SPIi", .op = chunk, .chunk = &spi_i },
++ { .key = "SPIr", .op = chunk, .chunk = &spi_r },
++ { .key = "SKEYSEED", .op = ignore },
++ { .key = "DKM", .op = ignore },
++ { .key = "DKM(Child SA)", .op = ignore },
++ { .key = "DKM(Child SA D-H)", .op = ignore },
++ { .key = "SKEYSEED(Rekey)", .op = ignore },
++ { .op = NULL }
++};
++
++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);
++}
++
++struct cavp cavp_ikev2 = {
++ .alias = "v2",
++ .description = "IKE v2",
++ .print_config = ikev2_config,
++ .run = run_ikev2,
++ .config = config_entries,
++ .data = data_entries,
++};
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_ikev2.h libreswan-3.12/programs/pluto/cavp_ikev2.h
+--- libreswan-3.12-orig/programs/pluto/cavp_ikev2.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_ikev2.h 2015-05-06 11:45:32.914301347 -0400
+@@ -0,0 +1,17 @@
++/*
++ * Parse IKEv1 CAVP test functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++struct cavp cavp_ikev2;
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_print.c libreswan-3.12/programs/pluto/cavp_print.c
+--- libreswan-3.12-orig/programs/pluto/cavp_print.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_print.c 2015-05-06 11:45:32.914301347 -0400
+@@ -0,0 +1,73 @@
++/*
++ * Parse CAVP test vectors, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++#include
++
++#include "constants.h"
++#include "lswalloc.h"
++#include "crypt_symkey.h"
++#include "cavp_print.h"
++
++/*
++ * The test vectors are CR-LF terminated, mimic this.
++ */
++static const char crlf[] = "\r\n";
++
++void config_key(const char *key)
++{
++ fputs("[", stdout);
++ fputs(key, stdout);
++ fputs("]", stdout);
++ fputs(crlf, stdout);
++}
++
++void config_number(const char *key, int number)
++{
++ printf("[%s = %d]%s", key, number, crlf);
++}
++
++void print_chunk(const char *prefix, chunk_t chunk, size_t binlen)
++{
++ printf("%s = ", prefix);
++ size_t len = binlen == 0 ? chunk.len
++ : binlen < chunk.len ? binlen
++ : chunk.len;
++
++ size_t i = 0;
++ for (i = 0; i < len; i++) {
++ printf("%02x", chunk.ptr[i]);
++ }
++ printf("%s", crlf);
++}
++
++void print_symkey(const char *prefix, PK11SymKey *key, size_t binlen)
++{
++ chunk_t chunk = chunk_from_symkey(prefix, key);
++ print_chunk(prefix, chunk, binlen);
++ freeanychunk(chunk);
++}
++
++void print_number(const char *prefix, int number)
++{
++ printf("%s = %d%s", prefix, number, crlf);
++}
++
++void print_line(const char *line)
++{
++ fputs(line, stdout);
++ fputs(crlf, stdout);
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_print.h libreswan-3.12/programs/pluto/cavp_print.h
+--- libreswan-3.12-orig/programs/pluto/cavp_print.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_print.h 2015-05-06 11:45:32.914301347 -0400
+@@ -0,0 +1,23 @@
++/*
++ * Parse CAVP test vectors, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++void config_number(const char *prefix, int number);
++void config_key(const char *key);
++
++void print_chunk(const char *prefix, chunk_t chunk, size_t binlen);
++void print_symkey(const char *prefix, PK11SymKey *key, size_t binlen);
++void print_number(const char *prefix, int number);
++void print_line(const char *line);
+diff -Naur libreswan-3.12-orig/programs/pluto/cavp_stubs.c libreswan-3.12/programs/pluto/cavp_stubs.c
+--- libreswan-3.12-orig/programs/pluto/cavp_stubs.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/cavp_stubs.c 2015-05-06 11:45:32.915301359 -0400
+@@ -0,0 +1,21 @@
++#include
++
++#include "constants.h"
++#include "libreswan/passert.h"
++
++/*
++ * Crud to get main to link.
++ */
++libreswan_passert_fail_t libreswan_passert_fail;
++enum kernel_interface kern_interface;
++extern void exit_pluto(int status);
++void exit_pluto(int status UNUSED) { }
++extern void show_setup_plutomain();
++void show_setup_plutomain() { }
++extern char *pluto_listen;
++char *pluto_listen = NULL;
++u_int16_t secctx_attr_type = 0;
++u_int16_t secctx_attr_value = 0;
++bool force_busy = FALSE;
++bool strict_crl_policy = FALSE;
++deltatime_t crl_check_interval = { 0 };
+diff -Naur libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c libreswan-3.12/programs/pluto/cbc_test_vectors.c
+--- libreswan-3.12-orig/programs/pluto/cbc_test_vectors.c 2015-05-06 11:44:21.562466284 -0400
++++ libreswan-3.12/programs/pluto/cbc_test_vectors.c 2015-05-06 11:45:32.915301359 -0400
+@@ -13,6 +13,7 @@
+
+ #include "nss.h"
+ #include "pk11pub.h"
++#include "crypt_symkey.h"
+
+ struct cbc_test_vector {
+ const char *description;
+@@ -183,7 +184,7 @@
+ }
+
+ /* Clean up. */
+- PK11_FreeSymKey(sym_key);
++ free_any_symkey("sym_key", &sym_key);
+
+ DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s",
+ test->description, ok ? "passed" : "failed"));
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.c libreswan-3.12/programs/pluto/crypt_dh.c
+--- libreswan-3.12-orig/programs/pluto/crypt_dh.c 2015-05-06 11:44:21.583466531 -0400
++++ libreswan-3.12/programs/pluto/crypt_dh.c 2015-05-06 11:45:32.917301382 -0400
+@@ -57,90 +57,20 @@
+ #include "id.h"
+ #include "secrets.h"
+ #include "keys.h"
+-#include "ikev2_prfplus.h"
++#include "crypt_dh.h"
++#include "crypt_symkey.h"
+
+ #include
+ #include
+ #include
+ #include "lswconf.h"
+
+-/* #define PK11_Derive(base, mechanism, param, target, operation, keysize) \
+- * PK11_Derive_lsw(base, mechanism, param, target, operation, keysize)
+- */
+-
+-/* MUST BE THREAD-SAFE */
+-static PK11SymKey *pk11_extract_derive_wrapper_lsw(PK11SymKey *base,
+- CK_EXTRACT_PARAMS bs,
+- CK_MECHANISM_TYPE target,
+- CK_ATTRIBUTE_TYPE operation,
+- int keySize)
+-{
+- SECItem param;
+-
+- param.data = (unsigned char*)&bs;
+- param.len = sizeof(bs);
+-
+- return PK11_Derive_lsw(base, CKM_EXTRACT_KEY_FROM_KEY, ¶m, target,
+- operation, keySize);
+-}
+-
+-static CK_MECHANISM_TYPE nss_encryption_mech(
+- const struct encrypt_desc *encrypter)
+-{
+- /* the best wey have for "undefined" */
+- CK_MECHANISM_TYPE mechanism = CKM_VENDOR_DEFINED;
+-
+- switch (encrypter->common.algo_id) {
+- case OAKLEY_3DES_CBC:
+- mechanism = CKM_DES3_CBC;
+- break;
+-#ifdef NOT_YET
+- case OAKLEY_CAST_CBC:
+- mechanism = CKM_CAST5_CBC:
+- break;
+-#endif
+- case OAKLEY_AES_CBC:
+- mechanism = CKM_AES_CBC;
+- break;
+- case OAKLEY_CAMELLIA_CBC:
+- mechanism = CKM_CAMELLIA_CBC;
+- break;
+- case OAKLEY_AES_CTR:
+- mechanism = CKM_AES_CTR;
+- break;
+-#ifdef NOT_YET
+- case OAKLEY_AES_CCM_8:
+- case OAKLEY_AES_CCM_12:
+- case OAKLEY_AES_CCM_16:
+- mechanism = CKM_AES_CCM;
+- break;
+-#endif
+- case OAKLEY_AES_GCM_8:
+- case OAKLEY_AES_GCM_12:
+- case OAKLEY_AES_GCM_16:
+- mechanism = CKM_AES_GCM;
+- break;
+-#ifdef NOT_YET
+- case OAKLEY_TWOFISH_CBC:
+- mechanism = CKM_TWOFISH_CBC;
+- break;
+-#endif
+- default:
+- loglog(RC_LOG_SERIOUS,
+- "NSS: Unsupported encryption mechanism for %s",
+- strip_prefix(enum_name(&oakley_enc_names,
+- encrypter->common.algo_id), "OAKLEY_"));
+- break;
+- }
+- return mechanism;
+-}
+-
+ /** Compute DH shared secret from our local secret and the peer's public value.
+ * We make the leap that the length should be that of the group
+ * (see quoted passage at start of ACCEPT_KE).
+ */
+ /* MUST BE THREAD-SAFE */
+-static PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */
++PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */
+ /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */
+ const struct oakley_group_desc *group,
+ const SECKEYPublicKey *local_pubk)
+@@ -214,7 +144,7 @@
+ CKM_CONCATENATE_DATA_AND_BASE,
+ CKA_DERIVE, 0);
+ passert(newdhshared != NULL);
+- PK11_FreeSymKey(dhshared);
++ free_any_symkey("dhshared", &dhshared);
+ dhshared = newdhshared;
+ freeanychunk(zeros);
+ } else {
+@@ -240,862 +170,6 @@
+ return dhshared;
+ }
+
+-/* SKEYID for preshared keys.
+- * See draft-ietf-ipsec-ike-01.txt 4.1
+- */
+-
+-static PK11SymKey *skeyid_preshared(const chunk_t pss,
+- const chunk_t ni,
+- const chunk_t nr,
+- PK11SymKey *shared,
+- const struct hash_desc *hasher)
+-{
+- struct hmac_ctx ctx;
+-
+- passert(hasher != NULL);
+-
+- chunk_t nir;
+- unsigned int k;
+- CK_MECHANISM_TYPE mechanism;
+- u_char buf1[HMAC_BUFSIZE * 2], buf2[HMAC_BUFSIZE * 2];
+- chunk_t buf1_chunk, buf2_chunk;
+- PK11SymKey *skeyid;
+-
+- DBG(DBG_CRYPT, {
+- DBG_log("NSS: skeyid inputs (pss+NI+NR+shared-secret) hasher: %s",
+- hasher->common.name);
+- DBG_log("shared-secret (pointer in chunk_t): %p", shared);
+- DBG_dump_chunk("ni: ", ni);
+- DBG_dump_chunk("nr: ", nr);
+- });
+-
+- /* We need to hmac_init with the concatenation of Ni_b and Nr_b,
+- * so we have to build a temporary concatentation.
+- */
+-
+- nir.len = ni.len + nr.len;
+- nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_preshared");
+- memcpy(nir.ptr, ni.ptr, ni.len);
+- memcpy(nir.ptr + ni.len, nr.ptr, nr.len);
+-
+- zero(&buf1);
+-
+- if (pss.len <= hasher->hash_block_size) {
+- memcpy(buf1, pss.ptr, pss.len);
+- } else {
+- hasher->hash_init(&ctx.hash_ctx);
+- hasher->hash_update(&ctx.hash_ctx, pss.ptr, pss.len);
+- hasher->hash_final(buf1, &ctx.hash_ctx);
+- }
+-
+- memcpy(buf2, buf1, hasher->hash_block_size);
+-
+- for (k = 0; k < hasher->hash_block_size; k++) {
+- buf1[k] ^= HMAC_IPAD;
+- buf2[k] ^= HMAC_OPAD;
+- }
+-
+- /* pfree(nir.ptr); */
+-
+- mechanism = nss_key_derivation_mech(hasher);
+- buf1_chunk.ptr = buf1;
+- buf1_chunk.len = hasher->hash_block_size;
+-
+- buf2_chunk.ptr = buf2;
+- buf2_chunk.len = hasher->hash_block_size;
+-
+- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(shared,
+- CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE,
+- 0);
+- /* nss_symkey_log(tkey4, "pss+ipad+shared"); */
+-
+- CK_EXTRACT_PARAMS bs = 0;
+- PK11SymKey *tkey5 = pk11_extract_derive_wrapper_lsw(tkey4, bs,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- hasher->hash_block_size);
+- /* nss_symkey_log(tkey5, "pss+ipad"); */
+-
+- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5,
+- CKM_CONCATENATE_BASE_AND_DATA, nir, mechanism, CKA_DERIVE,
+- 0);
+- pfree(nir.ptr);
+- /* nss_symkey_log(tkey6, "pss+ipad+nir"); */
+-
+- /* PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(shared, CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, mechanism, CKA_DERIVE, 0); */
+- PK11SymKey *tkey2 = PK11_Derive_lsw(tkey6, mechanism, NULL,
+- CKM_CONCATENATE_DATA_AND_BASE,
+- CKA_DERIVE, 0);
+- /* nss_symkey_log(tkey2, "pss : tkey2"); */
+-
+- PK11SymKey *tkey3 = pk11_derive_wrapper_lsw(tkey2,
+- CKM_CONCATENATE_DATA_AND_BASE, buf2_chunk, mechanism, CKA_DERIVE,
+- 0);
+- skeyid = PK11_Derive_lsw(tkey3, mechanism, NULL,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0);
+- /* nss_symkey_log(tkey2, "pss : tkey3"); */
+-
+- PK11_FreeSymKey(tkey4);
+- PK11_FreeSymKey(tkey5);
+- PK11_FreeSymKey(tkey6);
+- PK11_FreeSymKey(tkey2);
+- PK11_FreeSymKey(tkey3);
+-
+- DBG(DBG_CRYPT,
+- DBG_log("NSS: skeyid in skeyid_preshared() (pointer) %p: ",
+- skeyid));
+- return skeyid;
+-}
+-
+-/* MUST BE THREAD-SAFE */
+-static PK11SymKey *skeyid_digisig(const chunk_t ni,
+- const chunk_t nr,
+- /*const*/ PK11SymKey *shared, /* NSS doesn't do const */
+- const struct hash_desc *hasher)
+-{
+- struct hmac_ctx ctx;
+- chunk_t nir;
+- unsigned int k;
+- CK_MECHANISM_TYPE mechanism;
+- u_char buf1[HMAC_BUFSIZE * 2], buf2[HMAC_BUFSIZE * 2];
+- chunk_t buf1_chunk, buf2_chunk;
+- PK11SymKey *skeyid;
+-
+- DBG(DBG_CRYPT, {
+- DBG_log("skeyid inputs (digi+NI+NR+shared) hasher: %s",
+- hasher->common.name);
+- DBG_dump_chunk("ni: ", ni);
+- DBG_dump_chunk("nr: ", nr);
+- });
+-
+- /* We need to hmac_init with the concatenation of Ni_b and Nr_b,
+- * so we have to build a temporary concatentation.
+- */
+- nir.len = ni.len + nr.len;
+- nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_digisig");
+- memcpy(nir.ptr, ni.ptr, ni.len);
+- memcpy(nir.ptr + ni.len, nr.ptr, nr.len);
+- zero(&buf1);
+- if (nir.len <= hasher->hash_block_size) {
+- memcpy(buf1, nir.ptr, nir.len);
+- } else {
+- hasher->hash_init(&ctx.hash_ctx);
+- hasher->hash_update(&ctx.hash_ctx, nir.ptr, nir.len);
+- hasher->hash_final(buf1, &ctx.hash_ctx);
+- }
+-
+- memcpy(buf2, buf1, hasher->hash_block_size);
+-
+- for (k = 0; k < hasher->hash_block_size; k++) {
+- buf1[k] ^= HMAC_IPAD;
+- buf2[k] ^= HMAC_OPAD;
+- }
+-
+- pfree(nir.ptr);
+- mechanism = nss_key_derivation_mech(hasher);
+- buf1_chunk.ptr = buf1;
+- buf1_chunk.len = hasher->hash_block_size;
+-
+- buf2_chunk.ptr = buf2;
+- buf2_chunk.len = hasher->hash_block_size;
+-
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(shared,
+- CKM_CONCATENATE_DATA_AND_BASE, buf1_chunk, mechanism, CKA_DERIVE,
+- 0);
+- PK11SymKey *tkey2 = PK11_Derive_lsw(tkey1, mechanism, NULL,
+- CKM_CONCATENATE_DATA_AND_BASE,
+- CKA_DERIVE, 0);
+- PK11SymKey *tkey3 = pk11_derive_wrapper_lsw(tkey2,
+- CKM_CONCATENATE_DATA_AND_BASE, buf2_chunk, mechanism, CKA_DERIVE,
+- 0);
+- skeyid = PK11_Derive_lsw(tkey3, mechanism, NULL,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0);
+-
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey2);
+- PK11_FreeSymKey(tkey3);
+-
+- DBG(DBG_CRYPT,
+- DBG_log("NSS: digisig skeyid pointer: %p", skeyid));
+-
+- return skeyid;
+-}
+-
+-/* Generate the SKEYID_* and new IV
+- * See draft-ietf-ipsec-ike-01.txt 4.1
+- */
+-/* MUST BE THREAD-SAFE */
+-static void calc_skeyids_iv(struct pcr_skeyid_q *skq,
+- /*const*/ PK11SymKey *shared, /* NSS doesn't do const */
+- const size_t keysize, /* = st->st_oakley.enckeylen/BITS_PER_BYTE; */
+- PK11SymKey **skeyid_out, /* output */
+- PK11SymKey **skeyid_d_out, /* output */
+- PK11SymKey **skeyid_a_out, /* output */
+- PK11SymKey **skeyid_e_out, /* output */
+- chunk_t *new_iv, /* output */
+- PK11SymKey **enc_key_out /* output */
+- )
+-{
+- oakley_auth_t auth = skq->auth;
+- oakley_hash_t hash = skq->prf_hash;
+- const struct hash_desc *hasher = crypto_get_hasher(hash);
+- chunk_t ni;
+- chunk_t nr;
+- chunk_t gi;
+- chunk_t gr;
+- chunk_t icookie;
+- chunk_t rcookie;
+- PK11SymKey
+- *skeyid,
+- *skeyid_d,
+- *skeyid_a,
+- *skeyid_e,
+- *enc_key;
+- const struct encrypt_desc *encrypter = skq->encrypter;
+-
+- /* this doesn't allocate any memory */
+- setchunk_from_wire(gi, skq, &skq->gi);
+- setchunk_from_wire(gr, skq, &skq->gr);
+- setchunk_from_wire(ni, skq, &skq->ni);
+- setchunk_from_wire(nr, skq, &skq->nr);
+- setchunk_from_wire(icookie, skq, &skq->icookie);
+- setchunk_from_wire(rcookie, skq, &skq->rcookie);
+-
+- /* Generate the SKEYID */
+- switch (auth) {
+- case OAKLEY_PRESHARED_KEY:
+- {
+- chunk_t pss;
+-
+- setchunk_from_wire(pss, skq, &skq->pss);
+- skeyid = skeyid_preshared(pss, ni, nr, shared, hasher);
+- }
+- break;
+-
+- case OAKLEY_RSA_SIG:
+- skeyid = skeyid_digisig(ni, nr, shared, hasher);
+- break;
+-
+- /* Not implemented */
+- case OAKLEY_DSS_SIG:
+- case OAKLEY_RSA_ENC:
+- case OAKLEY_RSA_REVISED_MODE:
+- case OAKLEY_ECDSA_P256:
+- case OAKLEY_ECDSA_P384:
+- case OAKLEY_ECDSA_P521:
+- default:
+- bad_case(auth);
+- }
+-
+- /* generate SKEYID_* from SKEYID */
+- {
+-
+- chunk_t hmac_opad, hmac_ipad, hmac_pad, hmac_zerobyte,
+- hmac_val1, hmac_val2;
+- CK_OBJECT_HANDLE keyhandle;
+- SECItem param, param1;
+-
+- hmac_opad = hmac_pads(HMAC_OPAD, hasher->hash_block_size);
+- hmac_ipad = hmac_pads(HMAC_IPAD, hasher->hash_block_size);
+- hmac_pad = hmac_pads(0x00,
+- hasher->hash_block_size -
+- hasher->hash_digest_len);
+- hmac_zerobyte = hmac_pads(0x00, 1);
+- hmac_val1 = hmac_pads(0x01, 1);
+- hmac_val2 = hmac_pads(0x02, 1);
+-
+- DBG(DBG_CRYPT, DBG_log("NSS: Started key computation"));
+-
+- /*Deriving SKEYID_d = hmac_xxx(SKEYID, g^xy | CKY-I | CKY-R | 0) */
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(skeyid,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_pad,
+- CKM_XOR_BASE_AND_DATA,
+- CKA_DERIVE,
+- hasher->hash_block_size);
+-
+- passert(tkey1 != NULL);
+-
+- /*DBG(DBG_CRYPT, DBG_log("Started key computation: 1, length=%d", PK11_GetKeyLength(tkey1)));
+- * nss_symkey_log(tkey1, "1");
+- */
+-
+- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(tkey1,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_ipad,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+-
+- passert(tkey2 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(shared);
+- param.data = (unsigned char *) &keyhandle;
+- param.len = sizeof(keyhandle);
+- DBG(DBG_CRYPT,
+- DBG_log("NSS: dh shared param len=%d", param.len));
+-
+- PK11SymKey *tkey3 = PK11_Derive_lsw(tkey2,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey3 != NULL);
+-
+- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(tkey3,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- icookie,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey4 != NULL);
+-
+- PK11SymKey *tkey5 = pk11_derive_wrapper_lsw(tkey4,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- rcookie,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+-
+- passert(tkey5 != NULL);
+-
+- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_zerobyte,
+- nss_key_derivation_mech(hasher),
+- CKA_DERIVE,
+- 0);
+-
+- passert(tkey6 != NULL);
+-
+- PK11SymKey *tkey7 = PK11_Derive_lsw(tkey6,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey7 != NULL);
+-
+- PK11SymKey *tkey8 = pk11_derive_wrapper_lsw(tkey1,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_opad,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey8 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey7);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey9 = PK11_Derive_lsw(tkey8,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- nss_key_derivation_mech(hasher),
+- CKA_DERIVE,
+- 0);
+- passert(tkey9 != NULL);
+-
+- skeyid_d = PK11_Derive_lsw(tkey9,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(skeyid_d != NULL);
+- /* nss_symkey_log(skeyid_d, "skeyid_d"); */
+- /*****End of SKEYID_d derivation***************************************/
+-
+- /*Deriving SKEYID_a = hmac_xxx(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1)*/
+- keyhandle = PK11_GetSymKeyHandle(skeyid_d);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey10 = PK11_Derive_lsw(tkey2,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey10 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(shared);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey11 = PK11_Derive_lsw(tkey10,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey11 != NULL);
+-
+- PK11SymKey *tkey12 = pk11_derive_wrapper_lsw(tkey11,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- icookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey12 != NULL);
+-
+- PK11SymKey *tkey13 = pk11_derive_wrapper_lsw(tkey12,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- rcookie,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey13 != NULL);
+-
+- PK11SymKey *tkey14 = pk11_derive_wrapper_lsw(tkey13,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_val1,
+- nss_key_derivation_mech(hasher),
+- CKA_DERIVE,
+- 0);
+- passert(tkey14 != NULL);
+-
+- PK11SymKey *tkey15 = PK11_Derive_lsw(tkey14,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey15 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey15);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey16 = PK11_Derive_lsw(tkey8,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m,
+- nss_key_derivation_mech(hasher),
+- CKA_DERIVE,
+- 0);
+- passert(tkey16 != NULL);
+-
+- skeyid_a = PK11_Derive_lsw(tkey16,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(skeyid_a != NULL);
+- /* nss_symkey_log(skeyid_a, "skeyid_a"); */
+- /*****End of SKEYID_a derivation***************************************/
+-
+- /*Deriving SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2)*/
+- keyhandle = PK11_GetSymKeyHandle(skeyid_a);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey17 = PK11_Derive_lsw(tkey2,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey17 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(shared);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey18 = PK11_Derive_lsw(tkey17,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey18 != NULL);
+-
+- PK11SymKey *tkey19 = pk11_derive_wrapper_lsw(tkey18,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- icookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey19 != NULL);
+-
+- PK11SymKey *tkey20 = pk11_derive_wrapper_lsw(tkey19,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- rcookie, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey20 != NULL);
+-
+- PK11SymKey *tkey21 = pk11_derive_wrapper_lsw(tkey20,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_val2,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey21 != NULL);
+-
+- PK11SymKey *tkey22 = PK11_Derive_lsw(tkey21, nss_key_derivation_mech(
+- hasher), NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey22 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey22);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey23 = PK11_Derive_lsw(tkey8,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey23 != NULL);
+-
+- DBG(DBG_CRYPT, DBG_log("NSS: enc keysize=%d", (int)keysize));
+- /* Deriving encryption key from SKEYID_e */
+- /* Oakley Keying Material
+- * Derived from Skeyid_e: if it is not big enough, generate more
+- * using the PRF.
+- * See RFC 2409 "IKE" Appendix B
+- */
+-
+- CK_EXTRACT_PARAMS bitstart = 0;
+- param1.data = (unsigned char*)&bitstart;
+- param1.len = sizeof(bitstart);
+-
+- if (keysize <= hasher->hash_digest_len) {
+- skeyid_e = PK11_Derive_lsw(tkey23,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_EXTRACT_KEY_FROM_KEY, /* note */
+- CKA_DERIVE, 0);
+- passert(skeyid_e != NULL);
+- /* nss_symkey_log(skeyid_e, "skeyid_e"); */
+-
+- enc_key = PK11_DeriveWithFlags(skeyid_e,
+- CKM_EXTRACT_KEY_FROM_KEY, ¶m1,
+- nss_encryption_mech(encrypter),
+- CKA_FLAGS_ONLY, keysize,
+- CKF_ENCRYPT | CKF_DECRYPT);
+- passert(enc_key != NULL);
+-
+- /* nss_symkey_log(enc_key, "enc_key"); */
+- } else {
+- size_t i = 0;
+- PK11SymKey *keymat;
+-
+- skeyid_e = PK11_Derive_lsw(tkey23,
+- nss_key_derivation_mech(hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA, /* note */
+- CKA_DERIVE, 0);
+- passert(skeyid_e != NULL);
+- /* nss_symkey_log(skeyid_e, "skeyid_e"); */
+-
+- PK11SymKey *tkey25 = pk11_derive_wrapper_lsw(skeyid_e,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE,
+- hasher->hash_block_size);
+- passert(tkey25 != NULL);
+-
+- PK11SymKey *tkey26 = pk11_derive_wrapper_lsw(tkey25,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_ipad, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey26 != NULL);
+-
+- PK11SymKey *tkey27 = pk11_derive_wrapper_lsw(tkey26,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_zerobyte,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey27 != NULL);
+-
+- PK11SymKey *tkey28 = PK11_Derive_lsw(tkey27, nss_key_derivation_mech(
+- hasher), NULL,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey28 != NULL);
+-
+- PK11SymKey *tkey29 = pk11_derive_wrapper_lsw(tkey25,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_opad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey29 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey28);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey30 = PK11_Derive_lsw(tkey29,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey30 != NULL);
+-
+- PK11SymKey *tkey31 = PK11_Derive_lsw(tkey30, nss_key_derivation_mech(
+- hasher), NULL, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey31 != NULL);
+-
+- keymat = tkey31;
+-
+- i += hasher->hash_digest_len;
+-
+- PK11SymKey *tkey32 = pk11_derive_wrapper_lsw(skeyid_e,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE,
+- hasher->hash_block_size);
+- passert(tkey32 != NULL);
+-
+- PK11SymKey *tkey33 = pk11_derive_wrapper_lsw(tkey32,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_ipad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey33 != NULL);
+-
+- PK11SymKey *tkey36 = pk11_derive_wrapper_lsw(tkey32,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_opad, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey36 != NULL);
+-
+- for (;; ) {
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey31);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey34 = PK11_Derive_lsw(tkey33,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey34 != NULL);
+-
+- PK11SymKey *tkey35 = PK11_Derive_lsw(tkey34, nss_key_derivation_mech(
+- hasher), NULL,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey35 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey35);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey37 = PK11_Derive_lsw(tkey36,
+- CKM_CONCATENATE_BASE_AND_KEY, ¶m,
+- nss_key_derivation_mech(
+- hasher), CKA_DERIVE,
+- 0);
+- passert(tkey37 != NULL);
+-
+- PK11SymKey *tkey38 = PK11_Derive_lsw(tkey37, nss_key_derivation_mech(
+- hasher), NULL, CKM_CONCATENATE_BASE_AND_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey38 != NULL);
+-
+- i += hasher->hash_digest_len;
+-
+- if (i >= keysize ) {
+-
+- /*concatenating K1 and K2 */
+- keyhandle =
+- PK11_GetSymKeyHandle(tkey38);
+- param.data =
+- (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey39 = PK11_Derive_lsw(
+- keymat,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- CKA_DERIVE, 0);
+- passert(tkey39 != NULL);
+-
+- enc_key = PK11_DeriveWithFlags(tkey39,
+- CKM_EXTRACT_KEY_FROM_KEY, ¶m1,
+- nss_encryption_mech(encrypter),
+- CKA_FLAGS_ONLY, /*0*/ keysize,
+- CKF_ENCRYPT | CKF_DECRYPT);
+-
+- /* nss_symkey_log(enc_key, "enc_key"); */
+- passert(enc_key != NULL);
+-
+- PK11_FreeSymKey(tkey25);
+- PK11_FreeSymKey(tkey26);
+- PK11_FreeSymKey(tkey27);
+- PK11_FreeSymKey(tkey28);
+- PK11_FreeSymKey(tkey29);
+- PK11_FreeSymKey(tkey30);
+- PK11_FreeSymKey(tkey31);
+- PK11_FreeSymKey(tkey32);
+- PK11_FreeSymKey(tkey33);
+- PK11_FreeSymKey(tkey34);
+- PK11_FreeSymKey(tkey35);
+- PK11_FreeSymKey(tkey36);
+- PK11_FreeSymKey(tkey37);
+- PK11_FreeSymKey(tkey38);
+- PK11_FreeSymKey(tkey39);
+- PK11_FreeSymKey(keymat);
+-
+- DBG(DBG_CRYPT,
+- DBG_log(
+- "NSS: Freed 25-39 symkeys"));
+- break;
+- } else {
+-
+- keyhandle =
+- PK11_GetSymKeyHandle(tkey38);
+- param.data =
+- (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey39 = PK11_Derive_lsw(
+- keymat,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE, 0);
+- passert(tkey39 != NULL);
+-
+- keymat = tkey39;
+- PK11_FreeSymKey(tkey31);
+- tkey31 = tkey38;
+- PK11_FreeSymKey(tkey34);
+- PK11_FreeSymKey(tkey35);
+- PK11_FreeSymKey(tkey37);
+-
+- DBG(DBG_CRYPT,
+- DBG_log(
+- "NSS: Freed symkeys 31 34 35 37"));
+- }
+- } /*end for*/
+- } /*end else skeyid_e */
+-
+- /*****End of SKEYID_e and encryption key derivation***************************************/
+-
+- /********Saving pointers of all derived keys**********************************************/
+- *skeyid_out = skeyid;
+- *skeyid_d_out = skeyid_d;
+- *skeyid_a_out = skeyid_a;
+- *skeyid_e_out = skeyid_e;
+- *enc_key_out = enc_key;
+-
+- DBG(DBG_CRYPT, DBG_log("NSS: pointers skeyid_d %p, skeyid_a %p, skeyid_e %p, enc_key %p",
+- skeyid_d, skeyid_a, skeyid_e, enc_key));
+-
+-
+- /*****Freeing tmp keys***************************************/
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey2);
+- PK11_FreeSymKey(tkey3);
+- PK11_FreeSymKey(tkey4);
+- PK11_FreeSymKey(tkey5);
+- PK11_FreeSymKey(tkey6);
+- PK11_FreeSymKey(tkey7);
+- PK11_FreeSymKey(tkey8);
+- PK11_FreeSymKey(tkey9);
+- PK11_FreeSymKey(tkey10);
+- PK11_FreeSymKey(tkey11);
+- PK11_FreeSymKey(tkey12);
+- PK11_FreeSymKey(tkey13);
+- PK11_FreeSymKey(tkey14);
+- PK11_FreeSymKey(tkey15);
+- PK11_FreeSymKey(tkey16);
+- PK11_FreeSymKey(tkey17);
+- PK11_FreeSymKey(tkey18);
+- PK11_FreeSymKey(tkey19);
+- PK11_FreeSymKey(tkey20);
+- PK11_FreeSymKey(tkey21);
+- PK11_FreeSymKey(tkey22);
+- PK11_FreeSymKey(tkey23);
+-
+- DBG(DBG_CRYPT, DBG_log("NSS: Freed symkeys 1-23"));
+-
+- freeanychunk(hmac_opad);
+- freeanychunk(hmac_ipad);
+- freeanychunk(hmac_pad);
+- freeanychunk(hmac_zerobyte);
+- freeanychunk(hmac_val1);
+- freeanychunk(hmac_val2);
+- DBG(DBG_CRYPT, DBG_log("NSS: Freed padding chunks"));
+- }
+-
+- /* generate IV */
+- {
+- union hash_ctx hash_ctx;
+-
+- new_iv->len = hasher->hash_digest_len;
+- new_iv->ptr = alloc_bytes(new_iv->len, "calculated new iv");
+-
+- DBG(DBG_CRYPT, {
+- DBG_dump_chunk("DH_i:", gi);
+- DBG_dump_chunk("DH_r:", gr);
+- });
+- hasher->hash_init(&hash_ctx);
+- hasher->hash_update(&hash_ctx, gi.ptr, gi.len);
+- hasher->hash_update(&hash_ctx, gr.ptr, gr.len);
+- hasher->hash_final(new_iv->ptr, &hash_ctx);
+- DBG(DBG_CRYPT, DBG_log("end of IV generation"));
+- }
+-}
+-
+-/* MUST BE THREAD-SAFE */
+-void calc_dh_iv(struct pluto_crypto_req *r)
+-{
+- struct pcr_skeyid_r *skr = &r->pcr_d.dhr;
+- struct pcr_skeyid_q dhq;
+- const struct oakley_group_desc *group;
+- PK11SymKey *shared;
+- chunk_t g;
+- SECKEYPrivateKey *ltsecret;
+- PK11SymKey
+- *skeyid,
+- *skeyid_d,
+- *skeyid_a,
+- *skeyid_e,
+- *enc_key;
+- chunk_t new_iv;
+- SECKEYPublicKey *pubk;
+-
+- /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
+- memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));
+-
+- /* clear out the reply */
+- zero(skr);
+- INIT_WIRE_ARENA(*skr);
+-
+- group = lookup_group(dhq.oakley_group);
+- passert(group != NULL);
+-
+- ltsecret = dhq.secret;
+- pubk = dhq.pubk;
+-
+- /* now calculate the (g^x)(g^y) ---
+- * need gi on responder, gr on initiator
+- */
+-
+- setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr);
+-
+- DBG(DBG_CRYPT,
+- DBG_dump_chunk("peer's g: ", g));
+-
+- shared = calc_dh_shared(g, ltsecret, group, pubk);
+-
+- zero(&new_iv);
+-
+- /* okay, so now calculate IV */
+- calc_skeyids_iv(&dhq,
+- shared,
+- dhq.key_size,
+- &skeyid,
+- &skeyid_d,
+- &skeyid_a,
+- &skeyid_e,
+- &new_iv,
+- &enc_key);
+-
+- skr->shared = shared;
+- skr->skeyid = skeyid;
+- skr->skeyid_d = skeyid_d;
+- skr->skeyid_a = skeyid_a;
+- skr->skeyid_e = skeyid_e;
+- skr->enc_key = enc_key;
+-
+-
+- WIRE_CLONE_CHUNK(*skr, new_iv, new_iv);
+- freeanychunk(new_iv);
+-}
+
+ /* MUST BE THREAD-SAFE */
+ void calc_dh(struct pluto_crypto_req *r)
+@@ -1128,496 +202,3 @@
+
+ skr->shared = calc_dh_shared(g, ltsecret, group, pubk);
+ }
+-
+-static chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key,
+- size_t next_bit, size_t byte_size)
+-{
+- if (byte_size == 0) {
+- DBG(DBG_CRYPT, DBG_log("chunk_from_symkey: %s: zero size", name));
+- return empty_chunk;
+- }
+- CK_EXTRACT_PARAMS bs = next_bit;
+- SECItem param = { .data = (unsigned char*)&bs, .len = sizeof(bs) };
+- PK11SymKey *sym_key = PK11_DeriveWithFlags(source_key,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- ¶m,
+- CKM_VENDOR_DEFINED,
+- CKA_FLAGS_ONLY, byte_size, 0);
+- if (sym_key == NULL) {
+- loglog(RC_LOG_SERIOUS, "NSS: PK11_DeriveWithFlags failed while generating %s", name);
+- return empty_chunk;
+- }
+- SECStatus s = PK11_ExtractKeyValue(sym_key);
+- if (s != SECSuccess) {
+- loglog(RC_LOG_SERIOUS, "NSS: PK11_ExtractKeyValue failed while generating %s", name);
+- return empty_chunk;
+- }
+- /* Internal structure address, do not free. */
+- SECItem *data = PK11_GetKeyData(sym_key);
+- if (data == NULL) {
+- loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData failed while generating %s", name);
+- return empty_chunk;
+- }
+- DBG(DBG_CRYPT,
+- DBG_log("chunk_from_symkey: %s: extracted len %d bytes at %p",
+- name, data->len, data->data));
+- if (data->len != byte_size) {
+- loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData returned wrong number of bytes while generating %s", name);
+- return empty_chunk;
+- }
+- chunk_t chunk;
+- clonetochunk(chunk, data->data, data->len, name);
+- DBG(DBG_CRYPT, DBG_dump_chunk(name, chunk));
+- PK11_FreeSymKey(sym_key);
+- return chunk;
+-}
+-
+-/*
+- * IKEv2 - RFC4306 2.14 SKEYSEED - calculation.
+- */
+-
+-/* 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
+- )
+-{
+- struct v2prf_stuff vpss;
+-
+- chunk_t hmac_opad, hmac_ipad, hmac_pad_prf;
+- /* chunk_t hmac_pad_integ, hmac_zerobyte, hmac_val1, hmac_val2; */
+-
+- CK_OBJECT_HANDLE keyhandle;
+- SECItem param, param1;
+- 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;
+-
+- zero(&vpss);
+-
+- /* this doesn't take any memory, it's just moving pointers around */
+- setchunk_from_wire(vpss.ni, skq, &skq->ni);
+- setchunk_from_wire(vpss.nr, skq, &skq->nr);
+- setchunk_from_wire(vpss.spii, skq, &skq->icookie);
+- setchunk_from_wire(vpss.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);
+-
+- hmac_opad = hmac_pads(HMAC_OPAD, prf_hasher->hash_block_size);
+- hmac_ipad = hmac_pads(HMAC_IPAD, prf_hasher->hash_block_size);
+- hmac_pad_prf = hmac_pads(0x00,
+- prf_hasher->hash_block_size -
+- prf_hasher->hash_digest_len);
+-
+- /* generate SKEYSEED from key=(Ni|Nr), hash of shared */
+- skeyseed_k = skeyid_digisig(vpss.ni, vpss.nr, shared, prf_hasher);
+- 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;
+- DBG(DBG_CRYPT,
+- DBG_log("calc_skeyseed_v2: %zd = %d(d) + 2*%d(p) + 2*%zd(key) + 2*%zd(salt) + 2*%d(integ) bytes",
+- total_keysize, skd_bytes, skp_bytes, key_size, salt_size, integ_size));
+- vpss.counter[0] = 0x01;
+- vpss.t.len = 0;
+-
+- DBG(DBG_CRYPT, {
+- DBG_log("PRF+ input");
+- DBG_dump_chunk("Ni", vpss.ni);
+- DBG_dump_chunk("Nr", vpss.nr);
+- DBG_dump_chunk("SPIi", vpss.spii);
+- DBG_dump_chunk("SPIr", vpss.spir);
+- DBG_log("Total keysize needed %zd",
+- total_keysize);
+- });
+-
+- PK11SymKey *finalkey = NULL;
+- PK11SymKey *tkey11 = NULL;
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(skeyseed_k,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_pad_prf, CKM_XOR_BASE_AND_DATA, CKA_DERIVE,
+- prf_hasher->hash_block_size);
+- passert(tkey1 != NULL);
+-
+- for (;; ) {
+- PK11SymKey *tkey3 = NULL;
+-
+- if (vpss.counter[0] == 0x01) {
+- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(
+- tkey1, CKM_XOR_BASE_AND_DATA,
+- hmac_ipad,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey2 != NULL);
+-
+- tkey3 = pk11_derive_wrapper_lsw(tkey2,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- vpss.ni, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- PK11_FreeSymKey(tkey2);
+- } else {
+- PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(
+- tkey1, CKM_XOR_BASE_AND_DATA,
+- hmac_ipad,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey2 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey11);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey12 = PK11_Derive_lsw(tkey2,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- passert(tkey12 != NULL);
+-
+- tkey3 = pk11_derive_wrapper_lsw(tkey12,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- vpss.ni, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- 0);
+- PK11_FreeSymKey(tkey2);
+- PK11_FreeSymKey(tkey11);
+- PK11_FreeSymKey(tkey12);
+- }
+-
+- passert(tkey3 != NULL);
+-
+- PK11SymKey *tkey4 = pk11_derive_wrapper_lsw(tkey3,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- vpss.nr,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey4 != NULL);
+-
+- PK11SymKey *tkey5 = pk11_derive_wrapper_lsw(tkey4,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- vpss.spii,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey5 != NULL);
+-
+- PK11SymKey *tkey6 = pk11_derive_wrapper_lsw(tkey5,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- vpss.spir,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey6 != NULL);
+-
+- chunk_t counter;
+-
+- setchunk(counter, &vpss.counter[0], sizeof(vpss.counter[0]));
+- PK11SymKey *tkey7 = pk11_derive_wrapper_lsw(tkey6,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- counter,
+- nss_key_derivation_mech(prf_hasher),
+- CKA_DERIVE,
+- 0);
+- passert(tkey7 != NULL);
+-
+- PK11SymKey *tkey8 = PK11_Derive_lsw(tkey7,
+- nss_key_derivation_mech(prf_hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- passert(tkey8 != NULL);
+-
+- PK11SymKey *tkey9 = pk11_derive_wrapper_lsw(tkey1,
+- CKM_XOR_BASE_AND_DATA,
+- hmac_opad,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey9 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey8);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- PK11SymKey *tkey10 = PK11_Derive_lsw(tkey9,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- nss_key_derivation_mech(prf_hasher),
+- CKA_DERIVE,
+- 0);
+- passert(tkey10 != NULL);
+-
+- if (vpss.counter[0] == 0x01) {
+- finalkey = PK11_Derive_lsw(tkey10,
+- nss_key_derivation_mech(prf_hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(finalkey != NULL);
+-
+- tkey11 = PK11_Derive_lsw(tkey10,
+- nss_key_derivation_mech(prf_hasher),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey11 != NULL);
+- } else {
+- tkey11 = PK11_Derive_lsw(tkey10,
+- nss_key_derivation_mech(prf_hasher),
+- NULL,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey11 != NULL);
+-
+- keyhandle = PK11_GetSymKeyHandle(tkey11);
+- param.data = (unsigned char*)&keyhandle;
+- param.len = sizeof(keyhandle);
+-
+- if ( total_keysize <=
+- (PK11_GetKeyLength(finalkey) +
+- PK11_GetKeyLength(tkey11)) ) {
+- finalkey = PK11_Derive_lsw(finalkey,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(finalkey != NULL);
+- } else {
+- finalkey = PK11_Derive_lsw(finalkey,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(finalkey != NULL);
+- }
+- }
+-
+- PK11_FreeSymKey(tkey3);
+- PK11_FreeSymKey(tkey4);
+- PK11_FreeSymKey(tkey5);
+- PK11_FreeSymKey(tkey6);
+- PK11_FreeSymKey(tkey7);
+- PK11_FreeSymKey(tkey8);
+- PK11_FreeSymKey(tkey9);
+- PK11_FreeSymKey(tkey10);
+-
+- if (total_keysize <= PK11_GetKeyLength(finalkey)) {
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey11);
+- break;
+- }
+-
+- vpss.counter[0]++;
+- }
+-
+- DBG(DBG_CRYPT,
+- DBG_log("NSS ikev2: finished computing key material for IKEv2 SA"));
+-
+- CK_EXTRACT_PARAMS bs = 0;
+- size_t next_bit = 0;
+-
+- SK_d_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- skd_bytes);
+- next_bit += skd_bytes * BITS_PER_BYTE;
+-
+- SK_ai_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- integ_size);
+- next_bit += integ_size * BITS_PER_BYTE;
+-
+- SK_ar_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- integ_size);
+- next_bit += integ_size * BITS_PER_BYTE;
+-
+- bs = next_bit;
+- param1.data = (unsigned char*)&bs;
+- param1.len = sizeof(bs);
+- SK_ei_k = PK11_DeriveWithFlags(finalkey,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- ¶m1,
+- nss_encryption_mech(encrypter),
+- CKA_FLAGS_ONLY, key_size,
+- CKF_ENCRYPT | CKF_DECRYPT);
+- next_bit += key_size * BITS_PER_BYTE;
+-
+- initiator_salt = chunk_from_symkey("initiator salt", finalkey,
+- next_bit, salt_size);
+- next_bit += salt_size * BITS_PER_BYTE;
+-
+- bs = next_bit;
+- param1.data = (unsigned char*)&bs;
+- param1.len = sizeof(bs);
+- SK_er_k = PK11_DeriveWithFlags(finalkey,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- ¶m1,
+- nss_encryption_mech(encrypter),
+- CKA_FLAGS_ONLY, key_size,
+- CKF_ENCRYPT | CKF_DECRYPT);
+- next_bit += key_size * BITS_PER_BYTE;
+-
+- responder_salt = chunk_from_symkey("responder salt", finalkey,
+- next_bit, salt_size);
+- next_bit += salt_size * BITS_PER_BYTE;
+-
+- SK_pi_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- skp_bytes);
+- next_bit += skp_bytes * BITS_PER_BYTE;
+-
+- SK_pr_k = pk11_extract_derive_wrapper_lsw(finalkey, next_bit,
+- CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE,
+- skp_bytes);
+- next_bit += skp_bytes * BITS_PER_BYTE;
+-
+- DBG(DBG_CRYPT,
+- DBG_log("NSS ikev2: finished computing individual keys for IKEv2 SA"));
+- PK11_FreeSymKey(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;
+-
+- freeanychunk(hmac_opad);
+- freeanychunk(hmac_ipad);
+- freeanychunk(hmac_pad_prf);
+- }
+- 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));
+-}
+-
+-/* MUST BE THREAD-SAFE */
+-void calc_dh_v2(struct pluto_crypto_req *r)
+-{
+- struct pcr_skeycalc_v2_r *skr = &r->pcr_d.dhv2;
+- struct pcr_skeyid_q dhq;
+- const struct oakley_group_desc *group;
+- PK11SymKey *shared;
+- chunk_t g;
+- SECKEYPrivateKey *ltsecret;
+- PK11SymKey *skeyseed;
+- PK11SymKey
+- *SK_d,
+- *SK_ai,
+- *SK_ar,
+- *SK_ei,
+- *SK_er,
+- *SK_pi,
+- *SK_pr;
+- chunk_t initiator_salt;
+- chunk_t responder_salt;
+- SECKEYPublicKey *pubk;
+-
+- /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
+- memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));
+-
+- /* clear out the reply */
+- zero(skr);
+- INIT_WIRE_ARENA(*skr);
+-
+- group = lookup_group(dhq.oakley_group);
+- passert(group != NULL);
+-
+- ltsecret = dhq.secret;
+- pubk = dhq.pubk;
+-
+- /* now calculate the (g^x)(g^y) --- need gi on responder, gr on initiator */
+-
+- setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr);
+-
+- DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g));
+-
+- shared = calc_dh_shared(g, ltsecret, group, pubk);
+-
+- /* okay, so now all the shared key material */
+- calc_skeyseed_v2(&dhq, /* input */
+- shared, /* input */
+- dhq.key_size, /* input */
+- dhq.salt_size, /* input */
+-
+- &skeyseed, /* output */
+- &SK_d, /* output */
+- &SK_ai, /* output */
+- &SK_ar, /* output */
+- &SK_ei, /* output */
+- &SK_er, /* output */
+- &SK_pi, /* output */
+- &SK_pr, /* output */
+- &initiator_salt, /* output */
+- &responder_salt); /* output */
+-
+- skr->shared = shared;
+- skr->skeyseed = skeyseed;
+- skr->skeyid_d = SK_d;
+- skr->skeyid_ai = SK_ai;
+- skr->skeyid_ar = SK_ar;
+- skr->skeyid_ei = SK_ei;
+- skr->skeyid_er = SK_er;
+- skr->skeyid_pi = SK_pi;
+- skr->skeyid_pr = SK_pr;
+- skr->skey_initiator_salt = initiator_salt;
+- skr->skey_responder_salt = responder_salt;
+-}
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_dh.h libreswan-3.12/programs/pluto/crypt_dh.h
+--- libreswan-3.12-orig/programs/pluto/crypt_dh.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypt_dh.h 2015-05-06 11:45:32.918301394 -0400
+@@ -0,0 +1,46 @@
++/*
++ * DH crypto functions, for libreswan
++ *
++ * Copyright (C) 2007-2008 Michael C. Richardson
++ * Copyright (C) 2008 Antony Antony
++ * Copyright (C) 2009 David McCullough
++ * Copyright (C) 2009-2012 Avesh Agarwal
++ * Copyright (C) 2009-2010 Paul Wouters
++ * Copyright (C) 2010 Tuomo Soini
++ * Copyright (C) 2012-2013 Paul Wouters
++ * Copyright (C) 2012 Wes Hardaker
++ * Copyright (C) 2013 Antony Antony
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Paul Wouters
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#ifndef crypt_dh_h
++#define crypt_dh_h
++
++#include
++#include "lswalloc.h"
++
++struct oakley_group_desc;
++
++PK11SymKey *calc_dh_shared(chunk_t g, /* converted to SECItem */
++ /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */
++ const struct oakley_group_desc *group,
++ const SECKEYPublicKey *local_pubk);
++
++
++struct pluto_crypto_req;
++
++void calc_dh(struct pluto_crypto_req *r);
++
++#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/crypto.h libreswan-3.12/programs/pluto/crypto.h
+--- libreswan-3.12-orig/programs/pluto/crypto.h 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypto.h 2015-05-06 11:45:32.918301394 -0400
+@@ -127,24 +127,14 @@
+ aes_xcbc_context ctx_aes_xcbc;
+ };
+
+-/* HMAC package
+- * Note that hmac_ctx can be (and is) copied since there are
+- * no persistent pointers into it.
++/*
++ * HMAC package (new code should use crypt_prf).
+ */
+
++struct crypt_prf;
+ struct hmac_ctx {
+- const struct hash_desc *h; /* underlying hash function */
+- size_t hmac_digest_len; /* copy of h->hash_digest_len */
+- union hash_ctx hash_ctx; /* ctx for hash function */
+- u_char buf1[HMAC_BUFSIZE], buf2[HMAC_BUFSIZE];
+-#ifdef USE_SHA2
+- sha256_context ctx_sha256;
+- sha512_context ctx_sha512;
+-#endif
+- aes_xcbc_context ctx_aes_xcbc;
+-
+- PK11SymKey *ikey, *okey;
+- PK11Context *ctx_nss;
++ struct crypt_prf *prf;
++ size_t hmac_digest_len;
+ };
+
+ extern void hmac_init(struct hmac_ctx *ctx,
+@@ -167,18 +157,7 @@
+ }
+
+ extern CK_MECHANISM_TYPE nss_key_derivation_mech(const struct hash_desc *hasher);
+-extern void nss_symkey_log(PK11SymKey *key, const char *msg);
+ extern chunk_t hmac_pads(u_char val, unsigned int len);
+-extern PK11SymKey *pk11_derive_wrapper_lsw(PK11SymKey *base,
+- CK_MECHANISM_TYPE mechanism,
+- chunk_t data,
+- CK_MECHANISM_TYPE target,
+- CK_ATTRIBUTE_TYPE operation,
+- int keySize);
+-extern PK11SymKey *PK11_Derive_lsw(PK11SymKey *base,
+- CK_MECHANISM_TYPE mechanism,
+- SECItem *param, CK_MECHANISM_TYPE target,
+- CK_ATTRIBUTE_TYPE operation, int keySize);
+
+ enum crk_proto {
+ CRK_ESPorAH,
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_prf.c libreswan-3.12/programs/pluto/crypt_prf.c
+--- libreswan-3.12-orig/programs/pluto/crypt_prf.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypt_prf.c 2015-05-06 11:45:32.919301405 -0400
+@@ -0,0 +1,203 @@
++/*
++ * PRF helper functions, for libreswan
++ *
++ * Copyright (C) 2007-2008 Michael C. Richardson
++ * Copyright (C) 2008 Antony Antony
++ * Copyright (C) 2009 David McCullough
++ * Copyright (C) 2009-2012 Avesh Agarwal
++ * Copyright (C) 2009-2010 Paul Wouters
++ * Copyright (C) 2010 Tuomo Soini
++ * Copyright (C) 2012-2013 Paul Wouters
++ * Copyright (C) 2012 Wes Hardaker
++ * Copyright (C) 2013 Antony Antony
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Paul Wouters
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++
++//#include "libreswan.h"
++#include "lswalloc.h"
++#include "lswlog.h"
++#include "ike_alg.h"
++#include "crypt_prf.h"
++#include "crypt_symkey.h"
++#include "crypto.h"
++
++struct crypt_prf {
++ const char *name;
++ const struct hash_desc *hasher;
++ /* for converting chunks to symkeys */
++ PK11SymKey *scratch;
++ /* Did we allocate KEY? */
++ bool we_own_key;
++ /* intermediate values */
++ PK11SymKey *key;
++ PK11SymKey *inner;
++};
++
++/*
++ * During the init phase, accumulate the key material in KEY.
++ */
++struct crypt_prf *crypt_prf_init(const char *name, const struct hash_desc *hasher,
++ PK11SymKey *scratch)
++{
++ struct crypt_prf *prf = alloc_bytes(sizeof(struct crypt_prf), name);
++ DBG(DBG_CRYPT, DBG_log("%s prf: init %p", name, prf));
++ prf->name = name;
++ prf->hasher = hasher;
++ prf->scratch = scratch;
++ prf->we_own_key = FALSE;
++ prf->key = NULL;
++ prf->inner = NULL;
++ return prf;
++}
++
++/*
++ * Update KEY marking it as ours. Only call with a KEY we created.
++ */
++static void update_key(struct crypt_prf *prf, PK11SymKey *key)
++{
++ if (prf->we_own_key) {
++ free_any_symkey(__func__, &prf->key);
++ }
++ prf->we_own_key = TRUE;
++ prf->key = key;
++}
++
++void crypt_prf_init_symkey(const char *name, struct crypt_prf *prf, PK11SymKey *key)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: init symkey %s %p (length %d)",
++ prf->name, name, key, PK11_GetKeyLength(key)));
++ if (prf->key == NULL) {
++ prf->we_own_key = FALSE;
++ prf->key = key;
++ } else {
++ update_key(prf, concat_symkey_symkey(prf->hasher, prf->key, key));
++ }
++}
++
++void crypt_prf_init_chunk(const char *name, struct crypt_prf *prf, chunk_t key)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: init chunk %s %p (length %zd)",
++ prf->name, name, key.ptr, key.len));
++ if (prf->key == NULL) {
++ prf->key = symkey_from_chunk(prf->scratch, key);
++ prf->we_own_key = TRUE;
++ } else {
++ update_key(prf, concat_symkey_chunk(prf->hasher, prf->key, key));
++ }
++}
++
++/*
++ * Prepare for update phase (accumulate seed material).
++ */
++void crypt_prf_update(struct crypt_prf *prf)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: update", prf->name));
++ /* create the prf key from KEY. */
++ passert(prf->key != NULL);
++ /* If the key is too big, re-hash it down to size. */
++ if (PK11_GetKeyLength(prf->key) > prf->hasher->hash_block_size) {
++ update_key(prf, hash_symkey(prf->hasher, prf->key));
++ }
++ /* If the key is too small, pad it. */
++ if (PK11_GetKeyLength(prf->key) < prf->hasher->hash_block_size) {
++ /* pad it to block_size. */
++ chunk_t hmac_pad_prf = hmac_pads(0x00,
++ (prf->hasher->hash_block_size -
++ PK11_GetKeyLength(prf->key)));
++ update_key(prf, concat_symkey_chunk(prf->hasher, prf->key,
++ hmac_pad_prf));
++ freeanychunk(hmac_pad_prf);
++ }
++ passert(prf->key != NULL);
++
++ /* Start forming the inner hash input: (key^IPAD)|... */
++ passert(prf->inner == NULL);
++ chunk_t hmac_ipad = hmac_pads(HMAC_IPAD, prf->hasher->hash_block_size);
++ prf->inner = xor_symkey_chunk(prf->key, hmac_ipad);
++ freeanychunk(hmac_ipad);
++}
++
++void crypt_prf_update_chunk(const char *name, struct crypt_prf *prf,
++ chunk_t update)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: update chunk %s %p (length %zd)",
++ prf->name, name, update.ptr, update.len));
++ append_symkey_chunk(prf->hasher, &(prf->inner), update);
++}
++
++void crypt_prf_update_symkey(const char *name, struct crypt_prf *prf,
++ PK11SymKey *update)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: update symkey %s %p (length %d)",
++ prf->name, name, update,
++ PK11_GetKeyLength(update)));
++ append_symkey_symkey(prf->hasher, &(prf->inner), update);
++}
++
++void crypt_prf_update_byte(const char *name, struct crypt_prf *prf,
++ uint8_t update)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: update byte %s", prf->name, name));
++ append_symkey_byte(prf->hasher, &(prf->inner), update);
++}
++
++void crypt_prf_update_bytes(const char *name, struct crypt_prf *prf,
++ const void *update, size_t sizeof_update)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: update bytes %s %p (length %zd)",
++ prf->name, name, update, sizeof_update));
++ append_symkey_bytes(prf->hasher, &(prf->inner), update, sizeof_update);
++}
++
++PK11SymKey *crypt_prf_final(struct crypt_prf *prf)
++{
++ DBG(DBG_CRYPT, DBG_log("%s prf: final", prf->name));
++ passert(prf->inner != NULL);
++ /* run that through hasher */
++ PK11SymKey *hashed_inner = hash_symkey(prf->hasher, prf->inner);
++ free_any_symkey("prf inner", &prf->inner);
++
++ /* Input to outer hash: (key^OPAD)|hashed_inner. */
++ chunk_t hmac_opad = hmac_pads(HMAC_OPAD, prf->hasher->hash_block_size);
++ PK11SymKey *outer = xor_symkey_chunk(prf->key, hmac_opad);
++ freeanychunk(hmac_opad);
++ append_symkey_symkey(prf->hasher, &outer, hashed_inner);
++ free_any_symkey("prf hashed inner", &hashed_inner);
++
++ /* Finally hash that */
++ PK11SymKey *hashed_outer = hash_symkey(prf->hasher, outer);
++ free_any_symkey("prf outer", &outer);
++
++ if (prf->we_own_key) {
++ free_any_symkey("prf key", &prf->key);
++ }
++ prf->key = NULL; /* help debug */
++ pfree(prf);
++
++ DBG(DBG_CRYPT, DBG_dump_symkey("prf result", hashed_outer));
++ return hashed_outer;
++}
++
++void crypt_prf_final_bytes(struct crypt_prf *prf,
++ void *bytes, size_t sizeof_bytes)
++{
++ const char *name = prf->name;
++ PK11SymKey *result = crypt_prf_final(prf);
++ prf = NULL; /* no longer valid */
++ bytes_from_symkey_bytes(name, result, 0, bytes, sizeof_bytes);
++ free_any_symkey(__func__, &result);
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_prf.h libreswan-3.12/programs/pluto/crypt_prf.h
+--- libreswan-3.12-orig/programs/pluto/crypt_prf.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypt_prf.h 2015-05-06 11:45:32.919301405 -0400
+@@ -0,0 +1,86 @@
++/*
++ * prf and keying material helper functions, for libreswan
++ *
++ * Copyright (C) 2007 Michael C. Richardson
++ * Copyright (C) 2010 Paul Wouters
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#ifndef crypt_prf_h
++#define crypt_prf_h
++
++#include
++
++struct hash_desc;
++struct crypt_prf;
++
++/*
++ * Primitives implementing PRF described in rfc2104.
++ *
++ * This implementation tries to keep all the input and output material
++ * secure inside SymKeys. To that end, it should be good for
++ * generating keying material.
++ *
++ * The slightly clunky, interface is described in-line below.
++ */
++
++/*
++ * Call this first; always.
++ *
++ * SCRATCH is used as a secure starting point when the key is formed
++ * from raw bytes (or memory).
++ */
++struct crypt_prf *crypt_prf_init(const char *name,
++ const struct hash_desc *hasher,
++ PK11SymKey *scratch);
++
++/*
++ * Next load up the raw-key by calling one or more of the following.
++ * Multiple calls concatenate the key.
++ *
++ * Even when SCRATCH above was passed the KEY, the below must be
++ * called.
++ */
++void crypt_prf_init_symkey(const char *name, struct crypt_prf *prf, PK11SymKey *key);
++void crypt_prf_init_chunk(const char *name, struct crypt_prf *prf,
++ chunk_t key);
++void crypt_prf_init_bytes(const char *name, struct crypt_prf *prf,
++ const void *key, size_t sizeof_key);
++
++/*
++ * Then call this to flip to seed/data/text mode; always.
++ */
++void crypt_prf_update(struct crypt_prf *prf);
++
++/*
++ * Call these to accumulate the seed/data/text.
++ */
++void crypt_prf_update_chunk(const char *name, struct crypt_prf *prf,
++ chunk_t update);
++void crypt_prf_update_symkey(const char *name, struct crypt_prf *prf,
++ PK11SymKey *update);
++void crypt_prf_update_byte(const char *name, struct crypt_prf *prf, uint8_t byte);
++void crypt_prf_update_bytes(const char *name, struct crypt_prf *prf,
++ const void *bytes, size_t count);
++
++/*
++ * Finally ...
++ *
++ * This will free PRF.
++ */
++PK11SymKey *crypt_prf_final(struct crypt_prf *prf);
++void crypt_prf_final_bytes(struct crypt_prf *prf,
++ void *bytes, size_t sizeof_bytes);
++
++#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_symkey.c libreswan-3.12/programs/pluto/crypt_symkey.c
+--- libreswan-3.12-orig/programs/pluto/crypt_symkey.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypt_symkey.c 2015-05-06 11:45:32.920301417 -0400
+@@ -0,0 +1,468 @@
++/*
++ * SYMKEY manipulation functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include "libreswan.h"
++#include "lswalloc.h"
++#include "lswlog.h"
++#include "ike_alg.h"
++#include "crypt_symkey.h"
++#include "crypto.h"
++
++/*
++ * XXX: Is there an NSS version of this?
++ */
++
++static const char *ckm_to_string(CK_MECHANISM_TYPE mechanism)
++{
++ const char *t;
++#define CASE(T) case T: t = #T; eat(t, "CKM_"); return t
++ switch (mechanism) {
++
++ CASE(CKM_CONCATENATE_BASE_AND_DATA);
++ CASE(CKM_CONCATENATE_BASE_AND_KEY);
++ CASE(CKM_CONCATENATE_DATA_AND_BASE);
++
++ CASE(CKM_XOR_BASE_AND_DATA);
++
++ CASE(CKM_EXTRACT_KEY_FROM_KEY);
++
++ CASE(CKM_VENDOR_DEFINED);
++
++ CASE(CKM_AES_CBC);
++ CASE(CKM_DES3_CBC);
++ CASE(CKM_CAMELLIA_CBC);
++ CASE(CKM_AES_CTR);
++ CASE(CKM_AES_GCM);
++
++ CASE(CKM_MD5_KEY_DERIVATION);
++ CASE(CKM_SHA1_KEY_DERIVATION);
++ CASE(CKM_SHA256_KEY_DERIVATION);
++ CASE(CKM_SHA384_KEY_DERIVATION);
++ CASE(CKM_SHA512_KEY_DERIVATION);
++
++ default:
++ DBG(DBG_CRYPT, DBG_log("unknown mechanism 0x%08x", (int) mechanism));
++ return "unknown-mechanism";
++ }
++#undef CASE
++}
++
++void free_any_symkey(const char *prefix, PK11SymKey **key)
++{
++ if (*key != NULL) {
++ DBG(DBG_CRYPT, DBG_log("%s: free key %p", prefix, *key));
++ PK11_FreeSymKey(*key);
++ } else {
++ DBG(DBG_CRYPT, DBG_log("%s: free key NULL", prefix));
++ }
++ *key = NULL;
++}
++
++void DBG_dump_symkey(const char *prefix, PK11SymKey *key)
++{
++ if (key == NULL) {
++ /*
++ * For instance, when a zero-length key gets extracted
++ * from an existing key.
++ */
++ DBG_log("%s key is NULL", prefix);
++ } else {
++ DBG_log("%s key %p %d mechanism(type) %s",
++ prefix, key, PK11_GetKeyLength(key),
++ ckm_to_string(PK11_GetMechanism(key)));
++ if (DBGP(DBG_PRIVATE)) {
++ chunk_t chunk = chunk_from_symkey(prefix, key);
++ DBG_dump_chunk(prefix, chunk);
++ freeanychunk(chunk);
++ } else {
++ DBG_log("%s contents are private", prefix);
++ }
++ }
++}
++
++/*
++ * XXX: Is there any documentation on this generic operation?
++ */
++static PK11SymKey *merge_symkey_bytes(PK11SymKey *base_key,
++ const void *bytes, size_t sizeof_bytes,
++ CK_MECHANISM_TYPE derive,
++ CK_MECHANISM_TYPE target)
++{
++ passert(sizeof_bytes > 0);
++ CK_KEY_DERIVATION_STRING_DATA string = {
++ .pData = (void *)bytes,
++ .ulLen = sizeof_bytes,
++ };
++ SECItem param = {
++ .data = (unsigned char*)&string,
++ .len = sizeof(string),
++ };
++ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE;
++ int key_size = 0;
++
++ DBG(DBG_CRYPT,
++ DBG_log("derive %s using %s", ckm_to_string(derive),
++ ckm_to_string(target));
++ DBG_dump_symkey("base", base_key);
++ DBG_dump("data", bytes, sizeof_bytes));
++ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target,
++ operation, key_size);
++ DBG(DBG_CRYPT, DBG_dump_symkey("result", result));
++
++ return result;
++}
++
++/*
++ * SYMKEY I/O operations.
++ *
++ * SYMKEY_FROM_CHUNK uses the SCRATCH key as a secure starting point
++ * for creating the key.
++ */
++
++PK11SymKey *symkey_from_bytes(PK11SymKey *scratch, const void *bytes,
++ size_t sizeof_bytes)
++{
++ PK11SymKey *tmp = merge_symkey_bytes(scratch, bytes, sizeof_bytes,
++ CKM_CONCATENATE_DATA_AND_BASE,
++ CKM_EXTRACT_KEY_FROM_KEY);
++ passert(tmp != NULL);
++ PK11SymKey *key = key_from_symkey_bytes(tmp, 0, sizeof_bytes);
++ passert(key != NULL);
++ free_any_symkey(__func__, &tmp);
++ return key;
++}
++
++PK11SymKey *symkey_from_chunk(PK11SymKey *scratch, chunk_t chunk)
++{
++ return symkey_from_bytes(scratch, chunk.ptr, chunk.len);
++}
++
++/*
++ * Concatenate two pieces of keying material creating a
++ * new SYMKEY object.
++ */
++
++PK11SymKey *concat_symkey_symkey(const struct hash_desc *hasher,
++ PK11SymKey *lhs, PK11SymKey *rhs)
++{
++ CK_OBJECT_HANDLE keyhandle = PK11_GetSymKeyHandle(rhs);
++ /* give the parameters explicit names - there are too many */
++ PK11SymKey *base_key = lhs;
++ CK_MECHANISM_TYPE derive = CKM_CONCATENATE_BASE_AND_KEY;
++ SECItem param = {
++ .data = (unsigned char*)&keyhandle,
++ .len = sizeof(keyhandle)
++ };
++ CK_MECHANISM_TYPE target = nss_key_derivation_mech(hasher);
++ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE;
++ int key_size = 0;
++
++ DBG(DBG_CRYPT,
++ DBG_log("concate symkey(base) symkey(key) target %s",
++ ckm_to_string(target));
++ DBG_dump_symkey("base", lhs);
++ DBG_dump_symkey("key", rhs));
++ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target,
++ operation, key_size);
++ DBG(DBG_CRYPT, DBG_dump_symkey("result", result));
++
++ return result;
++}
++
++PK11SymKey *concat_symkey_bytes(const struct hash_desc *hasher,
++ PK11SymKey *lhs, const void *rhs,
++ size_t sizeof_rhs)
++{
++ CK_MECHANISM_TYPE mechanism = nss_key_derivation_mech(hasher);
++ return merge_symkey_bytes(lhs, rhs, sizeof_rhs,
++ CKM_CONCATENATE_BASE_AND_DATA,
++ mechanism);
++}
++
++PK11SymKey *concat_symkey_chunk(const struct hash_desc *hasher,
++ PK11SymKey *lhs, chunk_t rhs)
++{
++ return concat_symkey_bytes(hasher, lhs, rhs.ptr, rhs.len);
++}
++
++PK11SymKey *concat_symkey_byte(const struct hash_desc *hasher,
++ PK11SymKey *lhs, uint8_t rhs)
++{
++ return concat_symkey_bytes(hasher, lhs, &rhs, sizeof(rhs));
++}
++
++/*
++ * Append new keying material to an existing key; replace the existing
++ * key with the result.
++ *
++ * Use this to chain a series of concat operations.
++ */
++
++void append_symkey_symkey(const struct hash_desc *hasher,
++ PK11SymKey **lhs, PK11SymKey *rhs)
++{
++ PK11SymKey *newkey = concat_symkey_symkey(hasher, *lhs, rhs);
++ free_any_symkey(__func__, lhs);
++ *lhs = newkey;
++}
++
++void append_symkey_bytes(const struct hash_desc *hasher,
++ PK11SymKey **lhs, const void *rhs,
++ size_t sizeof_rhs)
++{
++ PK11SymKey *newkey = concat_symkey_bytes(hasher, *lhs,
++ rhs, sizeof_rhs);
++ free_any_symkey(__func__, lhs);
++ *lhs = newkey;
++}
++
++void append_symkey_chunk(const struct hash_desc *hasher,
++ PK11SymKey **lhs, chunk_t rhs)
++{
++ append_symkey_bytes(hasher, lhs, rhs.ptr, rhs.len);
++}
++
++void append_symkey_byte(const struct hash_desc *hasher,
++ PK11SymKey **lhs, uint8_t rhs)
++{
++ append_symkey_bytes(hasher, lhs, &rhs, sizeof(rhs));
++}
++
++/*
++ * Extract raw-bytes from a SYMKEY.
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ */
++
++static PK11SymKey *key_from_key_bits(PK11SymKey *base_key,
++ CK_MECHANISM_TYPE target,
++ CK_FLAGS flags,
++ size_t next_bit, size_t key_size)
++{
++ /* spell out all the parameters */
++ CK_EXTRACT_PARAMS bs = next_bit;
++ SECItem param = {
++ .data = (unsigned char*)&bs,
++ .len = sizeof(bs),
++ };
++ CK_MECHANISM_TYPE derive = CKM_EXTRACT_KEY_FROM_KEY;
++ CK_ATTRIBUTE_TYPE operation = CKA_FLAGS_ONLY;
++
++ DBG(DBG_CRYPT,
++ DBG_log("%s key from base key bits %zd length %zd flags 0x%lx",
++ ckm_to_string(target), next_bit, key_size, flags);
++ DBG_dump_symkey("base key", base_key));
++ PK11SymKey *result = PK11_DeriveWithFlags(base_key, derive, ¶m,
++ target, operation,
++ key_size, flags);
++ DBG(DBG_CRYPT, DBG_dump_symkey("result", result));
++
++ return result;
++}
++
++void *bytes_from_symkey_bits(const char *name,
++ PK11SymKey *source_key, size_t next_bit,
++ void *bytes, size_t sizeof_bytes)
++{
++ DBG(DBG_CRYPT,
++ DBG_log("%s: extracting %zd bytes starting at bit %zd from symkey %p into %p",
++ name, sizeof_bytes, next_bit, source_key, bytes));
++ if (sizeof_bytes == 0) {
++ return NULL;
++ }
++ PK11SymKey *sym_key = key_from_key_bits(source_key,
++ CKM_VENDOR_DEFINED, 0,
++ next_bit, sizeof_bytes);
++ if (sym_key == NULL) {
++ loglog(RC_LOG_SERIOUS, "NSS key-from-key failed while generating %s", name);
++ return NULL;
++ }
++ SECStatus s = PK11_ExtractKeyValue(sym_key);
++ if (s != SECSuccess) {
++ loglog(RC_LOG_SERIOUS, "NSS: PK11_ExtractKeyValue failed while generating %s", name);
++ return NULL;
++ }
++ /* Internal structure address, do not free. */
++ SECItem *data = PK11_GetKeyData(sym_key);
++ if (data == NULL) {
++ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData failed while generating %s", name);
++ return NULL;
++ }
++ DBG(DBG_CRYPT,
++ DBG_log("chunk_from_symkey: %s: extracted len %d bytes at %p",
++ name, data->len, data->data));
++ if (data->len != sizeof_bytes) {
++ loglog(RC_LOG_SERIOUS, "NSS: PK11_GetKeyData returned wrong number of bytes while generating %s", name);
++ return NULL;
++ }
++ /* Only alloc, when all looks good. */
++ if (bytes == NULL) {
++ bytes = alloc_bytes(sizeof_bytes, name);
++ DBG(DBG_CRYPT,
++ DBG_log("%s: allocated %zd bytes at %p",
++ name, sizeof_bytes, bytes));
++ }
++ memcpy(bytes, data->data, sizeof_bytes);
++ DBG(DBG_PRIVATE, DBG_dump(name, bytes, sizeof_bytes));
++ free_any_symkey(__func__, &sym_key);
++
++ return bytes;
++}
++
++void *bytes_from_symkey_bytes(const char *name, PK11SymKey *source_key,
++ size_t next_byte, void *bytes,
++ size_t sizeof_bytes)
++{
++ return bytes_from_symkey_bits(name, source_key,
++ next_byte * BITS_PER_BYTE,
++ bytes, sizeof_bytes);
++}
++
++chunk_t chunk_from_symkey_bits(const char *name, PK11SymKey *source_key,
++ size_t next_bit, size_t sizeof_chunk)
++{
++ void *bytes = bytes_from_symkey_bits(name, source_key, next_bit,
++ NULL, sizeof_chunk);
++ if (bytes == NULL) {
++ return empty_chunk;
++ }
++ chunk_t chunk;
++ setchunk(chunk, bytes, sizeof_chunk);
++ return chunk;
++}
++
++chunk_t chunk_from_symkey_bytes(const char *name, PK11SymKey *source_key,
++ size_t next_byte, size_t sizeof_chunk)
++{
++ return chunk_from_symkey_bits(name, source_key,
++ next_byte * BITS_PER_BYTE, sizeof_chunk);
++}
++
++chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key)
++{
++ return chunk_from_symkey_bits(name, source_key, 0,
++ PK11_GetKeyLength(source_key));
++}
++
++/*
++ * Extract SIZEOF_SYMKEY bytes of keying material as an ENCRYPTER key
++ * (i.e., can be used to encrypt/decrypt data using ENCRYPTER).
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ */
++
++PK11SymKey *encrypt_key_from_symkey_bits(PK11SymKey *source_key,
++ const struct encrypt_desc *encrypter,
++ size_t next_bit, size_t sizeof_symkey)
++{
++ return key_from_key_bits(source_key,
++ nss_encryption_mech(encrypter),
++ CKF_ENCRYPT | CKF_DECRYPT,
++ next_bit, sizeof_symkey);
++}
++
++PK11SymKey *encrypt_key_from_symkey_bytes(PK11SymKey *source_key,
++ const struct encrypt_desc *encrypter,
++ size_t next_byte, size_t sizeof_symkey)
++{
++ return encrypt_key_from_symkey_bits(source_key, encrypter,
++ next_byte * BITS_PER_BYTE,
++ sizeof_symkey);
++}
++
++/*
++ * Extract SIZEOF_KEY bytes of keying material as a KEY. It inherits
++ * the BASE_KEYs type. Good for hash keys.
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ */
++
++PK11SymKey *key_from_symkey_bits(PK11SymKey *base_key,
++ size_t next_bit, size_t key_size)
++{
++ CK_EXTRACT_PARAMS bs = next_bit;
++ SECItem param = {
++ .data = (unsigned char*)&bs,
++ .len = sizeof(bs),
++ };
++ CK_MECHANISM_TYPE derive = CKM_EXTRACT_KEY_FROM_KEY;
++ CK_MECHANISM_TYPE target = CKM_CONCATENATE_BASE_AND_DATA;
++ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE;
++ /* XXX: can this use key_from_key_bits? */
++
++ DBG(DBG_CRYPT,
++ DBG_log("%s key from symkey(base key) bits %zd length %zd",
++ ckm_to_string(target),
++ next_bit, key_size);
++ DBG_dump_symkey("base key", base_key));
++ PK11SymKey *result = PK11_Derive(base_key, derive, ¶m, target,
++ operation, key_size);
++ DBG(DBG_CRYPT, DBG_dump_symkey("result", result));
++
++ return result;
++}
++
++PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key,
++ size_t next_byte, size_t sizeof_key)
++{
++ return key_from_symkey_bits(source_key,
++ next_byte * BITS_PER_BYTE,
++ sizeof_key);
++}
++
++/*
++ * Run HASHER on the key.
++ *
++ * This assumes that NSS works. Based on old code, 3.14 may have had
++ * problems with SHA-2.
++ */
++PK11SymKey *hash_symkey(const struct hash_desc *hasher,
++ PK11SymKey *base_key)
++{
++ CK_MECHANISM_TYPE derive = nss_key_derivation_mech(hasher);
++ SECItem *param = NULL;
++ CK_MECHANISM_TYPE target = CKM_CONCATENATE_BASE_AND_KEY;
++ CK_ATTRIBUTE_TYPE operation = CKA_DERIVE;
++ int key_size = 0;
++
++ DBG(DBG_CRYPT,
++ DBG_log("%s hash symkey(base key)", ckm_to_string(derive));
++ DBG_dump_symkey("base key", base_key));
++ PK11SymKey *result = PK11_Derive(base_key, derive, param, target,
++ operation, key_size);
++ DBG(DBG_CRYPT, DBG_dump_symkey("result", result));
++
++ return result;
++}
++
++/*
++ * XOR a symkey with a chunk.
++ *
++ * XXX: hmac.c had very similar code, only, instead of
++ * target=CKM_CONCATENATE_BASE_AND_DATA it used
++ * target=hasher-to-ckm(hasher).
++ *
++ * hasher-to-ckm maped hasher->common.alg_id to CMK vis: OAKLEY_MD5 ->
++ * CKM_MD5; OAKLEY_SHA1 -> CKM_SHA_1; OAKLEY_SHA2_256 -> CKM_SHA256;
++ * OAKLEY_SHA2_384 -> CKM_SHA384; OAKLEY_SHA2_512 -> CKM_SHA512; only
++ * in the default case it would set target to 0x80000000????
++ */
++PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs)
++{
++ return merge_symkey_bytes(lhs, rhs.ptr, rhs.len,
++ CKM_XOR_BASE_AND_DATA,
++ CKM_CONCATENATE_BASE_AND_DATA);
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/crypt_symkey.h libreswan-3.12/programs/pluto/crypt_symkey.h
+--- libreswan-3.12-orig/programs/pluto/crypt_symkey.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/crypt_symkey.h 2015-05-06 11:45:32.920301417 -0400
+@@ -0,0 +1,131 @@
++/*
++ * SYMKEY manipulation functions, for libreswan
++ *
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#ifndef crypt_symkey_h
++#define crypt_symkey_h
++
++#include
++#include
++#include "lswalloc.h"
++
++struct hash_desc;
++struct encrypt_desc;
++
++void DBG_dump_symkey(const char *prefix, PK11SymKey *key);
++
++/*
++ * Free any symkey and then stomp on the pointer.
++ */
++void free_any_symkey(const char *prefix, PK11SymKey **key);
++
++/*
++ * Use SCRATCH key as a secure starting point for creating the key
++ * from the raw bytes, or chunk.
++ */
++
++PK11SymKey *symkey_from_bytes(PK11SymKey *scratch, const void *bytes,
++ size_t sizeof_bytes);
++
++PK11SymKey *symkey_from_chunk(PK11SymKey *scratch, chunk_t chunk);
++
++/*
++ * Concatenate two pieces of keying material creating a
++ * new SYMKEY object.
++ */
++PK11SymKey *concat_symkey_symkey(const struct hash_desc *hasher,
++ PK11SymKey *lhs, PK11SymKey *rhs);
++PK11SymKey *concat_symkey_bytes(const struct hash_desc *hasher,
++ PK11SymKey *lhs, const void *rhs,
++ size_t sizeof_rhs);
++PK11SymKey *concat_symkey_chunk(const struct hash_desc *hasher,
++ PK11SymKey *lhs, chunk_t rhs);
++PK11SymKey *concat_symkey_byte(const struct hash_desc *hasher,
++ PK11SymKey *lhs, uint8_t rhs);
++
++/*
++ * Append new keying material to an existing key; replace the existing
++ * key with the result.
++ *
++ * Use this to chain a series of concat operations.
++ */
++void append_symkey_symkey(const struct hash_desc *hasher,
++ PK11SymKey **lhs, PK11SymKey *rhs);
++void append_symkey_bytes(const struct hash_desc *hasher,
++ PK11SymKey **lhs, const void *rhs,
++ size_t sizeof_rhs);
++void append_symkey_chunk(const struct hash_desc *hasher,
++ PK11SymKey **lhs, chunk_t rhs);
++void append_symkey_byte(const struct hash_desc *hasher,
++ PK11SymKey **lhs, uint8_t rhs);
++
++/*
++ * Extract raw-bytes from a SYMKEY.
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ *
++ * bytes_from_ has a querk where, if BYTES is NULL, the buffer is
++ * allocated.
++ */
++void *bytes_from_symkey_bits(const char *name, PK11SymKey *source_key,
++ size_t next_bit, void *bytes,
++ size_t sizeof_bytes);
++void *bytes_from_symkey_bytes(const char *name, PK11SymKey *source_key,
++ size_t next_byte, void *bytes,
++ size_t sizeof_bytes);
++chunk_t chunk_from_symkey_bits(const char *name, PK11SymKey *source_key,
++ size_t next_bit, size_t sizeof_chunk);
++chunk_t chunk_from_symkey_bytes(const char *name, PK11SymKey *source_key,
++ size_t next_byte, size_t sizeof_chunk);
++chunk_t chunk_from_symkey(const char *name, PK11SymKey *source_key);
++
++/*
++ * Extract SIZEOF_SYMKEY bytes of keying material as an ENCRYPTER key
++ * (i.e., can be used to encrypt/decrypt data using ENCRYPTER).
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ */
++PK11SymKey *encrypt_key_from_symkey_bytes(PK11SymKey *source_key,
++ const struct encrypt_desc *encrypter,
++ size_t next_byte, size_t sizeof_symkey);
++PK11SymKey *encrypt_key_from_symkey_bits(PK11SymKey *source_key,
++ const struct encrypt_desc *encrypter,
++ size_t next_bit, size_t sizeof_symkey);
++
++/*
++ * Extract SIZEOF_KEY bytes of keying material as a KEY. It inherits
++ * the BASE_KEYs type. Good for hash keys.
++ *
++ * Offset into the SYMKEY is in either BITS or BYTES.
++ */
++PK11SymKey *key_from_symkey_bits(PK11SymKey *base_key,
++ size_t next_bit, size_t key_size);
++PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key,
++ size_t next_byte, size_t sizeof_key);
++
++/*
++ * Hash a symkey using HASHER.
++ *
++ * This gets used by the PRF when the BASE_KEY is too long.
++ */
++PK11SymKey *hash_symkey(const struct hash_desc *hasher,
++ PK11SymKey *base_key);
++
++/*
++ * XOR a symkey with a chunk.
++ */
++PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs);
++
++#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c libreswan-3.12/programs/pluto/ctr_test_vectors.c
+--- libreswan-3.12-orig/programs/pluto/ctr_test_vectors.c 2015-05-06 11:44:21.564466307 -0400
++++ libreswan-3.12/programs/pluto/ctr_test_vectors.c 2015-05-06 11:45:32.921301428 -0400
+@@ -12,6 +12,7 @@
+
+ #include "nss.h"
+ #include "pk11pub.h"
++#include "crypt_symkey.h"
+
+ struct ctr_test_vector {
+ // CK_MECHANISM_TYPE cipher_mechanism;
+@@ -203,7 +204,8 @@
+ ok = 0;
+ }
+
+- PK11_FreeSymKey(sym_key);
++ /* Clean up. */
++ free_any_symkey("sym_key", &sym_key);
+ DBG(DBG_CRYPT, DBG_log("test_ctr_vector: %s %s",
+ test->description, ok ? "passed" : "failed"));
+ return ok;
+diff -Naur libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c libreswan-3.12/programs/pluto/gcm_test_vectors.c
+--- libreswan-3.12-orig/programs/pluto/gcm_test_vectors.c 2015-05-06 11:44:21.584466542 -0400
++++ libreswan-3.12/programs/pluto/gcm_test_vectors.c 2015-05-06 11:45:32.921301428 -0400
+@@ -24,6 +24,7 @@
+
+ #include "nss.h"
+ #include "pk11pub.h"
++#include "crypt_symkey.h"
+
+ struct gcm_test_vector {
+ const char *key;
+@@ -165,14 +166,16 @@
+ }
+
+ freeanychunk(salted_iv);
+- freeanychunk(wire_iv);
+ freeanychunk(salt);
+- freeanychunk(tag);
++ freeanychunk(wire_iv);
++ freeanychunk(aad);
+ freeanychunk(plaintext);
+ freeanychunk(ciphertext);
++ freeanychunk(tag);
+ freeanychunk(text_and_tag);
+
+- PK11_FreeSymKey(sym_key);
++ /* Clean up. */
++ free_any_symkey("sym_key", &sym_key);
+ DBG(DBG_CRYPT, DBG_log("test_gcm_vector: %s", ok ? "passed" : "failed"));
+ return ok;
+ }
+diff -Naur libreswan-3.12-orig/programs/pluto/hmac.c libreswan-3.12/programs/pluto/hmac.c
+--- libreswan-3.12-orig/programs/pluto/hmac.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/hmac.c 2015-05-06 11:45:32.921301428 -0400
+@@ -5,8 +5,9 @@
+ * Copyright (C) 2009 Paul Wouters
+ * Copyright (C) 2010-2012 Avesh Agarwal
+ * Copyright (C) 2012 Paul Wouters
+- * Copyright (C) 2012-2013 Paul Wouters
++ * Copyright (C) 2012-2015 Paul Wouters
+ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015, Andrew Cagney
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+@@ -40,272 +41,42 @@
+ #include
+ #include "lswconf.h"
+ #include "lswlog.h"
++#include "crypt_symkey.h"
++#include "crypt_prf.h"
+
+ /* HMAC package
+ * rfc2104.txt specifies how HMAC works.
+ */
+
+-static CK_MECHANISM_TYPE nss_hash_mech(const struct hash_desc *hasher);
+-static SECOidTag nss_hash_oid(const struct hash_desc *hasher);
+-
+ void hmac_init(struct hmac_ctx *ctx,
+ const struct hash_desc *h,
+ /*const*/ PK11SymKey *symkey) /* NSS doesn't like const! */
+ {
+- SECStatus status;
+- PK11SymKey
+- *tkey1,
+- *tkey2;
+- unsigned int klen = PK11_GetKeyLength(symkey);
+- chunk_t hmac_opad, hmac_ipad, hmac_pad;
+-
+- ctx->h = h;
++ /*
++ * Note: The SYMKEY passed to crypt_prf_init is used to
++ * generate secure keying material from nothing.
++ * crypt_prf_init_symkey() establishes the actual key.
++ */
++ ctx->prf = crypt_prf_init("hmac", h, symkey);
+ ctx->hmac_digest_len = h->hash_digest_len;
+-
+- /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */
+-
+- hmac_opad = hmac_pads(HMAC_OPAD, h->hash_block_size);
+- hmac_ipad = hmac_pads(HMAC_IPAD, h->hash_block_size);
+- hmac_pad = hmac_pads(0x00, h->hash_block_size - klen);
+-
+- if (klen > h->hash_block_size) {
+- tkey1 = PK11_Derive_lsw(symkey, nss_key_derivation_mech(h),
+- NULL,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE,
+- 0);
+- } else {
+- tkey1 = symkey;
+- }
+-
+- tkey2 = pk11_derive_wrapper_lsw(tkey1, CKM_CONCATENATE_BASE_AND_DATA,
+- hmac_pad,
+- CKM_XOR_BASE_AND_DATA, CKA_DERIVE,
+- h->hash_block_size);
+- passert(tkey2 != NULL);
+-
+- ctx->ikey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA,
+- hmac_ipad, nss_hash_mech(h),
+- CKA_DIGEST, 0);
+- passert(ctx->ikey != NULL);
+-
+- ctx->okey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA,
+- hmac_opad, nss_hash_mech(h),
+- CKA_DIGEST, 0);
+- passert(ctx->okey != NULL);
+-
+- if (tkey1 != symkey)
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey2);
+-
+- freeanychunk(hmac_opad);
+- freeanychunk(hmac_ipad);
+- freeanychunk(hmac_pad);
+- ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h));
+- passert(ctx->ctx_nss != NULL);
+-
+- status = PK11_DigestBegin(ctx->ctx_nss);
+- passert(status == SECSuccess);
+-
+- status = PK11_DigestKey(ctx->ctx_nss, ctx->ikey);
+- passert(status == SECSuccess);
++ crypt_prf_init_symkey("symkey", ctx->prf, symkey);
++ crypt_prf_update(ctx->prf);
+ }
+
+ void hmac_update(struct hmac_ctx *ctx,
+ const u_char *data, size_t data_len)
+ {
+- DBG(DBG_CRYPT, DBG_dump("hmac_update data value: ", data, data_len));
+- if (data_len > 0) {
+- SECStatus status;
+-
+- DBG(DBG_CRYPT, DBG_log("hmac_update: inside if"));
+- status = PK11_DigestOp(ctx->ctx_nss, data, data_len);
+- DBG(DBG_CRYPT, DBG_log("hmac_update: after digest"));
+- passert(status == SECSuccess);
+- DBG(DBG_CRYPT, DBG_log("hmac_update: after assert"));
+- }
++ crypt_prf_update_bytes("data", ctx->prf, data, data_len);
+ }
+
+ void hmac_final(u_char *output, struct hmac_ctx *ctx)
+ {
+- unsigned int outlen;
+- SECStatus status;
+-
+- status = PK11_DigestFinal(ctx->ctx_nss, output, &outlen,
+- ctx->hmac_digest_len);
+- passert(status == SECSuccess);
+- passert(outlen == ctx->hmac_digest_len);
+- PK11_DestroyContext(ctx->ctx_nss, PR_TRUE);
+- ctx->ctx_nss = NULL;
+-
+- ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(ctx->h));
+- passert(ctx->ctx_nss != NULL);
+-
+- status = PK11_DigestBegin(ctx->ctx_nss);
+- passert(status == SECSuccess);
+-
+- status = PK11_DigestKey(ctx->ctx_nss, ctx->okey);
+- passert(status == SECSuccess);
+-
+- status = PK11_DigestOp(ctx->ctx_nss, output, outlen);
+- passert(status == SECSuccess);
+-
+- status = PK11_DigestFinal(ctx->ctx_nss, output, &outlen,
+- ctx->hmac_digest_len);
+- passert(status == SECSuccess);
+- passert(outlen == ctx->hmac_digest_len);
+- PK11_DestroyContext(ctx->ctx_nss, PR_TRUE);
+-
+- if (ctx->ikey != NULL)
+- PK11_FreeSymKey(ctx->ikey);
+- if (ctx->okey != NULL)
+- PK11_FreeSymKey(ctx->okey);
+- /* DBG(DBG_CRYPT, DBG_log("NSS: hmac final end")); */
+-}
+-
+-static SECOidTag nss_hash_oid(const struct hash_desc *hasher)
+-{
+- SECOidTag mechanism;
+-
+- switch (hasher->common.algo_id) {
+- case OAKLEY_MD5:
+- mechanism = SEC_OID_MD5;
+- break;
+- case OAKLEY_SHA1:
+- mechanism = SEC_OID_SHA1;
+- break;
+- case OAKLEY_SHA2_256:
+- mechanism = SEC_OID_SHA256;
+- break;
+- case OAKLEY_SHA2_384:
+- mechanism = SEC_OID_SHA384;
+- break;
+- case OAKLEY_SHA2_512:
+- mechanism = SEC_OID_SHA512;
+- break;
+- default:
+- libreswan_log("NSS: key derivation mechanism (hasher->common.algo_id=%d not supported",
+- hasher->common.algo_id);
+- mechanism = 0; /* ??? what should we do to recover? */
+- break;
+- }
+- return mechanism;
+-}
+-
+-static CK_MECHANISM_TYPE nss_hash_mech(const struct hash_desc *hasher)
+-{
+- CK_MECHANISM_TYPE mechanism;
+-
+- switch (hasher->common.algo_id) {
+- case OAKLEY_MD5:
+- mechanism = CKM_MD5;
+- break;
+- case OAKLEY_SHA1:
+- mechanism = CKM_SHA_1;
+- break;
+- case OAKLEY_SHA2_256:
+- mechanism = CKM_SHA256;
+- break;
+- case OAKLEY_SHA2_384:
+- mechanism = CKM_SHA384;
+- break;
+- case OAKLEY_SHA2_512:
+- mechanism = CKM_SHA512;
+- break;
+- default:
+- /* ??? surely this requires more than a DBG entry! */
+- DBG(DBG_CRYPT,
+- DBG_log("NSS: key derivation mechanism not supported"));
+- mechanism = 0x80000000; /* ??? what should we do to recover? */
+- break;
+- }
+- return mechanism;
+-}
+-
+-PK11SymKey *pk11_derive_wrapper_lsw(PK11SymKey *base,
+- CK_MECHANISM_TYPE mechanism,
+- chunk_t data, CK_MECHANISM_TYPE target,
+- CK_ATTRIBUTE_TYPE operation, int keySize)
+-{
+- CK_KEY_DERIVATION_STRING_DATA string;
+- SECItem param;
+-
+- string.pData = data.ptr;
+- string.ulLen = data.len;
+- param.data = (unsigned char*)&string;
+- param.len = sizeof(string);
+-
+- return PK11_Derive(base, mechanism, ¶m, target, operation,
+- keySize);
++ crypt_prf_final_bytes(ctx->prf, output, ctx->hmac_digest_len);
+ }
+
+-/* MUST BE THREAD-SAFE */
+-PK11SymKey *PK11_Derive_lsw(PK11SymKey *base, CK_MECHANISM_TYPE mechanism,
+- SECItem *param, CK_MECHANISM_TYPE target,
+- CK_ATTRIBUTE_TYPE operation, int keysize)
+-{
+- if (param == NULL && keysize == 0) {
+- SECOidTag oid;
+- PK11Context *ctx;
+- unsigned char dkey[HMAC_BUFSIZE * 2];
+- SECItem dkey_param;
+- SECStatus status;
+- unsigned int len;
+- CK_EXTRACT_PARAMS bs;
+- chunk_t dkey_chunk;
+-
+- switch (mechanism) {
+- case CKM_SHA256_KEY_DERIVATION:
+- oid = SEC_OID_SHA256;
+- break;
+- case CKM_SHA384_KEY_DERIVATION:
+- oid = SEC_OID_SHA384;
+- break;
+- case CKM_SHA512_KEY_DERIVATION:
+- oid = SEC_OID_SHA512;
+- break;
+- default:
+- return PK11_Derive(base, mechanism, param, target,
+- operation, keysize);
+- }
+-
+- ctx = PK11_CreateDigestContext(oid);
+- passert(ctx != NULL);
+- status = PK11_DigestBegin(ctx);
+- passert(status == SECSuccess);
+- status = PK11_DigestKey(ctx, base);
+- passert(status == SECSuccess);
+- status = PK11_DigestFinal(ctx, dkey, &len, sizeof dkey);
+- passert(status == SECSuccess);
+- PK11_DestroyContext(ctx, PR_TRUE);
+-
+- dkey_chunk.ptr = dkey;
+- dkey_chunk.len = len;
+-
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(base,
+- CKM_CONCATENATE_DATA_AND_BASE, dkey_chunk, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey1 != NULL);
+-
+- bs = 0;
+- dkey_param.data = (unsigned char*)&bs;
+- dkey_param.len = sizeof(bs);
+- PK11SymKey *tkey2 = PK11_Derive(tkey1,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- &dkey_param, target, operation,
+- len);
+- passert(tkey2 != NULL);
+-
+- if (tkey1 != NULL)
+- PK11_FreeSymKey(tkey1);
+-
+- return tkey2;
+-
+- } else {
+- return PK11_Derive(base, mechanism, param, target, operation,
+- keysize);
+- }
+-}
++/*
++ * XXX: This should be moved to crypt_symkey.c and made private.
++ */
+
+ CK_MECHANISM_TYPE nss_key_derivation_mech(const struct hash_desc *hasher)
+ {
+@@ -335,6 +106,11 @@
+ return mechanism;
+ }
+
++/*
++ * XXX: This has nothing to do with HMAC; it should be made part of
++ * the chunk_t library code.
++ */
++
+ chunk_t hmac_pads(u_char val, unsigned int len)
+ {
+ chunk_t ret;
+@@ -346,31 +122,3 @@
+
+ return ret;
+ }
+-
+-void nss_symkey_log(PK11SymKey *key, const char *msg)
+-{
+- if (key == NULL) {
+- /* ??? should we print this even if !DBG_CRYPT? */
+- DBG_log("NULL key %s", msg);
+- } else {
+- DBG(DBG_CRYPT, {
+- DBG_log("computed key %s with length =%d", msg,
+- PK11_GetKeyLength(key));
+-
+- if (!PK11_IsFIPS()) {
+- SECStatus status = PK11_ExtractKeyValue(key);
+-
+- if (status == SECSuccess) {
+- SECItem *keydata = PK11_GetKeyData(key);
+-
+- DBG_dump("value: ", keydata->data,
+- keydata->len);
+-
+- SECITEM_FreeItem(keydata, PR_TRUE); /* ??? this was commented out. Why? */
+- } else {
+- DBG_log("unobtainable key %s", msg);
+- }
+- }
+- });
+- }
+-}
+diff -Naur libreswan-3.12-orig/programs/pluto/hostpair.c libreswan-3.12/programs/pluto/hostpair.c
+--- libreswan-3.12-orig/programs/pluto/hostpair.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/hostpair.c 2015-05-06 11:45:32.922301440 -0400
+@@ -286,7 +286,7 @@
+ */
+ passert(p == *pp);
+
+- terminate_connection(p->name);
++ // terminate_connection(p->name);
+ p->interface = NULL;
+
+ *pp = p->hp_next; /* advance *pp */
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_aes.c libreswan-3.12/programs/pluto/ike_alg_aes.c
+--- libreswan-3.12-orig/programs/pluto/ike_alg_aes.c 2015-05-06 11:44:21.609466836 -0400
++++ libreswan-3.12/programs/pluto/ike_alg_aes.c 2015-05-06 11:45:47.617471739 -0400
+@@ -410,7 +410,11 @@
+
+ void ike_alg_aes_init(void)
+ {
+- bool fips = libreswan_fipsmode();
++#ifdef FIPS_CHECK
++ bool fips = libreswan_fipsproduct() || libreswan_fipskernel();
++#else
++ bool fips = FALSE;
++#endif
+ if (!fips && !test_aes_cbc(&algo_aes_cbc)) {
+ loglog(RC_LOG_SERIOUS, "CKM_AES_CBC: test failure");
+ exit_pluto(6);
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.c libreswan-3.12/programs/pluto/ike_alg.c
+--- libreswan-3.12-orig/programs/pluto/ike_alg.c 2015-05-06 11:44:21.585466554 -0400
++++ libreswan-3.12/programs/pluto/ike_alg.c 2015-05-06 11:45:32.922301440 -0400
+@@ -322,3 +322,53 @@
+ ret = lookup_group(c->alg_info_esp->esp_pfsgroup);
+ return ret;
+ }
++
++CK_MECHANISM_TYPE nss_encryption_mech(const struct encrypt_desc *encrypter)
++{
++ /* the best wey have for "undefined" */
++ CK_MECHANISM_TYPE mechanism = CKM_VENDOR_DEFINED;
++
++ switch (encrypter->common.algo_id) {
++ case OAKLEY_3DES_CBC:
++ mechanism = CKM_DES3_CBC;
++ break;
++#ifdef NOT_YET
++ case OAKLEY_CAST_CBC:
++ mechanism = CKM_CAST5_CBC:
++ break;
++#endif
++ case OAKLEY_AES_CBC:
++ mechanism = CKM_AES_CBC;
++ break;
++ case OAKLEY_CAMELLIA_CBC:
++ mechanism = CKM_CAMELLIA_CBC;
++ break;
++ case OAKLEY_AES_CTR:
++ mechanism = CKM_AES_CTR;
++ break;
++#ifdef NOT_YET
++ case OAKLEY_AES_CCM_8:
++ case OAKLEY_AES_CCM_12:
++ case OAKLEY_AES_CCM_16:
++ mechanism = CKM_AES_CCM;
++ break;
++#endif
++ case OAKLEY_AES_GCM_8:
++ case OAKLEY_AES_GCM_12:
++ case OAKLEY_AES_GCM_16:
++ mechanism = CKM_AES_GCM;
++ break;
++#ifdef NOT_YET
++ case OAKLEY_TWOFISH_CBC:
++ mechanism = CKM_TWOFISH_CBC;
++ break;
++#endif
++ default:
++ loglog(RC_LOG_SERIOUS,
++ "NSS: Unsupported encryption mechanism for %s",
++ strip_prefix(enum_name(&oakley_enc_names,
++ encrypter->common.algo_id), "OAKLEY_"));
++ break;
++ }
++ return mechanism;
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c libreswan-3.12/programs/pluto/ike_alg_camellia.c
+--- libreswan-3.12-orig/programs/pluto/ike_alg_camellia.c 2015-05-06 11:44:21.610466848 -0400
++++ libreswan-3.12/programs/pluto/ike_alg_camellia.c 2015-05-06 11:45:47.617471739 -0400
+@@ -95,7 +95,7 @@
+ void ike_alg_camellia_init(void)
+ {
+ #ifdef FIPS_CHECK
+- bool fips = libreswan_fipsmode();
++ bool fips = libreswan_fipsproduct() || libreswan_fipskernel();
+ #else
+ bool fips = FALSE;
+ #endif
+diff -Naur libreswan-3.12-orig/programs/pluto/ike_alg.h libreswan-3.12/programs/pluto/ike_alg.h
+--- libreswan-3.12-orig/programs/pluto/ike_alg.h 2015-05-06 11:44:21.585466554 -0400
++++ libreswan-3.12/programs/pluto/ike_alg.h 2015-05-06 11:45:32.922301440 -0400
+@@ -186,5 +186,6 @@
+ extern void ike_alg_sha2_init(void);
+ #endif
+
++CK_MECHANISM_TYPE nss_encryption_mech(const struct encrypt_desc *encrypter);
+
+ #endif /* _IKE_ALG_H */
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_prf.c libreswan-3.12/programs/pluto/ikev1_prf.c
+--- libreswan-3.12-orig/programs/pluto/ikev1_prf.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev1_prf.c 2015-05-06 11:45:32.923301452 -0400
+@@ -0,0 +1,348 @@
++/*
++ * Calculate IKEv1 prf and keying material, for libreswan
++ *
++ * Copyright (C) 2007 Michael C. Richardson
++ * Copyright (C) 2010 Paul Wouters
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#include
++#include
++
++#include "libreswan.h"
++#include "lswlog.h"
++#include "constants.h"
++#include "defs.h"
++#include "sysqueue.h"
++#include "crypto.h"
++#include "crypt_dh.h"
++#include "crypt_prf.h"
++#include "ikev1_prf.h"
++#include "ike_alg.h"
++#include "packet.h"
++#include "pluto_crypt.h"
++#include "crypt_symkey.h"
++
++/*
++ * Compute: SKEYID = prf(Ni_b | Nr_b, g^xy)
++ *
++ * MUST BE THREAD-SAFE
++ */
++PK11SymKey *ikev1_signature_skeyid(const struct hash_desc *hasher,
++ const chunk_t Ni,
++ const chunk_t Nr,
++ /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */)
++{
++ struct crypt_prf *prf = crypt_prf_init("SKEYID sig", hasher, dh_secret);
++ /* key = Ni|Nr */
++ crypt_prf_init_chunk("Ni", prf, Ni);
++ crypt_prf_init_chunk("Nr", prf, Nr);
++ /* seed = g^xy */
++ crypt_prf_update(prf);
++ crypt_prf_update_symkey("g^xy", prf, dh_secret);
++ /* generate */
++ return crypt_prf_final(prf);
++}
++
++/*
++ * Compute: SKEYID = prf(pre-shared-key, Ni_b | Nr_b)
++ */
++PK11SymKey *ikev1_pre_shared_key_skeyid(const struct hash_desc *hasher,
++ chunk_t pre_shared_key,
++ chunk_t Ni, chunk_t Nr,
++ PK11SymKey *scratch)
++{
++ struct crypt_prf *prf = crypt_prf_init("SKEYID psk", hasher, scratch);
++ /* key = pre-shared-key */
++ crypt_prf_init_chunk("psk", prf, pre_shared_key);
++ /* seed = Ni_b | Nr_b */
++ crypt_prf_update(prf);
++ crypt_prf_update_chunk("Ni", prf, Ni);
++ crypt_prf_update_chunk("Nr", prf, Nr);
++ /* generate */
++ return crypt_prf_final(prf);
++}
++
++/*
++ * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0)
++ */
++PK11SymKey *ikev1_skeyid_d(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r)
++{
++ struct crypt_prf *prf = crypt_prf_init("SKEYID_d", hasher, dh_secret);
++ /* key = SKEYID */
++ crypt_prf_init_symkey("SKEYID", prf, skeyid);
++ /* seed = g^xy | CKY-I | CKY-R | 0 */
++ crypt_prf_update(prf);
++ crypt_prf_update_symkey("g^xy", prf, dh_secret);
++ crypt_prf_update_chunk("CKI_i", prf, cky_i);
++ crypt_prf_update_chunk("CKI_r", prf, cky_r);
++ crypt_prf_update_byte("0", prf, 0);
++ /* generate */
++ return crypt_prf_final(prf);
++}
++
++/*
++ * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1)
++ */
++PK11SymKey *ikev1_skeyid_a(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *skeyid_d, PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r)
++{
++ struct crypt_prf *prf = crypt_prf_init("SKEYID_a", hasher, dh_secret);
++ /* key = SKEYID */
++ crypt_prf_init_symkey("SKEYID", prf, skeyid);
++ /* seed = SKEYID_d | g^xy | CKY-I | CKY-R | 1 */
++ crypt_prf_update(prf);
++ crypt_prf_update_symkey("SKEYID_d", prf, skeyid_d);
++ crypt_prf_update_symkey("g^xy", prf, dh_secret);
++ crypt_prf_update_chunk("CKI_i", prf, cky_i);
++ crypt_prf_update_chunk("CKI_r", prf, cky_r);
++ crypt_prf_update_byte("1", prf, 1);
++ /* generate */
++ return crypt_prf_final(prf);
++}
++
++/*
++ * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2)
++ */
++PK11SymKey *ikev1_skeyid_e(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *skeyid_a, PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r)
++{
++ struct crypt_prf *prf = crypt_prf_init("SKEYID_e", hasher, dh_secret);
++ /* key = SKEYID */
++ crypt_prf_init_symkey("SKEYID", prf, skeyid);
++ /* seed = SKEYID_a | g^xy | CKY-I | CKY-R | 2 */
++ crypt_prf_update(prf);
++ crypt_prf_update_symkey("SKEYID_a", prf, skeyid_a);
++ crypt_prf_update_symkey("g^xy", prf, dh_secret);
++ crypt_prf_update_chunk("CKI_i", prf, cky_i);
++ crypt_prf_update_chunk("CKI_r", prf, cky_r);
++ crypt_prf_update_byte("2", prf, 2);
++ /* generate */
++ return crypt_prf_final(prf);
++}
++
++static PK11SymKey *appendix_b_keymat_e(const struct hash_desc *hasher,
++ const struct encrypt_desc *encrypter,
++ PK11SymKey *skeyid_e,
++ unsigned required_keymat)
++{
++ if (PK11_GetKeyLength(skeyid_e) >= required_keymat) {
++ return encrypt_key_from_symkey_bytes(skeyid_e, encrypter, 0,
++ required_keymat);
++ }
++ /* K1 = prf(skeyid_e, 0) */
++ PK11SymKey *keymat;
++ {
++ struct crypt_prf *prf = crypt_prf_init("appendix_b",
++ hasher, skeyid_e);
++ crypt_prf_init_symkey("SKEYID_e", prf, skeyid_e);
++ crypt_prf_update(prf);
++ crypt_prf_update_byte("0", prf, 0);
++ keymat = crypt_prf_final(prf);
++ }
++
++ /* make a copy to keep things easy */
++ PK11SymKey *old_k = key_from_symkey_bytes(keymat, 0, PK11_GetKeyLength(keymat));
++ while (PK11_GetKeyLength(keymat) < required_keymat) {
++ /* Kn = prf(skeyid_e, Kn-1) */
++ struct crypt_prf *prf = crypt_prf_init("SKEYID_e", hasher, skeyid_e);
++ crypt_prf_init_symkey("SKEYID_e", prf, skeyid_e);
++ crypt_prf_update(prf);
++ crypt_prf_update_symkey("old_k", prf, old_k);
++ PK11SymKey *new_k = crypt_prf_final(prf);
++ append_symkey_symkey(hasher, &keymat, new_k);
++ free_any_symkey("old_k#N", &old_k);
++ old_k = new_k;
++ }
++ free_any_symkey("old_k#final", &old_k);
++ PK11SymKey *cryptkey = encrypt_key_from_symkey_bytes(keymat, encrypter, 0,
++ required_keymat);
++ free_any_symkey("keymat", &keymat);
++ return cryptkey;
++}
++
++/* Generate the SKEYID_* and new IV
++ * See draft-ietf-ipsec-ike-01.txt 4.1
++ */
++/* MUST BE THREAD-SAFE */
++static void calc_skeyids_iv(struct pcr_skeyid_q *skq,
++ /*const*/ PK11SymKey *shared, /* NSS doesn't do const */
++ const size_t keysize, /* = st->st_oakley.enckeylen/BITS_PER_BYTE; */
++ PK11SymKey **skeyid_out, /* output */
++ PK11SymKey **skeyid_d_out, /* output */
++ PK11SymKey **skeyid_a_out, /* output */
++ PK11SymKey **skeyid_e_out, /* output */
++ chunk_t *new_iv, /* output */
++ PK11SymKey **enc_key_out /* output */
++ )
++{
++ oakley_auth_t auth = skq->auth;
++ oakley_hash_t hash = skq->prf_hash;
++ const struct hash_desc *hasher = crypto_get_hasher(hash);
++ chunk_t ni;
++ chunk_t nr;
++ chunk_t gi;
++ chunk_t gr;
++ chunk_t icookie;
++ chunk_t rcookie;
++ const struct encrypt_desc *encrypter = skq->encrypter;
++
++ /* this doesn't allocate any memory */
++ setchunk_from_wire(gi, skq, &skq->gi);
++ setchunk_from_wire(gr, skq, &skq->gr);
++ setchunk_from_wire(ni, skq, &skq->ni);
++ setchunk_from_wire(nr, skq, &skq->nr);
++ setchunk_from_wire(icookie, skq, &skq->icookie);
++ setchunk_from_wire(rcookie, skq, &skq->rcookie);
++
++ /* Generate the SKEYID */
++ PK11SymKey *skeyid;
++ switch (auth) {
++ case OAKLEY_PRESHARED_KEY:
++ {
++ chunk_t pss;
++
++ setchunk_from_wire(pss, skq, &skq->pss);
++ skeyid = ikev1_pre_shared_key_skeyid(hasher, pss,
++ ni, nr, shared);
++ }
++ break;
++
++ case OAKLEY_RSA_SIG:
++ skeyid = ikev1_signature_skeyid(hasher, ni, nr, shared);
++ break;
++
++ /* Not implemented */
++ case OAKLEY_DSS_SIG:
++ case OAKLEY_RSA_ENC:
++ case OAKLEY_RSA_REVISED_MODE:
++ case OAKLEY_ECDSA_P256:
++ case OAKLEY_ECDSA_P384:
++ case OAKLEY_ECDSA_P521:
++ default:
++ bad_case(auth);
++ }
++
++ /* generate SKEYID_* from SKEYID */
++ PK11SymKey *skeyid_d = ikev1_skeyid_d(hasher, skeyid, shared,
++ icookie, rcookie);
++ PK11SymKey *skeyid_a = ikev1_skeyid_a(hasher, skeyid, skeyid_d,
++ shared, icookie, rcookie);
++ PK11SymKey *skeyid_e = ikev1_skeyid_e(hasher, skeyid, skeyid_a,
++ shared, icookie, rcookie);
++
++ PK11SymKey *enc_key = appendix_b_keymat_e(hasher, encrypter,
++ skeyid_e, keysize);
++
++ *skeyid_out = skeyid;
++ *skeyid_d_out = skeyid_d;
++ *skeyid_a_out = skeyid_a;
++ *skeyid_e_out = skeyid_e;
++ *enc_key_out = enc_key;
++
++ DBG(DBG_CRYPT, DBG_log("NSS: pointers skeyid_d %p, skeyid_a %p, skeyid_e %p, enc_key %p",
++ skeyid_d, skeyid_a, skeyid_e, enc_key));
++
++ /* generate IV */
++ {
++ union hash_ctx hash_ctx;
++
++ new_iv->len = hasher->hash_digest_len;
++ new_iv->ptr = alloc_bytes(new_iv->len, "calculated new iv");
++
++ DBG(DBG_CRYPT, {
++ DBG_dump_chunk("DH_i:", gi);
++ DBG_dump_chunk("DH_r:", gr);
++ });
++ hasher->hash_init(&hash_ctx);
++ hasher->hash_update(&hash_ctx, gi.ptr, gi.len);
++ hasher->hash_update(&hash_ctx, gr.ptr, gr.len);
++ hasher->hash_final(new_iv->ptr, &hash_ctx);
++ DBG(DBG_CRYPT, DBG_log("end of IV generation"));
++ }
++}
++
++/* MUST BE THREAD-SAFE */
++void calc_dh_iv(struct pluto_crypto_req *r)
++{
++ struct pcr_skeyid_r *skr = &r->pcr_d.dhr;
++ struct pcr_skeyid_q dhq;
++ const struct oakley_group_desc *group;
++ PK11SymKey *shared;
++ chunk_t g;
++ SECKEYPrivateKey *ltsecret;
++ PK11SymKey
++ *skeyid,
++ *skeyid_d,
++ *skeyid_a,
++ *skeyid_e,
++ *enc_key;
++ chunk_t new_iv;
++ SECKEYPublicKey *pubk;
++
++ /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
++ memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));
++
++ /* clear out the reply */
++ zero(skr);
++ INIT_WIRE_ARENA(*skr);
++
++ group = lookup_group(dhq.oakley_group);
++ passert(group != NULL);
++
++ ltsecret = dhq.secret;
++ pubk = dhq.pubk;
++
++ /* now calculate the (g^x)(g^y) ---
++ * need gi on responder, gr on initiator
++ */
++
++ setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr);
++
++ DBG(DBG_CRYPT,
++ DBG_dump_chunk("peer's g: ", g));
++
++ shared = calc_dh_shared(g, ltsecret, group, pubk);
++
++ zero(&new_iv);
++
++ /* okay, so now calculate IV */
++ calc_skeyids_iv(&dhq,
++ shared,
++ dhq.key_size,
++ &skeyid,
++ &skeyid_d,
++ &skeyid_a,
++ &skeyid_e,
++ &new_iv,
++ &enc_key);
++
++ skr->shared = shared;
++ skr->skeyid = skeyid;
++ skr->skeyid_d = skeyid_d;
++ skr->skeyid_a = skeyid_a;
++ skr->skeyid_e = skeyid_e;
++ skr->enc_key = enc_key;
++
++
++ WIRE_CLONE_CHUNK(*skr, new_iv, new_iv);
++ freeanychunk(new_iv);
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_prf.h libreswan-3.12/programs/pluto/ikev1_prf.h
+--- libreswan-3.12-orig/programs/pluto/ikev1_prf.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev1_prf.h 2015-05-06 11:45:32.923301452 -0400
+@@ -0,0 +1,66 @@
++/*
++ * Calculate IKEv1 prf and keying material, for libreswan
++ *
++ * Copyright (C) 2007 Michael C. Richardson
++ * Copyright (C) 2010 Paul Wouters
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#ifndef ikev1_prf_h
++#define ikev1_prf_h
++
++/*
++ * IKE SA SKEYID for authentication
++ *
++ * Be warned, this is not DSS (even though NIST call it Digital
++ * Signature Algorithm). It is used by RSA-SIG.
++ */
++PK11SymKey *ikev1_signature_skeyid(const struct hash_desc *hasher,
++ const chunk_t Ni_b, const chunk_t Nr_b,
++ PK11SymKey *dh_secret);
++
++PK11SymKey *ikev1_pre_shared_key_skeyid(const struct hash_desc *hasher,
++ chunk_t pre_shared_key,
++ chunk_t Ni_b, chunk_t Nr_b,
++ PK11SymKey *scratch);
++
++/*
++ * Authenticated keying material.
++ *
++ * Perhaps this should just return a struct?
++ */
++
++PK11SymKey *ikev1_skeyid_d(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r);
++
++PK11SymKey *ikev1_skeyid_a(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *skeyid_d, PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r);
++
++PK11SymKey *ikev1_skeyid_e(const struct hash_desc *hasher,
++ PK11SymKey *skeyid,
++ PK11SymKey *skeyid_a, PK11SymKey *dh_secret,
++ chunk_t cky_i, chunk_t cky_r);
++
++/*
++ * Old way.
++ */
++struct pluto_crypto_req;
++
++void calc_dh_iv(struct pluto_crypto_req *r);
++
++#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev1_quick.c libreswan-3.12/programs/pluto/ikev1_quick.c
+--- libreswan-3.12-orig/programs/pluto/ikev1_quick.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev1_quick.c 2015-05-06 11:45:32.923301452 -0400
+@@ -70,6 +70,7 @@
+ #include "plutoalg.h"
+
+ #include "pluto_crypt.h"
++#include "crypt_prf.h"
+ #include "ikev1.h"
+ #include "ikev1_quick.h"
+ #include "ikev1_continuations.h"
+@@ -470,13 +471,8 @@
+
+ for (i = 0;; ) {
+ if (st->st_shared_nss != NULL) {
+- /* PFS: include the g^xy */
+- SECStatus s;
+-
+- s = PK11_DigestKey(ctx_me.ctx_nss, st->st_shared_nss);
+- passert(s == SECSuccess);
+- s = PK11_DigestKey(ctx_peer.ctx_nss, st->st_shared_nss);
+- passert(s == SECSuccess);
++ crypt_prf_update_symkey("g^xy", ctx_me.prf, st->st_shared_nss);
++ crypt_prf_update_symkey("g^xy", ctx_peer.prf, st->st_shared_nss);
+ }
+ hmac_update(&ctx_me, &protoid, sizeof(protoid));
+ hmac_update(&ctx_peer, &protoid, sizeof(protoid));
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_crypto.c libreswan-3.12/programs/pluto/ikev2_crypto.c
+--- libreswan-3.12-orig/programs/pluto/ikev2_crypto.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_crypto.c 2015-05-06 11:45:32.924301463 -0400
+@@ -49,15 +49,16 @@
+ #include "crypto.h" /* requires sha1.h and md5.h */
+ #include "demux.h"
+ #include "ikev2.h"
+-#include "ikev2_prfplus.h"
++#include "ikev2_prf.h"
+ #include "ike_alg.h"
+ #include "alg_info.h"
+ #include "kernel_alg.h"
++#include "crypt_symkey.h"
++#include "ikev2_prf.h"
++
+
+ void ikev2_derive_child_keys(struct state *st, enum phase1_role role)
+ {
+- struct v2prf_stuff childsacalc;
+-
+ chunk_t ikeymat, rkeymat;
+ /* ??? note assumption that AH and ESP cannot be combined */
+ struct ipsec_proto_info *ipi =
+@@ -81,17 +82,6 @@
+ passert(ei != NULL);
+ ipi->attrs.transattrs.ei = ei;
+
+- zero(&childsacalc);
+- childsacalc.prf_hasher = st->st_oakley.prf_hasher;
+-
+- setchunk(childsacalc.ni, st->st_ni.ptr, st->st_ni.len);
+- setchunk(childsacalc.nr, st->st_nr.ptr, st->st_nr.len);
+- childsacalc.spii.len = 0;
+- childsacalc.spir.len = 0;
+-
+- childsacalc.counter[0] = 1;
+- childsacalc.skeyseed = st->st_skey_d_nss;
+-
+ /* ??? no account is taken of AH */
+ /* transid is same as esp_ealg_id */
+ switch (ei->transid) {
+@@ -150,11 +140,20 @@
+ * salt (AES_GCM_SALT_BYTES)
+ */
+
+- v2genbytes(&ikeymat, ipi->keymat_len,
+- "initiator keys", &childsacalc);
+-
+- v2genbytes(&rkeymat, ipi->keymat_len,
+- "responder keys", &childsacalc);
++ chunk_t ni;
++ chunk_t nr;
++ setchunk(ni, st->st_ni.ptr, st->st_ni.len);
++ setchunk(nr, st->st_nr.ptr, st->st_nr.len);
++
++ PK11SymKey *keymat = ikev2_child_sa_keymat(st->st_oakley.prf_hasher,
++ st->st_skey_d_nss,
++ NULL/*dh*/, ni, nr,
++ ipi->keymat_len * 2);
++ ikeymat = chunk_from_symkey_bytes("initiator keys", keymat,
++ 0, ipi->keymat_len);
++ rkeymat = chunk_from_symkey_bytes("initiator keys", keymat,
++ ipi->keymat_len, ipi->keymat_len);
++ free_any_symkey("keymat", &keymat);
+
+ if (role != O_INITIATOR) {
+ DBG(DBG_CRYPT, {
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prf.c libreswan-3.12/programs/pluto/ikev2_prf.c
+--- libreswan-3.12-orig/programs/pluto/ikev2_prf.c 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_prf.c 2015-05-06 11:45:32.924301463 -0400
+@@ -0,0 +1,405 @@
++/*
++ * Calculate IKEv2 prf and keying material, for libreswan
++ *
++ * Copyright (C) 2007 Michael C. Richardson
++ * Copyright (C) 2010 Paul Wouters
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * This code was developed with the support of Redhat corporation.
++ *
++ */
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++#include
++
++#include "sysdep.h"
++#include "constants.h"
++#include "defs.h"
++#include "packet.h"
++#include "demux.h"
++#include "crypto.h"
++#include "rnd.h"
++#include "state.h"
++#include "pluto_crypt.h"
++#include "lswlog.h"
++#include "log.h"
++#include "timer.h"
++#include "ike_alg.h"
++#include "id.h"
++#include "secrets.h"
++#include "keys.h"
++#include "ikev2_prf.h"
++#include "crypt_prf.h"
++#include "crypt_dh.h"
++#include "crypt_symkey.h"
++
++/*
++ * IKEv2 - RFC4306 2.14 SKEYSEED - calculation.
++ */
++
++/* 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
++ )
++
++{
++ 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;
++
++
++
++ /* 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;
++ initiator_salt = chunk_from_symkey_bytes("initiator salt", finalkey,
++ next_byte, salt_size);
++ 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;
++ responder_salt = chunk_from_symkey_bytes("responder salt", finalkey,
++ next_byte, salt_size);
++ next_byte += salt_size;
++
++ SK_pi_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes);
++
++
++
++ next_byte += skp_bytes;
++
++ SK_pr_k = key_from_symkey_bytes(finalkey, next_byte, skp_bytes);
++
++
++
++ next_byte += skp_bytes;
++
++ 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;
++
++
++
++ DBG(DBG_PRIVATE,
++ 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);
++ );
++
++}
++
++/* MUST BE THREAD-SAFE */
++void calc_dh_v2(struct pluto_crypto_req *r)
++{
++ struct pcr_skeycalc_v2_r *skr = &r->pcr_d.dhv2;
++ struct pcr_skeyid_q dhq;
++ const struct oakley_group_desc *group;
++ PK11SymKey *shared;
++ chunk_t g;
++ SECKEYPrivateKey *ltsecret;
++ PK11SymKey *skeyseed;
++ PK11SymKey
++ *SK_d,
++ *SK_ai,
++ *SK_ar,
++ *SK_ei,
++ *SK_er,
++ *SK_pi,
++ *SK_pr;
++ chunk_t initiator_salt;
++ chunk_t responder_salt;
++
++
++ SECKEYPublicKey *pubk;
++
++ /* copy the request, since the reply will re-use the memory of the r->pcr_d.dhq */
++ memcpy(&dhq, &r->pcr_d.dhq, sizeof(r->pcr_d.dhq));
++
++ /* clear out the reply */
++ zero(skr);
++ INIT_WIRE_ARENA(*skr);
++
++ group = lookup_group(dhq.oakley_group);
++ passert(group != NULL);
++
++ ltsecret = dhq.secret;
++ pubk = dhq.pubk;
++
++ /* now calculate the (g^x)(g^y) --- need gi on responder, gr on initiator */
++
++ setchunk_from_wire(g, &dhq, dhq.role == O_RESPONDER ? &dhq.gi : &dhq.gr);
++
++ DBG(DBG_CRYPT, DBG_dump_chunk("peer's g: ", g));
++
++ shared = calc_dh_shared(g, ltsecret, group, pubk);
++
++ /* okay, so now all the shared key material */
++ calc_skeyseed_v2(&dhq, /* input */
++ shared, /* input */
++ dhq.key_size, /* input */
++ dhq.salt_size, /* input */
++
++ &skeyseed, /* output */
++ &SK_d, /* output */
++ &SK_ai, /* output */
++ &SK_ar, /* output */
++ &SK_ei, /* output */
++ &SK_er, /* output */
++ &SK_pi, /* output */
++ &SK_pr, /* output */
++ &initiator_salt, /* output */
++ &responder_salt /* output */
++ );
++
++
++ skr->shared = shared;
++ skr->skeyseed = skeyseed;
++ skr->skeyid_d = SK_d;
++ skr->skeyid_ai = SK_ai;
++ skr->skeyid_ar = SK_ar;
++ skr->skeyid_ei = SK_ei;
++ skr->skeyid_er = SK_er;
++ skr->skeyid_pi = SK_pi;
++ skr->skeyid_pr = SK_pr;
++ skr->skey_initiator_salt = initiator_salt;
++ skr->skey_responder_salt = responder_salt;
++
++
++}
++
++static PK11SymKey *ikev2_prfplus(const struct hash_desc *hasher,
++ 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("prf+0",
++ hasher, key);
++ crypt_prf_init_symkey("key", prf, key);
++ crypt_prf_update(prf);
++ 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, PK11_GetKeyLength(prfplus));
++ while (PK11_GetKeyLength(prfplus) < required_keymat) {
++ /* Tn = prf(KEY, Tn-1|SEED|n) */
++ struct crypt_prf *prf = crypt_prf_init("prf+N",
++ hasher, key);
++ crypt_prf_init_symkey("key", prf, key);
++ crypt_prf_update(prf);
++ 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(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 hash_desc *hasher,
++ PK11SymKey *SK_d_old,
++ PK11SymKey *new_dh_secret,
++ const chunk_t Ni, const chunk_t Nr)
++{
++ struct crypt_prf *prf = crypt_prf_init("ike sa rekey skeyseed",
++ hasher, new_dh_secret);
++ /* key = SK_d (old) */
++ crypt_prf_init_symkey("SK_d (old)", prf, SK_d_old);
++ /* seed: g^ir (new) | Ni | Nr) */
++ crypt_prf_update(prf);
++ 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);
++}
++
++/*
++ * Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
++ */
++PK11SymKey *ikev2_ike_sa_keymat(const struct hash_desc *hasher,
++ PK11SymKey *skeyseed,
++ const chunk_t Ni, const chunk_t Nr,
++ const chunk_t SPIi, const chunk_t SPIr,
++ size_t required_bytes)
++{
++ PK11SymKey *data = symkey_from_chunk(skeyseed, Ni);
++ append_symkey_chunk(hasher, &data, Nr);
++ append_symkey_chunk(hasher, &data, SPIi);
++ append_symkey_chunk(hasher, &data, SPIr);
++ PK11SymKey *prfplus = ikev2_prfplus(hasher, skeyseed, data,
++ required_bytes);
++ free_any_symkey(__func__, &data);
++ return prfplus;
++}
++
++/*
++ * Compute: prf+(SK_d, [ g^ir (new) | ] Ni | Nr)
++ */
++PK11SymKey *ikev2_child_sa_keymat(const struct hash_desc *hasher,
++ PK11SymKey *SK_d,
++ PK11SymKey *new_dh_secret,
++ const chunk_t Ni, const chunk_t Nr,
++ size_t required_bytes)
++{
++ PK11SymKey *data;
++ if (new_dh_secret == NULL) {
++ data = symkey_from_chunk(SK_d, Ni);
++ append_symkey_chunk(hasher, &data, Nr);
++ } else {
++ data = concat_symkey_chunk(hasher, new_dh_secret, Ni);
++ append_symkey_chunk(hasher, &data, Nr);
++ }
++ PK11SymKey *prfplus = ikev2_prfplus(hasher, SK_d, data,
++ required_bytes);
++ free_any_symkey(__func__, &data);
++ return prfplus;
++}
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prf.h libreswan-3.12/programs/pluto/ikev2_prf.h
+--- libreswan-3.12-orig/programs/pluto/ikev2_prf.h 1969-12-31 19:00:00.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_prf.h 2015-05-06 11:45:32.924301463 -0400
+@@ -0,0 +1,58 @@
++/*
++ * Calculate IKEv2 prf and keying material, for libreswan
++ *
++ * Copyright (C) 2007 Michael C. Richardson
++ * Copyright (C) 2010 Paul Wouters
++ * Copyright (C) 2013 D. Hugh Redelmeier
++ * Copyright (C) 2015 Andrew Cagney
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version. See .
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ */
++
++#ifndef _IKEV2_PRF_H
++#define _IKEV2_PRF_H
++
++/*
++ * IKE SA
++ */
++PK11SymKey *ikev2_ike_sa_skeyseed(const struct hash_desc *prf_hasher,
++ const chunk_t Ni, const chunk_t Nr,
++ PK11SymKey *dh_secret);
++
++PK11SymKey *ikev2_ike_sa_rekey_skeyseed(const struct hash_desc *prf_hasher,
++ PK11SymKey *old_SK_d,
++ PK11SymKey *new_dh_secret,
++ const chunk_t Ni, const chunk_t Nr);
++
++PK11SymKey *ikev2_ike_sa_keymat(const struct hash_desc *prf_hasher,
++ PK11SymKey *skeyseed,
++ const chunk_t Ni, const chunk_t Nr,
++ const chunk_t SPIi, const chunk_t SPIr,
++ size_t required_bytes);
++
++/*
++ * Child SA
++ */
++PK11SymKey *ikev2_child_sa_keymat(const struct hash_desc *prf_hasher,
++ PK11SymKey *SK_d,
++ PK11SymKey *new_dh_secret,
++ const chunk_t Ni, const chunk_t Nr,
++ size_t required_bytes);
++
++/*
++ * Old way ...
++ */
++
++struct pluto_crypto_req;
++
++void calc_dh_v2(struct pluto_crypto_req *r);
++
++#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prfplus.c libreswan-3.12/programs/pluto/ikev2_prfplus.c
+--- libreswan-3.12-orig/programs/pluto/ikev2_prfplus.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_prfplus.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,106 +0,0 @@
+-/*
+- * Cryptographic helper function - calculate prf+() for ikev2
+- *
+- * Copyright (C) 2007 Michael C. Richardson
+- * Copyright (C) 2010 Paul Wouters
+- * Copyright (C) 2013 D. Hugh Redelmeier
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version. See .
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+- * for more details.
+- *
+- * This code was developed with the support of Redhat corporation.
+- *
+- */
+-
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-#include
+-
+-#include
+-
+-#include "sysdep.h"
+-#include "constants.h"
+-#include "defs.h"
+-#include "packet.h"
+-#include "demux.h"
+-#include "crypto.h"
+-#include "rnd.h"
+-#include "state.h"
+-#include "pluto_crypt.h"
+-#include "lswlog.h"
+-#include "log.h"
+-#include "timer.h"
+-#include "ike_alg.h"
+-#include "id.h"
+-#include "secrets.h"
+-#include "keys.h"
+-#include "ikev2_prfplus.h"
+-
+-static void v2prfplus(struct v2prf_stuff *vps)
+-{
+- struct hmac_ctx ctx;
+-
+- hmac_init(&ctx, vps->prf_hasher, vps->skeyseed);
+- hmac_update_chunk(&ctx, vps->t);
+- hmac_update_chunk(&ctx, vps->ni);
+- hmac_update_chunk(&ctx, vps->nr);
+- hmac_update_chunk(&ctx, vps->spii);
+- hmac_update_chunk(&ctx, vps->spir);
+- hmac_update(&ctx, vps->counter, 1);
+- hmac_final_chunk(vps->t, "skeyseed_t1", &ctx);
+- DBG(DBG_CRYPT, {
+- char b[20];
+- snprintf(b, sizeof(b), "prf+[%u]:", vps->counter[0]);
+- DBG_dump_chunk(b, vps->t);
+- });
+-
+- vps->counter[0]++;
+- vps->availbytes = vps->t.len;
+- vps->nextbytes = 0;
+-}
+-
+-void v2genbytes(chunk_t *need,
+- unsigned int needed, const char *name,
+- struct v2prf_stuff *vps)
+-{
+- u_char *target;
+-
+- need->ptr = alloc_bytes(needed, name);
+- need->len = needed;
+- target = need->ptr;
+-
+- while (needed > vps->availbytes) {
+- if (vps->availbytes) {
+- /* use any bytes which are presently in the buffer */
+- memcpy(target, &vps->t.ptr[vps->nextbytes],
+- vps->availbytes);
+- target += vps->availbytes;
+- needed -= vps->availbytes;
+- vps->availbytes = 0;
+- }
+- /* generate more bits into t1 */
+- v2prfplus(vps);
+- }
+- passert(needed <= vps->availbytes);
+-
+- memcpy(target, &vps->t.ptr[vps->nextbytes], needed);
+- vps->availbytes -= needed;
+- vps->nextbytes += needed;
+-}
+-
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_prfplus.h libreswan-3.12/programs/pluto/ikev2_prfplus.h
+--- libreswan-3.12-orig/programs/pluto/ikev2_prfplus.h 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_prfplus.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,20 +0,0 @@
+-#ifndef _IKEV2_PRF_H
+-#define _IKEV2_PRF_H
+-struct v2prf_stuff {
+- chunk_t t;
+- const struct hash_desc *prf_hasher;
+- PK11SymKey *skeyseed;
+- chunk_t ni;
+- chunk_t nr;
+- chunk_t spii;
+- chunk_t spir;
+- u_char counter[1]; /* why is this an array of 1? */
+- unsigned int availbytes;
+- unsigned int nextbytes;
+-};
+-
+-extern void v2genbytes(chunk_t *need,
+- unsigned int needed, const char *name,
+- struct v2prf_stuff *vps);
+-
+-#endif
+diff -Naur libreswan-3.12-orig/programs/pluto/ikev2_psk.c libreswan-3.12/programs/pluto/ikev2_psk.c
+--- libreswan-3.12-orig/programs/pluto/ikev2_psk.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/ikev2_psk.c 2015-05-06 11:45:32.925301475 -0400
+@@ -54,12 +54,14 @@
+ #include "server.h"
+ #include "vendor.h"
+ #include "keys.h"
++#include "crypt_prf.h"
++#include "crypt_symkey.h"
+
+ #include
+ #include
+
+-static u_char psk_key_pad_str[] = "Key Pad for IKEv2"; /* 4306 2:15 */
+-static int psk_key_pad_str_len = 17; /* sizeof( psk_key_pad_str); -1 */
++static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* 4306 2:15 */
++static const size_t psk_key_pad_str_len = 17; /* sizeof( psk_key_pad_str); -1 */
+
+ static bool ikev2_calculate_psk_sighash(struct state *st,
+ enum phase1_role role,
+@@ -71,8 +73,7 @@
+ const char *nonce_name;
+ const struct connection *c = st->st_connection;
+ const chunk_t *pss = get_preshared_secret(c);
+- unsigned int hash_len = st->st_oakley.prf_hasher->hash_digest_len;
+- unsigned char prf_psk[hash_len];
++ const size_t hash_len = st->st_oakley.prf_hasher->hash_digest_len;
+
+ if (pss == NULL) {
+ libreswan_log("No matching PSK found for connection:%s",
+@@ -80,52 +81,25 @@
+ return FALSE; /* failure: no PSK to use */
+ }
+
+- CK_EXTRACT_PARAMS bs;
+- SECItem param;
+-
+ /* RFC 4306 2.15:
+ * AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), )
+ */
+
+ /* calculate inner prf */
++ PK11SymKey *prf_psk;
+ {
+- struct hmac_ctx id_ctx;
+-
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(st->st_shared_nss,
+- CKM_CONCATENATE_DATA_AND_BASE, *pss, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE,
+- 0);
+- passert(tkey1 != NULL);
+-
+- bs = 0;
+- param.data = (unsigned char*)&bs;
+- param.len = sizeof(bs);
+- PK11SymKey *tkey2 = PK11_Derive(tkey1,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE, pss->len);
+- passert(tkey2 != NULL);
+-
+- hmac_init(&id_ctx, st->st_oakley.prf_hasher, tkey2);
+-
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey2);
+- hmac_update(&id_ctx, psk_key_pad_str, psk_key_pad_str_len);
+- hmac_final(prf_psk, &id_ctx);
++ struct crypt_prf *prf =
++ crypt_prf_init((""
++ " = prf(,\"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);
+ }
+
+- DBG(DBG_CRYPT,
+- DBG_log("negotiated prf: %s hash length: %lu",
+- st->st_oakley.prf_hasher->common.name,
+- (long unsigned) hash_len));
+- DBG(DBG_PRIVATE,
+- DBG_log("PSK , secret, used %s, length %lu",
+- pss->ptr, (long unsigned) pss->len);
+- DBG_log("keypad used \"%s\", length %d", psk_key_pad_str,
+- psk_key_pad_str_len));
+- DBG(DBG_CRYPT,
+- DBG_dump("inner prf output", prf_psk, hash_len));
+-
+ /* decide nonce based on the role */
+ if (role == O_INITIATOR) {
+ /* on initiator, we need to hash responders nonce */
+@@ -138,52 +112,32 @@
+
+ /* calculate outer prf */
+ {
+- struct hmac_ctx id_ctx;
+- chunk_t pp_chunk;
+-
+- pp_chunk.ptr = prf_psk;
+- pp_chunk.len = hash_len;
+-
+- PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(st->st_shared_nss,
+- CKM_CONCATENATE_DATA_AND_BASE,
+- pp_chunk,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- CKA_DERIVE,
+- 0);
+- passert(tkey1 != NULL);
+-
+- bs = 0;
+- param.data = (unsigned char*)&bs;
+- param.len = sizeof(bs);
+- PK11SymKey *tkey2 = PK11_Derive(tkey1,
+- CKM_EXTRACT_KEY_FROM_KEY,
+- ¶m,
+- CKM_CONCATENATE_BASE_AND_DATA,
+- CKA_DERIVE, hash_len);
+- passert(tkey2 != NULL);
+-
+- hmac_init(&id_ctx, st->st_oakley.prf_hasher, tkey2);
+-
+- PK11_FreeSymKey(tkey1);
+- PK11_FreeSymKey(tkey2);
+-
+-/*
+- * 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.
+- */
+-
+- hmac_update(&id_ctx, firstpacket.ptr, firstpacket.len);
+- hmac_update(&id_ctx, nonce->ptr, nonce->len);
+- hmac_update(&id_ctx, idhash, hash_len);
+- hmac_final(signed_octets, &id_ctx);
+-
++ struct crypt_prf *prf =
++ crypt_prf_init((""
++ " = prf(, )"),
++ st->st_oakley.prf_hasher,
++ st->st_shared_nss /*scratch*/);
++ crypt_prf_init_symkey("", 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);
+
+ DBG(DBG_CRYPT,
+ DBG_dump_chunk("inputs to hash1 (first packet)", firstpacket);
+diff -Naur libreswan-3.12-orig/programs/pluto/initiate.c libreswan-3.12/programs/pluto/initiate.c
+--- libreswan-3.12-orig/programs/pluto/initiate.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/initiate.c 2015-05-06 11:45:32.925301475 -0400
+@@ -132,7 +132,7 @@
+ c->name, c->interface->ip_dev->id_rname,
+ p->ip_dev->id_rname);
+ }
+- terminate_connection(c->name);
++ // terminate_connection(c->name);
+ c->interface = NULL; /* withdraw orientation */
+ return FALSE;
+ }
+diff -Naur libreswan-3.12-orig/programs/pluto/log.c libreswan-3.12/programs/pluto/log.c
+--- libreswan-3.12-orig/programs/pluto/log.c 2015-05-06 11:44:21.548466119 -0400
++++ libreswan-3.12/programs/pluto/log.c 2015-05-06 11:45:32.926301486 -0400
+@@ -1208,7 +1208,7 @@
+ if (!st->st_ikev2) {
+ /* ikev1 takes integ from prf, ecept of cause gcm */
+ /* but we dont support gcm in ikev1 for now */
+- snprintf(integname, sizeof(integname), prfname);
++ jam_str(integname, sizeof(integname), prfname);
+ } else {
+ snprintf(integname, sizeof(integname), "none");
+ }
+diff -Naur libreswan-3.12-orig/programs/pluto/Makefile libreswan-3.12/programs/pluto/Makefile
+--- libreswan-3.12-orig/programs/pluto/Makefile 2015-05-06 11:44:21.590466613 -0400
++++ libreswan-3.12/programs/pluto/Makefile 2015-05-06 11:45:32.926301486 -0400
+@@ -129,7 +129,8 @@
+ ikev1_dpd.c ikev1_dpd.h ikev1_spdb_struct.c \
+ ikev1_msgid.c \
+ ikev2.c ikev2_parent.c ikev2_child.c ikev2_crypto.c \
+- ikev2_prfplus.c ikev2_spdb_struct.c \
++ crypt_symkey.c crypt_prf.c ikev1_prf.c ikev2_prf.c \
++ ikev2_spdb_struct.c \
+ ikev2_rsa.c ikev2_psk.c ikev2_x509.c \
+ kernel.c kernel.h \
+ ${NETKEY_SRCS} \
+@@ -176,7 +177,8 @@
+ OBJSPLUTO += myid.o ipsec_doi.o
+ OBJSPLUTO += ikev1.o ikev1_main.o ikev1_quick.o ikev1_dpd.o ikev1_spdb_struct.o ikev1_msgid.o
+ OBJSPLUTO += ikev2.o ikev2_parent.o ikev2_child.o ikev2_spdb_struct.o
+-OBJSPLUTO += ikev2_rsa.o ikev2_psk.o ikev2_x509.o ikev2_crypto.o ikev2_prfplus.o
++OBJSPLUTO += ikev2_rsa.o ikev2_psk.o ikev2_x509.o ikev2_crypto.o
++OBJSPLUTO += crypt_symkey.o crypt_prf.o ikev1_prf.o ikev2_prf.o
+ OBJSPLUTO += kernel.o
+ OBJSPLUTO += $(NETKEY_OBJS) $(BSDKAME_OBJS) ${KLIPS_OBJS} ${MAST_OBJS} ${WIN2K_OBJS} ${PFKEYv2_OBJS}
+ OBJSPLUTO += kernel_noklips.o rcv_whack.o
+@@ -203,14 +205,16 @@
+ OBJSWHACK = whack.o
+ OBJSWHACKINIT = whackinit.o
+
++CAVP += cavp
++
+ # we can't do tests with two conditions, but we can concatenate the strings
+ SHOULDWERESTART=${USE_OBJDIR}$(wildcard plutomain.c)
+ ifeq ($(SHOULDWERESTART),trueplutomain.c)
+ all programs clean install:
+ cd ${LIBRESWANSRCDIR} && cd ${OBJDIRTOP}/programs/pluto && $(MAKE) $@
+ else
+-all: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) #$(BINNAMEWHACKINIT)
+-programs: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(MANPAGES) #$(BINNAMEWHACKINIT)
++all: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(CAVP) #$(BINNAMEWHACKINIT)
++programs: $(BINNAMEPLUTO) $(BINNAMEADNSIFNEEDED) $(BINNAMEWHACK) $(MANPAGES) $(CAVP) #$(BINNAMEWHACKINIT)
+ clean: cleanall
+ install: doinstall
+ endif
+@@ -290,6 +294,20 @@
+
+ checkprograms:
+
++# Cryptographic Algorithm Validation Program (CAVP)
++# see: http://csrc.nist.gov/groups/STM/cavp/index.html
++CAVPSRC += cavp.c
++CAVPSRC += cavp_print.c
++CAVPSRC += cavp_stubs.c
++CAVPSRC += cavp_ikev1.c
++CAVPSRC += cavp_ikev2.c
++DISTSRC += $(CAVPSRC)
++OBJSCAVP = $(CAVPSRC:.c=.o) $(filter-out plutomain.o, $(OBJSPLUTO))
++cavp: $(OBJSCAVP)
++ $(CC) -o $@ $(OBJSCAVP) \
++ $(LDFLAGS) $(USERLINK) $(LIBSPLUTO) ${PLUTOMINUSL}
++
++
+ .c.o:
+ $(CC) $(USERCOMPILE) ${PORTINCLUDE} $(COPTS) $(ALLFLAGS) -c $<
+
+diff -Naur libreswan-3.12-orig/programs/pluto/pluto_constants.c libreswan-3.12/programs/pluto/pluto_constants.c
+--- libreswan-3.12-orig/programs/pluto/pluto_constants.c 2015-05-06 11:44:21.549466131 -0400
++++ libreswan-3.12/programs/pluto/pluto_constants.c 2015-05-06 11:45:32.926301486 -0400
+@@ -161,6 +161,9 @@
+ /* story for state */
+
+ const char *const state_story[] = {
++ "not defined and probably dead (internal)", /* STATE_UNDEFINED */
++ "got an ACQUIRE message for this pair (internal)", /* OPPO_QCQUIRE */
++ "got TXT specifying gateway (internal)", /* OPPO_GW_DISCOVERED */
+ "expecting MI1", /* STATE_MAIN_R0 */
+ "sent MI1, expecting MR1", /* STATE_MAIN_I1 */
+ "sent MR1, expecting MI2", /* STATE_MAIN_R1 */
+@@ -206,7 +209,7 @@
+ };
+
+ enum_names state_stories =
+- { STATE_MAIN_R0, STATE_IKEv2_ROOF - 1, state_story, NULL };
++ { STATE_UNDEFINED, STATE_IKEv2_ROOF - 1, state_story, NULL };
+
+ static const char *const natt_method_result_name[] = {
+ };
+diff -Naur libreswan-3.12-orig/programs/pluto/pluto_crypt.c libreswan-3.12/programs/pluto/pluto_crypt.c
+--- libreswan-3.12-orig/programs/pluto/pluto_crypt.c 2014-11-06 22:52:50.000000000 -0500
++++ libreswan-3.12/programs/pluto/pluto_crypt.c 2015-05-06 11:45:32.927301498 -0400
+@@ -63,6 +63,10 @@
+ #include "lswconf.h"
+
+ #include "lsw_select.h"
++#include "ikev2_prf.h"
++#include "crypt_dh.h"
++#include "ikev1_prf.h"
++
+
+ TAILQ_HEAD(req_queue, pluto_crypto_req_cont);
+
+diff -Naur libreswan-3.12-orig/programs/pluto/pluto_crypt.h libreswan-3.12/programs/pluto/pluto_crypt.h
+--- libreswan-3.12-orig/programs/pluto/pluto_crypt.h 2015-05-06 11:44:21.570466378 -0400
++++ libreswan-3.12/programs/pluto/pluto_crypt.h 2015-05-06 11:45:32.927301498 -0400
+@@ -382,10 +382,6 @@
+ extern void finish_dh_v2(struct state *st,
+ const struct pluto_crypto_req *r);
+
+-extern void calc_dh_iv(struct pluto_crypto_req *r);
+-extern void calc_dh(struct pluto_crypto_req *r);
+-extern void calc_dh_v2(struct pluto_crypto_req *r);
+-
+ extern void unpack_KE_from_helper(
+ struct state *st,
+ const struct pluto_crypto_req *r,
+diff -Naur libreswan-3.12-orig/programs/pluto/state.c libreswan-3.12/programs/pluto/state.c
+--- libreswan-3.12-orig/programs/pluto/state.c 2015-05-06 11:44:21.571466389 -0400
++++ libreswan-3.12/programs/pluto/state.c 2015-05-06 11:45:32.928301510 -0400
+@@ -65,6 +65,7 @@
+ #include "md5.h"
+ #include "cookie.h"
+ #include "crypto.h" /* requires sha1.h and md5.h */
++#include "crypt_symkey.h"
+ #include "spdb.h"
+
+ #include
+@@ -525,12 +526,7 @@
+ freeanychunk(st->st_nr);
+
+
+-# define free_any_nss_symkey(p) { \
+- if ((p) != NULL) { \
+- PK11_FreeSymKey(p); \
+- (p) = NULL; \
+- } \
+- }
++# define free_any_nss_symkey(p) free_any_symkey(#p, &(p))
+ /* ??? free_any_nss_symkey(st->st_shared_nss); */
+ free_any_nss_symkey(st->st_skeyseed_nss); /* same as st_skeyid_nss */
+ free_any_nss_symkey(st->st_skey_d_nss); /* same as st_skeyid_d_nss */
+@@ -1440,7 +1436,7 @@
+ c->name, inst,
+ st->st_remoteport,
+ enum_name(&state_names, st->st_state),
+- state_story[st->st_state - STATE_MAIN_R0],
++ enum_name(&state_stories, st->st_state),
+ st->st_event ? enum_name(&timer_event_names,
+ st->st_event->ev_type) : "none",
+ delta,
+diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.c libreswan-3.12/programs/pluto/test_buffer.c
+--- libreswan-3.12-orig/programs/pluto/test_buffer.c 2015-05-06 11:44:21.591466625 -0400
++++ libreswan-3.12/programs/pluto/test_buffer.c 2015-05-06 11:45:32.928301510 -0400
+@@ -40,7 +40,7 @@
+ * If this function fails, crash and burn. Its been fed static data
+ * so should never ever have a problem.
+ */
+-static chunk_t decode_hex_to_chunk(const char *original, const char *string)
++chunk_t decode_hex_to_chunk(const char *original, const char *string)
+ {
+ /* The decoded buffer can't be bigger than the encoded string. */
+ chunk_t chunk = zalloc_chunk(strlen(string), original);
+@@ -154,8 +154,15 @@
+ PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism,
+ const char *encoded_key)
+ {
+- PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL);
+ chunk_t raw_key = decode_to_chunk("key", encoded_key);
++ PK11SymKey *sym_key = chunk_to_key(cipher_mechanism, raw_key);
++ freeanychunk(raw_key);
++ return sym_key;
++}
++
++PK11SymKey *chunk_to_key(CK_MECHANISM_TYPE cipher_mechanism, chunk_t raw_key)
++{
++ PK11SlotInfo *slot = PK11_GetBestSlot(cipher_mechanism, NULL);
+ SECItem key_item;
+ key_item.type = siBuffer;
+ key_item.data = raw_key.ptr; /* ptr to an array of key bytes */
+@@ -163,7 +170,6 @@
+ PK11SymKey *sym_key = PK11_ImportSymKey(slot, cipher_mechanism,
+ PK11_OriginUnwrap,
+ CKA_ENCRYPT, &key_item, NULL);
+- freeanychunk(raw_key);
+ PK11_FreeSlot(slot);
+ return sym_key;
+ }
+diff -Naur libreswan-3.12-orig/programs/pluto/test_buffer.h libreswan-3.12/programs/pluto/test_buffer.h
+--- libreswan-3.12-orig/programs/pluto/test_buffer.h 2015-05-06 11:44:21.592466636 -0400
++++ libreswan-3.12/programs/pluto/test_buffer.h 2015-05-06 11:45:32.928301510 -0400
+@@ -13,6 +13,7 @@
+ * for more details.
+ */
+
++chunk_t decode_hex_to_chunk(const char *original, const char *string);
+ chunk_t decode_to_chunk(const char *prefix, const char *string);
+ int compare_chunks(const char *prefix,
+ chunk_t expected,
+@@ -24,3 +25,5 @@
+ size_t offset, size_t length);
+
+ PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, const char *string);
++
++PK11SymKey *chunk_to_key(CK_MECHANISM_TYPE cipher_mechanism, chunk_t raw_key);
diff --git a/SOURCES/libreswan-3.12-CVE-2015-3204.patch b/SOURCES/libreswan-3.12-CVE-2015-3204.patch
new file mode 100644
index 0000000..8dfd1f5
--- /dev/null
+++ b/SOURCES/libreswan-3.12-CVE-2015-3204.patch
@@ -0,0 +1,169 @@
+diff --git a/lib/libswan/constants.c b/lib/libswan/constants.c
+index a003e99..8f3a107 100644
+--- a/lib/libswan/constants.c
++++ b/lib/libswan/constants.c
+@@ -43,12 +43,11 @@
+ * The buffer bound (size) must be greater than 0.
+ * That allows a guarantee that the result is NUL-terminated.
+ *
+- * The result is a pointer:
+- * if the string fits, to the NUL at the end of the string in dest;
+- * if the string was truncated, to the roof of dest.
++ * The result is a pointer to the NUL at the end of the string in dest.
+ *
+- * Warning: Is it really wise to silently truncate? Only the caller knows.
+- * The caller SHOULD check by seeing if the result equals dest's roof.
++ * Warning: no indication of truncation is returned.
++ * An earlier version did indicate truncation, but that feature was never used.
++ * This version is more robust and has a simpler contract.
+ */
+ char *jam_str(char *dest, size_t size, const char *src)
+ {
+@@ -56,12 +55,11 @@ char *jam_str(char *dest, size_t size, const char *src)
+
+ {
+ size_t full_len = strlen(src);
+- bool oflow = size - 1 < full_len;
+- size_t copy_len = oflow ? size - 1 : full_len;
++ size_t copy_len = size - 1 < full_len ? size - 1 : full_len;
+
+ memcpy(dest, src, copy_len);
+ dest[copy_len] = '\0';
+- return dest + copy_len + (oflow ? 1 : 0);
++ return dest + copy_len;
+ }
+ }
+
+diff --git a/include/packet.h b/include/packet.h
+index c9b0df9..55f8b11 100644
+--- a/include/packet.h
++++ b/include/packet.h
+@@ -657,6 +657,8 @@ struct isakmp_nat_oa {
+ extern struct_desc isakmp_nat_d;
+ extern struct_desc isakmp_nat_oa;
+
++extern struct_desc isakmp_ignore_desc; /* generic payload (when ignoring) */
++
+ /* ISAKMP IKE Fragmentation Payload
+ * Cisco proprietary, undocumented
+ * Microsoft documentation link: http://msdn.microsoft.com/en-us/library/cc233452.aspx
+diff --git a/programs/pluto/ikev1.c b/programs/pluto/ikev1.c
+index e8157bb..155a27c 100644
+--- a/programs/pluto/ikev1.c
++++ b/programs/pluto/ikev1.c
+@@ -1810,8 +1810,7 @@ void process_packet_tail(struct msg_digest **mdp)
+ switch (np) {
+ case ISAKMP_NEXT_NATD_RFC:
+ case ISAKMP_NEXT_NATOA_RFC:
+- if (st == NULL ||
+- (st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) == LEMPTY) {
++ if ((st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES) == LEMPTY) {
+ /*
+ * don't accept NAT-D/NAT-OA reloc directly in message,
+ * unless we're using NAT-T RFC
+@@ -1832,6 +1831,7 @@ void process_packet_tail(struct msg_digest **mdp)
+ /* payload type is out of range or requires special handling */
+ switch (np) {
+ case ISAKMP_NEXT_ID:
++ /* ??? two kinds of ID payloads */
+ sd = (IS_PHASE1(from_state) ||
+ IS_PHASE15(from_state)) ?
+ &isakmp_identification_desc :
+@@ -1839,20 +1839,48 @@ void process_packet_tail(struct msg_digest **mdp)
+ break;
+
+ case ISAKMP_NEXT_NATD_DRAFTS:
+- np = ISAKMP_NEXT_NATD_RFC; /* NAT-D was a private use type before RFC-3947 */
++ /* NAT-D was a private use type before RFC-3947 -- same format */
++ np = ISAKMP_NEXT_NATD_RFC;
+ sd = payload_desc(np);
+ break;
+
+ case ISAKMP_NEXT_NATOA_DRAFTS:
+- np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA was a private use type before RFC-3947 */
++ /* NAT-OA was a private use type before RFC-3947 -- same format */
++ np = ISAKMP_NEXT_NATOA_RFC;
+ sd = payload_desc(np);
+ break;
+
+- case ISAKMP_NEXT_SAK: /* AKA ISAKMP_NEXT_NATD_BADDRAFTS */
++ case ISAKMP_NEXT_SAK: /* or ISAKMP_NEXT_NATD_BADDRAFTS */
++ /*
++ * Official standards say that this is ISAKMP_NEXT_SAK,
++ * a part of Group DOI, something we don't implement.
++ * Old non-updated Cisco gear abused this number in ancient NAT drafts.
++ * We ignore (rather than reject) this in support of people
++ * with crufty Cisco machines.
++ */
+ loglog(RC_LOG_SERIOUS,
+- "%smessage with unsupported payload ISAKMP_NEXT_SAK (as ISAKMP_NEXT_NATD_BADDRAFTS) ignored",
++ "%smessage with unsupported payload ISAKMP_NEXT_SAK (or ISAKMP_NEXT_NATD_BADDRAFTS) ignored",
+ excuse);
+- break;
++ /*
++ * Hack to discard payload, whatever it was.
++ * Since we are skipping the rest of the loop
++ * body we must do some things ourself:
++ * - demarshall the payload
++ * - grab the next payload number (np)
++ * - don't keep payload (don't increment pd)
++ * - skip rest of loop body
++ */
++ if (!in_struct(&pd->payload, &isakmp_ignore_desc, &md->message_pbs,
++ &pd->pbs)) {
++ loglog(RC_LOG_SERIOUS,
++ "%smalformed payload in packet",
++ excuse);
++ SEND_NOTIFICATION(PAYLOAD_MALFORMED);
++ return;
++ }
++ np = pd->payload.generic.isag_np;
++ /* NOTE: we do not increment pd! */
++ continue; /* skip rest of the loop */
+
+ default:
+ loglog(RC_LOG_SERIOUS,
+@@ -1865,6 +1893,8 @@ void process_packet_tail(struct msg_digest **mdp)
+ passert(sd != NULL);
+ }
+
++ passert(np < LELEM_ROOF);
++
+ {
+ lset_t s = LELEM(np);
+
+diff --git a/programs/pluto/packet.c b/programs/pluto/packet.c
+index 2b104db..e759b5e 100644
+--- a/programs/pluto/packet.c
++++ b/programs/pluto/packet.c
+@@ -81,9 +81,6 @@ static field_desc isag_fields[] = {
+ { ft_end, 0, NULL, NULL }
+ };
+
+-static struct_desc isakmp_generic_desc =
+- { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) };
+-
+ /* ISAKMP Data Attribute (generic representation within payloads)
+ * layout from RFC 2408 "ISAKMP" section 3.3
+ * This is not a payload type.
+@@ -647,6 +644,11 @@ struct_desc isakmp_nat_oa =
+ { "ISAKMP NAT-OA Payload", isanat_oa_fields,
+ sizeof(struct isakmp_nat_oa) };
+
++/* Generic payload (when ignoring) */
++
++struct_desc isakmp_ignore_desc =
++ { "ignored ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) };
++
+ /* ISAKMP IKE Fragmentation Payload
+ * Cisco proprietary, undocumented
+ *
+@@ -1892,7 +1894,7 @@ bool out_generic(u_int8_t np, struct_desc *sd,
+ {
+ struct isakmp_generic gen;
+
+- passert(sd->fields == isakmp_generic_desc.fields);
++ passert(sd->fields == isag_fields);
+ gen.isag_np = np;
+ return out_struct(&gen, sd, outs, obj_pbs);
+ }
diff --git a/SOURCES/v6neighbor-hole.conf b/SOURCES/v6neighbor-hole.conf
new file mode 100644
index 0000000..8ac7616
--- /dev/null
+++ b/SOURCES/v6neighbor-hole.conf
@@ -0,0 +1,58 @@
+# Passthrough For proper IPv6 Neighbor Discovery (RFC 4861)
+#
+# The unicast Neighbor Advertisement reply message must be sent
+# in plaintext) even if we have an IPsec SA for the destination,
+# because the other end might have crashed or rebooted and lost
+# its IPsec SA with our end. It will use IPv6 Neighbor Discovery
+# to find our end again. Without this policy hole, the neighbor
+# discovery answer packet is caught by the kernel and encrypted.
+# As a result, the rebooted end won't be able to find us and won't
+# be able to send us an IKE packet to re-establish the IPsec SA.
+#
+# While the Neighbor Solicitation is multicast and would not
+# not be caught by the IPsec stack, we use it in the configuration
+# to limit the range of ipv6-icmp covered. In a way, this would
+# only need to be an outbound SA, but SA's come in bundles, so we
+# need an unbound SA as well. Leaving protoport empty or set to
+# any ipv6-icmp would cause us to send out more unencrypted traffic,
+# which would be dropped once the IPsec SA has re-established.
+# So we set the inbound protoport to ipv6-icmp Neighbor Advertisement.
+# (solution by Jaroslav Aster)
+#
+# Configuration
+#
+# ipv6-icmp Neighbor Solicitation is Type 135, Code 0.
+# ipv6-icmp Neighbor Advertisement is Type 136, Code 0.
+# As per RFC 4301/5996, icmp type is put in the most significant 8 bits
+# and the icmp code is in the least significant 8 bits of port field.
+# proto is 58 (ipv6-icmp)
+# type = 135 (0x87) or 136 (0x88)
+# code = 0 (0x00)
+# so "port" in protoport is 0x8700 (34560) for Neighbor Solicitation.
+# so "port" in protoport is 0x8800 (34816) for Neighbor Advertisement.
+
+conn v6neighbor-hole-in
+ left=::1
+ leftsubnet=::0/0
+ leftprotoport=58/34560
+ rightprotoport=58/34816
+ rightsubnet=::0/0
+ right=::0
+ connaddrfamily=ipv6
+ authby=never
+ type=passthrough
+ auto=route
+ priority=10
+
+conn v6neighbor-hole-out
+ left=::1
+ leftsubnet=::0/0
+ leftprotoport=58/34816
+ rightprotoport=58/34560
+ rightsubnet=::0/0
+ right=::0
+ connaddrfamily=ipv6
+ authby=never
+ type=passthrough
+ auto=route
+ priority=10
diff --git a/SPECS/libreswan.spec b/SPECS/libreswan.spec
index 5b4280e..ef05c54 100644
--- a/SPECS/libreswan.spec
+++ b/SPECS/libreswan.spec
@@ -16,10 +16,14 @@
Name: libreswan
Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols
Version: 3.12
-Release: %{?prever:0.}5%{?prever:.%{prever}}%{?dist}
+Release: %{?prever:0.}10.1%{?prever:.%{prever}}%{?dist}
License: GPLv2
Url: https://www.libreswan.org/
Source: https://download.libreswan.org/%{name}-%{version}%{?prever}.tar.gz
+Source1: v6neighbor-hole.conf
+Source2: ikev1_dsa.fax.bz2
+Source3: ikev1_psk.fax.bz2
+Source4: ikev2.fax.bz2
Group: System Environment/Daemons
BuildRequires: gmp-devel bison flex redhat-rpm-config pkgconfig
BuildRequires: systemd
@@ -36,6 +40,17 @@ Patch5: libreswan-3.12-1131503-invalid-ke.patch
Patch6: libreswan-3.12-1134297-aes_ctr.patch
Patch7: libreswan-3.12-1162770-gcm-man.patch
Patch8: libreswan-3.12-826264-ike-aes-gcm.patch
+#rhbz 1198650
+Patch9: libreswan-3.12-1170018-netlink-label.patch
+#rhbz 1198649
+Patch10: libreswan-3.12-1182224-bsi-random.patch
+#rhbz 1211146
+Patch11: libreswan-3.12-1203794-fipstest.patch
+# rhbz 1213652
+Patch12: libreswan-3.12-1212121-cavs.patch
+# rhbz 1208022
+Patch13: libreswan-3.12-1207689-blacklist.patch
+Patch14: libreswan-3.12-CVE-2015-3204.patch
Conflicts: openswan < %{version}-%{release}
Obsoletes: openswan < %{version}-%{release}
@@ -97,6 +112,13 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04
%patch6 -p1
%patch7 -p1
%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+
# remove man page for ipsec.conf so it is forced to regenerate
rm ./programs/configs/ipsec.conf.5
@@ -176,6 +198,24 @@ install -m644 packaging/fedora/libreswan-prelink.conf %{buildroot}%{_sysconfdir}
echo "include /etc/ipsec.d/*.secrets" > %{buildroot}%{_sysconfdir}/ipsec.secrets
rm -fr %{buildroot}/etc/rc.d/rc*
+install -m644 %{SOURCE1} %{buildroot}%{_sysconfdir}/ipsec.d/v6neighbor-hole.conf
+sed -i "s/#include \/etc\/ipsec.d\/\*.conf/include \/etc\/ipsec.d\/\*.conf/" %{buildroot}%{_sysconfdir}/ipsec.conf
+# cavs testing
+cp -a OBJ.*/programs/pluto/cavp %{buildroot}%{_libexecdir}/ipsec
+
+%check
+# There is an elaborate upstream testing infrastructure which we do not run here
+# We only run the CAVS tests here
+cp %{SOURCE2} %{SOURCE3} %{SOURCE4} .
+bunzip2 *.fax.bz2
+echo "starting CAVS test for IKEv2"
+OBJ.linux.*/programs/pluto/cavp -v2 ikev2.fax | diff -u ikev2.fax - > /dev/null
+echo "starting CAVS test for IKEv1 RSASIG"
+OBJ.linux.*/programs/pluto/cavp -v1sig ikev1_dsa.fax | diff -u ikev1_dsa.fax - > /dev/null
+echo "starting CAVS test for IKEv1 PSK"
+OBJ.linux.*/programs/pluto/cavp -v1psk ikev1_psk.fax | diff -u ikev1_psk.fax - > /dev/null
+echo "CAVS tests passed"
+
%files
%doc CHANGES COPYING CREDITS README* LICENSE
%doc docs/*.* docs/examples
@@ -184,6 +224,7 @@ rm -fr %{buildroot}/etc/rc.d/rc*
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/pluto
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets
%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d
+%attr(0644,root,root) %{_sysconfdir}/ipsec.d/v6neighbor-hole.conf
%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/cacerts
%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/crls
%attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies
@@ -217,6 +258,29 @@ if [ ! -f %{_sysconfdir}/ipsec.d/cert8.db ] ; then
fi
%changelog
+* Fri May 29 2015 Paul Wouters - 3.12-10.1
+- Resolves: rhbz#1226407 CVE-2015-3204 libreswan: crafted IKE packet causes daemon restart
+
+* Tue May 05 2015 Paul Wouters - 3.12-10
+- Resolves: rhbz#1213652 Support CAVS [updated another prf() free symkey, bogus fips mode fix]
+
+* Tue Apr 28 2015 Paul Wouters - 3.12-9
+- Resolves: rhbz#1213652 Support CAVS [updated to kill another copy of prf()]
+- Resolves: rhbz#1208023 Libreswan with IPv6 [updated patch by Jaroslav Aster]
+- Resolves: rhbz#1208022 libreswan ignores module blacklist [updated modprobe handling]
+
+* Mon Apr 20 2015 Paul Wouters - 3.12-8
+- Resolves: rhbz#1213652 Support CAVS testing of the PRF/PRF+ functions
+
+* Mon Apr 13 2015 Paul Wouters - 3.12-7
+- Resolves: rhbz#1208022 libreswan ignores module blacklist rules
+- Resolves: rhbz#1208023 Libreswan with IPv6 in RHEL7 fails after reboot
+- Resolves: rhbz#1211146 pluto crashes in fips mode
+
+* Tue Mar 17 2015 Paul Wouters - 3.12-6
+- Resolves: rhbz#1198650 SELinux context string size limit
+- Resolves: rhbz#1198649 Add new option for BSI random requirement
+
* Tue Jan 20 2015 Paul Wouters - 3.12-5
- Resolves: rhbz#826264 aes-gcm implementation support (for IKEv2)
- Resolves: rhbz#1074018 Audit key agreement (integ gcm fixup)