Subject: kern/22766: cgdconfig(8) should be able to read from /dev/urandom too
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tv@pobox.com>
List: netbsd-bugs
Date: 09/12/2003 15:54:36
>Number:         22766
>Category:       kern
>Synopsis:       cgdconfig(8) should be able to read from /dev/urandom too
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Sep 12 19:58:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Todd Vierling
>Release:        NetBSD-current 20030912
>Organization:
	DUH.ORG:  Pointing out the obvious since 1994.
>Environment:
>Description:

cgdconfig(8), using keygen method "randomkey", reads /dev/random -- which
may block waiting for entropy if there is not enough available.  Some
systems may not have enough entropy generated by the time cgdconfig is
called (say, from /etc/rc.d/cgd), so this could be a risky keygen to use
for boot-time configuration of swap on a randomly keyed cgd.

On my shark system, for instance, hard entropy is at a premium, but I'm
perfectly happy using pseudo-random bits for the encryption used on
swap.  After all, it is a throwaway key, which is never written to disk
at all.

>How-To-Repeat:
>Fix:

The following implements reading of /dev/urandom using a new keygen
method keyword, "urandomkey".  The manual page is updated as well
to indicate this new option, along with a warning that the generated
key may not be as secure as "randomkey".

Though /dev/urandom itself may qualify as a good configuration option
itself, this makes me think that a plain-file keygen method might
be useful as a generalization.  Such an option would be the
configuration equivalent of the "-s" command line option, which reads
a binary key from stdin.

Index: cgdconfig.8
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.8,v
retrieving revision 1.14
diff -u -r1.14 cgdconfig.8
--- cgdconfig.8	2003/06/27 23:02:16	1.14
+++ cgdconfig.8	2003/09/12 19:45:51
@@ -151,6 +151,17 @@
 a disk volume with meaningless data prior to use.
 .It storedkey
 This method stores its key in the parameters file.
+.It urandomkey
+The method simply reads
+.Pa /dev/urandom
+and uses the resulting bits as the key.  This is similar to the
+.Pa randomkey
+method, but it guarantees that cgdconfig will not stall waiting for
+hard-random bits.
+Note, however, that some or all of the bits used to generate the
+key may be obtained from a pseudo-random number generator,
+which may not be as secure as the entropy based hard-random
+number generator.
 .El
 .Ss Verification Method
 The verification method is how
Index: cgdconfig.c
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.c,v
retrieving revision 1.8
diff -u -r1.8 cgdconfig.c
--- cgdconfig.c	2003/05/17 23:09:06	1.8
+++ cgdconfig.c	2003/09/12 19:45:51
@@ -96,7 +96,7 @@
 				  struct params *);
 static bits_t	*getkey(const char *, struct keygen *, int);
 static bits_t	*getkey_storedkey(const char *, struct keygen *, int);
-static bits_t	*getkey_randomkey(const char *, struct keygen *, int);
+static bits_t	*getkey_randomkey(const char *, struct keygen *, int, int);
 static bits_t	*getkey_pkcs5_pbkdf2(const char *, struct keygen *, int);
 static int	 opendisk_werror(const char *, char *, int);
 static int	 unconfigure_fd(int);
@@ -254,8 +254,11 @@
 			tmp = getkey_storedkey(dev, kg, len);
 			break;
 		case KEYGEN_RANDOMKEY:
-			tmp = getkey_randomkey(dev, kg, len);
+			tmp = getkey_randomkey(dev, kg, len, 1);
 			break;
+		case KEYGEN_URANDOMKEY:
+			tmp = getkey_randomkey(dev, kg, len, 0);
+			break;
 		case KEYGEN_PKCS5_PBKDF2:
 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len);
 			break;
@@ -286,10 +289,10 @@
 
 /*ARGSUSED*/
 static bits_t *
-getkey_randomkey(const char *target, struct keygen *kg, int keylen)
+getkey_randomkey(const char *target, struct keygen *kg, int keylen, int hard)
 {
 
-	return bits_getrandombits(keylen);
+	return bits_getrandombits(keylen, hard);
 }
 
 /*ARGSUSED*/
Index: params.c
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/params.c,v
retrieving revision 1.7
diff -u -r1.7 params.c
--- params.c	2003/07/13 07:58:19	1.7
+++ params.c	2003/09/12 19:45:52
@@ -354,12 +354,13 @@
 			warnx("keygen storedkey does not need `salt'");
 		break;
 	case KEYGEN_RANDOMKEY:
+	case KEYGEN_URANDOMKEY:
 		if (kg->kg_iterations != -1)
-			warnx("keygen randomkey does not need `iterations'");
+			warnx("keygen [u]randomkey does not need `iterations'");
 		if (kg->kg_key)
-			warnx("keygen randomkey does not need `key'");
+			warnx("keygen [u]randomkey does not need `key'");
 		if (kg->kg_salt)
-			warnx("keygen randomkey does not need `salt'");
+			warnx("keygen [u]randomkey does not need `salt'");
 		break;
 	}
 	return keygen_verify(kg->next);
@@ -394,9 +395,10 @@
 		return 0;
 	switch (kg->kg_method) {
 	case KEYGEN_RANDOMKEY:
+	case KEYGEN_URANDOMKEY:
 		break;
 	case KEYGEN_PKCS5_PBKDF2:
-		kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN);
+		kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1);
 		kg->kg_iterations =
 		    pkcs5_pbkdf2_calibrate(keylen, DEFAULT_ITERATION_TIME);
 		if (kg->kg_iterations < 1) {
@@ -407,7 +409,7 @@
 		break;
 	case KEYGEN_STOREDKEY:
 		/* Generate a random stored key */
-		kg->kg_key = bits_getrandombits(keylen);
+		kg->kg_key = bits_getrandombits(keylen, 1);
 		if (!kg->kg_key) {
 			warnx("can't generate random bits for storedkey");
 			return -1;
@@ -459,6 +461,8 @@
 		kg->kg_method = KEYGEN_RANDOMKEY;
 	if (!strcmp("storedkey", kgm))
 		kg->kg_method = KEYGEN_STOREDKEY;
+	if (!strcmp("urandomkey", kgm))
+		kg->kg_method = KEYGEN_URANDOMKEY;
 
 	string_free(in);
 
@@ -667,6 +671,9 @@
 		break;
 	case KEYGEN_RANDOMKEY:
 		fprintf(f, "randomkey;\n");
+		break;
+	case KEYGEN_URANDOMKEY:
+		fprintf(f, "urandomkey;\n");
 		break;
 	case KEYGEN_PKCS5_PBKDF2:
 		fprintf(f, "pkcs5_pbkdf2 {\n");
Index: params.h
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/params.h,v
retrieving revision 1.4
diff -u -r1.4 params.h
--- params.h	2003/03/24 02:02:51	1.4
+++ params.h	2003/09/12 19:45:52
@@ -66,6 +66,7 @@
 #define KEYGEN_RANDOMKEY	0x1
 #define KEYGEN_PKCS5_PBKDF2	0x2
 #define KEYGEN_STOREDKEY	0x3
+#define KEYGEN_URANDOMKEY	0x4
 
 /* verification methods */
 
Index: utils.c
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/utils.c,v
retrieving revision 1.2
diff -u -r1.2 utils.c
--- utils.c	2003/03/24 02:02:52	1.2
+++ utils.c	2003/09/12 19:45:52
@@ -461,10 +461,10 @@
 }
 
 bits_t *
-bits_getrandombits(int len)
+bits_getrandombits(int len, int hard)
 {
 
-	return bits_cget("/dev/random", len);
+	return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
 }
 
 void
Index: utils.h
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/utils.h,v
retrieving revision 1.2
diff -u -r1.2 utils.h
--- utils.h	2003/03/24 02:02:52	1.2
+++ utils.h	2003/09/12 19:45:52
@@ -86,7 +86,7 @@
 
 bits_t		 *bits_cget(const char *, int);
 bits_t		 *bits_fget(FILE *, int);
-bits_t		 *bits_getrandombits(int);
+bits_t		 *bits_getrandombits(int, int);
 
 void		  bits_fprint(FILE *, const bits_t *);
 __END_DECLS
>Release-Note:
>Audit-Trail:
>Unformatted: