summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorkrishna <none@none>2006-11-11 21:39:34 -0800
committerkrishna <none@none>2006-11-11 21:39:34 -0800
commitf317a3a3712d9b82387b437ac621db3733d8c804 (patch)
treee200b5e95a7ef6ff466317efee22cc1f0b2d6a66 /usr/src
parentc92ff65068cd791405fb72f945470ff128896dfb (diff)
downloadillumos-joyent-f317a3a3712d9b82387b437ac621db3733d8c804.tar.gz
6488985 kcf_submit_request() should handle the EMPTYQ case for a hardware provider
6478655 kcf should not log complaints as frequently as it does 6470608 /dev/urandom should provide data blocks larger then 1040 bytes 6478016 crypto_mechanism32_t should be available from sys/crypto/spi.h
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/crypto/api/kcf_random.c37
-rw-r--r--usr/src/uts/common/crypto/core/kcf_sched.c54
-rw-r--r--usr/src/uts/common/crypto/io/dca_dsa.c4
-rw-r--r--usr/src/uts/common/crypto/io/dca_rsa.c4
-rw-r--r--usr/src/uts/common/io/random.c2
-rw-r--r--usr/src/uts/common/sys/crypto/common.h40
-rw-r--r--usr/src/uts/common/sys/crypto/ioctl.h45
7 files changed, 105 insertions, 81 deletions
diff --git a/usr/src/uts/common/crypto/api/kcf_random.c b/usr/src/uts/common/crypto/api/kcf_random.c
index ee133d2702..2ff8a80ac7 100644
--- a/usr/src/uts/common/crypto/api/kcf_random.c
+++ b/usr/src/uts/common/crypto/api/kcf_random.c
@@ -123,6 +123,8 @@ static struct pollhead rnd_pollhead;
static timeout_id_t kcf_rndtimeout_id;
static crypto_mech_type_t rngmech_type = CRYPTO_MECH_INVALID;
rnd_stats_t rnd_stats;
+static boolean_t rng_prov_found = B_TRUE;
+static boolean_t rng_ok_to_log = B_TRUE;
static void rndc_addbytes(uint8_t *, size_t);
static void rndc_getbytes(uint8_t *ptr, size_t len);
@@ -175,9 +177,18 @@ kcf_rngprov_check(void)
if ((pd = kcf_get_mech_provider(rngmech_type, NULL, &rv,
NULL, CRYPTO_FG_RANDOM, B_FALSE, 0)) != NULL) {
KCF_PROV_REFRELE(pd);
+ /*
+ * We logged a warning once about no provider being available
+ * and now a provider became available. So, set the flag so
+ * that we can log again if the problem recurs.
+ */
+ rng_ok_to_log = B_TRUE;
+ rng_prov_found = B_TRUE;
return (B_TRUE);
- } else
+ } else {
+ rng_prov_found = B_FALSE;
return (B_FALSE);
+ }
}
/*
@@ -276,7 +287,12 @@ try_next:
kcf_free_triedlist(list);
if (prov_cnt == 0) { /* no provider could be found. */
+ rng_prov_found = B_FALSE;
return (-1);
+ } else {
+ rng_prov_found = B_TRUE;
+ /* See comments in kcf_rngprov_check() */
+ rng_ok_to_log = B_TRUE;
}
return (total_bytes);
@@ -416,7 +432,12 @@ try_next:
}
if (prov_cnt == 0) { /* no provider could be found. */
+ rng_prov_found = B_FALSE;
return (-1);
+ } else {
+ rng_prov_found = B_TRUE;
+ /* See comments in kcf_rngprov_check() */
+ rng_ok_to_log = B_TRUE;
}
return (total_bytes);
@@ -429,10 +450,7 @@ rngprov_task(void *arg)
uchar_t tbuf[MAXEXTRACTBYTES];
ASSERT(len <= MAXEXTRACTBYTES);
- if (rngprov_getbytes(tbuf, len, B_FALSE, B_TRUE) == -1) {
- cmn_err(CE_WARN, "No randomness provider enabled for "
- "/dev/random. Use cryptoadm(1M) to enable a provider.");
- }
+ (void) rngprov_getbytes(tbuf, len, B_FALSE, B_TRUE);
}
/*
@@ -846,6 +864,12 @@ rnd_handler(void *arg)
{
int len = 0;
+ if (!rng_prov_found && rng_ok_to_log) {
+ cmn_err(CE_WARN, "No randomness provider enabled for "
+ "/dev/random. Use cryptoadm(1M) to enable a provider.");
+ rng_ok_to_log = B_FALSE;
+ }
+
if (num_waiters > 0)
len = MAXEXTRACTBYTES;
else if (rnbyte_cnt < RNDPOOLSIZE)
@@ -854,9 +878,6 @@ rnd_handler(void *arg)
if (len > 0) {
(void) taskq_dispatch(system_taskq, rngprov_task,
(void *)(uintptr_t)len, TQ_NOSLEEP);
- } else if (!kcf_rngprov_check()) {
- cmn_err(CE_WARN, "No randomness provider enabled for "
- "/dev/random. Use cryptoadm(1M) to enable a provider.");
}
mutex_enter(&rndpool_lock);
diff --git a/usr/src/uts/common/crypto/core/kcf_sched.c b/usr/src/uts/common/crypto/core/kcf_sched.c
index 651327f252..aaf516d7a6 100644
--- a/usr/src/uts/common/crypto/core/kcf_sched.c
+++ b/usr/src/uts/common/crypto/core/kcf_sched.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -578,6 +577,7 @@ kcf_resubmit_request(kcf_areq_node_t *areq)
return (error);
}
+#define EMPTY_TASKQ(tq) ((tq)->tq_task.tqent_next == &(tq)->tq_task)
/*
* Routine called by both ioctl and k-api. The consumer should
@@ -613,11 +613,6 @@ kcf_submit_request(kcf_provider_desc_t *pd, crypto_ctx_t *ctx,
break;
case CRYPTO_HW_PROVIDER:
- /*
- * Bug# 4715197
- * TO DO - Add the logic for EMPTYQ() case.
- * For now, we always queue.
- */
sreq = kmem_cache_alloc(kcf_sreq_cache, KM_SLEEP);
sreq->sn_state = REQ_ALLOCATED;
sreq->sn_rv = CRYPTO_FAILED;
@@ -635,22 +630,33 @@ kcf_submit_request(kcf_provider_desc_t *pd, crypto_ctx_t *ctx,
ASSERT(taskq != NULL);
/*
- * We can not tell from taskq_dispatch() return
- * value if we exceeded maxalloc. Hence the check
- * here. Since we are allowed to wait in the
- * synchronous case, we wait for the taskq to
- * become empty.
+ * Call the SPI directly if the taskq is empty and the
+ * provider is not busy, else dispatch to the taskq.
+ * Calling directly is fine as this is the synchronous
+ * case. This is unlike the asynchronous case where we
+ * must always dispatch to the taskq.
*/
- if (taskq->tq_nalloc >= crypto_taskq_maxalloc) {
- taskq_wait(taskq);
- }
- if (taskq_dispatch(taskq,
- process_req_hwp, sreq, TQ_SLEEP) ==
- (taskqid_t)0) {
- error = CRYPTO_HOST_MEMORY;
- KCF_PROV_REFRELE(sreq->sn_provider);
- kmem_cache_free(kcf_sreq_cache, sreq);
- goto done;
+ if (EMPTY_TASKQ(taskq) &&
+ pd->pd_state == KCF_PROV_READY) {
+ process_req_hwp(sreq);
+ } else {
+ /*
+ * We can not tell from taskq_dispatch() return
+ * value if we exceeded maxalloc. Hence the
+ * check here. Since we are allowed to wait in
+ * the synchronous case, we wait for the taskq
+ * to become empty.
+ */
+ if (taskq->tq_nalloc >= crypto_taskq_maxalloc) {
+ taskq_wait(taskq);
+ }
+ if (taskq_dispatch(taskq, process_req_hwp,
+ sreq, TQ_SLEEP) == (taskqid_t)0) {
+ error = CRYPTO_HOST_MEMORY;
+ KCF_PROV_REFRELE(sreq->sn_provider);
+ kmem_cache_free(kcf_sreq_cache, sreq);
+ goto done;
+ }
}
/*
diff --git a/usr/src/uts/common/crypto/io/dca_dsa.c b/usr/src/uts/common/crypto/io/dca_dsa.c
index 8e16346940..fae4bea536 100644
--- a/usr/src/uts/common/crypto/io/dca_dsa.c
+++ b/usr/src/uts/common/crypto/io/dca_dsa.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,9 +34,7 @@
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/kmem.h>
-#include <sys/crypto/common.h>
#include <sys/crypto/spi.h>
-#include <sys/crypto/ioctl.h>
#include <sys/crypto/dca.h>
/*
diff --git a/usr/src/uts/common/crypto/io/dca_rsa.c b/usr/src/uts/common/crypto/io/dca_rsa.c
index 71ec60d82c..bcfe1ebdea 100644
--- a/usr/src/uts/common/crypto/io/dca_rsa.c
+++ b/usr/src/uts/common/crypto/io/dca_rsa.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,9 +35,7 @@
#include <sys/sunddi.h>
#include <sys/kmem.h>
#include <sys/note.h>
-#include <sys/crypto/common.h>
#include <sys/crypto/spi.h>
-#include <sys/crypto/ioctl.h>
#include <sys/crypto/dca.h>
diff --git a/usr/src/uts/common/io/random.c b/usr/src/uts/common/io/random.c
index 9d3a7d8b56..1455625587 100644
--- a/usr/src/uts/common/io/random.c
+++ b/usr/src/uts/common/io/random.c
@@ -259,7 +259,7 @@ rnd_read(dev_t dev, struct uio *uiop, cred_t *credp)
nbytes += len;
- if (nbytes >= MAXRETBYTES)
+ if (devno == DEVRANDOM && nbytes >= MAXRETBYTES)
break;
} else if ((error == EAGAIN) && (nbytes > 0)) {
diff --git a/usr/src/uts/common/sys/crypto/common.h b/usr/src/uts/common/sys/crypto/common.h
index b4016684d6..d597a6b567 100644
--- a/usr/src/uts/common/sys/crypto/common.h
+++ b/usr/src/uts/common/sys/crypto/common.h
@@ -56,6 +56,16 @@ typedef struct crypto_mechanism {
size_t cm_param_len; /* mech. parameter len */
} crypto_mechanism_t;
+#ifdef _SYSCALL32
+
+typedef struct crypto_mechanism32 {
+ crypto_mech_type_t cm_type; /* mechanism type */
+ caddr32_t cm_param; /* mech. parameter */
+ size32_t cm_param_len; /* mech. parameter len */
+} crypto_mechanism32_t;
+
+#endif /* _SYSCALL32 */
+
/*
* The measurement unit flag for a mechanism's minimum or maximum key size.
* The unit are mechanism dependant. It can be in bits or in bytes.
@@ -197,6 +207,36 @@ typedef struct crypto_key {
} cku_data; /* Crypto Key union */
} crypto_key_t;
+#ifdef _SYSCALL32
+
+typedef struct crypto_object_attribute32 {
+ uint64_t oa_type; /* attribute type */
+ caddr32_t oa_value; /* attribute value */
+ ssize32_t oa_value_len; /* length of attribute value */
+} crypto_object_attribute32_t;
+
+typedef struct crypto_key32 {
+ crypto_key_format_t ck_format; /* format identifier */
+ union {
+ /* for CRYPTO_KEY_RAW ck_format */
+ struct {
+ uint32_t cku_v_length; /* # of bytes in ck_data */
+ caddr32_t cku_v_data; /* ptr to key value */
+ } cku_key_value;
+
+ /* for CRYPTO_KEY_REFERENCE ck_format */
+ crypto_object_id_t cku_key_id; /* reference to object key */
+
+ /* for CRYPTO_KEY_ATTR_LIST ck_format */
+ struct {
+ uint32_t cku_a_count; /* number of attributes */
+ caddr32_t cku_a_oattr;
+ } cku_key_attrs;
+ } cku_data; /* Crypto Key union */
+} crypto_key32_t;
+
+#endif /* _SYSCALL32 */
+
#define ck_data cku_data.cku_key_value.cku_v_data
#define ck_length cku_data.cku_key_value.cku_v_length
#define ck_obj_id cku_data.cku_key_id
diff --git a/usr/src/uts/common/sys/crypto/ioctl.h b/usr/src/uts/common/sys/crypto/ioctl.h
index 1547a6c703..24389b3df3 100644
--- a/usr/src/uts/common/sys/crypto/ioctl.h
+++ b/usr/src/uts/common/sys/crypto/ioctl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -482,44 +481,6 @@ typedef struct crypto_decrypt_verify_update {
#ifdef _KERNEL
#ifdef _SYSCALL32
-/* crypto_mechanism_t is defined in <sys/crypto/common.h> */
-
-typedef struct crypto_mechanism32 {
- crypto_mech_type_t cm_type; /* mech. type */
- caddr32_t cm_param; /* mech. parameter */
- size32_t cm_param_len; /* mech. parameter len */
-} crypto_mechanism32_t;
-
-/* crypto_object_attribute_t is defined in <sys/crypto/common.h> */
-
-typedef struct crypto_object_attribute32 {
- uint64_t oa_type; /* attribute type */
- caddr32_t oa_value; /* attribute value */
- ssize32_t oa_value_len; /* length of attribute value */
-} crypto_object_attribute32_t;
-
-/* crypto_key_t is defined in <sys/crypto/common.h> */
-
-typedef struct crypto_key32 {
- crypto_key_format_t ck_format; /* format identifier */
- union {
- /* for CRYPTO_KEY_RAW ck_format */
- struct {
- uint32_t cku_v_length; /* # of bytes in ck_data */
- caddr32_t cku_v_data; /* ptr to key value */
- } cku_key_value;
-
- /* for CRYPTO_KEY_REFERENCE ck_format */
- crypto_object_id_t cku_key_id; /* reference to object key */
-
- /* for CRYPTO_KEY_ATTR_LIST ck_format */
- struct {
- uint32_t cku_a_count; /* number of attributes */
- caddr32_t cku_a_oattr;
- } cku_key_attrs;
- } cku_data; /* Crypto Key union */
-} crypto_key32_t;
-
typedef struct crypto_encrypt32 {
uint32_t ce_return_value;
crypto_session_id_t ce_session;