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