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 /*
30  * Core KCF (Kernel Cryptographic Framework). This file implements
31  * the cryptoadm entry points.
32  */
33 
34 #include <sys/systm.h>
35 #include <sys/errno.h>
36 #include <sys/cmn_err.h>
37 #include <sys/rwlock.h>
38 #include <sys/kmem.h>
39 #include <sys/modctl.h>
40 #include <sys/sunddi.h>
41 #include <sys/door.h>
42 #include <sys/crypto/common.h>
43 #include <sys/crypto/api.h>
44 #include <sys/crypto/spi.h>
45 #include <sys/crypto/impl.h>
46 #include <sys/crypto/sched_impl.h>
47 
48 /* protects the the soft_config_list. */
49 kmutex_t soft_config_mutex;
50 
51 /*
52  * This linked list contains software configuration entries that
53  * are loaded into the kernel by the CRYPTO_LOAD_SOFT_CONFIG ioctl.
54  * It is protected by the soft_config_mutex.
55  */
56 kcf_soft_conf_entry_t *soft_config_list;
57 
58 static int add_soft_config(char *, uint_t, crypto_mech_name_t *);
59 static int dup_mech_names(kcf_provider_desc_t *, crypto_mech_name_t **,
60     uint_t *, int);
61 static void free_soft_config_entry(kcf_soft_conf_entry_t *);
62 
63 #define	KCF_MAX_CONFIG_ENTRIES 512 /* maximum entries in soft_config_list */
64 
65 void
66 kcf_soft_config_init(void)
67 {
68 	mutex_init(&soft_config_mutex, NULL, MUTEX_DRIVER, NULL);
69 }
70 
71 
72 /*
73  * Utility routine to identify the providers to filter out and
74  * present only one provider. This happens when a hardware provider
75  * registers multiple units of the same device instance.
76  */
77 static void
78 filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
79 	char *skip_providers, int *mech_counts, int *new_count)
80 {
81 	int i, j;
82 	kcf_provider_desc_t *prov1, *prov2;
83 	int n = 0;
84 
85 	for (i = 0; i < count; i++) {
86 		if (skip_providers[i] == 1)
87 			continue;
88 
89 		prov1 = provider_array[i];
90 		mech_counts[i] = prov1->pd_mech_list_count;
91 		for (j = i + 1; j < count; j++) {
92 			prov2 = provider_array[j];
93 			if (strncmp(prov1->pd_name, prov2->pd_name,
94 			    MAXNAMELEN) == 0 &&
95 			    prov1->pd_instance == prov2->pd_instance) {
96 				skip_providers[j] = 1;
97 				mech_counts[i] += prov2->pd_mech_list_count;
98 			}
99 		}
100 		n++;
101 	}
102 
103 	*new_count = n;
104 }
105 
106 
107 /* called from the CRYPTO_GET_DEV_LIST ioctl */
108 int
109 crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
110 {
111 	kcf_provider_desc_t **provider_array;
112 	kcf_provider_desc_t *pd;
113 	crypto_dev_list_entry_t *p;
114 	size_t skip_providers_size, mech_counts_size;
115 	char *skip_providers;
116 	uint_t provider_count;
117 	int rval, i, j, new_count, *mech_counts;
118 
119 	/*
120 	 * Take snapshot of provider table returning only hardware providers
121 	 * that are in a usable state. Logical providers not included.
122 	 */
123 	rval =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
124 	    NULL, 0, B_FALSE);
125 	if (rval != CRYPTO_SUCCESS)
126 		return (rval);
127 
128 	if (provider_count == 0) {
129 		*array = NULL;
130 		*count = 0;
131 		return (CRYPTO_SUCCESS);
132 	}
133 
134 	skip_providers_size = provider_count * sizeof (char);
135 	mech_counts_size = provider_count * sizeof (int);
136 
137 	skip_providers = kmem_zalloc(skip_providers_size, KM_SLEEP);
138 	mech_counts = kmem_zalloc(mech_counts_size, KM_SLEEP);
139 	filter_providers(provider_count, provider_array, skip_providers,
140 	    mech_counts, &new_count);
141 
142 	p = kmem_alloc(new_count * sizeof (crypto_dev_list_entry_t), KM_SLEEP);
143 	for (i = 0, j = 0; i < provider_count; i++) {
144 		if (skip_providers[i] == 1) {
145 			ASSERT(mech_counts[i] == 0);
146 			continue;
147 		}
148 		pd = provider_array[i];
149 		p[j].le_mechanism_count = mech_counts[i];
150 		p[j].le_dev_instance = pd->pd_instance;
151 		(void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
152 		j++;
153 	}
154 
155 	kcf_free_provider_tab(provider_count, provider_array);
156 	kmem_free(skip_providers, skip_providers_size);
157 	kmem_free(mech_counts, mech_counts_size);
158 
159 	*array = p;
160 	*count = new_count;
161 	return (CRYPTO_SUCCESS);
162 }
163 
164 /*
165  * Called from the CRYPTO_GET_SOFT_LIST ioctl, this routine returns
166  * a buffer containing the null terminated names of software providers
167  * loaded by CRYPTO_LOAD_SOFT_CONFIG.
168  */
169 int
170 crypto_get_soft_list(uint_t *count, char **array, size_t *len)
171 {
172 	char *names = NULL, *namep, *end;
173 	kcf_soft_conf_entry_t *p;
174 	uint_t n = 0, cnt = 0, final_count = 0;
175 	size_t name_len, final_size = 0;
176 
177 	/* first estimate */
178 	mutex_enter(&soft_config_mutex);
179 	for (p = soft_config_list; p != NULL; p = p->ce_next) {
180 		n += strlen(p->ce_name) + 1;
181 		cnt++;
182 	}
183 	mutex_exit(&soft_config_mutex);
184 
185 	if (cnt == 0)
186 		goto out;
187 
188 again:
189 	namep = names = kmem_alloc(n, KM_SLEEP);
190 	end = names + n;
191 	final_size = 0;
192 	final_count = 0;
193 
194 	mutex_enter(&soft_config_mutex);
195 	for (p = soft_config_list; p != NULL; p = p->ce_next) {
196 		name_len = strlen(p->ce_name) + 1;
197 		/* check for enough space */
198 		if ((namep + name_len) > end) {
199 			mutex_exit(&soft_config_mutex);
200 			kmem_free(names, n);
201 			n = n << 1;
202 			goto again;
203 		}
204 		(void) strcpy(namep, p->ce_name);
205 		namep += name_len;
206 		final_size += name_len;
207 		final_count++;
208 	}
209 	mutex_exit(&soft_config_mutex);
210 
211 	ASSERT(final_size <= n);
212 
213 	/* check if buffer we allocated is too large */
214 	if (final_size < n) {
215 		char *final_buffer;
216 
217 		final_buffer = kmem_alloc(final_size, KM_SLEEP);
218 		bcopy(names, final_buffer, final_size);
219 		kmem_free(names, n);
220 		names = final_buffer;
221 	}
222 out:
223 	*array = names;
224 	*count = final_count;
225 	*len = final_size;
226 	return (CRYPTO_SUCCESS);
227 }
228 
229 /* called from the CRYPTO_GET_DEV_INFO ioctl */
230 int
231 crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
232     crypto_mech_name_t **array)
233 {
234 	int rv;
235 	crypto_mech_name_t *mech_names;
236 	int i, j, k, all_count;
237 	uint_t provider_count;
238 	kcf_provider_desc_t **provider_array;
239 	kcf_provider_desc_t *pd;
240 
241 	/*
242 	 * Get provider table entries matching name and instance
243 	 * for hardware providers that are in a usable state.
244 	 * Logical providers not included. NULL name matches
245 	 * all hardware providers.
246 	 */
247 	rv =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
248 	    name, instance, B_FALSE);
249 	if (rv != CRYPTO_SUCCESS)
250 		return (rv);
251 
252 	if (provider_count == 0)
253 		return (CRYPTO_ARGUMENTS_BAD);
254 
255 	/* Get count */
256 	all_count = 0;
257 	for (i = 0; i < provider_count; i++)
258 		all_count += provider_array[i]->pd_mech_list_count;
259 
260 	if (all_count == 0) {
261 		mech_names = NULL;
262 		goto out;
263 	}
264 
265 	/* Allocate space and copy mech names */
266 	mech_names = kmem_alloc(all_count * sizeof (crypto_mech_name_t),
267 	    KM_SLEEP);
268 
269 	k = 0;
270 	for (i = 0; i < provider_count; i++) {
271 		pd = provider_array[i];
272 		for (j = 0; j < pd->pd_mech_list_count; j++, k++)
273 			bcopy(&pd->pd_mechanisms[j].cm_mech_name[0],
274 			    &mech_names[k][0], sizeof (crypto_mech_name_t));
275 	}
276 
277 out:
278 	kcf_free_provider_tab(provider_count, provider_array);
279 	*count = all_count;
280 	*array = mech_names;
281 
282 	return (CRYPTO_SUCCESS);
283 }
284 
285 /* called from the CRYPTO_GET_SOFT_INFO ioctl */
286 int
287 crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
288 {
289 	ddi_modhandle_t modh = NULL;
290 	kcf_provider_desc_t *provider;
291 	int rv;
292 
293 	provider = kcf_prov_tab_lookup_by_name(name);
294 	if (provider == NULL) {
295 		if (in_soft_config_list(name)) {
296 			char *tmp;
297 			int name_len;
298 
299 			/* strlen("crypto/") + NULL terminator == 8 */
300 			name_len = strlen(name);
301 			tmp = kmem_alloc(name_len + 8, KM_SLEEP);
302 			bcopy("crypto/", tmp, 7);
303 			bcopy(name, &tmp[7], name_len);
304 			tmp[name_len + 7] = '\0';
305 
306 			modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
307 			kmem_free(tmp, name_len + 8);
308 
309 			if (modh == NULL) {
310 				return (CRYPTO_ARGUMENTS_BAD);
311 			}
312 
313 			provider = kcf_prov_tab_lookup_by_name(name);
314 			if (provider == NULL) {
315 				return (CRYPTO_ARGUMENTS_BAD);
316 			}
317 		} else {
318 			return (CRYPTO_ARGUMENTS_BAD);
319 		}
320 	}
321 
322 	rv = dup_mech_names(provider, array, count, KM_SLEEP);
323 	KCF_PROV_REFRELE(provider);
324 	if (modh != NULL)
325 		(void) ddi_modclose(modh);
326 	return (rv);
327 }
328 
329 static void
330 kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count,
331     crypto_mech_name_t *array, crypto_event_change_t direction)
332 {
333 	crypto_notify_event_change_t ec;
334 	crypto_mech_info_t *mi;
335 	kcf_prov_mech_desc_t *pmd;
336 	char *mech;
337 	int i, j, n;
338 
339 	ASSERT(direction == CRYPTO_EVENT_CHANGE_ADDED ||
340 	    direction == CRYPTO_EVENT_CHANGE_REMOVED);
341 
342 	if (provider == NULL) {
343 		/*
344 		 * Nothing to add or remove from the tables since
345 		 * the provider isn't registered.
346 		 */
347 		return;
348 	}
349 
350 	for (i = 0; i < count; i++) {
351 		if (array[i][0] == '\0')
352 			continue;
353 
354 		mech = &array[i][0];
355 
356 		n = provider->pd_mech_list_count;
357 		for (j = 0; j < n; j++) {
358 			mi = &provider->pd_mechanisms[j];
359 			if (strncmp(mi->cm_mech_name, mech,
360 			    CRYPTO_MAX_MECH_NAME) == 0)
361 				break;
362 		}
363 		if (j == n)
364 			continue;
365 
366 		switch (direction) {
367 		case CRYPTO_EVENT_CHANGE_ADDED:
368 			(void) kcf_add_mech_provider(mi, provider, &pmd);
369 			break;
370 
371 		case CRYPTO_EVENT_CHANGE_REMOVED:
372 			kcf_remove_mech_provider(mech, provider);
373 			break;
374 		}
375 
376 		/* Inform interested clients of the event */
377 		ec.ec_provider_type = provider->pd_prov_type;
378 		ec.ec_change = direction;
379 
380 		(void) strncpy(ec.ec_mech_name, mech, CRYPTO_MAX_MECH_NAME);
381 		kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDERS_CHANGE, &ec);
382 	}
383 }
384 
385 /*
386  * If a mech name in the second array (prev_array) is also in the
387  * first array, then a NULL character is written into the first byte
388  * of the mech name in the second array.  This effectively removes
389  * the mech name from the second array.
390  */
391 static void
392 kcf_compare_mechs(uint_t count, crypto_mech_name_t *array, uint_t prev_count,
393     crypto_mech_name_t *prev_array)
394 {
395 	int i, j;
396 
397 	for (i = 0; i < prev_count; i++) {
398 		for (j = 0; j < count; j++) {
399 			if (strncmp(&prev_array[i][0], &array[j][0],
400 			    CRYPTO_MAX_MECH_NAME) == 0) {
401 				prev_array[i][0] = '\0';
402 			}
403 		}
404 	}
405 }
406 
407 /*
408  * Called from CRYPTO_LOAD_DEV_DISABLED ioctl.
409  * If new_count is 0, then completely remove the entry.
410  */
411 int
412 crypto_load_dev_disabled(char *name, uint_t instance, uint_t new_count,
413     crypto_mech_name_t *new_array)
414 {
415 	kcf_provider_desc_t *provider = NULL;
416 	kcf_provider_desc_t **provider_array;
417 	crypto_mech_name_t *prev_array;
418 	uint_t provider_count, prev_count;
419 	int i, rv = CRYPTO_SUCCESS;
420 
421 	/*
422 	 * Remove the policy entry if new_count is 0, otherwise put disabled
423 	 * mechanisms into policy table.
424 	 */
425 	if (new_count == 0) {
426 		kcf_policy_remove_by_dev(name, instance, &prev_count,
427 		    &prev_array);
428 	} else if ((rv = kcf_policy_load_dev_disabled(name, instance, new_count,
429 	    new_array, &prev_count, &prev_array)) != CRYPTO_SUCCESS) {
430 		return (rv);
431 	}
432 
433 	/*
434 	 * Get provider table entries matching name and instance
435 	 * for providers that are are in a usable or unverified state.
436 	 */
437 	rv =  kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
438 	    name, instance, B_TRUE);
439 	if (rv != CRYPTO_SUCCESS)
440 		return (rv);
441 
442 	for (i = 0; i < provider_count; i++) {
443 		provider = provider_array[i];
444 
445 		/* previously disabled mechanisms may become enabled */
446 		if (prev_array != NULL) {
447 			kcf_compare_mechs(new_count, new_array,
448 			    prev_count, prev_array);
449 			kcf_change_mechs(provider, prev_count, prev_array,
450 			    CRYPTO_EVENT_CHANGE_ADDED);
451 		}
452 
453 		kcf_change_mechs(provider, new_count, new_array,
454 		    CRYPTO_EVENT_CHANGE_REMOVED);
455 	}
456 
457 	kcf_free_provider_tab(provider_count, provider_array);
458 	crypto_free_mech_list(prev_array, prev_count);
459 	return (rv);
460 }
461 
462 /*
463  * Called from CRYPTO_LOAD_SOFT_DISABLED ioctl.
464  * If new_count is 0, then completely remove the entry.
465  */
466 int
467 crypto_load_soft_disabled(char *name, uint_t new_count,
468     crypto_mech_name_t *new_array)
469 {
470 	kcf_provider_desc_t *provider = NULL;
471 	crypto_mech_name_t *prev_array;
472 	uint_t prev_count = 0;
473 	int rv;
474 
475 	provider = kcf_prov_tab_lookup_by_name(name);
476 	if (provider != NULL) {
477 		mutex_enter(&provider->pd_lock);
478 		/*
479 		 * Check if any other thread is disabling or removing
480 		 * this provider. We return if this is the case.
481 		 */
482 		if (provider->pd_state >= KCF_PROV_DISABLED) {
483 			mutex_exit(&provider->pd_lock);
484 			KCF_PROV_REFRELE(provider);
485 			return (CRYPTO_BUSY);
486 		}
487 		provider->pd_state = KCF_PROV_DISABLED;
488 		mutex_exit(&provider->pd_lock);
489 
490 		undo_register_provider(provider, B_TRUE);
491 		KCF_PROV_REFRELE(provider);
492 		if (provider->pd_kstat != NULL)
493 			KCF_PROV_REFRELE(provider);
494 
495 		mutex_enter(&provider->pd_lock);
496 		/* Wait till the existing requests complete. */
497 		while (provider->pd_state != KCF_PROV_FREED) {
498 			cv_wait(&provider->pd_remove_cv, &provider->pd_lock);
499 		}
500 		mutex_exit(&provider->pd_lock);
501 	}
502 
503 	if (new_count == 0) {
504 		kcf_policy_remove_by_name(name, &prev_count, &prev_array);
505 		crypto_free_mech_list(prev_array, prev_count);
506 		rv = CRYPTO_SUCCESS;
507 		goto out;
508 	}
509 
510 	/* put disabled mechanisms into policy table */
511 	if ((rv = kcf_policy_load_soft_disabled(name, new_count, new_array,
512 	    &prev_count, &prev_array)) == CRYPTO_SUCCESS) {
513 		crypto_free_mech_list(prev_array, prev_count);
514 	}
515 
516 out:
517 	if (provider != NULL) {
518 		redo_register_provider(provider);
519 		if (provider->pd_kstat != NULL)
520 			KCF_PROV_REFHOLD(provider);
521 		mutex_enter(&provider->pd_lock);
522 		provider->pd_state = KCF_PROV_READY;
523 		mutex_exit(&provider->pd_lock);
524 	} else if (rv == CRYPTO_SUCCESS) {
525 		/*
526 		 * There are some cases where it is useful to kCF clients
527 		 * to have a provider whose mechanism is enabled now to be
528 		 * available. So, we attempt to load it here.
529 		 *
530 		 * The check, new_count < prev_count, ensures that we do this
531 		 * only in the case where a mechanism(s) is now enabled.
532 		 * This check assumes that enable and disable are separate
533 		 * administrative actions and are not done in a single action.
534 		 */
535 		if (new_count < prev_count && (in_soft_config_list(name)) &&
536 		    (modload("crypto", name) != -1)) {
537 			struct modctl *mcp;
538 			boolean_t load_again = B_FALSE;
539 
540 			if ((mcp = mod_hold_by_name(name)) != NULL) {
541 				mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;
542 
543 				/* memory pressure may have unloaded module */
544 				if (!mcp->mod_installed)
545 					load_again = B_TRUE;
546 				mod_release_mod(mcp);
547 
548 				if (load_again)
549 					(void) modload("crypto", name);
550 			}
551 		}
552 	}
553 
554 	return (rv);
555 }
556 
557 /* called from the CRYPTO_LOAD_SOFT_CONFIG ioctl */
558 int
559 crypto_load_soft_config(caddr_t name, uint_t count, crypto_mech_name_t *array)
560 {
561 	return (add_soft_config(name, count, array));
562 }
563 
564 /* called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl */
565 int
566 crypto_unload_soft_module(caddr_t name)
567 {
568 	int error;
569 	modid_t id;
570 	kcf_provider_desc_t *provider;
571 	struct modctl *mcp;
572 
573 	/* verify that 'name' refers to a registered crypto provider */
574 	if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
575 		return (CRYPTO_UNKNOWN_PROVIDER);
576 
577 	/*
578 	 * We save the module id and release the reference. We need to
579 	 * do this as modunload() calls unregister which waits for the
580 	 * refcnt to drop to zero.
581 	 */
582 	id = provider->pd_module_id;
583 	KCF_PROV_REFRELE(provider);
584 
585 	if ((mcp = mod_hold_by_name(name)) != NULL) {
586 		mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
587 		mod_release_mod(mcp);
588 	}
589 
590 	if ((error = modunload(id)) != 0) {
591 		return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
592 	}
593 
594 	return (CRYPTO_SUCCESS);
595 }
596 
597 /* called from CRYPTO_GET_DEV_LIST ioctl */
598 void
599 crypto_free_dev_list(crypto_dev_list_entry_t *array, uint_t count)
600 {
601 	if (count ==  0 || array == NULL)
602 		return;
603 
604 	kmem_free(array, count * sizeof (crypto_dev_list_entry_t));
605 }
606 
607 /*
608  * Returns duplicate array of mechanisms.  The array is allocated and
609  * must be freed by the caller.
610  */
611 static int
612 dup_mech_names(kcf_provider_desc_t *provider, crypto_mech_name_t **array,
613     uint_t *count, int kmflag)
614 {
615 	crypto_mech_name_t *mech_names;
616 	uint_t n;
617 	uint_t i;
618 
619 	if ((n = provider->pd_mech_list_count) == 0) {
620 		*count = 0;
621 		*array = NULL;
622 		return (CRYPTO_SUCCESS);
623 	}
624 
625 	mech_names = kmem_alloc(n * sizeof (crypto_mech_name_t), kmflag);
626 	if (mech_names == NULL)
627 		return (CRYPTO_HOST_MEMORY);
628 
629 	for (i = 0; i < n; i++) {
630 		bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
631 		    &mech_names[i][0], sizeof (crypto_mech_name_t));
632 	}
633 
634 	*count = n;
635 	*array = mech_names;
636 	return (CRYPTO_SUCCESS);
637 }
638 
639 /*
640  * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
641  */
642 boolean_t
643 is_mech_disabled_byname(crypto_provider_type_t prov_type, char *pd_name,
644     uint_t pd_instance, crypto_mech_name_t mech_name)
645 {
646 	kcf_policy_desc_t *policy;
647 	uint_t i;
648 
649 	ASSERT(prov_type == CRYPTO_SW_PROVIDER ||
650 	    prov_type == CRYPTO_HW_PROVIDER);
651 
652 	switch (prov_type) {
653 	case CRYPTO_SW_PROVIDER:
654 		policy = kcf_policy_lookup_by_name(pd_name);
655 		/* no policy for provider - so mechanism can't be disabled */
656 		if (policy == NULL)
657 			return (B_FALSE);
658 		break;
659 
660 	case CRYPTO_HW_PROVIDER:
661 		policy = kcf_policy_lookup_by_dev(pd_name, pd_instance);
662 		/* no policy for provider - so mechanism can't be disabled */
663 		if (policy == NULL)
664 			return (B_FALSE);
665 		break;
666 	}
667 
668 	mutex_enter(&policy->pd_mutex);
669 	for (i = 0; i < policy->pd_disabled_count; i ++) {
670 		if (strncmp(mech_name, &policy->pd_disabled_mechs[i][0],
671 		    CRYPTO_MAX_MECH_NAME) == 0) {
672 			mutex_exit(&policy->pd_mutex);
673 			KCF_POLICY_REFRELE(policy);
674 			return (B_TRUE);
675 		}
676 	}
677 	mutex_exit(&policy->pd_mutex);
678 	KCF_POLICY_REFRELE(policy);
679 	return (B_FALSE);
680 }
681 
682 /*
683  * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
684  *
685  * This is a wrapper routine around is_mech_disabled_byname() above and
686  * takes a pointer kcf_provider_desc structure as argument.
687  */
688 boolean_t
689 is_mech_disabled(kcf_provider_desc_t *provider, crypto_mech_name_t name)
690 {
691 	kcf_provider_list_t *e;
692 	kcf_provider_desc_t *pd;
693 	boolean_t found = B_FALSE;
694 	uint_t count, i;
695 
696 	if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
697 		return (is_mech_disabled_byname(provider->pd_prov_type,
698 		    provider->pd_name, provider->pd_instance, name));
699 	}
700 
701 	/*
702 	 * Lock the logical provider just in case one of its hardware
703 	 * provider members unregisters.
704 	 */
705 	mutex_enter(&provider->pd_lock);
706 	for (e = provider->pd_provider_list; e != NULL; e = e->pl_next) {
707 
708 		pd = e->pl_provider;
709 		ASSERT(pd->pd_prov_type == CRYPTO_HW_PROVIDER);
710 
711 		/* find out if mechanism is offered by hw provider */
712 		count = pd->pd_mech_list_count;
713 		for (i = 0; i < count; i++) {
714 			if (strncmp(&pd->pd_mechanisms[i].cm_mech_name[0],
715 			    name, MAXNAMELEN) == 0) {
716 				break;
717 			}
718 		}
719 		if (i == count)
720 			continue;
721 
722 		found = !is_mech_disabled_byname(pd->pd_prov_type,
723 		    pd->pd_name, pd->pd_instance, name);
724 
725 		if (found)
726 			break;
727 	}
728 	mutex_exit(&provider->pd_lock);
729 	/*
730 	 * If we found the mechanism, then it means it is still enabled for
731 	 * at least one hardware provider, so the mech can't be disabled
732 	 * for the logical provider.
733 	 */
734 	return (!found);
735 }
736 
737 /*
738  * Builds array of permitted mechanisms.  The array is allocated and
739  * must be freed by the caller.
740  */
741 int
742 crypto_build_permitted_mech_names(kcf_provider_desc_t *provider,
743     crypto_mech_name_t **array, uint_t *count, int kmflag)
744 {
745 	crypto_mech_name_t *mech_names, *p;
746 	uint_t i;
747 	uint_t scnt = provider->pd_mech_list_count;
748 	uint_t dcnt = 0;
749 
750 	/*
751 	 * Compute number of 'permitted mechanisms', which is
752 	 * 'supported mechanisms' - 'disabled mechanisms'.
753 	 */
754 	for (i = 0; i < scnt; i++) {
755 		if (is_mech_disabled(provider,
756 		    &provider->pd_mechanisms[i].cm_mech_name[0])) {
757 			dcnt++;
758 		}
759 	}
760 
761 	/* all supported mechanisms have been disabled */
762 	if (scnt == dcnt) {
763 		*count = 0;
764 		*array = NULL;
765 		return (CRYPTO_SUCCESS);
766 	}
767 
768 	mech_names = kmem_alloc((scnt - dcnt) * sizeof (crypto_mech_name_t),
769 	    kmflag);
770 	if (mech_names == NULL)
771 		return (CRYPTO_HOST_MEMORY);
772 
773 	/* build array of permitted mechanisms */
774 	for (i = 0, p = mech_names; i < scnt; i++) {
775 		if (!is_mech_disabled(provider,
776 		    &provider->pd_mechanisms[i].cm_mech_name[0])) {
777 			bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
778 			    p++, sizeof (crypto_mech_name_t));
779 		}
780 	}
781 
782 	*count = scnt - dcnt;
783 	*array = mech_names;
784 	return (CRYPTO_SUCCESS);
785 }
786 
787 static void
788 free_soft_config_entry(kcf_soft_conf_entry_t *p)
789 {
790 	kmem_free(p->ce_name, strlen(p->ce_name) + 1);
791 	crypto_free_mech_list(p->ce_mechs, p->ce_count);
792 	kmem_free(p, sizeof (kcf_soft_conf_entry_t));
793 }
794 
795 /*
796  * Called from the CRYPTO_LOAD_SOFT_CONFIG ioctl, this routine stores
797  * configuration information for software providers in a linked list.
798  * If the list already contains an entry for the specified provider
799  * and the specified mechanism list has at least one mechanism, then
800  * the mechanism list for the provider is updated. If the mechanism list
801  * is empty, the entry for the provider is removed.
802  *
803  * Important note: the array argument is consumed.
804  */
805 static int
806 add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
807 {
808 	static uint_t soft_config_count = 0;
809 	kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
810 	size_t name_len;
811 
812 	/*
813 	 * Allocate storage for a new entry.
814 	 * Free later if an entry already exists.
815 	 */
816 	name_len = strlen(name) + 1;
817 	new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
818 	new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
819 	(void) strcpy(new_entry->ce_name, name);
820 
821 	mutex_enter(&soft_config_mutex);
822 	p = soft_config_list;
823 	if (p != NULL) {
824 		do {
825 			if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) {
826 				entry = p;
827 				break;
828 			}
829 			prev = p;
830 
831 		} while ((p = p->ce_next) != NULL);
832 	}
833 
834 	if (entry == NULL) {
835 		if (count == 0) {
836 			mutex_exit(&soft_config_mutex);
837 			kmem_free(new_entry->ce_name, name_len);
838 			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
839 			return (CRYPTO_SUCCESS);
840 		}
841 
842 		if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) {
843 			mutex_exit(&soft_config_mutex);
844 			kmem_free(new_entry->ce_name, name_len);
845 			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
846 			cmn_err(CE_WARN, "out of soft_config_list entries");
847 			return (CRYPTO_FAILED);
848 		}
849 
850 		/* add to head of list */
851 		new_entry->ce_next = soft_config_list;
852 		soft_config_list = new_entry;
853 		soft_config_count++;
854 		entry = new_entry;
855 	} else {
856 		kmem_free(new_entry->ce_name, name_len);
857 		kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
858 	}
859 
860 	/* mechanism count == 0 means remove entry from list */
861 	if (count == 0) {
862 		if (prev == NULL) {
863 			/* remove first in list */
864 			soft_config_list = entry->ce_next;
865 		} else {
866 			prev->ce_next = entry->ce_next;
867 		}
868 		soft_config_count--;
869 		mutex_exit(&soft_config_mutex);
870 
871 		/* free entry */
872 		free_soft_config_entry(entry);
873 
874 		return (CRYPTO_SUCCESS);
875 	}
876 
877 
878 	/* replace mechanisms */
879 	if (entry->ce_mechs != NULL)
880 		crypto_free_mech_list(entry->ce_mechs, entry->ce_count);
881 
882 	entry->ce_mechs = array;
883 	entry->ce_count = count;
884 	mutex_exit(&soft_config_mutex);
885 
886 	return (CRYPTO_SUCCESS);
887 }
888 
889 /*
890  * This routine searches the soft_config_list for the first entry that
891  * has the specified mechanism in its mechanism list.  If found,
892  * a buffer containing the name of the software module that implements
893  * the mechanism is allocated and stored in 'name'.
894  */
895 int
896 get_sw_provider_for_mech(crypto_mech_name_t mech, char **name)
897 {
898 	kcf_soft_conf_entry_t *p, *next;
899 	char tmp_name[MAXNAMELEN];
900 	size_t name_len = 0;
901 	int i;
902 
903 	mutex_enter(&soft_config_mutex);
904 	p = soft_config_list;
905 	while (p != NULL) {
906 		next = p->ce_next;
907 		for (i = 0; i < p->ce_count; i++) {
908 			if (strcmp(mech, &p->ce_mechs[i][0]) == 0) {
909 				name_len = strlen(p->ce_name) + 1;
910 				bcopy(p->ce_name, tmp_name, name_len);
911 				break;
912 			}
913 		}
914 		p = next;
915 	}
916 	mutex_exit(&soft_config_mutex);
917 
918 	if (name_len == 0)
919 		return (CRYPTO_FAILED);
920 
921 	*name = kmem_alloc(name_len, KM_SLEEP);
922 	bcopy(tmp_name, *name, name_len);
923 	return (CRYPTO_SUCCESS);
924 }
925 
926 /*
927  * This routine searches the soft_config_list for the specified
928  * software provider, returning B_TRUE if it is in the list.
929  */
930 boolean_t
931 in_soft_config_list(char *provider_name)
932 {
933 	kcf_soft_conf_entry_t *p;
934 	boolean_t rv = B_FALSE;
935 
936 	mutex_enter(&soft_config_mutex);
937 	for (p = soft_config_list; p != NULL; p = p->ce_next) {
938 		if (strcmp(provider_name, p->ce_name) == 0) {
939 			rv = B_TRUE;
940 			break;
941 		}
942 	}
943 	mutex_exit(&soft_config_mutex);
944 	return (rv);
945 }
946