diff options
author | mcpowers <none@none> | 2006-05-01 16:17:15 -0700 |
---|---|---|
committer | mcpowers <none@none> | 2006-05-01 16:17:15 -0700 |
commit | 8047c9fb10f4d3f14385d535d6b23a5eb80c0c0f (patch) | |
tree | 192b7c0157fe031e0882c2cd25d196fd9ad70bc4 /usr | |
parent | b7b2cb069f0572c787a861df08054e686404c23e (diff) | |
download | illumos-joyent-8047c9fb10f4d3f14385d535d6b23a5eb80c0c0f.tar.gz |
PSARC 2006/214 Crypto Framework random number API/SPI update
6374503 C_SeedRandom is too slow causing poor performance with Apache/OpenSSL when using pkcs11
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/lib/pkcs11/libpkcs11/common/metaGeneral.c | 17 | ||||
-rw-r--r-- | usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.h | 9 | ||||
-rw-r--r-- | usr/src/lib/pkcs11/libpkcs11/common/metaRand.c | 42 | ||||
-rw-r--r-- | usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c | 13 | ||||
-rw-r--r-- | usr/src/lib/pkcs11/pkcs11_softtoken/common/softRand.c | 44 | ||||
-rw-r--r-- | usr/src/lib/pkcs11/pkcs11_softtoken/common/softRandom.h | 8 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/api/kcf_random.c | 36 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/core/kcf_callprov.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/io/crypto.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/io/dprov.c | 25 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/io/swrand.c | 92 | ||||
-rw-r--r-- | usr/src/uts/common/io/random.c | 26 | ||||
-rw-r--r-- | usr/src/uts/common/sys/crypto/impl.h | 12 | ||||
-rw-r--r-- | usr/src/uts/common/sys/crypto/ops_impl.h | 14 | ||||
-rw-r--r-- | usr/src/uts/common/sys/crypto/spi.h | 14 | ||||
-rw-r--r-- | usr/src/uts/common/sys/random.h | 9 |
16 files changed, 247 insertions, 122 deletions
diff --git a/usr/src/lib/pkcs11/libpkcs11/common/metaGeneral.c b/usr/src/lib/pkcs11/libpkcs11/common/metaGeneral.c index a9c60b1b1e..5f16e7727f 100644 --- a/usr/src/lib/pkcs11/libpkcs11/common/metaGeneral.c +++ b/usr/src/lib/pkcs11/libpkcs11/common/metaGeneral.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. */ @@ -110,7 +109,9 @@ struct CK_FUNCTION_LIST metaslot_functionList = { meta_WaitForSlotEvent }; -static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; + +int meta_urandom_seed_fd = -1; ses_to_be_freed_list_t ses_delay_freed; object_to_be_freed_list_t obj_delay_freed; @@ -163,7 +164,6 @@ meta_Initialize(CK_VOID_PTR pInitArgs) meta_slotManager_find_object_token(); - /* Initialize the object_to_be_freed list */ (void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL); obj_delay_freed.count = 0; @@ -200,6 +200,11 @@ meta_Finalize(CK_VOID_PTR pReserved) (void) pthread_mutex_lock(&initmutex); + if (meta_urandom_seed_fd > 0) { + (void) close(meta_urandom_seed_fd); + meta_urandom_seed_fd = -1; + } + meta_objectManager_finalize(); meta_sessionManager_finalize(); diff --git a/usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.h b/usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.h index 17757d574e..cf741e0a61 100644 --- a/usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.h +++ b/usr/src/lib/pkcs11/libpkcs11/common/metaGlobal.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -530,6 +529,8 @@ extern boolean_t metaslot_enabled; extern CK_SLOT_ID metaslot_keystore_slotid; extern boolean_t metaslot_auto_key_migrate; extern struct CK_FUNCTION_LIST metaslot_functionList; +extern int meta_urandom_seed_fd; +extern pthread_mutex_t initmutex; extern ses_to_be_freed_list_t ses_delay_freed; extern object_to_be_freed_list_t obj_delay_freed; diff --git a/usr/src/lib/pkcs11/libpkcs11/common/metaRand.c b/usr/src/lib/pkcs11/libpkcs11/common/metaRand.c index 53249240b5..ec3b9ad70d 100644 --- a/usr/src/lib/pkcs11/libpkcs11/common/metaRand.c +++ b/usr/src/lib/pkcs11/libpkcs11/common/metaRand.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. */ @@ -62,7 +61,6 @@ meta_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, { CK_RV rv; meta_session_t *session; - int fd; ssize_t n; if (pSeed == NULL || ulSeedLen == 0) @@ -74,25 +72,33 @@ meta_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, return (rv); REFRELEASE(session); - while ((fd = open(RANDOM_DEVICE, O_WRONLY)) < 0) { - if (errno != EINTR) - break; - } - if (fd == -1) { - if (errno == EACCES) - return (CKR_RANDOM_SEED_NOT_SUPPORTED); - else - return (CKR_DEVICE_ERROR); + if (meta_urandom_seed_fd < 0) { + (void) pthread_mutex_lock(&initmutex); + /* Check again holding the mutex */ + if (meta_urandom_seed_fd < 0) { + while ((meta_urandom_seed_fd = open( + RANDOM_DEVICE, O_WRONLY)) < 0) { + if (errno != EINTR) + break; + } + if (meta_urandom_seed_fd < 0) { + (void) pthread_mutex_unlock(&initmutex); + if (errno == EACCES) + return ( + CKR_RANDOM_SEED_NOT_SUPPORTED); + return (CKR_DEVICE_ERROR); + } + (void) fcntl(meta_urandom_seed_fd, F_SETFD, + FD_CLOEXEC); + } + (void) pthread_mutex_unlock(&initmutex); } - n = looping_write(fd, pSeed, ulSeedLen); + n = looping_write(meta_urandom_seed_fd, pSeed, ulSeedLen); if (n <= 0) { - (void) close(fd); return (CKR_DEVICE_ERROR); } - (void) close(fd); - return (CKR_OK); } diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c index 74ff7cd08f..6c5acf6875 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.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. */ @@ -123,6 +122,7 @@ soft_session_t *soft_session_list = NULL; int all_sessions_closing = 0; int soft_urandom_fd = -1; +int soft_urandom_seed_fd = -1; int soft_random_fd = -1; slot_t soft_slot; @@ -340,6 +340,11 @@ finalize_common(boolean_t force, CK_VOID_PTR pReserved) { soft_urandom_fd = -1; } + if (soft_urandom_seed_fd > 0) { + (void) close(soft_urandom_seed_fd); + soft_urandom_seed_fd = -1; + } + if (soft_random_fd > 0) { (void) close(soft_random_fd); soft_random_fd = -1; diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRand.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRand.c index 1b4d8ea0d3..8b74d88048 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRand.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRand.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. */ @@ -35,7 +34,6 @@ #include "softRandom.h" #include "softSession.h" - CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { @@ -43,7 +41,6 @@ C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) CK_RV rv; soft_session_t *session_p; boolean_t lock_held = B_FALSE; - int fd; long nwrite; if (!softtoken_initialized) @@ -60,25 +57,34 @@ C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) return (CKR_ARGUMENTS_BAD); } - while ((fd = open(DEV_URANDOM, O_WRONLY)) < 0) { - if (errno != EINTR) - break; - } - if (fd == -1) { - if (errno == EACCES) - return (CKR_RANDOM_SEED_NOT_SUPPORTED); - return (CKR_DEVICE_ERROR); + if (soft_urandom_seed_fd < 0) { + (void) pthread_mutex_lock(&soft_giant_mutex); + /* Check again holding the mutex */ + if (soft_urandom_seed_fd < 0) { + while ((soft_urandom_seed_fd = open(DEV_URANDOM, + O_WRONLY)) < 0) { + if (errno != EINTR) + break; + } + if (soft_urandom_seed_fd < 0) { + (void) pthread_mutex_unlock( + &soft_giant_mutex); + if (errno == EACCES) + return ( + CKR_RANDOM_SEED_NOT_SUPPORTED); + return (CKR_DEVICE_ERROR); + } + (void) fcntl(soft_urandom_seed_fd, F_SETFD, + FD_CLOEXEC); + } + (void) pthread_mutex_unlock(&soft_giant_mutex); } - (void) fcntl(fd, F_SETFD, FD_CLOEXEC); - nwrite = looping_write(fd, pSeed, ulSeedLen); + nwrite = looping_write(soft_urandom_seed_fd, pSeed, ulSeedLen); if (nwrite <= 0) { - (void) close(fd); return (CKR_DEVICE_ERROR); } - (void) close(fd); - return (CKR_OK); } diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRandom.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRandom.h index a0b25cb3e5..6f0f5ce440 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRandom.h +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softRandom.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. */ @@ -39,6 +38,7 @@ extern "C" { #include "softSession.h" extern int soft_urandom_fd; +extern int soft_urandom_seed_fd; extern int soft_random_fd; #define DEV_URANDOM "/dev/urandom" diff --git a/usr/src/uts/common/crypto/api/kcf_random.c b/usr/src/uts/common/crypto/api/kcf_random.c index 0271a7ad11..ee133d2702 100644 --- a/usr/src/uts/common/crypto/api/kcf_random.c +++ b/usr/src/uts/common/crypto/api/kcf_random.c @@ -19,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. */ @@ -185,15 +185,13 @@ kcf_rngprov_check(void) * its random number generator. */ static void -rngprov_seed(uint8_t *buf, int len) +rngprov_seed(uint8_t *buf, int len, uint_t entropy_est, uint32_t flags) { kcf_provider_desc_t *pd = NULL; - kcf_req_params_t params; if (kcf_get_sw_prov(rngmech_type, &pd, B_FALSE) == CRYPTO_SUCCESS) { - KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, - pd->pd_sid, buf, len); - (void) kcf_submit_request(pd, NULL, NULL, ¶ms, B_FALSE); + (void) KCF_PROV_SEED_RANDOM(pd, pd->pd_sid, buf, len, + entropy_est, flags, NULL); KCF_PROV_REFRELE(pd); } } @@ -249,7 +247,7 @@ rngprov_getbytes(uint8_t *ptr, size_t need, boolean_t from_user_api, } KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, - pd->pd_sid, ptr, need); + pd->pd_sid, ptr, need, 0, 0); rv = kcf_submit_request(pd, NULL, NULL, ¶ms, B_FALSE); ASSERT(rv != CRYPTO_QUEUED); @@ -346,7 +344,7 @@ rngprov_getbytes_nblk(uint8_t *ptr, size_t len, boolean_t from_user_api) req.cr_callback_arg = rndbuf; KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, - pd->pd_sid, rndbuf, MINEXTRACTBYTES); + pd->pd_sid, rndbuf, MINEXTRACTBYTES, 0, 0); break; case CRYPTO_SW_PROVIDER: @@ -357,7 +355,7 @@ rngprov_getbytes_nblk(uint8_t *ptr, size_t len, boolean_t from_user_api) */ KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, - pd->pd_sid, ptr, len); + pd->pd_sid, ptr, len, 0, 0); break; } @@ -999,14 +997,28 @@ rndc_getbytes(uint8_t *ptr, size_t len) * Mix the supplied bytes into the entropy pool of a kCF * RNG provider. */ -/* ARGSUSED */ int -random_add_entropy(uint8_t *ptr, size_t len, uint16_t entropy_est) +random_add_pseudo_entropy(uint8_t *ptr, size_t len, uint_t entropy_est) +{ + if (len < 1) + return (-1); + + rngprov_seed(ptr, len, entropy_est, 0); + + return (0); +} + +/* + * Mix the supplied bytes into the entropy pool of a kCF + * RNG provider. Mix immediately. + */ +int +random_add_entropy(uint8_t *ptr, size_t len, uint_t entropy_est) { if (len < 1) return (-1); - rngprov_seed(ptr, len); + rngprov_seed(ptr, len, entropy_est, CRYPTO_SEED_NOW); return (0); } diff --git a/usr/src/uts/common/crypto/core/kcf_callprov.c b/usr/src/uts/common/crypto/core/kcf_callprov.c index 2f51ae27fd..de2268dcc2 100644 --- a/usr/src/uts/common/crypto/core/kcf_callprov.c +++ b/usr/src/uts/common/crypto/core/kcf_callprov.c @@ -1270,7 +1270,8 @@ common_submit_request(kcf_provider_desc_t *pd, crypto_ctx_t *ctx, switch (optype) { case KCF_OP_RANDOM_SEED: err = KCF_PROV_SEED_RANDOM(pd, rops->rn_sid, - rops->rn_buf, rops->rn_buflen, rhndl); + rops->rn_buf, rops->rn_buflen, rops->rn_entropy_est, + rops->rn_flags, rhndl); break; case KCF_OP_RANDOM_GENERATE: diff --git a/usr/src/uts/common/crypto/io/crypto.c b/usr/src/uts/common/crypto/io/crypto.c index 491e318ca9..047c5f4b0e 100644 --- a/usr/src/uts/common/crypto/io/crypto.c +++ b/usr/src/uts/common/crypto/io/crypto.c @@ -4086,7 +4086,8 @@ seed_random(dev_t dev, caddr_t arg, int mode, int *rval) } KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED, - sp->sd_provider_session->ps_session, seed_buffer, seed_len); + sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0, + CRYPTO_SEED_NOW); rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); @@ -4176,7 +4177,7 @@ generate_random(dev_t dev, caddr_t arg, int mode, int *rval) } KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE, - sp->sd_provider_session->ps_session, buffer, len); + sp->sd_provider_session->ps_session, buffer, len, 0, 0); rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE); diff --git a/usr/src/uts/common/crypto/io/dprov.c b/usr/src/uts/common/crypto/io/dprov.c index 5bf0be0e90..7f36913563 100644 --- a/usr/src/uts/common/crypto/io/dprov.c +++ b/usr/src/uts/common/crypto/io/dprov.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. */ @@ -777,7 +776,7 @@ static crypto_dual_cipher_mac_ops_t dprov_cipher_mac_ops = { }; static int dprov_seed_random(crypto_provider_handle_t, crypto_session_id_t, - uchar_t *, size_t, crypto_req_handle_t); + uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); static int dprov_generate_random(crypto_provider_handle_t, crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); @@ -1272,6 +1271,8 @@ typedef struct dprov_random_req { uchar_t *rr_buf; size_t rr_len; crypto_session_id_t rr_session_id; + uint_t rr_entropy_est; + uint32_t rr_flags; } dprov_random_req_t; /* for DPROV_REQ_SESSION requests */ @@ -1396,7 +1397,8 @@ static int dprov_cipher_mac_submit_req(dprov_req_type_t, dprov_state_t *, crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *, crypto_data_t *, crypto_data_t *, int); static int dprov_random_submit_req(dprov_req_type_t, dprov_state_t *, - crypto_req_handle_t, uchar_t *, size_t, crypto_session_id_t); + crypto_req_handle_t, uchar_t *, size_t, crypto_session_id_t, uint_t, + uint32_t); static int dprov_session_submit_req(dprov_req_type_t, dprov_state_t *, crypto_req_handle_t, crypto_session_id_t *, crypto_session_id_t, crypto_user_type_t, char *, size_t); @@ -3384,7 +3386,8 @@ dprov_mac_verify_decrypt_atomic(crypto_provider_handle_t provider, static int dprov_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, - uchar_t *buf, size_t len, crypto_req_handle_t req) + uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags, + crypto_req_handle_t req) { int error = CRYPTO_FAILED; dprov_state_t *softc = (dprov_state_t *)provider; @@ -3396,7 +3399,7 @@ dprov_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, instance)); error = dprov_random_submit_req(DPROV_REQ_RANDOM_SEED, softc, - req, buf, len, sid); + req, buf, len, sid, entropy_est, flags); DPROV_DEBUG(D_RANDOM, ("(%d) dprov_seed_random: done err = 0x0%x\n", instance, error)); @@ -3418,7 +3421,7 @@ dprov_generate_random(crypto_provider_handle_t provider, instance)); error = dprov_random_submit_req(DPROV_REQ_RANDOM_GENERATE, softc, - req, buf, len, sid); + req, buf, len, sid, 0, 0); DPROV_DEBUG(D_RANDOM, ("(%d) dprov_generate_random: done " "err = 0x0%x\n", instance, error)); @@ -4548,7 +4551,7 @@ dprov_cipher_submit_req(dprov_req_type_t req_type, static int dprov_random_submit_req(dprov_req_type_t req_type, dprov_state_t *softc, crypto_req_handle_t req, uchar_t *buf, size_t len, - crypto_session_id_t sid) + crypto_session_id_t sid, uint_t entropy_est, uint32_t flags) { dprov_req_t *taskq_req; @@ -4559,6 +4562,8 @@ dprov_random_submit_req(dprov_req_type_t req_type, taskq_req->dr_random_req.rr_buf = buf; taskq_req->dr_random_req.rr_len = len; taskq_req->dr_random_req.rr_session_id = sid; + taskq_req->dr_random_req.rr_entropy_est = entropy_est; + taskq_req->dr_random_req.rr_flags = flags; return (dprov_taskq_dispatch(softc, taskq_req, (task_func_t *)dprov_random_task, KM_NOSLEEP)); diff --git a/usr/src/uts/common/crypto/io/swrand.c b/usr/src/uts/common/crypto/io/swrand.c index fc5543167d..63f30aa628 100644 --- a/usr/src/uts/common/crypto/io/swrand.c +++ b/usr/src/uts/common/crypto/io/swrand.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 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -83,12 +82,17 @@ typedef struct physmem_entsrc_s { } physmem_entsrc_t; static uint32_t srndpool[RNDPOOLSIZE/4]; /* Pool of random bits */ +static uint32_t buffer[RNDPOOLSIZE/4]; /* entropy mixed in later */ +static int buffer_bytes; /* bytes written to buffer */ static uint32_t entropy_bits; /* pool's current amount of entropy */ static kmutex_t srndpool_lock; /* protects r/w accesses to the pool, */ /* and the global variables */ +static kmutex_t buffer_lock; /* protects r/w accesses to buffer */ static kcondvar_t srndpool_read_cv; /* serializes poll/read syscalls */ static int pindex; /* Global index for adding/extracting */ /* from the pool */ +static int bstart, bindex; /* Global vars for adding/extracting */ + /* from the buffer */ static uint8_t leftover[HASHSIZE]; /* leftover output */ static int leftover_bytes; /* leftover length */ @@ -111,6 +115,7 @@ static void swrand_init(); static void swrand_schedule_timeout(void); static int swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t); static void swrand_add_entropy(uint8_t *ptr, size_t len, uint16_t entropy_est); +static void swrand_add_entropy_later(uint8_t *ptr, size_t len); /* Dynamic Reconfiguration related declarations */ kphysm_setup_vector_t rnd_dr_callback_vec = { @@ -146,7 +151,7 @@ static crypto_control_ops_t swrand_control_ops = { }; static int swrand_seed_random(crypto_provider_handle_t, crypto_session_id_t, - uchar_t *, size_t, crypto_req_handle_t); + uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); static int swrand_generate_random(crypto_provider_handle_t, crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); @@ -201,11 +206,15 @@ _init(void) } mutex_init(&srndpool_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&buffer_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&srndpool_read_cv, NULL, CV_DEFAULT, NULL); entropy_bits = 0; pindex = 0; + bindex = 0; + bstart = 0; snum_waiters = 0; leftover_bytes = 0; + buffer_bytes = 0; /* * Initialize the pool using @@ -224,6 +233,7 @@ _init(void) if (physmem_ent_init(&entsrc) != 0) { mutex_destroy(&srndpool_lock); + mutex_destroy(&buffer_lock); cv_destroy(&srndpool_read_cv); (void) crypto_unregister_provider(swrand_prov_handle); return (ENOMEM); @@ -231,6 +241,7 @@ _init(void) if ((ret = mod_install(&modlinkage)) != 0) { mutex_destroy(&srndpool_lock); + mutex_destroy(&buffer_lock); cv_destroy(&srndpool_read_cv); physmem_ent_fini(&entsrc); (void) crypto_unregister_provider(swrand_prov_handle); @@ -267,10 +278,14 @@ swrand_provider_status(crypto_provider_handle_t provider, uint_t *status) /* ARGSUSED */ static int swrand_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, - uchar_t *buf, size_t len, crypto_req_handle_t req) + uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags, + crypto_req_handle_t req) { /* The entropy estimate is always 0 in this path */ - swrand_add_entropy(buf, len, 0); + if (flags & CRYPTO_SEED_NOW) + swrand_add_entropy(buf, len, 0); + else + swrand_add_entropy_later(buf, len); return (CRYPTO_SUCCESS); } @@ -386,6 +401,15 @@ swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t nonblock) return (0); } +#define SWRAND_ADD_BYTES(ptr, len, i, pool) \ + ASSERT((ptr) != NULL && (len) > 0); \ + BUMP_SWRAND_STATS(ss_bytesIn, (len)); \ + while ((len)--) { \ + (pool)[(i)++] ^= *(ptr); \ + (ptr)++; \ + (i) &= (RNDPOOLSIZE - 1); \ + } + /* Write some more user-provided entropy to the pool */ static void swrand_add_bytes(uint8_t *ptr, size_t len) @@ -393,16 +417,25 @@ swrand_add_bytes(uint8_t *ptr, size_t len) uint8_t *pool = (uint8_t *)srndpool; ASSERT(MUTEX_HELD(&srndpool_lock)); - ASSERT(ptr != NULL && len > 0); + SWRAND_ADD_BYTES(ptr, len, pindex, pool); +} - BUMP_SWRAND_STATS(ss_bytesIn, len); - while (len--) { - pool[pindex++] ^= *ptr; - ptr++; - pindex &= (RNDPOOLSIZE - 1); - } +/* + * Add bytes to buffer. Adding the buffer to the random pool + * is deferred until the random pool is mixed. + */ +static void +swrand_add_bytes_later(uint8_t *ptr, size_t len) +{ + uint8_t *pool = (uint8_t *)buffer; + + ASSERT(MUTEX_HELD(&buffer_lock)); + SWRAND_ADD_BYTES(ptr, len, bindex, pool); + buffer_bytes += len; } +#undef SWRAND_ADD_BYTES + /* Mix the pool */ static void swrand_mix_pool(uint16_t entropy_est) @@ -411,9 +444,32 @@ swrand_mix_pool(uint16_t entropy_est) HASH_CTX hashctx; uint8_t digest[HASHSIZE]; uint8_t *pool = (uint8_t *)srndpool; + uint8_t *bp = (uint8_t *)buffer; ASSERT(MUTEX_HELD(&srndpool_lock)); + /* add deferred bytes */ + mutex_enter(&buffer_lock); + if (buffer_bytes > 0) { + if (buffer_bytes >= RNDPOOLSIZE) { + for (i = 0; i < RNDPOOLSIZE/4; i++) { + srndpool[i] ^= buffer[i]; + buffer[i] = 0; + } + bstart = bindex = 0; + } else { + for (i = 0; i < buffer_bytes; i++) { + pool[pindex++] ^= bp[bstart]; + bp[bstart++] = 0; + pindex &= (RNDPOOLSIZE - 1); + bstart &= (RNDPOOLSIZE - 1); + } + ASSERT(bstart == bindex); + } + buffer_bytes = 0; + } + mutex_exit(&buffer_lock); + start = 0; for (i = 0; i < RNDPOOLSIZE/HASHSIZE + 1; i++) { HashInit(&hashctx); @@ -449,6 +505,14 @@ swrand_mix_pool(uint16_t entropy_est) } static void +swrand_add_entropy_later(uint8_t *ptr, size_t len) +{ + mutex_enter(&buffer_lock); + swrand_add_bytes_later(ptr, len); + mutex_exit(&buffer_lock); +} + +static void swrand_add_entropy(uint8_t *ptr, size_t len, uint16_t entropy_est) { mutex_enter(&srndpool_lock); diff --git a/usr/src/uts/common/io/random.c b/usr/src/uts/common/io/random.c index d1d335ee7f..9d3a7d8b56 100644 --- a/usr/src/uts/common/io/random.c +++ b/usr/src/uts/common/io/random.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. @@ -19,7 +18,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. */ @@ -278,6 +277,9 @@ rnd_write(dev_t dev, struct uio *uiop, cred_t *credp) int error; uint8_t buf[WRITEBUFSIZE]; size_t bytes; + minor_t devno; + + devno = getminor(dev); while (uiop->uio_resid > 0) { bytes = min(sizeof (buf), uiop->uio_resid); @@ -287,9 +289,19 @@ rnd_write(dev_t dev, struct uio *uiop, cred_t *credp) if ((error = uiomove(buf, bytes, UIO_WRITE, uiop)) != 0) return (error); - /* Add bytes to the pool but don't change the entropy level */ - if ((error = random_add_entropy(buf, bytes, 0)) != 0) - return (error); + switch (devno) { + case DEVRANDOM: + if ((error = random_add_entropy(buf, bytes, 0)) != 0) + return (error); + break; + case DEVURANDOM: + if ((error = random_add_pseudo_entropy(buf, bytes, + 0)) != 0) + return (error); + break; + default: + return (ENXIO); + } } return (0); diff --git a/usr/src/uts/common/sys/crypto/impl.h b/usr/src/uts/common/sys/crypto/impl.h index b240dc0a5a..7ae06f4eda 100644 --- a/usr/src/uts/common/sys/crypto/impl.h +++ b/usr/src/uts/common/sys/crypto/impl.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -954,10 +953,10 @@ extern rctl_hndl_t rc_project_crypto_mem; * Wrappers for crypto_random_number_ops(9S) entry points. */ -#define KCF_PROV_SEED_RANDOM(pd, session, buf, len, req) ( \ +#define KCF_PROV_SEED_RANDOM(pd, session, buf, len, est, flags, req) ( \ (KCF_PROV_RANDOM_OPS(pd) && KCF_PROV_RANDOM_OPS(pd)->seed_random) ? \ KCF_PROV_RANDOM_OPS(pd)->seed_random((pd)->pd_prov_handle, \ - session, buf, len, req) : CRYPTO_NOT_SUPPORTED) + session, buf, len, est, flags, req) : CRYPTO_NOT_SUPPORTED) #define KCF_PROV_GENERATE_RANDOM(pd, session, buf, len, req) ( \ (KCF_PROV_RANDOM_OPS(pd) && \ @@ -1249,6 +1248,7 @@ extern void kcf_rnd_init(); extern boolean_t kcf_rngprov_check(void); extern int kcf_rnd_get_pseudo_bytes(uint8_t *, size_t); extern int kcf_rnd_get_bytes(uint8_t *, size_t, boolean_t, boolean_t); +extern int random_add_pseudo_entropy(uint8_t *, size_t, uint_t); extern void kcf_rnd_chpoll(int, short *, struct pollhead **); extern void kcf_rnd_schedule_timeout(boolean_t); diff --git a/usr/src/uts/common/sys/crypto/ops_impl.h b/usr/src/uts/common/sys/crypto/ops_impl.h index 5004c0396b..3552f50c17 100644 --- a/usr/src/uts/common/sys/crypto/ops_impl.h +++ b/usr/src/uts/common/sys/crypto/ops_impl.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. */ @@ -146,6 +145,8 @@ typedef struct kcf_random_number_ops_params { crypto_session_id_t rn_sid; uchar_t *rn_buf; size_t rn_buflen; + uint_t rn_entropy_est; + uint32_t rn_flags; } kcf_random_number_ops_params_t; /* @@ -476,7 +477,8 @@ typedef struct kcf_req_params { cmops->md_decr_templ = _decr_templ; \ } -#define KCF_WRAP_RANDOM_OPS_PARAMS(req, ftype, _sid, _buf, _buflen) { \ +#define KCF_WRAP_RANDOM_OPS_PARAMS(req, ftype, _sid, _buf, _buflen, \ + _est, _flags) { \ kcf_random_number_ops_params_t *rops = \ &(req)->rp_u.random_number_params; \ \ @@ -485,6 +487,8 @@ typedef struct kcf_req_params { rops->rn_sid = _sid; \ rops->rn_buf = _buf; \ rops->rn_buflen = _buflen; \ + rops->rn_entropy_est = _est; \ + rops->rn_flags = _flags; \ } #define KCF_WRAP_SESSION_OPS_PARAMS(req, ftype, _sid_ptr, _sid, \ diff --git a/usr/src/uts/common/sys/crypto/spi.h b/usr/src/uts/common/sys/crypto/spi.h index e06f260d02..3022cf1d01 100644 --- a/usr/src/uts/common/sys/crypto/spi.h +++ b/usr/src/uts/common/sys/crypto/spi.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -386,12 +385,17 @@ typedef struct crypto_dual_cipher_mac_ops { */ typedef struct crypto_random_number_ops { int (*seed_random)(crypto_provider_handle_t, crypto_session_id_t, - uchar_t *, size_t, crypto_req_handle_t); + uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); int (*generate_random)(crypto_provider_handle_t, crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); } crypto_random_number_ops_t; /* + * Flag values for seed_random. + */ +#define CRYPTO_SEED_NOW 0x00000001 + +/* * The crypto_session_ops structure contains pointers to session * operations for cryptographic providers. It is passed through * the crypto_ops(9S) structure when providers register with the diff --git a/usr/src/uts/common/sys/random.h b/usr/src/uts/common/sys/random.h index 2628277964..919e50fb31 100644 --- a/usr/src/uts/common/sys/random.h +++ b/usr/src/uts/common/sys/random.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. */ @@ -59,7 +58,7 @@ typedef struct swrand_stats { #define BUMP_RND_STATS(x, v) atomic_add_64(&(rnd_stats).x, (v)) #define BUMP_SWRAND_STATS(x, v) atomic_add_64(&(swrand_stats).x, (v)) -extern int random_add_entropy(uint8_t *, size_t, uint16_t); +extern int random_add_entropy(uint8_t *, size_t, uint_t); extern int random_get_bytes(uint8_t *, size_t); extern int random_get_pseudo_bytes(uint8_t *, size_t); |