10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53708Skrishna * Common Development and Distribution License (the "License").
63708Skrishna * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
2112304SValerie.Fenwick@Oracle.COM
220Sstevel@tonic-gate /*
2312304SValerie.Fenwick@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Core KCF (Kernel Cryptographic Framework). This file implements
280Sstevel@tonic-gate * the loadable module entry points and module verification routines.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <sys/systm.h>
320Sstevel@tonic-gate #include <sys/cmn_err.h>
330Sstevel@tonic-gate #include <sys/ddi.h>
340Sstevel@tonic-gate #include <sys/sunddi.h>
350Sstevel@tonic-gate #include <sys/modctl.h>
360Sstevel@tonic-gate #include <sys/errno.h>
370Sstevel@tonic-gate #include <sys/rwlock.h>
380Sstevel@tonic-gate #include <sys/kmem.h>
390Sstevel@tonic-gate #include <sys/door.h>
400Sstevel@tonic-gate #include <sys/kobj.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <sys/crypto/common.h>
430Sstevel@tonic-gate #include <sys/crypto/api.h>
440Sstevel@tonic-gate #include <sys/crypto/spi.h>
450Sstevel@tonic-gate #include <sys/crypto/impl.h>
460Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
470Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
4810732SAnthony.Scarpino@Sun.COM #include <sys/crypto/ioctladmin.h>
490Sstevel@tonic-gate
500Sstevel@tonic-gate #ifdef DEBUG
510Sstevel@tonic-gate int kcf_frmwrk_debug = 0;
520Sstevel@tonic-gate
530Sstevel@tonic-gate #define KCF_FRMWRK_DEBUG(l, x) if (kcf_frmwrk_debug >= l) printf x
540Sstevel@tonic-gate #else /* DEBUG */
550Sstevel@tonic-gate #define KCF_FRMWRK_DEBUG(l, x)
560Sstevel@tonic-gate #endif /* DEBUG */
570Sstevel@tonic-gate
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate * Door to make upcalls to kcfd. kcfd will send us this
600Sstevel@tonic-gate * handle when it is coming up.
610Sstevel@tonic-gate */
620Sstevel@tonic-gate kmutex_t kcf_dh_lock;
630Sstevel@tonic-gate door_handle_t kcf_dh = NULL;
640Sstevel@tonic-gate
6510732SAnthony.Scarpino@Sun.COM /* Setup FIPS 140 support variables */
6610732SAnthony.Scarpino@Sun.COM uint32_t global_fips140_mode = FIPS140_MODE_UNSET;
6710732SAnthony.Scarpino@Sun.COM kmutex_t fips140_mode_lock;
6810732SAnthony.Scarpino@Sun.COM kcondvar_t cv_fips140;
6910732SAnthony.Scarpino@Sun.COM
7010732SAnthony.Scarpino@Sun.COM /*
7110732SAnthony.Scarpino@Sun.COM * Kernel FIPS140 boundary module list
7210732SAnthony.Scarpino@Sun.COM * NOTE: "swrand" must be the last entry. FIPS 140 shutdown functions stop
7310732SAnthony.Scarpino@Sun.COM * before getting to swrand as it is used for non-FIPS 140
7410732SAnthony.Scarpino@Sun.COM * operations to. The FIPS 140 random API separately controls access.
7510732SAnthony.Scarpino@Sun.COM */
7610732SAnthony.Scarpino@Sun.COM #define FIPS140_MODULES_MAX 7
7710732SAnthony.Scarpino@Sun.COM static char *fips140_module_list[FIPS140_MODULES_MAX] = {
7810732SAnthony.Scarpino@Sun.COM "aes", "des", "ecc", "sha1", "sha2", "rsa", "swrand"
7910732SAnthony.Scarpino@Sun.COM };
800Sstevel@tonic-gate
810Sstevel@tonic-gate static struct modlmisc modlmisc = {
825072Smcpowers &mod_miscops, "Kernel Crypto Framework"
830Sstevel@tonic-gate };
840Sstevel@tonic-gate
850Sstevel@tonic-gate static struct modlinkage modlinkage = {
860Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL
870Sstevel@tonic-gate };
880Sstevel@tonic-gate
890Sstevel@tonic-gate static int rngtimer_started;
9011751SAnthony.Scarpino@Sun.COM extern int sys_shutdown;
910Sstevel@tonic-gate
920Sstevel@tonic-gate int
_init()930Sstevel@tonic-gate _init()
940Sstevel@tonic-gate {
9510732SAnthony.Scarpino@Sun.COM mutex_init(&fips140_mode_lock, NULL, MUTEX_DEFAULT, NULL);
9610732SAnthony.Scarpino@Sun.COM cv_init(&cv_fips140, NULL, CV_DEFAULT, NULL);
9710732SAnthony.Scarpino@Sun.COM
980Sstevel@tonic-gate /* initialize the mechanisms tables supported out-of-the-box */
990Sstevel@tonic-gate kcf_init_mech_tabs();
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate /* initialize the providers tables */
1020Sstevel@tonic-gate kcf_prov_tab_init();
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate /* initialize the policy table */
1050Sstevel@tonic-gate kcf_policy_tab_init();
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /* initialize soft_config_list */
1080Sstevel@tonic-gate kcf_soft_config_init();
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * Initialize scheduling structures. Note that this does NOT
1120Sstevel@tonic-gate * start any threads since it might not be safe to do so.
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate kcf_sched_init();
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /* initialize the RNG support structures */
1170Sstevel@tonic-gate rngtimer_started = 0;
1180Sstevel@tonic-gate kcf_rnd_init();
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate return (mod_install(&modlinkage));
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1240Sstevel@tonic-gate _info(struct modinfo *modinfop)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate /*
1300Sstevel@tonic-gate * We do not allow kcf to unload.
1310Sstevel@tonic-gate */
1320Sstevel@tonic-gate int
_fini(void)1330Sstevel@tonic-gate _fini(void)
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate return (EBUSY);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate
13810732SAnthony.Scarpino@Sun.COM
13910732SAnthony.Scarpino@Sun.COM /* Returns the value of global_fips140_mode */
14010500SHai-May.Chao@Sun.COM int
kcf_get_fips140_mode(void)14110500SHai-May.Chao@Sun.COM kcf_get_fips140_mode(void)
14210500SHai-May.Chao@Sun.COM {
14310500SHai-May.Chao@Sun.COM return (global_fips140_mode);
14410500SHai-May.Chao@Sun.COM }
14510500SHai-May.Chao@Sun.COM
14610500SHai-May.Chao@Sun.COM /*
14710732SAnthony.Scarpino@Sun.COM * If FIPS 140 has failed its tests. The providers must be disabled from the
14810732SAnthony.Scarpino@Sun.COM * framework.
14910732SAnthony.Scarpino@Sun.COM */
15010732SAnthony.Scarpino@Sun.COM void
kcf_fips140_shutdown()15110732SAnthony.Scarpino@Sun.COM kcf_fips140_shutdown()
15210732SAnthony.Scarpino@Sun.COM {
15310732SAnthony.Scarpino@Sun.COM kcf_provider_desc_t *pd;
15410732SAnthony.Scarpino@Sun.COM int i;
15510732SAnthony.Scarpino@Sun.COM
15610732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN,
15710732SAnthony.Scarpino@Sun.COM "Shutting down FIPS 140 boundary as verification failed.");
15810732SAnthony.Scarpino@Sun.COM
15910732SAnthony.Scarpino@Sun.COM /* Disable FIPS 140 modules, but leave swrand alone */
16010732SAnthony.Scarpino@Sun.COM for (i = 0; i < (FIPS140_MODULES_MAX - 1); i++) {
16110732SAnthony.Scarpino@Sun.COM /*
16210732SAnthony.Scarpino@Sun.COM * Remove the predefined entries from the soft_config_list
16310732SAnthony.Scarpino@Sun.COM * so the framework does not report the providers.
16410732SAnthony.Scarpino@Sun.COM */
16510732SAnthony.Scarpino@Sun.COM remove_soft_config(fips140_module_list[i]);
16610732SAnthony.Scarpino@Sun.COM
16710732SAnthony.Scarpino@Sun.COM pd = kcf_prov_tab_lookup_by_name(fips140_module_list[i]);
16810732SAnthony.Scarpino@Sun.COM if (pd == NULL)
16910732SAnthony.Scarpino@Sun.COM continue;
17010732SAnthony.Scarpino@Sun.COM
17110732SAnthony.Scarpino@Sun.COM /* Allow the unneeded providers to be unloaded */
17210732SAnthony.Scarpino@Sun.COM pd->pd_mctlp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
17310732SAnthony.Scarpino@Sun.COM
17410732SAnthony.Scarpino@Sun.COM /* Invalidate the FIPS 140 providers */
17510732SAnthony.Scarpino@Sun.COM mutex_enter(&pd->pd_lock);
17610732SAnthony.Scarpino@Sun.COM pd->pd_state = KCF_PROV_VERIFICATION_FAILED;
17710732SAnthony.Scarpino@Sun.COM mutex_exit(&pd->pd_lock);
17810732SAnthony.Scarpino@Sun.COM KCF_PROV_REFRELE(pd);
17910732SAnthony.Scarpino@Sun.COM undo_register_provider(pd, B_FALSE);
18010732SAnthony.Scarpino@Sun.COM
18110732SAnthony.Scarpino@Sun.COM }
18210732SAnthony.Scarpino@Sun.COM }
18310732SAnthony.Scarpino@Sun.COM
18410732SAnthony.Scarpino@Sun.COM /*
18510732SAnthony.Scarpino@Sun.COM * Activates the kernel providers
18610732SAnthony.Scarpino@Sun.COM *
18710732SAnthony.Scarpino@Sun.COM * If we are getting ready to enable FIPS 140 mode, then all providers should
18810732SAnthony.Scarpino@Sun.COM * be loaded and ready.
18910732SAnthony.Scarpino@Sun.COM *
19010732SAnthony.Scarpino@Sun.COM * If FIPS 140 is disabled, then we can skip any errors because some crypto
19110732SAnthony.Scarpino@Sun.COM * modules may not have been loaded.
19210732SAnthony.Scarpino@Sun.COM */
19310732SAnthony.Scarpino@Sun.COM void
kcf_activate()19410732SAnthony.Scarpino@Sun.COM kcf_activate()
19510732SAnthony.Scarpino@Sun.COM {
19610732SAnthony.Scarpino@Sun.COM kcf_provider_desc_t *pd;
19710732SAnthony.Scarpino@Sun.COM int i;
19810732SAnthony.Scarpino@Sun.COM
19910732SAnthony.Scarpino@Sun.COM for (i = 0; i < (FIPS140_MODULES_MAX - 1); i++) {
20010732SAnthony.Scarpino@Sun.COM pd = kcf_prov_tab_lookup_by_name(fips140_module_list[i]);
20110732SAnthony.Scarpino@Sun.COM if (pd == NULL) {
20210732SAnthony.Scarpino@Sun.COM if (global_fips140_mode == FIPS140_MODE_DISABLED)
20310732SAnthony.Scarpino@Sun.COM continue;
20410732SAnthony.Scarpino@Sun.COM
20510732SAnthony.Scarpino@Sun.COM /* There should never be a NULL value in FIPS 140 */
20610732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 activation: %s not in "
20710732SAnthony.Scarpino@Sun.COM "kernel provider table", fips140_module_list[i]);
20810732SAnthony.Scarpino@Sun.COM kcf_fips140_shutdown();
20910732SAnthony.Scarpino@Sun.COM break;
21010732SAnthony.Scarpino@Sun.COM }
21110732SAnthony.Scarpino@Sun.COM
21210732SAnthony.Scarpino@Sun.COM /*
21310732SAnthony.Scarpino@Sun.COM * Change the provider state so the verification functions
21410732SAnthony.Scarpino@Sun.COM * can signature verify, if necessary, and ready it.
21510732SAnthony.Scarpino@Sun.COM */
21610732SAnthony.Scarpino@Sun.COM if (pd->pd_state == KCF_PROV_UNVERIFIED_FIPS140) {
21710732SAnthony.Scarpino@Sun.COM mutex_enter(&pd->pd_lock);
21810732SAnthony.Scarpino@Sun.COM pd->pd_state = KCF_PROV_UNVERIFIED;
21910732SAnthony.Scarpino@Sun.COM mutex_exit(&pd->pd_lock);
22010732SAnthony.Scarpino@Sun.COM }
22110732SAnthony.Scarpino@Sun.COM
22210732SAnthony.Scarpino@Sun.COM KCF_PROV_REFRELE(pd);
22310732SAnthony.Scarpino@Sun.COM }
22410732SAnthony.Scarpino@Sun.COM
22510932SAnthony.Scarpino@Sun.COM /* If we are not in FIPS 140 mode, then exit */
22610745SAnthony.Scarpino@Sun.COM if (global_fips140_mode == FIPS140_MODE_DISABLED)
22710745SAnthony.Scarpino@Sun.COM return;
22810745SAnthony.Scarpino@Sun.COM
22910732SAnthony.Scarpino@Sun.COM /* If we in the process of validating FIPS 140, enable it */
23010745SAnthony.Scarpino@Sun.COM mutex_enter(&fips140_mode_lock);
23110745SAnthony.Scarpino@Sun.COM global_fips140_mode = FIPS140_MODE_ENABLED;
23210745SAnthony.Scarpino@Sun.COM cv_signal(&cv_fips140);
23310745SAnthony.Scarpino@Sun.COM mutex_exit(&fips140_mode_lock);
23410932SAnthony.Scarpino@Sun.COM cmn_err(CE_CONT, "?FIPS 140 enabled. Boundary check complete.");
23510732SAnthony.Scarpino@Sun.COM
23610732SAnthony.Scarpino@Sun.COM verify_unverified_providers();
23710732SAnthony.Scarpino@Sun.COM }
23810732SAnthony.Scarpino@Sun.COM
23910732SAnthony.Scarpino@Sun.COM
24010732SAnthony.Scarpino@Sun.COM /*
24110732SAnthony.Scarpino@Sun.COM * Perform a door call to kcfd to have it check the integrity of the
24210732SAnthony.Scarpino@Sun.COM * kernel boundary. Failure of the boundary will cause a FIPS 140
24310732SAnthony.Scarpino@Sun.COM * configuration to fail
24410732SAnthony.Scarpino@Sun.COM */
24510732SAnthony.Scarpino@Sun.COM int
kcf_fips140_integrity_check()24610732SAnthony.Scarpino@Sun.COM kcf_fips140_integrity_check()
24710732SAnthony.Scarpino@Sun.COM {
24810732SAnthony.Scarpino@Sun.COM door_arg_t darg;
24910732SAnthony.Scarpino@Sun.COM door_handle_t ldh;
250*13012SMisaki.Miyashita@Oracle.COM kcf_door_arg_t *kda = { 0 }, *rkda = NULL;
25110732SAnthony.Scarpino@Sun.COM int ret = 0;
25210732SAnthony.Scarpino@Sun.COM
25310732SAnthony.Scarpino@Sun.COM KCF_FRMWRK_DEBUG(1, ("Starting IC check"));
25410732SAnthony.Scarpino@Sun.COM
25510732SAnthony.Scarpino@Sun.COM mutex_enter(&kcf_dh_lock);
25610732SAnthony.Scarpino@Sun.COM if (kcf_dh == NULL) {
25710732SAnthony.Scarpino@Sun.COM mutex_exit(&kcf_dh_lock);
25810732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 Integrity Check failed, Door not "
25910732SAnthony.Scarpino@Sun.COM "available\n");
26010732SAnthony.Scarpino@Sun.COM return (1);
26110732SAnthony.Scarpino@Sun.COM }
26210732SAnthony.Scarpino@Sun.COM
26310732SAnthony.Scarpino@Sun.COM ldh = kcf_dh;
26410732SAnthony.Scarpino@Sun.COM door_ki_hold(ldh);
26510732SAnthony.Scarpino@Sun.COM mutex_exit(&kcf_dh_lock);
26610732SAnthony.Scarpino@Sun.COM
26710732SAnthony.Scarpino@Sun.COM kda = kmem_alloc(sizeof (kcf_door_arg_t), KM_SLEEP);
26810732SAnthony.Scarpino@Sun.COM kda->da_version = KCFD_FIPS140_INTCHECK;
26910732SAnthony.Scarpino@Sun.COM kda->da_iskernel = B_TRUE;
27010732SAnthony.Scarpino@Sun.COM
27110732SAnthony.Scarpino@Sun.COM darg.data_ptr = (char *)kda;
27210732SAnthony.Scarpino@Sun.COM darg.data_size = sizeof (kcf_door_arg_t);
27310732SAnthony.Scarpino@Sun.COM darg.desc_ptr = NULL;
27410732SAnthony.Scarpino@Sun.COM darg.desc_num = 0;
27510732SAnthony.Scarpino@Sun.COM darg.rbuf = (char *)kda;
27610732SAnthony.Scarpino@Sun.COM darg.rsize = sizeof (kcf_door_arg_t);
27710732SAnthony.Scarpino@Sun.COM
27810732SAnthony.Scarpino@Sun.COM ret = door_ki_upcall_limited(ldh, &darg, NULL, SIZE_MAX, 0);
27910732SAnthony.Scarpino@Sun.COM if (ret != 0) {
28010732SAnthony.Scarpino@Sun.COM ret = 1;
28110732SAnthony.Scarpino@Sun.COM goto exit;
28210732SAnthony.Scarpino@Sun.COM }
28310732SAnthony.Scarpino@Sun.COM
28410732SAnthony.Scarpino@Sun.COM KCF_FRMWRK_DEBUG(1, ("Integrity Check door returned = %d\n", ret));
28510732SAnthony.Scarpino@Sun.COM
28611413Sopensolaris@drydog.com rkda = (kcf_door_arg_t *)(void *)darg.rbuf;
28710732SAnthony.Scarpino@Sun.COM if (rkda->da_u.result.status != ELFSIGN_SUCCESS) {
28810732SAnthony.Scarpino@Sun.COM ret = 1;
28910732SAnthony.Scarpino@Sun.COM KCF_FRMWRK_DEBUG(1, ("Integrity Check failed = %d\n",
29010732SAnthony.Scarpino@Sun.COM rkda->da_u.result.status));
29110732SAnthony.Scarpino@Sun.COM goto exit;
29210732SAnthony.Scarpino@Sun.COM }
29310732SAnthony.Scarpino@Sun.COM
29410732SAnthony.Scarpino@Sun.COM KCF_FRMWRK_DEBUG(1, ("Integrity Check succeeds.\n"));
29510732SAnthony.Scarpino@Sun.COM
29610732SAnthony.Scarpino@Sun.COM exit:
297*13012SMisaki.Miyashita@Oracle.COM if ((rkda != NULL) && (rkda != kda))
29810732SAnthony.Scarpino@Sun.COM kmem_free(rkda, darg.rsize);
29910732SAnthony.Scarpino@Sun.COM
30010732SAnthony.Scarpino@Sun.COM kmem_free(kda, sizeof (kcf_door_arg_t));
30110732SAnthony.Scarpino@Sun.COM door_ki_rele(ldh);
30210732SAnthony.Scarpino@Sun.COM if (ret)
30310732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 Integrity Check failed.\n");
30410732SAnthony.Scarpino@Sun.COM return (ret);
30510732SAnthony.Scarpino@Sun.COM }
30610732SAnthony.Scarpino@Sun.COM
30710732SAnthony.Scarpino@Sun.COM /*
30810732SAnthony.Scarpino@Sun.COM * If FIPS 140 is configured to be enabled, before it can be turned on, the
30910732SAnthony.Scarpino@Sun.COM * providers must run their Power On Self Test (POST) and we must wait to sure
31010732SAnthony.Scarpino@Sun.COM * userland has performed its validation tests.
31110732SAnthony.Scarpino@Sun.COM */
31210732SAnthony.Scarpino@Sun.COM void
kcf_fips140_validate()31310732SAnthony.Scarpino@Sun.COM kcf_fips140_validate()
31410732SAnthony.Scarpino@Sun.COM {
31510732SAnthony.Scarpino@Sun.COM kcf_provider_desc_t *pd;
31610732SAnthony.Scarpino@Sun.COM kthread_t *post_thr;
31710732SAnthony.Scarpino@Sun.COM int post_rv[FIPS140_MODULES_MAX];
31810732SAnthony.Scarpino@Sun.COM kt_did_t post_t_did[FIPS140_MODULES_MAX];
31910732SAnthony.Scarpino@Sun.COM int ret = 0;
32010732SAnthony.Scarpino@Sun.COM int i;
32110732SAnthony.Scarpino@Sun.COM
32210732SAnthony.Scarpino@Sun.COM /*
32310732SAnthony.Scarpino@Sun.COM * Run POST tests for FIPS 140 modules, if they aren't loaded, load them
32410732SAnthony.Scarpino@Sun.COM */
32510732SAnthony.Scarpino@Sun.COM for (i = 0; i < FIPS140_MODULES_MAX; i++) {
32610732SAnthony.Scarpino@Sun.COM pd = kcf_prov_tab_lookup_by_name(fips140_module_list[i]);
32710732SAnthony.Scarpino@Sun.COM if (pd == NULL) {
32810732SAnthony.Scarpino@Sun.COM /* If the module isn't loaded, load it */
32910732SAnthony.Scarpino@Sun.COM ret = modload("crypto", fips140_module_list[i]);
33010732SAnthony.Scarpino@Sun.COM if (ret == -1) {
33110732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 validation failed: "
33210732SAnthony.Scarpino@Sun.COM "error modloading module %s.",
33310732SAnthony.Scarpino@Sun.COM fips140_module_list[i]);
33410732SAnthony.Scarpino@Sun.COM goto error;
33510732SAnthony.Scarpino@Sun.COM }
33610732SAnthony.Scarpino@Sun.COM
33710732SAnthony.Scarpino@Sun.COM /* Try again to get provider desc */
33810732SAnthony.Scarpino@Sun.COM pd = kcf_prov_tab_lookup_by_name(
33910732SAnthony.Scarpino@Sun.COM fips140_module_list[i]);
34010732SAnthony.Scarpino@Sun.COM if (pd == NULL) {
34110732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 validation failed: "
34210732SAnthony.Scarpino@Sun.COM "Could not find module %s.",
34310732SAnthony.Scarpino@Sun.COM fips140_module_list[i]);
34410732SAnthony.Scarpino@Sun.COM goto error;
34510732SAnthony.Scarpino@Sun.COM }
34610732SAnthony.Scarpino@Sun.COM }
34710732SAnthony.Scarpino@Sun.COM
34810732SAnthony.Scarpino@Sun.COM /* Make sure there are FIPS 140 entry points */
34910732SAnthony.Scarpino@Sun.COM if (KCF_PROV_FIPS140_OPS(pd) == NULL) {
35010732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 validation failed: "
35110732SAnthony.Scarpino@Sun.COM "No POST function entry point in %s.",
35210732SAnthony.Scarpino@Sun.COM fips140_module_list[i]);
35310732SAnthony.Scarpino@Sun.COM goto error;
35410732SAnthony.Scarpino@Sun.COM }
35510732SAnthony.Scarpino@Sun.COM
35610732SAnthony.Scarpino@Sun.COM /* Make sure the module is not unloaded */
35710732SAnthony.Scarpino@Sun.COM pd->pd_mctlp->mod_loadflags |= MOD_NOAUTOUNLOAD;
35810732SAnthony.Scarpino@Sun.COM
35910732SAnthony.Scarpino@Sun.COM /*
36010732SAnthony.Scarpino@Sun.COM * With the FIPS 140 POST function provided by the module in
36110732SAnthony.Scarpino@Sun.COM * SPI v4, start a thread to run the function.
36210732SAnthony.Scarpino@Sun.COM */
36310732SAnthony.Scarpino@Sun.COM post_rv[i] = CRYPTO_OPERATION_NOT_INITIALIZED;
36410732SAnthony.Scarpino@Sun.COM post_thr = thread_create(NULL, 0,
36510732SAnthony.Scarpino@Sun.COM (*(KCF_PROV_FIPS140_OPS(pd)->fips140_post)), &post_rv[i],
36610732SAnthony.Scarpino@Sun.COM 0, &p0, TS_RUN, MAXCLSYSPRI);
36710932SAnthony.Scarpino@Sun.COM post_t_did[i] = post_thr->t_did;
36810732SAnthony.Scarpino@Sun.COM KCF_FRMWRK_DEBUG(1, ("kcf_fips140_validate: started POST "
36910732SAnthony.Scarpino@Sun.COM "for %s\n", fips140_module_list[i]));
37010732SAnthony.Scarpino@Sun.COM KCF_PROV_REFRELE(pd);
37110732SAnthony.Scarpino@Sun.COM }
37210732SAnthony.Scarpino@Sun.COM
37310732SAnthony.Scarpino@Sun.COM /* Do integrity check of kernel boundary */
37410732SAnthony.Scarpino@Sun.COM ret = kcf_fips140_integrity_check();
37510732SAnthony.Scarpino@Sun.COM if (ret == 1)
37610732SAnthony.Scarpino@Sun.COM goto error;
37710732SAnthony.Scarpino@Sun.COM
37810732SAnthony.Scarpino@Sun.COM /* Wait for POST threads to come back and verify results */
37910732SAnthony.Scarpino@Sun.COM for (i = 0; i < FIPS140_MODULES_MAX; i++) {
38010932SAnthony.Scarpino@Sun.COM /* If the POST has already returned a success, we can move on */
38110932SAnthony.Scarpino@Sun.COM if (post_rv[i] == CRYPTO_SUCCESS)
38210932SAnthony.Scarpino@Sun.COM continue;
38310932SAnthony.Scarpino@Sun.COM
38410932SAnthony.Scarpino@Sun.COM /* POST test is taking more time, need to wait for thread */
38510932SAnthony.Scarpino@Sun.COM if (post_rv[i] == CRYPTO_OPERATION_NOT_INITIALIZED &&
38610932SAnthony.Scarpino@Sun.COM post_t_did[i] != NULL)
38710732SAnthony.Scarpino@Sun.COM thread_join(post_t_did[i]);
38810732SAnthony.Scarpino@Sun.COM
38910932SAnthony.Scarpino@Sun.COM if (post_rv[i] != CRYPTO_SUCCESS) {
39010732SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "FIPS 140 POST failed for %s. "
39110932SAnthony.Scarpino@Sun.COM "Error = 0x%x", fips140_module_list[i], post_rv[i]);
39210732SAnthony.Scarpino@Sun.COM goto error;
39310732SAnthony.Scarpino@Sun.COM }
39410732SAnthony.Scarpino@Sun.COM }
39510732SAnthony.Scarpino@Sun.COM
39610732SAnthony.Scarpino@Sun.COM kcf_activate();
39710732SAnthony.Scarpino@Sun.COM return;
39810732SAnthony.Scarpino@Sun.COM
39910732SAnthony.Scarpino@Sun.COM error:
40010732SAnthony.Scarpino@Sun.COM mutex_enter(&fips140_mode_lock);
40110732SAnthony.Scarpino@Sun.COM global_fips140_mode = FIPS140_MODE_SHUTDOWN;
40210732SAnthony.Scarpino@Sun.COM kcf_fips140_shutdown();
40310732SAnthony.Scarpino@Sun.COM cv_signal(&cv_fips140);
40410732SAnthony.Scarpino@Sun.COM mutex_exit(&fips140_mode_lock);
40510732SAnthony.Scarpino@Sun.COM
40610732SAnthony.Scarpino@Sun.COM }
40710732SAnthony.Scarpino@Sun.COM
40810732SAnthony.Scarpino@Sun.COM
40910732SAnthony.Scarpino@Sun.COM /*
4100Sstevel@tonic-gate * Return a pointer to the modctl structure of the
4110Sstevel@tonic-gate * provider's module.
4120Sstevel@tonic-gate */
4130Sstevel@tonic-gate struct modctl *
kcf_get_modctl(crypto_provider_info_t * pinfo)4140Sstevel@tonic-gate kcf_get_modctl(crypto_provider_info_t *pinfo)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate struct modctl *mctlp;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate /* Get the modctl struct for this module */
4190Sstevel@tonic-gate if (pinfo->pi_provider_type == CRYPTO_SW_PROVIDER)
4200Sstevel@tonic-gate mctlp = mod_getctl(pinfo->pi_provider_dev.pd_sw);
4210Sstevel@tonic-gate else {
4220Sstevel@tonic-gate major_t major;
4230Sstevel@tonic-gate char *drvmod;
4240Sstevel@tonic-gate
42511413Sopensolaris@drydog.com if ((major = ddi_driver_major(pinfo->pi_provider_dev.pd_hw))
42611413Sopensolaris@drydog.com != DDI_MAJOR_T_NONE) {
4270Sstevel@tonic-gate drvmod = ddi_major_to_name(major);
4280Sstevel@tonic-gate mctlp = mod_find_by_filename("drv", drvmod);
4290Sstevel@tonic-gate } else
4300Sstevel@tonic-gate return (NULL);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate return (mctlp);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate
43610732SAnthony.Scarpino@Sun.COM /* Check if this provider requires to be verified. */
43710732SAnthony.Scarpino@Sun.COM int
verifiable_provider(crypto_ops_t * prov_ops)43810732SAnthony.Scarpino@Sun.COM verifiable_provider(crypto_ops_t *prov_ops)
43910732SAnthony.Scarpino@Sun.COM {
44010732SAnthony.Scarpino@Sun.COM
44110732SAnthony.Scarpino@Sun.COM if (prov_ops->co_cipher_ops == NULL && prov_ops->co_dual_ops == NULL &&
44210732SAnthony.Scarpino@Sun.COM prov_ops->co_dual_cipher_mac_ops == NULL &&
44310732SAnthony.Scarpino@Sun.COM prov_ops->co_key_ops == NULL && prov_ops->co_sign_ops == NULL &&
44410732SAnthony.Scarpino@Sun.COM prov_ops->co_verify_ops == NULL)
44510732SAnthony.Scarpino@Sun.COM return (0);
44610732SAnthony.Scarpino@Sun.COM
44710732SAnthony.Scarpino@Sun.COM return (1);
44810732SAnthony.Scarpino@Sun.COM }
44910732SAnthony.Scarpino@Sun.COM
45010732SAnthony.Scarpino@Sun.COM /*
45110732SAnthony.Scarpino@Sun.COM * With a given provider being registered, this looks through the FIPS 140
45210732SAnthony.Scarpino@Sun.COM * modules list and returns a 1 if it's part of the FIPS 140 boundary and
45310732SAnthony.Scarpino@Sun.COM * the framework registration must be delayed until we know the FIPS 140 mode
45410732SAnthony.Scarpino@Sun.COM * status. A zero mean the provider does not need to wait for the FIPS 140
45510732SAnthony.Scarpino@Sun.COM * boundary.
45610732SAnthony.Scarpino@Sun.COM *
45710732SAnthony.Scarpino@Sun.COM * If the provider in the boundary only provides random (like swrand), we
45810732SAnthony.Scarpino@Sun.COM * can let it register as the random API will block operations.
45910732SAnthony.Scarpino@Sun.COM */
46010732SAnthony.Scarpino@Sun.COM int
kcf_need_fips140_verification(kcf_provider_desc_t * pd)46110732SAnthony.Scarpino@Sun.COM kcf_need_fips140_verification(kcf_provider_desc_t *pd)
46210732SAnthony.Scarpino@Sun.COM {
46310732SAnthony.Scarpino@Sun.COM int i, ret = 0;
46410732SAnthony.Scarpino@Sun.COM
46510732SAnthony.Scarpino@Sun.COM if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
46610732SAnthony.Scarpino@Sun.COM return (0);
46710732SAnthony.Scarpino@Sun.COM
46810732SAnthony.Scarpino@Sun.COM mutex_enter(&fips140_mode_lock);
46910732SAnthony.Scarpino@Sun.COM
47010732SAnthony.Scarpino@Sun.COM if (global_fips140_mode >= FIPS140_MODE_ENABLED)
47110732SAnthony.Scarpino@Sun.COM goto exit;
47210732SAnthony.Scarpino@Sun.COM
47310732SAnthony.Scarpino@Sun.COM for (i = 0; i < FIPS140_MODULES_MAX; i++) {
47410732SAnthony.Scarpino@Sun.COM if (strcmp(fips140_module_list[i], pd->pd_name) != 0)
47510732SAnthony.Scarpino@Sun.COM continue;
47610732SAnthony.Scarpino@Sun.COM
47710732SAnthony.Scarpino@Sun.COM /* If this module is only random, we can let it register */
47810732SAnthony.Scarpino@Sun.COM if (KCF_PROV_RANDOM_OPS(pd) &&
47910732SAnthony.Scarpino@Sun.COM !verifiable_provider(pd->pd_ops_vector))
48010732SAnthony.Scarpino@Sun.COM break;
48110732SAnthony.Scarpino@Sun.COM
48210732SAnthony.Scarpino@Sun.COM if (global_fips140_mode == FIPS140_MODE_SHUTDOWN) {
48310732SAnthony.Scarpino@Sun.COM ret = -1;
48410732SAnthony.Scarpino@Sun.COM break;
48510732SAnthony.Scarpino@Sun.COM }
48610732SAnthony.Scarpino@Sun.COM
48710732SAnthony.Scarpino@Sun.COM ret = 1;
48810732SAnthony.Scarpino@Sun.COM break;
48910732SAnthony.Scarpino@Sun.COM }
49010732SAnthony.Scarpino@Sun.COM
49110732SAnthony.Scarpino@Sun.COM exit:
49210732SAnthony.Scarpino@Sun.COM mutex_exit(&fips140_mode_lock);
49310732SAnthony.Scarpino@Sun.COM return (ret);
49410732SAnthony.Scarpino@Sun.COM }
49510732SAnthony.Scarpino@Sun.COM
49610732SAnthony.Scarpino@Sun.COM
4970Sstevel@tonic-gate /*
4984373Skrishna * Check if signature verification is needed for a provider.
4990Sstevel@tonic-gate *
5004373Skrishna * Returns 0, if no verification is needed. Returns 1, if
5014373Skrishna * verification is needed. Returns -1, if there is an
5024373Skrishna * error.
5030Sstevel@tonic-gate */
5040Sstevel@tonic-gate int
kcf_need_signature_verification(kcf_provider_desc_t * pd)5054373Skrishna kcf_need_signature_verification(kcf_provider_desc_t *pd)
5060Sstevel@tonic-gate {
5070Sstevel@tonic-gate struct module *mp;
5080Sstevel@tonic-gate struct modctl *mctlp = pd->pd_mctlp;
5090Sstevel@tonic-gate
5104373Skrishna if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
5114373Skrishna return (0);
5124373Skrishna
5130Sstevel@tonic-gate if (mctlp == NULL || mctlp->mod_mp == NULL)
5144373Skrishna return (-1);
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate mp = (struct module *)mctlp->mod_mp;
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate /*
51910732SAnthony.Scarpino@Sun.COM * Check if we need to verify this provider signature and if so,
52010732SAnthony.Scarpino@Sun.COM * make sure it has a signature section.
5210Sstevel@tonic-gate */
52210732SAnthony.Scarpino@Sun.COM if (verifiable_provider(pd->pd_ops_vector) == 0)
5230Sstevel@tonic-gate return (0);
5240Sstevel@tonic-gate
52510732SAnthony.Scarpino@Sun.COM /* See if this module has its required signature section. */
52610732SAnthony.Scarpino@Sun.COM if (mp->sigdata == NULL)
5274373Skrishna return (-1);
5284373Skrishna
5294373Skrishna return (1);
5304373Skrishna }
5314373Skrishna
5324373Skrishna /*
5334373Skrishna * Do the signature verification on the given module. This function can
5344373Skrishna * be called from user context or kernel context.
5354373Skrishna *
5364373Skrishna * We call kcfd with the full pathname of the module to be
53712304SValerie.Fenwick@Oracle.COM * verified. kcfd will return success/fail, signature length
53812304SValerie.Fenwick@Oracle.COM * and the actual signature in the ELF section of the module. If
53912304SValerie.Fenwick@Oracle.COM * kcfd returns success, we compare the signature and the length
54012304SValerie.Fenwick@Oracle.COM * with the values that krtld stored in the module structure. We
54112304SValerie.Fenwick@Oracle.COM * log an error message in case of a failure.
5424373Skrishna *
5434373Skrishna * The provider state is changed to KCF_PROV_READY on success.
5444373Skrishna */
5454373Skrishna void
kcf_verify_signature(void * arg)5464373Skrishna kcf_verify_signature(void *arg)
5474373Skrishna {
5484373Skrishna int rv;
5494373Skrishna int error = CRYPTO_MODVERIFICATION_FAILED;
5504373Skrishna door_arg_t darg;
5514373Skrishna door_handle_t ldh;
5524373Skrishna kcf_door_arg_t *kda;
5534373Skrishna char *filename;
5544373Skrishna kcf_provider_desc_t *pd = arg;
5554373Skrishna struct module *mp;
5564373Skrishna boolean_t do_notify = B_FALSE;
5574373Skrishna boolean_t modhold_done = B_FALSE;
5584373Skrishna struct modctl *mctlp = pd->pd_mctlp;
5594373Skrishna
5604373Skrishna ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
5614373Skrishna ASSERT(mctlp != NULL);
5624373Skrishna
56310732SAnthony.Scarpino@Sun.COM /*
56410732SAnthony.Scarpino@Sun.COM * Because of FIPS 140 delays module loading, we may be running through
56510732SAnthony.Scarpino@Sun.COM * this code with a non-crypto signed module; therefore, another
56610732SAnthony.Scarpino@Sun.COM * check is necessary
56710732SAnthony.Scarpino@Sun.COM */
56810732SAnthony.Scarpino@Sun.COM if (verifiable_provider(pd->pd_ops_vector) == 0) {
56910732SAnthony.Scarpino@Sun.COM error = 0;
57010732SAnthony.Scarpino@Sun.COM goto setverify;
57110732SAnthony.Scarpino@Sun.COM }
57210732SAnthony.Scarpino@Sun.COM
5734373Skrishna for (;;) {
5744373Skrishna mutex_enter(&pd->pd_lock);
5754373Skrishna /* No need to do verification */
5764373Skrishna if (pd->pd_state != KCF_PROV_UNVERIFIED) {
5774373Skrishna mutex_exit(&pd->pd_lock);
5784373Skrishna goto out;
5794373Skrishna }
5804373Skrishna mutex_exit(&pd->pd_lock);
5814373Skrishna
5824373Skrishna mutex_enter(&mod_lock);
5834373Skrishna if (mctlp->mod_mp == NULL) {
5844373Skrishna mutex_exit(&mod_lock);
5854373Skrishna goto out;
5864373Skrishna }
5874373Skrishna
5884373Skrishna /*
5894373Skrishna * This check is needed since a software provider can call
5904373Skrishna * us directly from the _init->crypto_register_provider path.
5914373Skrishna */
5924373Skrishna if (pd->pd_prov_type == CRYPTO_SW_PROVIDER &&
5934373Skrishna mctlp->mod_inprogress_thread == curthread) {
5944373Skrishna mutex_exit(&mod_lock);
5954373Skrishna modhold_done = B_FALSE;
5964373Skrishna break;
5974373Skrishna }
5984373Skrishna
5994373Skrishna /*
6004373Skrishna * We could be in a race with the register thread or
6014373Skrishna * the unregister thread. So, retry if register or
6024373Skrishna * unregister is in progress. Note that we can't do
6034373Skrishna * mod_hold_by_modctl without this check since that
6044373Skrishna * could result in a deadlock with the other threads.
6054373Skrishna */
6064373Skrishna if (mctlp->mod_busy) {
6074373Skrishna mutex_exit(&mod_lock);
6084373Skrishna /* delay for 10ms and try again */
6094373Skrishna delay(drv_usectohz(10000));
6104373Skrishna continue;
6114373Skrishna }
6124373Skrishna
6134373Skrishna (void) mod_hold_by_modctl(mctlp,
6144373Skrishna MOD_WAIT_FOREVER | MOD_LOCK_HELD);
6154373Skrishna mutex_exit(&mod_lock);
6164373Skrishna modhold_done = B_TRUE;
6174373Skrishna break;
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate /*
6210Sstevel@tonic-gate * Check if the door is set up yet. This will be set when kcfd
6224373Skrishna * comes up. If not, we return and leave the provider state unchanged
6234373Skrishna * at KCF_PROV_UNVERIFIED. This will trigger the verification of
6244373Skrishna * the module later when kcfd is up. This is safe as we NEVER use
6254373Skrishna * a provider that has not been verified yet.
6260Sstevel@tonic-gate */
6270Sstevel@tonic-gate mutex_enter(&kcf_dh_lock);
6280Sstevel@tonic-gate if (kcf_dh == NULL) {
6290Sstevel@tonic-gate mutex_exit(&kcf_dh_lock);
6304373Skrishna goto out;
6310Sstevel@tonic-gate }
6324373Skrishna
6334373Skrishna ldh = kcf_dh;
6344373Skrishna door_ki_hold(ldh);
6350Sstevel@tonic-gate mutex_exit(&kcf_dh_lock);
6360Sstevel@tonic-gate
6374373Skrishna mp = (struct module *)mctlp->mod_mp;
6384373Skrishna filename = mp->filename;
6394373Skrishna KCF_FRMWRK_DEBUG(2, ("Verifying module: %s\n", filename));
6404373Skrishna
6410Sstevel@tonic-gate kda = kmem_alloc(sizeof (kcf_door_arg_t) + mp->sigsize, KM_SLEEP);
6420Sstevel@tonic-gate kda->da_version = KCF_KCFD_VERSION1;
6430Sstevel@tonic-gate kda->da_iskernel = B_TRUE;
6440Sstevel@tonic-gate bcopy(filename, kda->da_u.filename, strlen(filename) + 1);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate darg.data_ptr = (char *)kda;
6470Sstevel@tonic-gate darg.data_size = sizeof (kcf_door_arg_t) + mp->sigsize;
6480Sstevel@tonic-gate darg.desc_ptr = NULL;
6490Sstevel@tonic-gate darg.desc_num = 0;
6500Sstevel@tonic-gate darg.rbuf = (char *)kda;
6510Sstevel@tonic-gate darg.rsize = sizeof (kcf_door_arg_t);
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate /*
6540Sstevel@tonic-gate * Make door upcall. door_ki_upcall() checks for validity of the handle.
6550Sstevel@tonic-gate */
6566997Sjwadams rv = door_ki_upcall_limited(ldh, &darg, NULL, SIZE_MAX, 0);
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate if (rv == 0) {
65911413Sopensolaris@drydog.com kcf_door_arg_t *rkda = (kcf_door_arg_t *)(void *)darg.rbuf;
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate KCF_FRMWRK_DEBUG(2,
6620Sstevel@tonic-gate ("passed: %d\n", rkda->da_u.result.status));
6630Sstevel@tonic-gate KCF_FRMWRK_DEBUG(2,
6640Sstevel@tonic-gate ("signature length: %d\n", rkda->da_u.result.siglen));
6650Sstevel@tonic-gate KCF_FRMWRK_DEBUG(2,
6660Sstevel@tonic-gate ("signature: %p\n", (void*)rkda->da_u.result.signature));
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate /* Check kcfd result and compare against module struct fields */
67012304SValerie.Fenwick@Oracle.COM if ((rkda->da_u.result.status != ELFSIGN_SUCCESS) ||
6710Sstevel@tonic-gate !(rkda->da_u.result.siglen == mp->sigsize) ||
6720Sstevel@tonic-gate (bcmp(rkda->da_u.result.signature, mp->sigdata,
6734373Skrishna mp->sigsize))) {
6740Sstevel@tonic-gate cmn_err(CE_WARN, "Module verification failed for %s.",
6754373Skrishna filename);
6760Sstevel@tonic-gate } else {
6770Sstevel@tonic-gate error = 0;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate if (rkda != kda)
6810Sstevel@tonic-gate kmem_free(rkda, darg.rsize);
6820Sstevel@tonic-gate
68311751SAnthony.Scarpino@Sun.COM } else if (sys_shutdown == 0) {
68411751SAnthony.Scarpino@Sun.COM cmn_err(CE_WARN, "Unable to use door to kcfd during module "
68511751SAnthony.Scarpino@Sun.COM "verification of %s. (errno: 0x%x)", filename, rv);
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate kmem_free(kda, sizeof (kcf_door_arg_t) + mp->sigsize);
6894373Skrishna door_ki_rele(ldh);
6904373Skrishna
69110732SAnthony.Scarpino@Sun.COM setverify:
6924373Skrishna mutex_enter(&pd->pd_lock);
6934373Skrishna /* change state only if the original state is unchanged */
6944373Skrishna if (pd->pd_state == KCF_PROV_UNVERIFIED) {
6954373Skrishna if (error == 0) {
6964373Skrishna pd->pd_state = KCF_PROV_READY;
6974373Skrishna do_notify = B_TRUE;
6984373Skrishna } else {
6994373Skrishna pd->pd_state = KCF_PROV_VERIFICATION_FAILED;
7004373Skrishna }
7014373Skrishna }
7024373Skrishna mutex_exit(&pd->pd_lock);
7034373Skrishna
7044373Skrishna if (do_notify) {
7054373Skrishna /* Dispatch events for this new provider */
7064373Skrishna kcf_do_notify(pd, B_TRUE);
7074373Skrishna }
7084373Skrishna
7094373Skrishna out:
7104373Skrishna if (modhold_done)
7114373Skrishna mod_release_mod(mctlp);
7124373Skrishna KCF_PROV_REFRELE(pd);
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /* called from the CRYPTO_LOAD_DOOR ioctl */
7160Sstevel@tonic-gate int
crypto_load_door(uint_t did)7170Sstevel@tonic-gate crypto_load_door(uint_t did)
7180Sstevel@tonic-gate {
71911751SAnthony.Scarpino@Sun.COM door_handle_t dh;
72011751SAnthony.Scarpino@Sun.COM
7210Sstevel@tonic-gate mutex_enter(&kcf_dh_lock);
72211751SAnthony.Scarpino@Sun.COM dh = door_ki_lookup(did);
72311751SAnthony.Scarpino@Sun.COM if (dh != NULL)
72411751SAnthony.Scarpino@Sun.COM kcf_dh = dh;
7250Sstevel@tonic-gate mutex_exit(&kcf_dh_lock);
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate verify_unverified_providers();
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate /* Start the timeout handler to get random numbers */
7300Sstevel@tonic-gate if (rngtimer_started == 0) {
7310Sstevel@tonic-gate kcf_rnd_schedule_timeout(B_TRUE);
7320Sstevel@tonic-gate rngtimer_started = 1;
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate return (0);
7350Sstevel@tonic-gate }
736