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 */
53kmutex_t		ntfy_list_lock;
54kcondvar_t		ntfy_list_cv;   /* cv the service thread waits on */
55static kcf_ntfy_elem_t *ntfy_list_head;
56static 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 */
82crypto_mech_type_t
83crypto_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 */
114crypto_mech_name_t *
115crypto_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
160again:
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
271done:
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 */
290void
291crypto_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 */
315crypto_notify_handle_t
316crypto_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 */
364void
365crypto_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
372retry:
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 */
432void
433kcf_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 */
503int
504crypto_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
580int
581crypto_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 */
614static void
615init_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 */
641int
642crypto_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);
662again:
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);
697bail:
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 */
707void
708crypto_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 */
738static int
739memcmp_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 */
777static boolean_t
778match_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 */
811crypto_provider_t
812crypto_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 */
851int
852crypto_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
877void
878crypto_release_provider(crypto_provider_t provider)
879{
880	KCF_PROV_REFRELE((kcf_provider_desc_t *)provider);
881}
882