summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordinak <none@none>2008-02-28 13:44:32 -0800
committerdinak <none@none>2008-02-28 13:44:32 -0800
commit26ff1ce9e5494c59fafe62a0c6e3ca41cd0f2a99 (patch)
treedbb32aebaf673fd792dee06c4125ff6aa2492fd8
parent9d68b18ee78271952aa02af7a316bfb825f35d97 (diff)
downloadillumos-joyent-26ff1ce9e5494c59fafe62a0c6e3ca41cd0f2a99.tar.gz
6665460 move random and nonzero random funcs out of pkcs11 to libcryptoutil
6665548 convert pkcs11 mechanism to corresponding key generation mechanism
-rw-r--r--usr/src/lib/libcryptoutil/Makefile.com5
-rw-r--r--usr/src/lib/libcryptoutil/common/cryptoutil.h5
-rw-r--r--usr/src/lib/libcryptoutil/common/mapfile-vers4
-rw-r--r--usr/src/lib/libcryptoutil/common/mechkeygen.c362
-rw-r--r--usr/src/lib/libcryptoutil/common/random.c163
5 files changed, 525 insertions, 14 deletions
diff --git a/usr/src/lib/libcryptoutil/Makefile.com b/usr/src/lib/libcryptoutil/Makefile.com
index ecefbef41b..7f8c7a0a43 100644
--- a/usr/src/lib/libcryptoutil/Makefile.com
+++ b/usr/src/lib/libcryptoutil/Makefile.com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -33,7 +33,8 @@ OBJECTS= \
mechstr.o \
config_parsing.o \
tohexstr.o \
- mechkeytype.o\
+ mechkeygen.o \
+ mechkeytype.o \
pkcserror.o \
passutils.o \
random.o \
diff --git a/usr/src/lib/libcryptoutil/common/cryptoutil.h b/usr/src/lib/libcryptoutil/common/cryptoutil.h
index 5d0c3c9ab3..671e02a1fe 100644
--- a/usr/src/lib/libcryptoutil/common/cryptoutil.h
+++ b/usr/src/lib/libcryptoutil/common/cryptoutil.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -127,6 +127,8 @@ extern uentry_t *getent_uef(char *);
extern void tohexstr(uchar_t *bytes, size_t blen, char *hexstr, size_t hexlen);
extern CK_RV pkcs11_mech2keytype(CK_MECHANISM_TYPE mech_type,
CK_KEY_TYPE *ktype);
+extern CK_RV pkcs11_mech2keygen(CK_MECHANISM_TYPE mech_type,
+ CK_MECHANISM_TYPE *gen_mech);
extern char *pkcs11_strerror(CK_RV rv);
extern int
@@ -141,6 +143,7 @@ extern int pkcs11_get_pass(char *token_name, char **pdata, size_t *psize,
size_t min_psize, boolean_t with_confirmation);
extern int pkcs11_random_data(void *dbuf, size_t dlen);
+extern int pkcs11_nzero_random_data(void *dbuf, size_t dlen);
extern int pkcs11_read_data(char *filename, void **dbuf, size_t *dlen);
#ifdef __cplusplus
diff --git a/usr/src/lib/libcryptoutil/common/mapfile-vers b/usr/src/lib/libcryptoutil/common/mapfile-vers
index b5e9fe2019..0e10ac1772 100644
--- a/usr/src/lib/libcryptoutil/common/mapfile-vers
+++ b/usr/src/lib/libcryptoutil/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -41,7 +41,9 @@ SUNWprivate {
pkcs11_default_token;
pkcs11_get_pass;
pkcs11_mech2keytype;
+ pkcs11_mech2keygen;
pkcs11_mech2str;
+ pkcs11_nzero_random_data;
pkcs11_random_data;
pkcs11_read_data;
pkcs11_str2mech;
diff --git a/usr/src/lib/libcryptoutil/common/mechkeygen.c b/usr/src/lib/libcryptoutil/common/mechkeygen.c
new file mode 100644
index 0000000000..586b913510
--- /dev/null
+++ b/usr/src/lib/libcryptoutil/common/mechkeygen.c
@@ -0,0 +1,362 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <cryptoutil.h>
+
+/*
+ * Get the key generation mechanism for the given mechanism.
+ *
+ * All mechanisms in PKCS #11 v2.20 are listed here.
+ */
+CK_RV
+pkcs11_mech2keygen(CK_MECHANISM_TYPE mech_type, CK_MECHANISM_TYPE *gen_mech)
+{
+ switch (mech_type) {
+
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ case CKM_RSA_PKCS:
+ case CKM_RSA_9796:
+ case CKM_RSA_X_509:
+ case CKM_MD2_RSA_PKCS:
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS_PSS:
+ case CKM_SHA384_RSA_PKCS_PSS:
+ case CKM_SHA512_RSA_PKCS_PSS:
+ case CKM_RIPEMD128_RSA_PKCS:
+ case CKM_RIPEMD160_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
+ *gen_mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ break;
+
+ case CKM_RSA_X9_31_KEY_PAIR_GEN:
+ case CKM_RSA_X9_31:
+ case CKM_SHA1_RSA_X9_31:
+ *gen_mech = CKM_RSA_X9_31_KEY_PAIR_GEN;
+ break;
+
+ case CKM_RSA_PKCS_PSS:
+ case CKM_SHA1_RSA_PKCS_PSS:
+ *gen_mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ break;
+
+ case CKM_DH_PKCS_PARAMETER_GEN:
+ *gen_mech = CKM_DH_PKCS_PARAMETER_GEN;
+ break;
+
+ case CKM_DSA_KEY_PAIR_GEN:
+ case CKM_DSA:
+ case CKM_DSA_SHA1:
+ *gen_mech = CKM_DSA_KEY_PAIR_GEN;
+ break;
+
+ case CKM_DSA_PARAMETER_GEN:
+ *gen_mech = CKM_DSA_PARAMETER_GEN;
+ break;
+
+ case CKM_FORTEZZA_TIMESTAMP:
+ *gen_mech = CKM_DSA_KEY_PAIR_GEN;
+ break;
+
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ case CKM_DH_PKCS_DERIVE:
+ *gen_mech = CKM_DH_PKCS_KEY_PAIR_GEN;
+ break;
+
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA1:
+ case CKM_EC_KEY_PAIR_GEN:
+ case CKM_ECDH1_DERIVE:
+ case CKM_ECDH1_COFACTOR_DERIVE:
+ case CKM_ECMQV_DERIVE:
+ *gen_mech = CKM_EC_KEY_PAIR_GEN;
+ break;
+
+ case CKM_X9_42_DH_KEY_PAIR_GEN:
+ case CKM_X9_42_DH_DERIVE:
+ case CKM_X9_42_DH_HYBRID_DERIVE:
+ case CKM_X9_42_MQV_DERIVE:
+ *gen_mech = CKM_X9_42_DH_KEY_PAIR_GEN;
+ break;
+
+ case CKM_X9_42_DH_PARAMETER_GEN:
+ *gen_mech = CKM_X9_42_DH_PARAMETER_GEN;
+ break;
+
+ case CKM_KEA_KEY_PAIR_GEN:
+ case CKM_KEA_KEY_DERIVE:
+ *gen_mech = CKM_KEA_KEY_PAIR_GEN;
+ break;
+
+ case CKM_MD2:
+ case CKM_MD2_HMAC:
+ case CKM_MD2_HMAC_GENERAL:
+ case CKM_MD5:
+ case CKM_MD5_HMAC:
+ case CKM_MD5_HMAC_GENERAL:
+ case CKM_SHA_1:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA_1_HMAC_GENERAL:
+ case CKM_SHA256:
+ case CKM_SHA256_HMAC:
+ case CKM_SHA256_HMAC_GENERAL:
+ case CKM_SHA384:
+ case CKM_SHA384_HMAC:
+ case CKM_SHA384_HMAC_GENERAL:
+ case CKM_SHA512:
+ case CKM_SHA512_HMAC:
+ case CKM_SHA512_HMAC_GENERAL:
+ case CKM_GENERIC_SECRET_KEY_GEN:
+ case CKM_FASTHASH:
+ case CKM_PKCS5_PBKD2:
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+ *gen_mech = CKM_GENERIC_SECRET_KEY_GEN;
+ break;
+
+ case CKM_SSL3_MD5_MAC:
+ case CKM_SSL3_SHA1_MAC:
+ case CKM_SSL3_PRE_MASTER_KEY_GEN:
+ case CKM_SSL3_MASTER_KEY_DERIVE:
+ case CKM_SSL3_KEY_AND_MAC_DERIVE:
+ case CKM_SSL3_MASTER_KEY_DERIVE_DH:
+ *gen_mech = CKM_SSL3_PRE_MASTER_KEY_GEN;
+ break;
+
+ case CKM_TLS_PRE_MASTER_KEY_GEN:
+ case CKM_TLS_MASTER_KEY_DERIVE:
+ case CKM_TLS_KEY_AND_MAC_DERIVE:
+ case CKM_TLS_MASTER_KEY_DERIVE_DH:
+ case CKM_TLS_PRF:
+ *gen_mech = CKM_TLS_PRE_MASTER_KEY_GEN;
+ break;
+
+ case CKM_WTLS_PRE_MASTER_KEY_GEN:
+ case CKM_WTLS_MASTER_KEY_DERIVE:
+ case CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC:
+ case CKM_WTLS_PRF:
+ case CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE:
+ case CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE:
+ *gen_mech = CKM_WTLS_PRE_MASTER_KEY_GEN;
+ break;
+
+ case CKM_CONCATENATE_BASE_AND_KEY:
+ case CKM_CONCATENATE_BASE_AND_DATA:
+ case CKM_CONCATENATE_DATA_AND_BASE:
+ case CKM_XOR_BASE_AND_DATA:
+ case CKM_EXTRACT_KEY_FROM_KEY:
+ case CKM_RIPEMD128:
+ case CKM_RIPEMD128_HMAC:
+ case CKM_RIPEMD128_HMAC_GENERAL:
+ case CKM_RIPEMD160:
+ case CKM_RIPEMD160_HMAC:
+ case CKM_RIPEMD160_HMAC_GENERAL:
+ case CKM_SHA1_KEY_DERIVATION:
+ case CKM_SHA256_KEY_DERIVATION:
+ case CKM_SHA384_KEY_DERIVATION:
+ case CKM_SHA512_KEY_DERIVATION:
+ case CKM_MD5_KEY_DERIVATION:
+ case CKM_MD2_KEY_DERIVATION:
+ /* not sure the following 2 should be CKK_DES or not */
+ case CKM_KEY_WRAP_LYNKS: /* wrap/unwrap secret key w/ DES key */
+ case CKM_KEY_WRAP_SET_OAEP: /* wrap/unwarp DES key w/ RSA key */
+ *gen_mech = CKM_GENERIC_SECRET_KEY_GEN;
+ break;
+
+ case CKM_RC2_KEY_GEN:
+ case CKM_RC2_ECB:
+ case CKM_RC2_CBC:
+ case CKM_RC2_MAC:
+ case CKM_RC2_MAC_GENERAL:
+ case CKM_RC2_CBC_PAD:
+ case CKM_PBE_SHA1_RC2_128_CBC:
+ case CKM_PBE_SHA1_RC2_40_CBC:
+ *gen_mech = CKM_RC2_KEY_GEN;
+ break;
+
+ case CKM_RC4_KEY_GEN:
+ case CKM_RC4:
+ case CKM_PBE_SHA1_RC4_128:
+ case CKM_PBE_SHA1_RC4_40:
+ *gen_mech = CKM_RC4_KEY_GEN;
+ break;
+
+ case CKM_DES_KEY_GEN:
+ case CKM_DES_ECB:
+ case CKM_DES_CBC:
+ case CKM_DES_MAC:
+ case CKM_DES_MAC_GENERAL:
+ case CKM_DES_CBC_PAD:
+ case CKM_PBE_MD2_DES_CBC:
+ case CKM_PBE_MD5_DES_CBC:
+ case CKM_DES_OFB64:
+ case CKM_DES_OFB8:
+ case CKM_DES_CFB64:
+ case CKM_DES_CFB8:
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ case CKM_DES_CBC_ENCRYPT_DATA:
+ *gen_mech = CKM_DES_KEY_GEN;
+ break;
+
+ case CKM_DES2_KEY_GEN:
+ case CKM_PBE_SHA1_DES2_EDE_CBC:
+ *gen_mech = CKM_DES2_KEY_GEN;
+ break;
+
+ case CKM_DES3_KEY_GEN:
+ case CKM_DES3_ECB:
+ case CKM_DES3_CBC:
+ case CKM_DES3_MAC:
+ case CKM_DES3_MAC_GENERAL:
+ case CKM_DES3_CBC_PAD:
+ case CKM_PBE_SHA1_DES3_EDE_CBC:
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ *gen_mech = CKM_DES3_KEY_GEN;
+ break;
+
+ case CKM_CAST_KEY_GEN:
+ case CKM_CAST_ECB:
+ case CKM_CAST_CBC:
+ case CKM_CAST_MAC:
+ case CKM_CAST_MAC_GENERAL:
+ case CKM_CAST_CBC_PAD:
+ case CKM_PBE_MD5_CAST_CBC:
+ *gen_mech = CKM_CAST_KEY_GEN;
+ break;
+
+ case CKM_CAST3_KEY_GEN:
+ case CKM_CAST3_ECB:
+ case CKM_CAST3_CBC:
+ case CKM_CAST3_MAC:
+ case CKM_CAST3_MAC_GENERAL:
+ case CKM_CAST3_CBC_PAD:
+ case CKM_PBE_MD5_CAST3_CBC:
+ *gen_mech = CKM_CAST3_KEY_GEN;
+ break;
+
+ case CKM_CAST128_KEY_GEN:
+ case CKM_CAST128_ECB:
+ case CKM_CAST128_CBC:
+ case CKM_CAST128_MAC:
+ case CKM_CAST128_MAC_GENERAL:
+ case CKM_CAST128_CBC_PAD:
+ case CKM_PBE_MD5_CAST128_CBC:
+ case CKM_PBE_SHA1_CAST128_CBC:
+ *gen_mech = CKM_CAST128_KEY_GEN;
+ break;
+
+ case CKM_RC5_KEY_GEN:
+ case CKM_RC5_ECB:
+ case CKM_RC5_CBC:
+ case CKM_RC5_MAC:
+ case CKM_RC5_MAC_GENERAL:
+ case CKM_RC5_CBC_PAD:
+ *gen_mech = CKM_RC5_KEY_GEN;
+ break;
+
+ case CKM_IDEA_KEY_GEN:
+ case CKM_IDEA_ECB:
+ case CKM_IDEA_CBC:
+ case CKM_IDEA_MAC:
+ case CKM_IDEA_MAC_GENERAL:
+ case CKM_IDEA_CBC_PAD:
+ *gen_mech = CKM_IDEA_KEY_GEN;
+ break;
+
+ case CKM_SKIPJACK_KEY_GEN:
+ case CKM_SKIPJACK_ECB64:
+ case CKM_SKIPJACK_CBC64:
+ case CKM_SKIPJACK_OFB64:
+ case CKM_SKIPJACK_CFB64:
+ case CKM_SKIPJACK_CFB32:
+ case CKM_SKIPJACK_CFB16:
+ case CKM_SKIPJACK_CFB8:
+ case CKM_SKIPJACK_WRAP:
+ case CKM_SKIPJACK_PRIVATE_WRAP:
+ case CKM_SKIPJACK_RELAYX:
+ *gen_mech = CKM_SKIPJACK_KEY_GEN;
+ break;
+
+ case CKM_BATON_KEY_GEN:
+ case CKM_BATON_ECB128:
+ case CKM_BATON_ECB96:
+ case CKM_BATON_CBC128:
+ case CKM_BATON_COUNTER:
+ case CKM_BATON_SHUFFLE:
+ case CKM_BATON_WRAP:
+ *gen_mech = CKM_BATON_KEY_GEN;
+ break;
+
+ case CKM_JUNIPER_KEY_GEN:
+ case CKM_JUNIPER_ECB128:
+ case CKM_JUNIPER_CBC128:
+ case CKM_JUNIPER_COUNTER:
+ case CKM_JUNIPER_SHUFFLE:
+ case CKM_JUNIPER_WRAP:
+ *gen_mech = CKM_JUNIPER_KEY_GEN;
+ break;
+
+ case CKM_CDMF_KEY_GEN:
+ case CKM_CDMF_ECB:
+ case CKM_CDMF_CBC:
+ case CKM_CDMF_MAC:
+ case CKM_CDMF_MAC_GENERAL:
+ case CKM_CDMF_CBC_PAD:
+ *gen_mech = CKM_CDMF_KEY_GEN;
+ break;
+
+ case CKM_AES_KEY_GEN:
+ case CKM_AES_ECB:
+ case CKM_AES_CBC:
+ case CKM_AES_MAC:
+ case CKM_AES_MAC_GENERAL:
+ case CKM_AES_CBC_PAD:
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ *gen_mech = CKM_AES_KEY_GEN;
+ break;
+
+ case CKM_BLOWFISH_KEY_GEN:
+ case CKM_BLOWFISH_CBC:
+ *gen_mech = CKM_BLOWFISH_KEY_GEN;
+ break;
+
+ case CKM_TWOFISH_KEY_GEN:
+ case CKM_TWOFISH_CBC:
+ *gen_mech = CKM_TWOFISH_KEY_GEN;
+ break;
+
+ default:
+ return (CKR_MECHANISM_INVALID);
+ break;
+ }
+
+ return (CKR_OK);
+}
diff --git a/usr/src/lib/libcryptoutil/common/random.c b/usr/src/lib/libcryptoutil/common/random.c
index ea3e83dedd..6d91dbfea4 100644
--- a/usr/src/lib/libcryptoutil/common/random.c
+++ b/usr/src/lib/libcryptoutil/common/random.c
@@ -19,19 +19,133 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <locale.h>
#include <cryptoutil.h>
-#define RANDOM_DEVICE "/dev/urandom" /* random device name */
+#ifdef _REENTRANT
+
+#include <pthread.h>
+
+static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define RAND_LOCK(x) (void) pthread_mutex_lock(x)
+#define RAND_UNLOCK(x) (void) pthread_mutex_unlock(x)
+
+#else
+
+#define RAND_LOCK(x)
+#define RAND_UNLOCK(x)
+
+#endif
+
+#define RANDOM_DEVICE "/dev/random" /* random device name */
+#define URANDOM_DEVICE "/dev/urandom" /* urandom device name */
+
+static int random_fd = -1;
+static int urandom_fd = -1;
+
+/*
+ * Equivalent of open(2) insulated from EINTR.
+ * Also sets close-on-exec.
+ */
+static int
+OPEN(const char *path, int oflag)
+{
+ int fd;
+
+ do {
+ if ((fd = open(path, oflag)) >= 0) {
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+ break;
+ }
+ /* errno definitely set by failed open() */
+ } while (errno == EINTR);
+ return (fd);
+}
+
+/*
+ * Equivalent of read(2) insulated from EINTR.
+ */
+static ssize_t
+READ(int fd, void *dbuf, size_t dlen)
+{
+ char *marker = dbuf;
+ size_t left = dlen;
+ ssize_t nread = 0, err;
+
+ for (err = 0; left > 0 && nread != -1; marker += nread, left -= nread) {
+ if ((nread = read(fd, marker, left)) < 0) {
+ if (errno == EINTR) { /* keep trying */
+ nread = 0;
+ continue;
+ }
+ err = nread; /* hard error */
+ break;
+ }
+ }
+ return (err != 0 ? err : dlen - left);
+}
+
+/*
+ * Opens the random number generator devices if not already open.
+ * Always returns the opened fd of the device, or error.
+ */
+int
+pkcs11_open_random(void)
+{
+ RAND_LOCK(&random_mutex);
+ if (random_fd < 0)
+ random_fd = OPEN(RANDOM_DEVICE, O_RDONLY);
+ RAND_UNLOCK(&random_mutex);
+ return (random_fd);
+}
+
+int
+pkcs11_open_urandom(void)
+{
+ RAND_LOCK(&urandom_mutex);
+ if (urandom_fd < 0)
+ urandom_fd = OPEN(URANDOM_DEVICE, O_RDONLY);
+ RAND_UNLOCK(&urandom_mutex);
+ return (urandom_fd);
+}
+
+/*
+ * Close the random number generator devices if already open.
+ */
+void
+pkcs11_close_random(void)
+{
+ if (random_fd < 0)
+ return;
+ RAND_LOCK(&random_mutex);
+ (void) close(random_fd);
+ random_fd = -1;
+ RAND_UNLOCK(&random_mutex);
+}
+
+void
+pkcs11_close_urandom(void)
+{
+ if (urandom_fd < 0)
+ return;
+ RAND_LOCK(&urandom_mutex);
+ (void) close(urandom_fd);
+ urandom_fd = -1;
+ RAND_UNLOCK(&urandom_mutex);
+}
/*
* Put the requested amount of random data into a preallocated buffer.
@@ -40,18 +154,47 @@
int
pkcs11_random_data(void *dbuf, size_t dlen)
{
- int fd;
-
if (dbuf == NULL || dlen == 0)
return (0);
/* Read random data directly from /dev/urandom */
- if ((fd = open(RANDOM_DEVICE, O_RDONLY)) != -1) {
- if (read(fd, dbuf, dlen) == dlen) {
- (void) close(fd);
- return (0);
+ if (pkcs11_open_urandom() < 0)
+ return (-1);
+
+ if (READ(urandom_fd, dbuf, dlen) == dlen)
+ return (0);
+ return (-1);
+}
+
+/*
+ * Same as pkcs11_random_data but ensures non zero data.
+ */
+int
+pkcs11_nzero_random_data(void *dbuf, size_t dlen)
+{
+ char extrarand[32];
+ size_t bytesleft = 0;
+ size_t i = 0;
+
+ /* Start with some random data */
+ if (pkcs11_random_data(dbuf, dlen) < 0)
+ return (-1);
+
+ /* Walk through data replacing any 0 bytes with more random data */
+ while (i < dlen) {
+ if (((char *)dbuf)[i] != 0) {
+ i++;
+ continue;
}
- (void) close(fd);
+
+ if (bytesleft == 0) {
+ bytesleft = sizeof (extrarand);
+ if (pkcs11_random_data(extrarand, bytesleft) < 0)
+ return (-1);
+ }
+ bytesleft--;
+
+ ((char *)dbuf)[i] = extrarand[bytesleft];
}
- return (-1);
+ return (0);
}