Blob Blame History Raw
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 @@
+  <varlistentry>
+  <term><emphasis remap='B'>seedbits</emphasis></term>
+  <listitem>
+<para>
+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).
+</para>
+  </listitem>
+  </varlistentry>
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 <http://docbook.sf.net/>
-.\"      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 @@
       <arg choice="opt">--secretsfile <replaceable>secrets-file</replaceable></arg>
       <arg choice="opt">--adns <replaceable>pathname</replaceable></arg>
       <arg choice="opt">--nhelpers <replaceable>number</replaceable></arg>
+      <arg choice="opt">--seedbits <replaceable>numbits</replaceable></arg>
       <arg choice="opt">--perpeerlog</arg>
       <arg choice="opt">--perpeerlogbase <replaceable>dirname</replaceable></arg>
       <arg choice="opt">--ipsecdir <replaceable>dirname</replaceable></arg>
@@ -984,6 +985,18 @@
       <emphasis remap="I">-1</emphasis> tells pluto to perform the above
       calculation. Any other value forces the number to that amount.</para>
 
+      <para>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 <emphasis remap="B">--seedbits</emphasis>
+      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.</para>
+
       <para><emphasis remap="B">pluto</emphasis> attempts to create a lockfile
       with the name <filename>/var/run/pluto/pluto.pid</filename>. If the
       lockfile cannot be created, <emphasis remap="B">pluto</emphasis> 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<network_list>", required_argument, NULL, '6' },
 	{ "nhelpers\0<number>", required_argument, NULL, 'j' },
+	{ "seedbits\0<number>", required_argument, NULL, 'c' },
 #ifdef HAVE_LABELED_IPSEC
 	{ "secctx_attr_value\0_", required_argument, NULL, 'w' },	/* _ */
 	{ "secctx-attr-value\0<number>", 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=<unsupported>");
 #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 <http://docbook.sf.net/>
-.\"      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 @@
   <command>ipsec</command>    
     <arg choice='plain'><replaceable>rsasigkey</replaceable></arg>
     <arg choice='opt'>--verbose </arg>
-    <arg choice='opt'>--random <replaceable>filename</replaceable></arg>
+    <arg choice='opt'>--random <replaceable>device</replaceable></arg>
+    <arg choice='opt'>--seed <replaceable>numbits</replaceable></arg>
     <arg choice='opt'>--configdir <replaceable>nssdbdir</replaceable></arg>
     <arg choice='opt'>--password <replaceable>nsspassword</replaceable></arg>
     <arg choice='opt'>--hostname <replaceable>hostname</replaceable></arg>
     <arg choice='opt'>nbits </arg>
 </cmdsynopsis>
-<cmdsynopsis>
-  <command>ipsec</command>    
-    <arg choice='plain'><replaceable>rsasigkey</replaceable></arg>
-    <arg choice='opt'>--verbose </arg>
-    <arg choice='opt'>--configdir <replaceable>nssdbdir</replaceable></arg>
-    <arg choice='opt'>--password <replaceable>nsspassword</replaceable></arg>
-    <arg choice='opt'>--hostname <replaceable>hostname</replaceable></arg>
-</cmdsynopsis>
 </refsynopsisdiv>
 
 
@@ -61,14 +54,22 @@
 source for random bits used to seed the crypto library's
 RNG. The default is <filename>/dev/random</filename> (see
 <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry>).
-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 <filename>/dev/*rng*</filename>
-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) </para>
 
+<para>The <option>--seedbits</option> 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.
+</para>
+
+<para>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.</para>
+
 <para>The <option>--configdir</option> 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 <filename>/etc/ipsec.d</filename>.</para>
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 <mcr@xelerance.com>
  * Copyright (C) 2003-2009 Paul Wouters <paul@xelerance.com>
  * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com>
- * Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
+ * Copyright (C) 2012-2015 Paul Wouters <paul@libreswan.org>
  *
  * 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 <device>] [--configdir <dir>] [--password <password>] [--hostname host] [<nbits>]";
+	"rsasigkey [--verbose] [--random <device>] [--configdir <dir>] [--password <password>] [--hostname host] [--seedbits bits] [<keybits>]";
 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);
+}
+