xref: /illumos-gate/usr/src/uts/common/crypto/spi/kcf_spi.c (revision cb6207858a9fcc2feaee22e626912fba281ac969)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This file is part of the core Kernel Cryptographic Framework.
30  * It implements the SPI functions exported to cryptographic
31  * providers.
32  */
33 
34 #include <sys/ksynch.h>
35 #include <sys/cmn_err.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/modctl.h>
39 #include <sys/crypto/common.h>
40 #include <sys/crypto/impl.h>
41 #include <sys/crypto/sched_impl.h>
42 #include <sys/crypto/spi.h>
43 #include <sys/taskq.h>
44 #include <sys/disp.h>
45 #include <sys/kstat.h>
46 #include <sys/policy.h>
47 
48 /*
49  * minalloc and maxalloc values to be used for taskq_create().
50  */
51 int crypto_taskq_minalloc = CYRPTO_TASKQ_MIN;
52 int crypto_taskq_maxalloc = CRYPTO_TASKQ_MAX;
53 
54 static void free_provider_list(kcf_provider_list_t *);
55 static void remove_provider(kcf_provider_desc_t *);
56 static void process_logical_providers(crypto_provider_info_t *,
57     kcf_provider_desc_t *);
58 static void copy_ops_vector_v1(crypto_ops_t *, crypto_ops_t *);
59 static void copy_ops_vector_v2(crypto_ops_t *, crypto_ops_t *);
60 static int init_prov_mechs(crypto_provider_info_t *, kcf_provider_desc_t *);
61 static int kcf_prov_kstat_update(kstat_t *, int);
62 
63 static kcf_prov_stats_t kcf_stats_ks_data_template = {
64 	{ "kcf_ops_total",		KSTAT_DATA_UINT64 },
65 	{ "kcf_ops_passed",		KSTAT_DATA_UINT64 },
66 	{ "kcf_ops_failed",		KSTAT_DATA_UINT64 },
67 	{ "kcf_ops_returned_busy",	KSTAT_DATA_UINT64 }
68 };
69 
70 #define	KCF_SPI_COPY_OPS(src, dst, ops) if ((src)->ops != NULL) \
71 	*((dst)->ops) = *((src)->ops);
72 
73 /*
74  * This routine is used to add cryptographic providers to the KEF framework.
75  * Providers pass a crypto_provider_info structure to crypto_register_provider()
76  * and get back a handle.  The crypto_provider_info structure contains a
77  * list of mechanisms supported by the provider and an ops vector containing
78  * provider entry points.  Hardware providers call this routine in their attach
79  * routines.  Software providers call this routine in their _init() routine.
80  */
81 int
82 crypto_register_provider(crypto_provider_info_t *info,
83     crypto_kcf_provider_handle_t *handle)
84 {
85 	int i;
86 	int vstatus = 0;
87 	struct modctl *mcp;
88 	char *name;
89 	char ks_name[KSTAT_STRLEN];
90 	crypto_notify_event_change_t ec;
91 
92 	kcf_provider_desc_t *prov_desc = NULL;
93 	int ret = CRYPTO_ARGUMENTS_BAD;
94 
95 	if (info->pi_interface_version > CRYPTO_SPI_VERSION_2)
96 		return (CRYPTO_VERSION_MISMATCH);
97 
98 	/*
99 	 * Check provider type, must be software, hardware, or logical.
100 	 */
101 	if (info->pi_provider_type != CRYPTO_HW_PROVIDER &&
102 	    info->pi_provider_type != CRYPTO_SW_PROVIDER &&
103 	    info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER)
104 		return (CRYPTO_ARGUMENTS_BAD);
105 
106 	/*
107 	 * Allocate and initialize a new provider descriptor. We also
108 	 * hold it and release it when done.
109 	 */
110 	prov_desc = kcf_alloc_provider_desc(info);
111 	KCF_PROV_REFHOLD(prov_desc);
112 
113 	prov_desc->pd_prov_type = info->pi_provider_type;
114 
115 	/* provider-private handle, opaque to KCF */
116 	prov_desc->pd_prov_handle = info->pi_provider_handle;
117 
118 	/* copy provider description string */
119 	if (info->pi_provider_description != NULL) {
120 		/*
121 		 * pi_provider_descriptor is a string that can contain
122 		 * up to CRYPTO_PROVIDER_DESCR_MAX_LEN + 1 characters
123 		 * INCLUDING the terminating null character. A bcopy()
124 		 * is necessary here as pd_description should not have
125 		 * a null character. See comments in kcf_alloc_provider_desc()
126 		 * for details on pd_description field.
127 		 */
128 		bcopy(info->pi_provider_description, prov_desc->pd_description,
129 		    min(strlen(info->pi_provider_description),
130 		    CRYPTO_PROVIDER_DESCR_MAX_LEN));
131 	}
132 
133 	if (info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER) {
134 		if (info->pi_ops_vector == NULL) {
135 			return (CRYPTO_ARGUMENTS_BAD);
136 		}
137 		copy_ops_vector_v1(info->pi_ops_vector,
138 		    prov_desc->pd_ops_vector);
139 		if (info->pi_interface_version == CRYPTO_SPI_VERSION_2) {
140 			copy_ops_vector_v2(info->pi_ops_vector,
141 			    prov_desc->pd_ops_vector);
142 			prov_desc->pd_flags = info->pi_flags;
143 		}
144 	}
145 
146 	/*
147 	 * For software providers, copy the module name and module ID.
148 	 * For hardware providers, copy the driver name and instance.
149 	 */
150 	switch (info->pi_provider_type) {
151 	case  CRYPTO_SW_PROVIDER:
152 		if (info->pi_provider_dev.pd_sw == NULL)
153 			goto bail;
154 
155 		if ((mcp = mod_getctl(info->pi_provider_dev.pd_sw)) == NULL)
156 			goto bail;
157 
158 		prov_desc->pd_module_id = mcp->mod_id;
159 		name = mcp->mod_modname;
160 		break;
161 
162 	case CRYPTO_HW_PROVIDER:
163 	case CRYPTO_LOGICAL_PROVIDER:
164 		if (info->pi_provider_dev.pd_hw == NULL)
165 			goto bail;
166 
167 		prov_desc->pd_instance =
168 		    ddi_get_instance(info->pi_provider_dev.pd_hw);
169 		name = (char *)ddi_driver_name(info->pi_provider_dev.pd_hw);
170 		break;
171 	}
172 	if (name == NULL)
173 		goto bail;
174 
175 	prov_desc->pd_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
176 	(void) strcpy(prov_desc->pd_name, name);
177 
178 	if ((prov_desc->pd_mctlp = kcf_get_modctl(info)) == NULL)
179 		goto bail;
180 
181 	/* process the mechanisms supported by the provider */
182 	if ((ret = init_prov_mechs(info, prov_desc)) != CRYPTO_SUCCESS)
183 		goto bail;
184 
185 	/*
186 	 * Add provider to providers tables, also sets the descriptor
187 	 * pd_prov_id field.
188 	 */
189 	if ((ret = kcf_prov_tab_add_provider(prov_desc)) != CRYPTO_SUCCESS) {
190 		undo_register_provider(prov_desc, B_FALSE);
191 		goto bail;
192 	}
193 
194 	if (info->pi_provider_type != CRYPTO_LOGICAL_PROVIDER) {
195 		if ((vstatus = kcf_verify_signature(prov_desc)) ==
196 		    CRYPTO_MODVERIFICATION_FAILED) {
197 			undo_register_provider(prov_desc, B_TRUE);
198 			ret = CRYPTO_MODVERIFICATION_FAILED;
199 			goto bail;
200 		}
201 	}
202 
203 	/*
204 	 * We create a taskq only for a hardware provider. The global
205 	 * software queue is used for software providers. The taskq
206 	 * is limited to one thread since tasks are guaranteed to be
207 	 * executed in the order they are scheduled, if nthreads == 1. We
208 	 * pass TASKQ_PREPOPULATE flag to keep some entries cached to
209 	 * improve performance.
210 	 */
211 	if (prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER)
212 		prov_desc->pd_sched_info.ks_taskq = taskq_create("kcf_taskq",
213 		    1, minclsyspri, crypto_taskq_minalloc,
214 		    crypto_taskq_maxalloc, TASKQ_PREPOPULATE);
215 	else
216 		prov_desc->pd_sched_info.ks_taskq = NULL;
217 
218 	/* no kernel session to logical providers */
219 	if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
220 		/*
221 		 * Open a session for session-oriented providers. This session
222 		 * is used for all kernel consumers. This is fine as a provider
223 		 * is required to support multiple thread access to a session.
224 		 * We can do this only after the taskq has been created as we
225 		 * do a kcf_submit_request() to open the session.
226 		 */
227 		if (KCF_PROV_SESSION_OPS(prov_desc) != NULL) {
228 			kcf_req_params_t params;
229 
230 			KCF_WRAP_SESSION_OPS_PARAMS(&params,
231 			    KCF_OP_SESSION_OPEN, &prov_desc->pd_sid, 0,
232 			    CRYPTO_USER, NULL, 0, prov_desc);
233 			ret = kcf_submit_request(prov_desc, NULL, NULL, &params,
234 			    B_FALSE);
235 
236 			if (ret != CRYPTO_SUCCESS) {
237 				undo_register_provider(prov_desc, B_TRUE);
238 				ret = CRYPTO_FAILED;
239 				goto bail;
240 			}
241 		}
242 	}
243 
244 	if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
245 		/*
246 		 * Create the kstat for this provider. There is a kstat
247 		 * installed for each successfully registered provider.
248 		 * This kstat is deleted, when the provider unregisters.
249 		 */
250 		if (prov_desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
251 			(void) snprintf(ks_name, KSTAT_STRLEN, "%s_%s",
252 			    prov_desc->pd_name, "provider_stats");
253 		} else {
254 			(void) snprintf(ks_name, KSTAT_STRLEN, "%s_%d_%u_%s",
255 			    prov_desc->pd_name, prov_desc->pd_instance,
256 			    prov_desc->pd_prov_id, "provider_stats");
257 		}
258 
259 		prov_desc->pd_kstat = kstat_create("kcf", 0, ks_name, "crypto",
260 		    KSTAT_TYPE_NAMED, sizeof (kcf_prov_stats_t) /
261 		    sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
262 
263 		if (prov_desc->pd_kstat != NULL) {
264 			bcopy(&kcf_stats_ks_data_template,
265 			    &prov_desc->pd_ks_data,
266 			    sizeof (kcf_stats_ks_data_template));
267 			prov_desc->pd_kstat->ks_data = &prov_desc->pd_ks_data;
268 			KCF_PROV_REFHOLD(prov_desc);
269 			KCF_PROV_IREFHOLD(prov_desc);
270 			prov_desc->pd_kstat->ks_private = prov_desc;
271 			prov_desc->pd_kstat->ks_update = kcf_prov_kstat_update;
272 			kstat_install(prov_desc->pd_kstat);
273 		}
274 	}
275 
276 	if (prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER)
277 		process_logical_providers(info, prov_desc);
278 
279 	/*
280 	 * Inform interested clients of the mechanisms becoming
281 	 * available. We skip this for logical providers as they
282 	 * do not affect mechanisms.
283 	 */
284 	if (prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
285 		ec.ec_provider_type = prov_desc->pd_prov_type;
286 		ec.ec_change = CRYPTO_MECH_ADDED;
287 		for (i = 0; i < prov_desc->pd_mech_list_count; i++) {
288 			/* Skip any mechanisms not allowed by the policy */
289 			if (is_mech_disabled(prov_desc,
290 			    prov_desc->pd_mechanisms[i].cm_mech_name))
291 				continue;
292 
293 			(void) strncpy(ec.ec_mech_name,
294 			    prov_desc->pd_mechanisms[i].cm_mech_name,
295 			    CRYPTO_MAX_MECH_NAME);
296 			kcf_walk_ntfylist(CRYPTO_EVENT_MECHS_CHANGED, &ec);
297 		}
298 
299 	}
300 
301 	/*
302 	 * Inform interested clients of the new provider. In case of a
303 	 * logical provider, we need to notify the event only
304 	 * for the logical provider and not for the underlying
305 	 * providers which are known by pi_logical_provider_count > 0.
306 	 */
307 	if (prov_desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER ||
308 	    info->pi_logical_provider_count == 0)
309 		kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDER_REGISTERED, prov_desc);
310 
311 	mutex_enter(&prov_desc->pd_lock);
312 	prov_desc->pd_state = (vstatus == 0) ? KCF_PROV_READY :
313 	    KCF_PROV_UNVERIFIED;
314 	mutex_exit(&prov_desc->pd_lock);
315 
316 	*handle = prov_desc->pd_kcf_prov_handle;
317 	KCF_PROV_REFRELE(prov_desc);
318 	return (CRYPTO_SUCCESS);
319 
320 bail:
321 	KCF_PROV_REFRELE(prov_desc);
322 	return (ret);
323 }
324 
325 /*
326  * This routine is used to notify the framework when a provider is being
327  * removed.  Hardware providers call this routine in their detach routines.
328  * Software providers call this routine in their _fini() routine.
329  */
330 int
331 crypto_unregister_provider(crypto_kcf_provider_handle_t handle)
332 {
333 	int i;
334 	uint_t mech_idx;
335 	kcf_provider_desc_t *desc;
336 	crypto_notify_event_change_t ec;
337 	kcf_prov_state_t saved_state;
338 
339 	/* lookup provider descriptor */
340 	if ((desc = kcf_prov_tab_lookup((crypto_provider_id_t)handle)) == NULL)
341 		return (CRYPTO_UNKNOWN_PROVIDER);
342 
343 	mutex_enter(&desc->pd_lock);
344 	/*
345 	 * Check if any other thread is disabling or removing
346 	 * this provider. We return if this is the case.
347 	 */
348 	if (desc->pd_state >= KCF_PROV_DISABLED) {
349 		mutex_exit(&desc->pd_lock);
350 		/* Release reference held by kcf_prov_tab_lookup(). */
351 		KCF_PROV_REFRELE(desc);
352 		return (CRYPTO_BUSY);
353 	}
354 
355 	saved_state = desc->pd_state;
356 	desc->pd_state = KCF_PROV_REMOVED;
357 
358 	if (saved_state == KCF_PROV_BUSY) {
359 		/*
360 		 * The per-provider taskq thread may be waiting. We
361 		 * signal it so that it can start failing requests.
362 		 * Note that we do not need a cv_broadcast() as we keep
363 		 * only a single thread per taskq.
364 		 */
365 		cv_signal(&desc->pd_resume_cv);
366 	}
367 
368 	if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
369 		/*
370 		 * Check if this provider is currently being used.
371 		 * pd_irefcnt is the number of holds from the internal
372 		 * structures. We add one to account for the above lookup.
373 		 */
374 		if (desc->pd_refcnt > desc->pd_irefcnt + 1) {
375 			desc->pd_state = saved_state;
376 			mutex_exit(&desc->pd_lock);
377 			/* Release reference held by kcf_prov_tab_lookup(). */
378 			KCF_PROV_REFRELE(desc);
379 			/*
380 			 * The administrator presumably will stop the clients
381 			 * thus removing the holds, when they get the busy
382 			 * return value.  Any retry will succeed then.
383 			 */
384 			return (CRYPTO_BUSY);
385 		}
386 	}
387 	mutex_exit(&desc->pd_lock);
388 
389 	if (desc->pd_prov_type != CRYPTO_SW_PROVIDER) {
390 		remove_provider(desc);
391 	}
392 
393 	if (desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
394 		/* remove the provider from the mechanisms tables */
395 		for (mech_idx = 0; mech_idx < desc->pd_mech_list_count;
396 		    mech_idx++) {
397 			kcf_remove_mech_provider(
398 			    desc->pd_mechanisms[mech_idx].cm_mech_name, desc);
399 		}
400 	}
401 
402 	/* remove provider from providers table */
403 	if (kcf_prov_tab_rem_provider((crypto_provider_id_t)handle) !=
404 	    CRYPTO_SUCCESS) {
405 		/* Release reference held by kcf_prov_tab_lookup(). */
406 		KCF_PROV_REFRELE(desc);
407 		return (CRYPTO_UNKNOWN_PROVIDER);
408 	}
409 
410 	/* destroy the kstat created for this provider */
411 	if (desc->pd_kstat != NULL) {
412 		kcf_provider_desc_t *kspd = desc->pd_kstat->ks_private;
413 
414 		/* release reference held by desc->pd_kstat->ks_private */
415 		ASSERT(desc == kspd);
416 		kstat_delete(kspd->pd_kstat);
417 		KCF_PROV_REFRELE(kspd);
418 		KCF_PROV_IREFRELE(kspd);
419 	}
420 
421 	if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
422 		/* Release reference held by kcf_prov_tab_lookup(). */
423 		KCF_PROV_REFRELE(desc);
424 
425 		/*
426 		 * Wait till the existing requests complete.
427 		 */
428 		mutex_enter(&desc->pd_lock);
429 		while (desc->pd_state != KCF_PROV_FREED)
430 			cv_wait(&desc->pd_remove_cv, &desc->pd_lock);
431 		mutex_exit(&desc->pd_lock);
432 	} else {
433 		/*
434 		 * Wait until requests that have been sent to the provider
435 		 * complete.
436 		 */
437 		mutex_enter(&desc->pd_lock);
438 		while (desc->pd_irefcnt > 0)
439 			cv_wait(&desc->pd_remove_cv, &desc->pd_lock);
440 		mutex_exit(&desc->pd_lock);
441 	}
442 
443 	/*
444 	 * Inform interested clients of the mechanisms becoming
445 	 * unavailable. We skip this for logical providers as they
446 	 * do not affect mechanisms.
447 	 */
448 	if (desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
449 		ec.ec_provider_type = desc->pd_prov_type;
450 		ec.ec_change = CRYPTO_MECH_REMOVED;
451 		for (i = 0; i < desc->pd_mech_list_count; i++) {
452 			/* Skip any mechanisms not allowed by the policy */
453 			if (is_mech_disabled(desc,
454 			    desc->pd_mechanisms[i].cm_mech_name))
455 				continue;
456 
457 			(void) strncpy(ec.ec_mech_name,
458 			    desc->pd_mechanisms[i].cm_mech_name,
459 			    CRYPTO_MAX_MECH_NAME);
460 			kcf_walk_ntfylist(CRYPTO_EVENT_MECHS_CHANGED, &ec);
461 		}
462 
463 	}
464 
465 	/*
466 	 * Inform interested clients about the departing provider.
467 	 * In case of a logical provider, we need to notify the event only
468 	 * for the logical provider and not for the underlying
469 	 * providers which are known by the KCF_LPROV_MEMBER bit.
470 	 */
471 	if (desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER ||
472 	    (desc->pd_flags & KCF_LPROV_MEMBER) == 0)
473 		kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDER_UNREGISTERED, desc);
474 
475 	if (desc->pd_prov_type == CRYPTO_SW_PROVIDER) {
476 		/*
477 		 * This is the only place where kcf_free_provider_desc()
478 		 * is called directly. KCF_PROV_REFRELE() should free the
479 		 * structure in all other places.
480 		 */
481 		ASSERT(desc->pd_state == KCF_PROV_FREED &&
482 		    desc->pd_refcnt == 0);
483 		kcf_free_provider_desc(desc);
484 	} else {
485 		KCF_PROV_REFRELE(desc);
486 	}
487 
488 	return (CRYPTO_SUCCESS);
489 }
490 
491 /*
492  * This routine is used to notify the framework that the state of
493  * a cryptographic provider has changed. Valid state codes are:
494  *
495  * CRYPTO_PROVIDER_READY
496  * 	The provider indicates that it can process more requests. A provider
497  *	will notify with this event if it previously has notified us with a
498  *	CRYPTO_PROVIDER_BUSY.
499  *
500  * CRYPTO_PROVIDER_BUSY
501  * 	The provider can not take more requests.
502  *
503  * CRYPTO_PROVIDER_FAILED
504  *	The provider encountered an internal error. The framework will not
505  * 	be sending any more requests to the provider. The provider may notify
506  *	with a CRYPTO_PROVIDER_READY, if it is able to recover from the error.
507  *
508  * This routine can be called from user or interrupt context.
509  */
510 void
511 crypto_provider_notification(crypto_kcf_provider_handle_t handle, uint_t state)
512 {
513 	kcf_provider_desc_t *pd;
514 
515 	/* lookup the provider from the given handle */
516 	if ((pd = kcf_prov_tab_lookup((crypto_provider_id_t)handle)) == NULL)
517 		return;
518 
519 	mutex_enter(&pd->pd_lock);
520 
521 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
522 		cmn_err(CE_WARN, "crypto_provider_notification: "
523 		    "logical provider (%x) ignored\n", handle);
524 		goto out;
525 	}
526 	switch (state) {
527 	case CRYPTO_PROVIDER_READY:
528 		switch (pd->pd_state) {
529 		case KCF_PROV_BUSY:
530 			pd->pd_state = KCF_PROV_READY;
531 			/*
532 			 * Signal the per-provider taskq thread that it
533 			 * can start submitting requests. Note that we do
534 			 * not need a cv_broadcast() as we keep only a
535 			 * single thread per taskq.
536 			 */
537 			cv_signal(&pd->pd_resume_cv);
538 			break;
539 
540 		case KCF_PROV_FAILED:
541 			/*
542 			 * The provider recovered from the error. Let us
543 			 * use it now.
544 			 */
545 			pd->pd_state = KCF_PROV_READY;
546 			break;
547 		}
548 		break;
549 
550 	case CRYPTO_PROVIDER_BUSY:
551 		switch (pd->pd_state) {
552 		case KCF_PROV_READY:
553 			pd->pd_state = KCF_PROV_BUSY;
554 			break;
555 		}
556 		break;
557 
558 	case CRYPTO_PROVIDER_FAILED:
559 		/*
560 		 * We note the failure and return. The per-provider taskq
561 		 * thread checks this flag and starts failing the
562 		 * requests, if it is set. See process_req_hwp() for details.
563 		 */
564 		switch (pd->pd_state) {
565 		case KCF_PROV_READY:
566 			pd->pd_state = KCF_PROV_FAILED;
567 			break;
568 
569 		case KCF_PROV_BUSY:
570 			pd->pd_state = KCF_PROV_FAILED;
571 			/*
572 			 * The per-provider taskq thread may be waiting. We
573 			 * signal it so that it can start failing requests.
574 			 */
575 			cv_signal(&pd->pd_resume_cv);
576 			break;
577 		}
578 		break;
579 	}
580 out:
581 	mutex_exit(&pd->pd_lock);
582 	KCF_PROV_REFRELE(pd);
583 }
584 
585 /*
586  * This routine is used to notify the framework the result of
587  * an asynchronous request handled by a provider. Valid error
588  * codes are the same as the CRYPTO_* errors defined in common.h.
589  *
590  * This routine can be called from user or interrupt context.
591  */
592 void
593 crypto_op_notification(crypto_req_handle_t handle, int error)
594 {
595 	kcf_call_type_t ctype;
596 
597 	if ((ctype = GET_REQ_TYPE(handle)) == CRYPTO_SYNCH) {
598 		kcf_sreq_node_t *sreq = (kcf_sreq_node_t *)handle;
599 
600 		if (error != CRYPTO_SUCCESS)
601 			sreq->sn_provider->pd_sched_info.ks_nfails++;
602 		KCF_PROV_IREFRELE(sreq->sn_provider);
603 		kcf_sop_done(sreq, error);
604 	} else {
605 		kcf_areq_node_t *areq = (kcf_areq_node_t *)handle;
606 
607 		ASSERT(ctype == CRYPTO_ASYNCH);
608 		if (error != CRYPTO_SUCCESS)
609 			areq->an_provider->pd_sched_info.ks_nfails++;
610 		KCF_PROV_IREFRELE(areq->an_provider);
611 		kcf_aop_done(areq, error);
612 	}
613 }
614 
615 /*
616  * This routine is used by software providers to determine
617  * whether to use KM_SLEEP or KM_NOSLEEP during memory allocation.
618  * Note that hardware providers can always use KM_SLEEP. So,
619  * they do not need to call this routine.
620  *
621  * This routine can be called from user or interrupt context.
622  */
623 int
624 crypto_kmflag(crypto_req_handle_t handle)
625 {
626 	return (REQHNDL2_KMFLAG(handle));
627 }
628 
629 
630 /*
631  * Copy an ops vector from src to dst. Used during provider registration
632  * to copy the ops vector from the provider info structure to the
633  * provider descriptor maintained by KCF.
634  * Copying the ops vector specified by the provider is needed since the
635  * framework does not require the provider info structure to be
636  * persistent.
637  */
638 static void
639 copy_ops_vector_v1(crypto_ops_t *src_ops, crypto_ops_t *dst_ops)
640 {
641 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_control_ops);
642 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_digest_ops);
643 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_cipher_ops);
644 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_mac_ops);
645 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_sign_ops);
646 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_verify_ops);
647 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_dual_ops);
648 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_dual_cipher_mac_ops);
649 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_random_ops);
650 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_session_ops);
651 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_object_ops);
652 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_key_ops);
653 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_provider_ops);
654 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_ctx_ops);
655 }
656 
657 static void
658 copy_ops_vector_v2(crypto_ops_t *src_ops, crypto_ops_t *dst_ops)
659 {
660 	KCF_SPI_COPY_OPS(src_ops, dst_ops, co_mech_ops);
661 }
662 
663 /*
664  * Process the mechanism info structures specified by the provider
665  * during registration. A NULL crypto_provider_info_t indicates
666  * an already initialized provider descriptor.
667  *
668  * Mechanisms are not added to the kernel's mechanism table if the
669  * provider is a logical provider.
670  *
671  * Returns CRYPTO_SUCCESS on success, CRYPTO_ARGUMENTS if one
672  * of the specified mechanisms was malformed, or CRYPTO_HOST_MEMORY
673  * if the table of mechanisms is full.
674  */
675 static int
676 init_prov_mechs(crypto_provider_info_t *info, kcf_provider_desc_t *desc)
677 {
678 	uint_t mech_idx;
679 	uint_t cleanup_idx;
680 	int err = CRYPTO_SUCCESS;
681 	kcf_prov_mech_desc_t *pmd;
682 	int desc_use_count = 0;
683 	int mcount = desc->pd_mech_list_count;
684 
685 	if (desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
686 		if (info != NULL) {
687 			ASSERT(info->pi_mechanisms != NULL);
688 			bcopy(info->pi_mechanisms, desc->pd_mechanisms,
689 			    sizeof (crypto_mech_info_t) * mcount);
690 		}
691 		return (CRYPTO_SUCCESS);
692 	}
693 
694 	/*
695 	 * Copy the mechanism list from the provider info to the provider
696 	 * descriptor. desc->pd_mechanisms has an extra crypto_mech_info_t
697 	 * element if the provider has random_ops since we keep an internal
698 	 * mechanism, SUN_RANDOM, in this case.
699 	 */
700 	if (info != NULL) {
701 		if (info->pi_ops_vector->co_random_ops != NULL) {
702 			crypto_mech_info_t *rand_mi;
703 
704 			/*
705 			 * Need the following check as it is possible to have
706 			 * a provider that implements just random_ops and has
707 			 * pi_mechanisms == NULL.
708 			 */
709 			if (info->pi_mechanisms != NULL) {
710 				bcopy(info->pi_mechanisms, desc->pd_mechanisms,
711 				    sizeof (crypto_mech_info_t) * (mcount - 1));
712 			}
713 			rand_mi = &desc->pd_mechanisms[mcount - 1];
714 
715 			bzero(rand_mi, sizeof (crypto_mech_info_t));
716 			(void) strncpy(rand_mi->cm_mech_name, SUN_RANDOM,
717 			    CRYPTO_MAX_MECH_NAME);
718 			rand_mi->cm_func_group_mask = CRYPTO_FG_RANDOM;
719 		} else {
720 			ASSERT(info->pi_mechanisms != NULL);
721 			bcopy(info->pi_mechanisms, desc->pd_mechanisms,
722 			    sizeof (crypto_mech_info_t) * mcount);
723 		}
724 	}
725 
726 	/*
727 	 * For each mechanism support by the provider, add the provider
728 	 * to the corresponding KCF mechanism mech_entry chain.
729 	 */
730 	for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; mech_idx++) {
731 		crypto_mech_info_t *mi = &desc->pd_mechanisms[mech_idx];
732 
733 		if ((mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BITS) &&
734 		    (mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BYTES)) {
735 			err = CRYPTO_ARGUMENTS_BAD;
736 			break;
737 		}
738 
739 		if (kcf_add_mech_provider(mech_idx, desc, &pmd) != KCF_SUCCESS)
740 			break;
741 
742 		if (pmd == NULL)
743 			continue;
744 
745 		/* The provider will be used for this mechanism */
746 		desc_use_count++;
747 	}
748 
749 	/*
750 	 * Don't allow multiple software providers with disabled mechanisms
751 	 * to register. Subsequent enabling of mechanisms will result in
752 	 * an unsupported configuration, i.e. multiple software providers
753 	 * per mechanism.
754 	 */
755 	if (desc_use_count == 0 && desc->pd_prov_type == CRYPTO_SW_PROVIDER)
756 		return (CRYPTO_ARGUMENTS_BAD);
757 
758 	if (err == KCF_SUCCESS)
759 		return (CRYPTO_SUCCESS);
760 
761 	/*
762 	 * An error occurred while adding the mechanism, cleanup
763 	 * and bail.
764 	 */
765 	for (cleanup_idx = 0; cleanup_idx < mech_idx; cleanup_idx++) {
766 		kcf_remove_mech_provider(
767 		    desc->pd_mechanisms[cleanup_idx].cm_mech_name, desc);
768 	}
769 
770 	if (err == KCF_MECH_TAB_FULL)
771 		return (CRYPTO_HOST_MEMORY);
772 
773 	return (CRYPTO_ARGUMENTS_BAD);
774 }
775 
776 /*
777  * Update routine for kstat. Only privileged users are allowed to
778  * access this information, since this information is sensitive.
779  * There are some cryptographic attacks (e.g. traffic analysis)
780  * which can use this information.
781  */
782 static int
783 kcf_prov_kstat_update(kstat_t *ksp, int rw)
784 {
785 	kcf_prov_stats_t *ks_data;
786 	kcf_provider_desc_t *pd = (kcf_provider_desc_t *)ksp->ks_private;
787 
788 	if (rw == KSTAT_WRITE)
789 		return (EACCES);
790 
791 	ks_data = ksp->ks_data;
792 
793 	if (secpolicy_sys_config(CRED(), B_TRUE) != 0) {
794 		ks_data->ps_ops_total.value.ui64 = 0;
795 		ks_data->ps_ops_passed.value.ui64 = 0;
796 		ks_data->ps_ops_failed.value.ui64 = 0;
797 		ks_data->ps_ops_busy_rval.value.ui64 = 0;
798 	} else {
799 		ks_data->ps_ops_total.value.ui64 =
800 		    pd->pd_sched_info.ks_ndispatches;
801 		ks_data->ps_ops_failed.value.ui64 =
802 		    pd->pd_sched_info.ks_nfails;
803 		ks_data->ps_ops_busy_rval.value.ui64 =
804 		    pd->pd_sched_info.ks_nbusy_rval;
805 		ks_data->ps_ops_passed.value.ui64 =
806 		    pd->pd_sched_info.ks_ndispatches -
807 		    pd->pd_sched_info.ks_nfails -
808 		    pd->pd_sched_info.ks_nbusy_rval;
809 	}
810 
811 	return (0);
812 }
813 
814 
815 /*
816  * Utility routine called from failure paths in crypto_register_provider()
817  * and from crypto_load_soft_disabled().
818  */
819 void
820 undo_register_provider(kcf_provider_desc_t *desc, boolean_t remove_prov)
821 {
822 	uint_t mech_idx;
823 
824 	/* remove the provider from the mechanisms tables */
825 	for (mech_idx = 0; mech_idx < desc->pd_mech_list_count;
826 	    mech_idx++) {
827 		kcf_remove_mech_provider(
828 		    desc->pd_mechanisms[mech_idx].cm_mech_name, desc);
829 	}
830 
831 	/* remove provider from providers table */
832 	if (remove_prov)
833 		(void) kcf_prov_tab_rem_provider(desc->pd_prov_id);
834 }
835 
836 /*
837  * Utility routine called from crypto_load_soft_disabled(). Callers
838  * should have done a prior undo_register_provider().
839  */
840 void
841 redo_register_provider(kcf_provider_desc_t *pd)
842 {
843 	/* process the mechanisms supported by the provider */
844 	(void) init_prov_mechs(NULL, pd);
845 
846 	/*
847 	 * Hold provider in providers table. We should not call
848 	 * kcf_prov_tab_add_provider() here as the provider descriptor
849 	 * is still valid which means it has an entry in the provider
850 	 * table.
851 	 */
852 	KCF_PROV_REFHOLD(pd);
853 	KCF_PROV_IREFHOLD(pd);
854 }
855 
856 /*
857  * Add provider (p1) to another provider's array of providers (p2).
858  * Hardware and logical providers use this array to cross-reference
859  * each other.
860  */
861 static void
862 add_provider_to_array(kcf_provider_desc_t *p1, kcf_provider_desc_t *p2)
863 {
864 	kcf_provider_list_t *new;
865 
866 	new = kmem_alloc(sizeof (kcf_provider_list_t), KM_SLEEP);
867 	mutex_enter(&p2->pd_lock);
868 	new->pl_next = p2->pd_provider_list;
869 	p2->pd_provider_list = new;
870 	KCF_PROV_IREFHOLD(p1);
871 	new->pl_provider = p1;
872 	mutex_exit(&p2->pd_lock);
873 }
874 
875 /*
876  * Remove provider (p1) from another provider's array of providers (p2).
877  * Hardware and logical providers use this array to cross-reference
878  * each other.
879  */
880 static void
881 remove_provider_from_array(kcf_provider_desc_t *p1, kcf_provider_desc_t *p2)
882 {
883 
884 	kcf_provider_list_t *pl = NULL, **prev;
885 
886 	mutex_enter(&p2->pd_lock);
887 	for (pl = p2->pd_provider_list, prev = &p2->pd_provider_list;
888 	    pl != NULL; prev = &pl->pl_next, pl = pl->pl_next) {
889 		if (pl->pl_provider == p1) {
890 			break;
891 		}
892 	}
893 
894 	if (p1 == NULL) {
895 		mutex_exit(&p2->pd_lock);
896 		return;
897 	}
898 
899 	/* detach and free kcf_provider_list structure */
900 	KCF_PROV_IREFRELE(p1);
901 	*prev = pl->pl_next;
902 	kmem_free(pl, sizeof (*pl));
903 	mutex_exit(&p2->pd_lock);
904 }
905 
906 /*
907  * Convert an array of logical provider handles (crypto_provider_id)
908  * stored in a crypto_provider_info structure into an array of provider
909  * descriptors (kcf_provider_desc_t) attached to a logical provider.
910  */
911 static void
912 process_logical_providers(crypto_provider_info_t *info, kcf_provider_desc_t *hp)
913 {
914 	kcf_provider_desc_t *lp;
915 	crypto_provider_id_t handle;
916 	int count = info->pi_logical_provider_count;
917 	int i;
918 
919 	/* add hardware provider to each logical provider */
920 	for (i = 0; i < count; i++) {
921 		handle = info->pi_logical_providers[i];
922 		lp = kcf_prov_tab_lookup((crypto_provider_id_t)handle);
923 		if (lp == NULL) {
924 			continue;
925 		}
926 		add_provider_to_array(hp, lp);
927 		hp->pd_flags |= KCF_LPROV_MEMBER;
928 
929 		/*
930 		 * A hardware provider has to have the provider descriptor of
931 		 * every logical provider it belongs to, so it can be removed
932 		 * from the logical provider if the hardware provider
933 		 * unregisters from the framework.
934 		 */
935 		add_provider_to_array(lp, hp);
936 		KCF_PROV_REFRELE(lp);
937 	}
938 }
939 
940 /*
941  * This routine removes a provider from all of the logical or
942  * hardware providers it belongs to, and frees the provider's
943  * array of pointers to providers.
944  */
945 static void
946 remove_provider(kcf_provider_desc_t *pp)
947 {
948 	kcf_provider_desc_t *p;
949 	kcf_provider_list_t *e, *next;
950 
951 	mutex_enter(&pp->pd_lock);
952 	for (e = pp->pd_provider_list; e != NULL; e = next) {
953 		p = e->pl_provider;
954 		remove_provider_from_array(pp, p);
955 		if (p->pd_prov_type == CRYPTO_HW_PROVIDER &&
956 		    p->pd_provider_list == NULL)
957 			p->pd_flags &= ~KCF_LPROV_MEMBER;
958 		KCF_PROV_IREFRELE(p);
959 		next = e->pl_next;
960 		kmem_free(e, sizeof (*e));
961 	}
962 	pp->pd_provider_list = NULL;
963 	mutex_exit(&pp->pd_lock);
964 }
965