xref: /illumos-gate/usr/src/uts/common/crypto/api/kcf_miscapi.c (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/sunddi.h>
31 #include <sys/disp.h>
32 #include <sys/modctl.h>
33 #include <sys/sysmacros.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/api.h>
36 #include <sys/crypto/impl.h>
37 #include <sys/crypto/sched_impl.h>
38 
39 #define	isspace(ch)	(((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
40 			((ch) == '\t') || ((ch) == '\f'))
41 
42 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
43 #define	CRYPTO_KEY_OFFSET(f)		offsetof(crypto_key_ops_t, f)
44 #define	CRYPTO_PROVIDER_OFFSET(f)	\
45 	offsetof(crypto_provider_management_ops_t, f)
46 
47 /* Miscellaneous exported entry points */
48 
49 /*
50  * All event subscribers are put on a list. kcf_notify_list_lock
51  * protects changes to this list.
52  *
53  * The following locking order is maintained in the code - The
54  * global kcf_notify_list_lock followed by the individual lock
55  * in a kcf_ntfy_elem structure (kn_lock).
56  */
57 kmutex_t		ntfy_list_lock;
58 kcondvar_t		ntfy_list_cv;   /* cv the service thread waits on */
59 static kcf_ntfy_elem_t *ntfy_list_head;
60 static kcf_ntfy_elem_t *ntfy_list_tail;
61 
62 /* count all the hardware and software providers */
63 #define	PROV_COUNT(me) \
64 	(((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov)
65 
66 /*
67  * crypto_mech2id()
68  *
69  * Arguments:
70  *	. mechname: A null-terminated string identifying the mechanism name.
71  *
72  * Description:
73  *	Walks the mechanisms tables, looking for an entry that matches the
74  *	mechname. Once it find it, it builds the 64-bit mech_type and returns
75  *	it.  If there are no hardware or software providers for the mechanism,
76  *	but there is an unloaded software provider, this routine will attempt
77  *	to load it.
78  *
79  * Context:
80  *	Process and interruption.
81  *
82  * Returns:
83  *	The unique mechanism identified by 'mechname', if found.
84  *	CRYPTO_MECH_INVALID otherwise.
85  */
86 crypto_mech_type_t
87 crypto_mech2id(char *mechname)
88 {
89 	return (crypto_mech2id_common(mechname, B_TRUE));
90 }
91 
92 /*
93  * crypto_get_mech_list()
94  *
95  * Arguments:
96  *	. countp: pointer to contain the number of mech names returned
97  *	. kmflag: memory allocation flag.
98  *
99  * Description:
100  *	Allocates an array of crypto_mech_name_t containing all the mechanisms
101  *	currently available on the system. Sets *countp with the number of
102  *	mechanism names returned.
103  *
104  *	We get a list of mech names which have a hardware provider by walking
105  *	all the mechanism tables. We merge them with mech names obtained from
106  *	the hint list. A mech name in the hint list is considered only if it
107  *	is not disabled for the provider. Note that the hint list contains only
108  *	software providers and the mech names supported by them.
109  *
110  * Context:
111  *	Process and interruption. kmflag should be KM_NOSLEEP when called
112  *	from an interruption context.
113  *
114  * Returns:
115  *	The array of the crypto_mech_t allocated.
116  *	NULL otherwise.
117  */
118 crypto_mech_name_t *
119 crypto_get_mech_list(uint_t *countp, int kmflag)
120 {
121 	uint_t count = 0, me_tab_size, i, j;
122 	kcf_ops_class_t cl;
123 	kcf_mech_entry_t *me, *me_tab;
124 	crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab;
125 	char *mech_name, *hint_mech, *end;
126 	kcf_soft_conf_entry_t *p;
127 	size_t n;
128 
129 	/*
130 	 * Count the maximum possible mechanisms that can come from the
131 	 * hint list.
132 	 */
133 	mutex_enter(&soft_config_mutex);
134 	p = soft_config_list;
135 	while (p != NULL) {
136 		count += p->ce_count;
137 		p = p->ce_next;
138 	}
139 	mutex_exit(&soft_config_mutex);
140 
141 	/* First let's count'em, for mem allocation */
142 	for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
143 		me_tab_size = kcf_mech_tabs_tab[cl].met_size;
144 		me_tab = kcf_mech_tabs_tab[cl].met_tab;
145 		for (i = 0; i < me_tab_size; i++) {
146 			me = &me_tab[i];
147 			mutex_enter(&(me->me_mutex));
148 			if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
149 				ASSERT(me->me_hw_prov_chain != NULL);
150 				count++;
151 			}
152 			mutex_exit(&(me->me_mutex));
153 		}
154 	}
155 
156 	/*
157 	 * Allocate a buffer to hold the mechanisms from
158 	 * mech tabs and mechanisms from the hint list.
159 	 */
160 	n = count * CRYPTO_MAX_MECH_NAME;
161 
162 again:
163 	count = 0;
164 	tmp_mech_name_tab = kmem_zalloc(n, kmflag);
165 	if (tmp_mech_name_tab == NULL) {
166 		*countp = 0;
167 		return (NULL);
168 	}
169 
170 	/*
171 	 * Second round, fill in the table
172 	 */
173 
174 	mech_name = (char *)tmp_mech_name_tab;
175 	end = mech_name + n;
176 
177 	for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
178 		me_tab_size = kcf_mech_tabs_tab[cl].met_size;
179 		me_tab = kcf_mech_tabs_tab[cl].met_tab;
180 		for (i = 0; i < me_tab_size; i++) {
181 			me = &me_tab[i];
182 			mutex_enter(&(me->me_mutex));
183 			if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
184 				ASSERT(me->me_hw_prov_chain != NULL);
185 				if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
186 					mutex_exit(&(me->me_mutex));
187 					kmem_free(tmp_mech_name_tab, n);
188 					n = n << 1;
189 					goto again;
190 				}
191 				(void) strncpy(mech_name, me->me_name,
192 				    CRYPTO_MAX_MECH_NAME);
193 
194 				mech_name += CRYPTO_MAX_MECH_NAME;
195 				count++;
196 			}
197 			mutex_exit(&(me->me_mutex));
198 		}
199 	}
200 
201 	/*
202 	 * Search tmp_mech_name_tab for each mechanism in the hint list. We
203 	 * have to add any new mechanisms found in the hint list. Note that we
204 	 * should not modload the providers here as it will be too early. It
205 	 * may be the case that the caller never uses a provider.
206 	 */
207 	mutex_enter(&soft_config_mutex);
208 	p = soft_config_list;
209 	while (p != NULL) {
210 		for (i = 0; i < p->ce_count; i++) {
211 			hint_mech = p->ce_mechs[i];
212 
213 			/* Do not consider the mechanism if it is disabled. */
214 			if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER,
215 			    p->ce_name, 0, hint_mech))
216 				continue;
217 
218 			/*
219 			 * There may be duplicate mechanisms in the hint list.
220 			 * So, we need to search all the entries that have been
221 			 * added so far. That number would be count.
222 			 */
223 			for (j = 0; j < count; j++) {
224 				if (strcmp(hint_mech,
225 				    tmp_mech_name_tab[j]) == 0)
226 					break;
227 			}
228 
229 			if (j == count) {	/* This is a new one. Add it. */
230 				ASSERT((char *)&tmp_mech_name_tab[count] ==
231 				    mech_name);
232 				if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
233 					mutex_exit(&soft_config_mutex);
234 					kmem_free(tmp_mech_name_tab, n);
235 					n = n << 1;
236 					goto again;
237 				}
238 				(void) strncpy(tmp_mech_name_tab[count],
239 				    hint_mech, CRYPTO_MAX_MECH_NAME);
240 				mech_name += CRYPTO_MAX_MECH_NAME;
241 				count++;
242 			}
243 		}
244 		p = p->ce_next;
245 	}
246 	mutex_exit(&soft_config_mutex);
247 
248 	/*
249 	 * Check if we have consumed all of the space. We are done if
250 	 * this is the case.
251 	 */
252 	ASSERT(mech_name <= end);
253 	if (mech_name == end) {
254 		mech_name_tab = tmp_mech_name_tab;
255 		goto done;
256 	}
257 
258 	/*
259 	 * Allocate a buffer of the right size now that we have the
260 	 * correct count.
261 	 */
262 	mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag);
263 	if (mech_name_tab == NULL) {
264 		kmem_free(tmp_mech_name_tab, n);
265 		*countp = 0;
266 		return (NULL);
267 	}
268 
269 	bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME);
270 	kmem_free(tmp_mech_name_tab, n);
271 
272 done:
273 	*countp = count;
274 	return (mech_name_tab);
275 }
276 
277 /*
278  * crypto_free_mech_list()
279  *
280  * Arguments:
281  *	. mech_names: An array of crypto_mech_name_t previously allocated by
282  *	  crypto_get_mech_list.
283  *	. count: the number of mech names in mech_names
284  *
285  * Description:
286  *	Frees the the mech_names array.
287  *
288  * Context:
289  *	Process and interruption.
290  */
291 void
292 crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count)
293 {
294 	if ((mech_names != NULL) && (count > 0))
295 		kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME);
296 }
297 
298 /*
299  * crypto_notify_events()
300  *
301  * Arguments:
302  *	. nf: Callback function to invoke when event occurs.
303  *	. event_mask: Mask of events.
304  *
305  * Description:
306  *	Allocates a new element and inserts it in to the notification
307  *	list.
308  *
309  * Context:
310  *	Process context.
311  *
312  * Returns:
313  *	A handle is returned if the client is put on the notification list.
314  *	NULL is returned otherwise.
315  */
316 crypto_notify_handle_t
317 crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask)
318 {
319 	kcf_ntfy_elem_t *nep;
320 	crypto_notify_handle_t hndl;
321 
322 	/*
323 	 * The only valid value for event_mask is CRYPTO_EVENT_PROVIDERS_CHANGE.
324 	 */
325 	if (nf == NULL || !(event_mask & CRYPTO_EVENT_PROVIDERS_CHANGE)) {
326 		return (NULL);
327 	}
328 
329 	nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP);
330 	mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL);
331 	cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL);
332 	nep->kn_state = NTFY_WAITING;
333 	nep->kn_func = nf;
334 	nep->kn_event_mask = event_mask;
335 
336 	mutex_enter(&ntfy_list_lock);
337 	if (ntfy_list_head == NULL) {
338 		ntfy_list_head = ntfy_list_tail = nep;
339 	} else {
340 		ntfy_list_tail->kn_next = nep;
341 		nep->kn_prev = ntfy_list_tail;
342 		ntfy_list_tail = nep;
343 	}
344 
345 	hndl = (crypto_notify_handle_t)nep;
346 	mutex_exit(&ntfy_list_lock);
347 
348 	return (hndl);
349 }
350 
351 /*
352  * crypto_unnotify_events()
353  *
354  * Arguments:
355  *	. hndl - Handle returned from an earlier crypto_notify_events().
356  *
357  * Description:
358  *	Removes the element specified by hndl from the notification list.
359  *	We wait for the notification routine to complete, if the routine
360  *	is currently being called. We also free the element.
361  *
362  * Context:
363  *	Process context.
364  */
365 void
366 crypto_unnotify_events(crypto_notify_handle_t hndl)
367 {
368 	kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl;
369 
370 	if (hndl == NULL)
371 		return;
372 
373 retry:
374 	mutex_enter(&ntfy_list_lock);
375 	mutex_enter(&nep->kn_lock);
376 
377 	if (nep->kn_state == NTFY_WAITING) {
378 		kcf_ntfy_elem_t *nextp = nep->kn_next;
379 		kcf_ntfy_elem_t *prevp = nep->kn_prev;
380 
381 		if (nextp != NULL)
382 			nextp->kn_prev = prevp;
383 		else
384 			ntfy_list_tail = prevp;
385 
386 		if (prevp != NULL)
387 			prevp->kn_next = nextp;
388 		else
389 			ntfy_list_head = nextp;
390 	} else {
391 		ASSERT(nep->kn_state == NTFY_RUNNING);
392 
393 		/*
394 		 * We have to drop this lock as the client might call
395 		 * crypto_notify_events() in the callback routine resulting
396 		 * in a deadlock.
397 		 */
398 		mutex_exit(&ntfy_list_lock);
399 
400 		/*
401 		 * Another thread is working on this element. We will wait
402 		 * for that thread to signal us when done. No other thread
403 		 * will free this element. So, we can be sure it stays valid
404 		 * after the wait.
405 		 */
406 		while (nep->kn_state == NTFY_RUNNING)
407 			cv_wait(&nep->kn_cv, &nep->kn_lock);
408 		mutex_exit(&nep->kn_lock);
409 
410 		/*
411 		 * We have to remove the element from the notification list.
412 		 * So, start over and do the work (acquire locks etc.). This is
413 		 * safe (i.e. We won't be in this routine forever) as the
414 		 * CRYPTO_EVENT_PROVIDERS_CHANGE event does not happen
415 		 * frequently. We have to revisit this code if we
416 		 * add a new event that happens often.
417 		 */
418 		goto retry;
419 	}
420 
421 	mutex_exit(&nep->kn_lock);
422 
423 	/* Free the element */
424 	mutex_destroy(&nep->kn_lock);
425 	cv_destroy(&nep->kn_cv);
426 	kmem_free(nep, sizeof (kcf_ntfy_elem_t));
427 
428 	mutex_exit(&ntfy_list_lock);
429 }
430 
431 /*
432  * This routine is called from crypto_register_provider() and
433  * crypto_unregister_provider() with the CRYPTO_EVENT_PROVIDERS_CHANGE event.
434  *
435  * We walk the notification list and do the callbacks.
436  */
437 void
438 kcf_walk_ntfylist(uint32_t event, void *event_arg)
439 {
440 	kcf_ntfy_elem_t *nep;
441 	int nelem = 0;
442 
443 	mutex_enter(&ntfy_list_lock);
444 
445 	/*
446 	 * Count how many clients are on the notification list. We need
447 	 * this count to ensure that clients which joined the list after we
448 	 * have started this walk, are not wrongly notified.
449 	 */
450 	for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
451 		nelem++;
452 
453 	for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
454 		nelem--;
455 
456 		/*
457 		 * Check if this client is interested in the
458 		 * event.
459 		 */
460 		if (!(nep->kn_event_mask & event))
461 			continue;
462 
463 		mutex_enter(&nep->kn_lock);
464 		nep->kn_state = NTFY_RUNNING;
465 		mutex_exit(&nep->kn_lock);
466 		mutex_exit(&ntfy_list_lock);
467 
468 		/*
469 		 * We invoke the callback routine with no locks held. Another
470 		 * client could have joined the list meanwhile. This is fine
471 		 * as we maintain nelem as stated above. The NULL check in the
472 		 * for loop guards against shrinkage. Also, any callers of
473 		 * crypto_unnotify_events() at this point cv_wait till kn_state
474 		 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
475 		 */
476 		(*nep->kn_func)(event, event_arg);
477 
478 		mutex_enter(&nep->kn_lock);
479 		nep->kn_state = NTFY_WAITING;
480 		cv_broadcast(&nep->kn_cv);
481 		mutex_exit(&nep->kn_lock);
482 
483 		mutex_enter(&ntfy_list_lock);
484 	}
485 
486 	mutex_exit(&ntfy_list_lock);
487 }
488 
489 /*
490  * crypto_key_check()
491  *
492  * Arguments:
493  *	. mech: the mechanism to check the key with.
494  *	. key: the key to check for validity and weakness.
495  *
496  * Description:
497  *	Checks the validity and strength of the key for the mechanism.
498  *	CRYPTO_KEY_REFERENCE is not supported for this routine.
499  *	If more than one provider is capable of key checking for the mechanism,
500  *	then run the key through them all.
501  *	A conservative approach is adopted here: New weak keys may be
502  *	discovered with more recent providers. If at least one provider is
503  *	not happy with a key, then it is no good.
504  *
505  * Context:
506  *	Process and interruption.
507  */
508 int
509 crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key)
510 {
511 	int error;
512 	kcf_mech_entry_t *me;
513 	kcf_provider_desc_t *pd;
514 	kcf_prov_mech_desc_t *prov_chain;
515 
516 	/* when mech is a valid mechanism, me will be its mech_entry */
517 	if ((mech == NULL) || (key == NULL) ||
518 	    (key->ck_format == CRYPTO_KEY_REFERENCE))
519 		return (CRYPTO_ARGUMENTS_BAD);
520 
521 	if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) {
522 		/* error is one of the KCF_INVALID_MECH_XXX's */
523 		return (CRYPTO_MECHANISM_INVALID);
524 	}
525 
526 	mutex_enter(&me->me_mutex);
527 
528 	/* First let the software provider check this key */
529 	if (me->me_sw_prov != NULL) {
530 		pd = me->me_sw_prov->pm_prov_desc;
531 		KCF_PROV_REFHOLD(pd);
532 
533 		if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
534 		    (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
535 			crypto_mechanism_t lmech;
536 
537 			mutex_exit(&me->me_mutex);
538 			lmech = *mech;
539 			KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
540 			error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
541 
542 			if (error != CRYPTO_SUCCESS) {
543 				KCF_PROV_REFRELE(pd);
544 				return (error);
545 			}
546 
547 			mutex_enter(&me->me_mutex);
548 		}
549 		KCF_PROV_REFRELE(pd);
550 	}
551 
552 	prov_chain = me->me_hw_prov_chain;
553 	while (prov_chain != NULL) {
554 		pd = prov_chain->pm_prov_desc;
555 		KCF_PROV_REFHOLD(pd);
556 
557 		if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
558 		    (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
559 			crypto_mechanism_t lmech;
560 
561 			mutex_exit(&me->me_mutex);
562 			lmech = *mech;
563 			KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd,
564 			    &lmech);
565 			error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
566 
567 			if (error != CRYPTO_SUCCESS) {
568 				KCF_PROV_REFRELE(pd);
569 				return (error);
570 			}
571 			mutex_enter(&me->me_mutex);
572 		}
573 		KCF_PROV_REFRELE(pd);
574 		prov_chain = prov_chain->pm_next;
575 	}
576 
577 	mutex_exit(&me->me_mutex);
578 
579 	/* All are happy with this key */
580 	return (CRYPTO_SUCCESS);
581 }
582 
583 int
584 crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech,
585     crypto_key_t *key)
586 {
587 	kcf_provider_desc_t *pd = provider;
588 	kcf_provider_desc_t *real_provider = pd;
589 	crypto_mechanism_t lmech;
590 	int rv;
591 
592 	ASSERT(KCF_PROV_REFHELD(pd));
593 
594 	if ((mech == NULL) || (key == NULL) ||
595 	    (key->ck_format == CRYPTO_KEY_REFERENCE))
596 		return (CRYPTO_ARGUMENTS_BAD);
597 
598 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
599 		rv = kcf_get_hardware_provider(mech->cm_type,
600 		    CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
601 		    CRYPTO_KEY_OFFSET(key_check), CHECK_RESTRICT_FALSE,
602 		    pd, &real_provider);
603 
604 		if (rv != CRYPTO_SUCCESS)
605 			return (rv);
606 	}
607 
608 	lmech = *mech;
609 	KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
610 	rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key);
611 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
612 		KCF_PROV_REFRELE(real_provider);
613 
614 	return (rv);
615 }
616 
617 /*
618  * Initialize the specified crypto_mechanism_info_t structure for
619  * the specified mechanism provider descriptor. Used by
620  * crypto_get_all_mech_info().
621  */
622 static void
623 init_mechanism_info(crypto_mechanism_info_t *mech_info,
624     kcf_prov_mech_desc_t *pmd)
625 {
626 	crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask;
627 
628 	/* min/max key sizes */
629 	mech_info->mi_keysize_unit =
630 	    pmd->pm_mech_info.cm_keysize_unit;
631 	mech_info->mi_min_key_size =
632 	    (size_t)pmd->pm_mech_info.cm_min_key_length;
633 	mech_info->mi_max_key_size =
634 	    (size_t)pmd->pm_mech_info.cm_max_key_length;
635 
636 	/* usage flag */
637 	mech_info->mi_usage = 0;
638 	if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC))
639 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT;
640 	if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC))
641 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT;
642 	if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC))
643 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC;
644 }
645 
646 /*
647  * Return the mechanism info for the specified mechanism.
648  */
649 int
650 crypto_get_all_mech_info(crypto_mech_type_t mech_type,
651     crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos,
652     int km_flag)
653 {
654 	uint_t ninfos, cur_info;
655 	kcf_mech_entry_t *me;
656 	int rv;
657 	kcf_prov_mech_desc_t *hwp;
658 	crypto_mechanism_info_t *infos;
659 	size_t infos_size;
660 
661 	/* get to the mech entry corresponding to the specified mech type */
662 	if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) {
663 		return (rv);
664 	}
665 
666 	/* compute the number of key size ranges to return */
667 	mutex_enter(&me->me_mutex);
668 again:
669 	ninfos = PROV_COUNT(me);
670 	mutex_exit(&me->me_mutex);
671 
672 	if (ninfos == 0) {
673 		infos = NULL;
674 		rv = CRYPTO_SUCCESS;
675 		goto bail;
676 	}
677 	infos_size = ninfos * sizeof (crypto_mechanism_info_t);
678 	infos = kmem_alloc(infos_size, km_flag);
679 	if (infos == NULL) {
680 		rv = CRYPTO_HOST_MEMORY;
681 		goto bail;
682 	}
683 
684 	mutex_enter(&me->me_mutex);
685 	if (ninfos != PROV_COUNT(me)) {
686 		kmem_free(infos, infos_size);
687 		goto again;
688 	}
689 
690 	/* populate array of crypto mechanism infos */
691 	cur_info = 0;
692 
693 	/* software provider, if present */
694 	if (me->me_sw_prov != NULL)
695 		init_mechanism_info(&infos[cur_info++], me->me_sw_prov);
696 
697 	/* hardware providers */
698 	for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next)
699 		init_mechanism_info(&infos[cur_info++], hwp);
700 
701 	mutex_exit(&me->me_mutex);
702 	ASSERT(cur_info == ninfos);
703 bail:
704 	*mech_infos = infos;
705 	*num_mech_infos = ninfos;
706 	return (rv);
707 }
708 
709 /*
710  * memcmp_pad_max() is a specialized version of memcmp() which
711  * compares two pieces of data up to a maximum length.  If the
712  * the two data match up the maximum length, they are considered
713  * matching.  Trailing blanks do not cause the match to fail if
714  * one of the data is shorter.
715  *
716  * Examples of matches:
717  *	"one"           |
718  *	"one      "     |
719  *	                ^maximum length
720  *
721  *	"Number One     |  X"	(X is beyond maximum length)
722  *	"Number One   " |
723  *	                ^maximum length
724  *
725  * Examples of mismatches:
726  *	" one"
727  *	"one"
728  *
729  *	"Number One    X|"
730  *	"Number One     |"
731  *	                ^maximum length
732  */
733 static int
734 memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
735 {
736 	uint_t		len, extra_len;
737 	char		*marker;
738 
739 	/* No point in comparing anything beyond max_sz */
740 	if (d1_len > max_sz)
741 		d1_len = max_sz;
742 	if (d2_len > max_sz)
743 		d2_len = max_sz;
744 
745 	/* Find shorter of the two data. */
746 	if (d1_len <= d2_len) {
747 		len = d1_len;
748 		extra_len = d2_len;
749 		marker = d2;
750 	} else {	/* d1_len > d2_len */
751 		len = d2_len;
752 		extra_len = d1_len;
753 		marker = d1;
754 	}
755 
756 	/* Have a match in the shortest length of data? */
757 	if (memcmp(d1, d2, len) != 0)
758 		/* CONSTCOND */
759 		return (!0);
760 
761 	/* If the rest of longer data is nulls or blanks, call it a match. */
762 	while (len < extra_len)
763 		if (!isspace(marker[len++]))
764 			/* CONSTCOND */
765 			return (!0);
766 	return (0);
767 }
768 
769 /*
770  * Obtain ext info for specified provider and see if it matches.
771  */
772 static boolean_t
773 match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial,
774     crypto_provider_ext_info_t *ext_info)
775 {
776 	kcf_provider_desc_t *real_provider;
777 	int rv;
778 	kcf_req_params_t params;
779 
780 	(void) kcf_get_hardware_provider_nomech(
781 	    CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
782 	    CHECK_RESTRICT_FALSE, pd, &real_provider);
783 
784 	if (real_provider != NULL) {
785 		ASSERT(real_provider == pd ||
786 		    pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
787 		KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_EXTINFO,
788 		    0, NULL, 0, NULL, 0, NULL, ext_info, pd);
789 		rv = kcf_submit_request(real_provider, NULL, NULL, &params,
790 		    B_FALSE);
791 		ASSERT(rv != CRYPTO_NOT_SUPPORTED);
792 		KCF_PROV_REFRELE(real_provider);
793 	}
794 
795 	if (rv != CRYPTO_SUCCESS)
796 		return (B_FALSE);
797 
798 	if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL,
799 	    label, strlen(label), CRYPTO_EXT_SIZE_LABEL))
800 		return (B_FALSE);
801 
802 	if (manuf != NULL) {
803 		if (memcmp_pad_max(ext_info->ei_manufacturerID,
804 		    CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf),
805 		    CRYPTO_EXT_SIZE_MANUF))
806 			return (B_FALSE);
807 	}
808 
809 	if (serial != NULL) {
810 		if (memcmp_pad_max(ext_info->ei_serial_number,
811 		    CRYPTO_EXT_SIZE_SERIAL, label, strlen(label),
812 		    CRYPTO_EXT_SIZE_SERIAL))
813 			return (B_FALSE);
814 	}
815 	return (B_TRUE);
816 }
817 
818 /*
819  * Find a provider based on its label, manufacturer ID, and serial number.
820  */
821 crypto_provider_t
822 crypto_get_provider(char *label, char *manuf, char *serial)
823 {
824 	kcf_provider_desc_t **provider_array, *pd;
825 	crypto_provider_ext_info_t *ext_info;
826 	uint_t count;
827 	int i;
828 
829 	/* manuf and serial are optional */
830 	if (label == NULL)
831 		return (NULL);
832 
833 	if (kcf_get_slot_list(&count, &provider_array, B_FALSE)
834 	    != CRYPTO_SUCCESS)
835 		return (NULL);
836 
837 	if (count == 0)
838 		return (NULL);
839 
840 	ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP);
841 
842 	for (i = 0; i < count; i++) {
843 		pd = provider_array[i];
844 		if (match_ext_info(pd, label, manuf, serial, ext_info)) {
845 			KCF_PROV_REFHOLD(pd);
846 			break;
847 		}
848 	}
849 	if (i == count)
850 		pd = NULL;
851 
852 	kcf_free_provider_tab(count, provider_array);
853 	kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
854 	return (pd);
855 }
856 
857 void
858 crypto_release_provider(crypto_provider_t provider)
859 {
860 	KCF_PROV_REFRELE((kcf_provider_desc_t *)provider);
861 }
862