xref: /onnv-gate/usr/src/uts/common/crypto/core/kcf.c (revision 13012:c176c071a066)
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