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 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Core KCF (Kernel Cryptographic Framework). This file implements
28 * the cryptoadm entry points.
29 */
30
31#include <sys/systm.h>
32#include <sys/errno.h>
33#include <sys/cmn_err.h>
34#include <sys/rwlock.h>
35#include <sys/kmem.h>
36#include <sys/modctl.h>
37#include <sys/sunddi.h>
38#include <sys/door.h>
39#include <sys/crypto/common.h>
40#include <sys/crypto/api.h>
41#include <sys/crypto/spi.h>
42#include <sys/crypto/impl.h>
43#include <sys/crypto/sched_impl.h>
44
45/* protects the the soft_config_list. */
46kmutex_t soft_config_mutex;
47
48/*
49 * This linked list contains software configuration entries.
50 * The initial list is just software providers loaded by kcf_soft_config_init().
51 * Additional entries may appear for both hardware and software providers
52 * from kcf.conf.  These come from "cryptoadm start", which reads file kcf.conf
53 * and updates this table using the CRYPTO_LOAD_SOFT_CONFIG ioctl.
54 * Further cryptoadm commands modify this file and update this table with ioctl.
55 * This list is protected by the soft_config_mutex.
56 */
57kcf_soft_conf_entry_t *soft_config_list;
58
59static int add_soft_config(char *, uint_t, crypto_mech_name_t *);
60static int dup_mech_names(kcf_provider_desc_t *, crypto_mech_name_t **,
61    uint_t *, int);
62static void free_soft_config_entry(kcf_soft_conf_entry_t *);
63
64#define	KCF_MAX_CONFIG_ENTRIES 512 /* maximum entries in soft_config_list */
65
66#if DEBUG
67extern int kcf_frmwrk_debug;
68static void kcf_soft_config_dump(char *message);
69#endif /* DEBUG */
70
71/*
72 * Count and return the number of mechanisms in an array of crypto_mech_name_t
73 * (excluding final NUL-character string element).
74 */
75static int
76count_mechanisms(crypto_mech_name_t mechs[])
77{
78	int	count;
79	for (count = 0; mechs[count][0] != '\0'; ++count)
80		;
81	return (count);
82}
83
84/*
85 * Initialize a mutex and populate soft_config_list with default entries
86 * of kernel software providers.
87 * Called from kcf module _init().
88 */
89	void
90kcf_soft_config_init(void)
91{
92	typedef struct {
93		char			*name;
94		crypto_mech_name_t	*mechs;
95	} initial_soft_config_entry_t;
96
97	/*
98	 * This provides initial default values to soft_config_list.
99	 * It is equivalent to these lines in /etc/crypto/kcf.conf
100	 * (without line breaks and indenting):
101	 *
102	 * # /etc/crypto/kcf.conf
103	 * des:supportedlist=CKM_DES_CBC,CKM_DES_ECB,CKM_DES3_CBC,CKM_DES3_ECB
104	 * aes:supportedlist=CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM,\
105	 * CKM_AES_GCM,CKM_AES_GMAC,CKM_AES_CMAC
106	 * arcfour:supportedlist=CKM_RC4
107	 * blowfish:supportedlist=CKM_BLOWFISH_ECB,CKM_BLOWFISH_CBC
108	 * ecc:supportedlist=CKM_EC_KEY_PAIR_GEN,CKM_ECDH1_DERIVE,CKM_ECDSA,\
109	 * CKM_ECDSA_SHA1
110	 * sha1:supportedlist=CKM_SHA_1,CKM_SHA_1_HMAC_GENERAL,CKM_SHA_1_HMAC
111	 * sha2:supportedlist=CKM_SHA256,CKM_SHA256_HMAC,\
112	 * CKM_SHA256_HMAC_GENERAL,CKM_SHA384,CKM_SHA384_HMAC,\
113	 * CKM_SHA384_HMAC_GENERAL,CKM_SHA512,CKM_SHA512_HMAC,\
114	 * CKM_SHA512_HMAC_GENERAL
115	 * md4:supportedlist=CKM_MD4
116	 * md5:supportedlist=CKM_MD5,CKM_MD5_HMAC_GENERAL,CKM_MD5_HMAC
117	 * rsa:supportedlist=CKM_RSA_PKCS,CKM_RSA_X_509,CKM_MD5_RSA_PKCS,\
118	 * CKM_SHA1_RSA_PKCS,CKM_SHA256_RSA_PKCS,CKM_SHA384_RSA_PKCS,\
119	 * CKM_SHA512_RSA_PKCS
120	 * swrand:supportedlist=random
121	 *
122	 * WARNING: If you add a new kernel crypto provider or mechanism,
123	 * you must update these structures.
124	 *
125	 * 1. To add a new mechanism to a provider add the string to the
126	 * appropriate array below and comment above.
127	 *
128	 * 2. To add a new provider, create a new *_mechs array listing the
129	 * provider's mechanism(s) and a new comment line above.
130	 * Add the new *_mechs array to initial_soft_config_entry[].
131	 *
132	 * 3. If appropriate (that is the new mechanism is needed before
133	 * cryptosvc runs), add to kcf_init_mech_tabs() in kcf_mech_tabs.c.
134	 */
135	static crypto_mech_name_t	des_mechs[] = {
136		"CKM_DES_CBC", "CKM_DES_ECB", "CKM_DES3_CBC", "CKM_DES3_ECB",
137		""};
138	static crypto_mech_name_t	aes_mechs[] = {
139		"CKM_AES_ECB", "CKM_AES_CBC", "CKM_AES_CTR", "CKM_AES_CCM",
140		"CKM_AES_GCM", "CKM_AES_GMAC", "CKM_AES_CMAC", ""};
141	static crypto_mech_name_t	arcfour_mechs[] = {
142		"CKM_RC4", ""};
143	static crypto_mech_name_t	blowfish_mechs[] = {
144		"CKM_BLOWFISH_ECB", "CKM_BLOWFISH_CBC", ""};
145	static crypto_mech_name_t	ecc_mechs[] = {
146		"CKM_EC_KEY_PAIR_GEN", "CKM_ECDH1_DERIVE", "CKM_ECDSA",
147		"CKM_ECDSA_SHA1", ""};
148	static crypto_mech_name_t	sha1_mechs[] = {
149		"CKM_SHA_1", "CKM_SHA_1_HMAC_GENERAL", "CKM_SHA_1_HMAC", ""};
150	static crypto_mech_name_t	sha2_mechs[] = {
151		"CKM_SHA256", "CKM_SHA256_HMAC", "CKM_SHA256_HMAC_GENERAL",
152		"CKM_SHA384", "CKM_SHA384_HMAC", "CKM_SHA384_HMAC_GENERAL",
153		"CKM_SHA512", "CKM_SHA512_HMAC", "CKM_SHA512_HMAC_GENERAL", ""};
154	static crypto_mech_name_t	md4_mechs[] = {
155		"CKM_MD4", ""};
156	static crypto_mech_name_t	md5_mechs[] = {
157		"CKM_MD5", "CKM_MD5_HMAC_GENERAL", "CKM_MD5_HMAC", ""};
158	static crypto_mech_name_t	rsa_mechs[] = {
159		"CKM_RSA_PKCS", "CKM_RSA_X_509", "CKM_MD5_RSA_PKCS",
160		"CKM_SHA1_RSA_PKCS", "CKM_SHA256_RSA_PKCS",
161		"CKM_SHA384_RSA_PKCS",
162		"CKM_SHA512_RSA_PKCS", ""};
163	static crypto_mech_name_t	swrand_mechs[] = {
164		"random", ""};
165	static initial_soft_config_entry_t
166		initial_soft_config_entry[] = {
167			"des", des_mechs,
168			"aes", aes_mechs,
169			"arcfour", arcfour_mechs,
170			"blowfish", blowfish_mechs,
171			"ecc", ecc_mechs,
172			"sha1", sha1_mechs,
173			"sha2", sha2_mechs,
174			"md4", md4_mechs,
175			"md5", md5_mechs,
176			"rsa", rsa_mechs,
177			"swrand", swrand_mechs
178		};
179	const int initial_soft_config_entries =
180	    sizeof (initial_soft_config_entry)
181	    / sizeof (initial_soft_config_entry_t);
182	int i;
183
184	mutex_init(&soft_config_mutex, NULL, MUTEX_DRIVER, NULL);
185
186	/*
187	 * Initialize soft_config_list with default providers.
188	 * Populate the linked list backwards so the first entry appears first.
189	 */
190	for (i = initial_soft_config_entries - 1; i >= 0; --i) {
191		initial_soft_config_entry_t *p = &initial_soft_config_entry[i];
192		crypto_mech_name_t	*mechsp;
193		uint_t			alloc_size;
194		int			mech_count, r;
195
196		/* allocate/initialize memory for mechanism list */
197		mech_count = count_mechanisms(p->mechs);
198		alloc_size = mech_count * CRYPTO_MAX_MECH_NAME;
199		mechsp = kmem_alloc(alloc_size, KM_SLEEP);
200		bcopy(p->mechs, mechsp, alloc_size);
201
202		r = add_soft_config(p->name, mech_count, mechsp);
203		if (r != 0) {
204			cmn_err(CE_WARN,
205			    "add_soft_config(%s) failed; returned %d\n",
206			    p->name, r);
207		}
208	}
209#if DEBUG
210	if (kcf_frmwrk_debug >= 1)
211		kcf_soft_config_dump("kcf_soft_config_init");
212#endif /* DEBUG */
213}
214
215
216#if DEBUG
217/*
218 * Dump soft_config_list, containing a list of kernel software providers
219 * and (optionally) hardware providers, with updates from kcf.conf.
220 * Dump mechanism lists too if kcf_frmwrk_debug is >= 2.
221 */
222static void
223kcf_soft_config_dump(char *message)
224{
225	kcf_soft_conf_entry_t	*p;
226	uint_t			i;
227
228	mutex_enter(&soft_config_mutex);
229	printf("Soft provider config list soft_config_list: %s\n",
230	    message != NULL ? message : "");
231
232	for (p = soft_config_list; p != NULL; p = p->ce_next) {
233		printf("ce_name: %s, %d ce_mechs\n", p->ce_name, p->ce_count);
234		if (kcf_frmwrk_debug >= 2) {
235			printf("\tce_mechs: ");
236			for (i = 0; i < p->ce_count; i++) {
237				printf("%s ", p->ce_mechs[i]);
238			}
239			printf("\n");
240		}
241	}
242	printf("(end of soft_config_list)\n");
243
244	mutex_exit(&soft_config_mutex);
245}
246#endif /* DEBUG */
247
248
249/*
250 * Utility routine to identify the providers to filter out and
251 * present only one provider. This happens when a hardware provider
252 * registers multiple units of the same device instance.
253 *
254 * Called from crypto_get_dev_list().
255 */
256static void
257filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
258    char *skip_providers, int *mech_counts, int *new_count)
259{
260	int i, j;
261	kcf_provider_desc_t *prov1, *prov2;
262	int n = 0;
263
264	for (i = 0; i < count; i++) {
265		if (skip_providers[i] == 1)
266			continue;
267
268		prov1 = provider_array[i];
269		mech_counts[i] = prov1->pd_mech_list_count;
270		for (j = i + 1; j < count; j++) {
271			prov2 = provider_array[j];
272			if (strncmp(prov1->pd_name, prov2->pd_name,
273			    MAXNAMELEN) == 0 &&
274			    prov1->pd_instance == prov2->pd_instance) {
275				skip_providers[j] = 1;
276				mech_counts[i] += prov2->pd_mech_list_count;
277			}
278		}
279		n++;
280	}
281
282	*new_count = n;
283}
284
285
286/*
287 * Return a list of kernel hardware providers and a count of each
288 * provider's supported mechanisms.
289 * Called from the CRYPTO_GET_DEV_LIST ioctl.
290 */
291int
292crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
293{
294	kcf_provider_desc_t **provider_array;
295	kcf_provider_desc_t *pd;
296	crypto_dev_list_entry_t *p;
297	size_t skip_providers_size, mech_counts_size;
298	char *skip_providers;
299	uint_t provider_count;
300	int rval, i, j, new_count, *mech_counts;
301
302	/*
303	 * Take snapshot of provider table returning only hardware providers
304	 * that are in a usable state. Logical providers not included.
305	 */
306	rval = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
307	    NULL, 0, B_FALSE);
308	if (rval != CRYPTO_SUCCESS)
309		return (rval);
310
311	if (provider_count == 0) {
312		*array = NULL;
313		*count = 0;
314		return (CRYPTO_SUCCESS);
315	}
316
317	skip_providers_size = provider_count * sizeof (char);
318	mech_counts_size = provider_count * sizeof (int);
319
320	skip_providers = kmem_zalloc(skip_providers_size, KM_SLEEP);
321	mech_counts = kmem_zalloc(mech_counts_size, KM_SLEEP);
322	filter_providers(provider_count, provider_array, skip_providers,
323	    mech_counts, &new_count);
324
325	p = kmem_alloc(new_count * sizeof (crypto_dev_list_entry_t), KM_SLEEP);
326	for (i = 0, j = 0; i < provider_count; i++) {
327		if (skip_providers[i] == 1) {
328			ASSERT(mech_counts[i] == 0);
329			continue;
330		}
331		pd = provider_array[i];
332		p[j].le_mechanism_count = mech_counts[i];
333		p[j].le_dev_instance = pd->pd_instance;
334		(void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
335		j++;
336	}
337
338	kcf_free_provider_tab(provider_count, provider_array);
339	kmem_free(skip_providers, skip_providers_size);
340	kmem_free(mech_counts, mech_counts_size);
341
342	*array = p;
343	*count = new_count;
344	return (CRYPTO_SUCCESS);
345}
346
347/*
348 * Return a buffer containing the null terminated names of software providers
349 * loaded by CRYPTO_LOAD_SOFT_CONFIG.
350 * Called from the CRYPTO_GET_SOFT_LIST ioctl.
351 */
352int
353crypto_get_soft_list(uint_t *count, char **array, size_t *len)
354{
355	char *names = NULL, *namep, *end;
356	kcf_soft_conf_entry_t *p;
357	uint_t n = 0, cnt = 0, final_count = 0;
358	size_t name_len, final_size = 0;
359
360	/* first estimate */
361	mutex_enter(&soft_config_mutex);
362	for (p = soft_config_list; p != NULL; p = p->ce_next) {
363		n += strlen(p->ce_name) + 1;
364		cnt++;
365	}
366	mutex_exit(&soft_config_mutex);
367
368	if (cnt == 0)
369		goto out;
370
371again:
372	namep = names = kmem_alloc(n, KM_SLEEP);
373	end = names + n;
374	final_size = 0;
375	final_count = 0;
376
377	mutex_enter(&soft_config_mutex);
378	for (p = soft_config_list; p != NULL; p = p->ce_next) {
379		name_len = strlen(p->ce_name) + 1;
380		/* check for enough space */
381		if ((namep + name_len) > end) {
382			mutex_exit(&soft_config_mutex);
383			kmem_free(names, n);
384			n = n << 1;
385			goto again;
386		}
387		(void) strcpy(namep, p->ce_name);
388		namep += name_len;
389		final_size += name_len;
390		final_count++;
391	}
392	mutex_exit(&soft_config_mutex);
393
394	ASSERT(final_size <= n);
395
396	/* check if buffer we allocated is too large */
397	if (final_size < n) {
398		char *final_buffer;
399
400		final_buffer = kmem_alloc(final_size, KM_SLEEP);
401		bcopy(names, final_buffer, final_size);
402		kmem_free(names, n);
403		names = final_buffer;
404	}
405out:
406	*array = names;
407	*count = final_count;
408	*len = final_size;
409	return (CRYPTO_SUCCESS);
410}
411
412/*
413 * Check if a mechanism name is already in a mechanism name array
414 * Called by crypto_get_dev_info().
415 */
416static boolean_t
417duplicate(char *name, crypto_mech_name_t *array, int count)
418{
419	int i;
420
421	for (i = 0; i < count; i++) {
422		if (strncmp(name, &array[i][0],
423		    sizeof (crypto_mech_name_t)) == 0)
424			return (B_TRUE);
425	}
426	return (B_FALSE);
427}
428
429/*
430 * Return a list of kernel hardware providers for a given name and instance.
431 * For each entry, also return a list of their supported mechanisms.
432 * Called from the CRYPTO_GET_DEV_INFO ioctl.
433 */
434int
435crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
436    crypto_mech_name_t **array)
437{
438	int rv;
439	crypto_mech_name_t *mech_names, *resized_array;
440	int i, j, k = 0, max_count;
441	uint_t provider_count;
442	kcf_provider_desc_t **provider_array;
443	kcf_provider_desc_t *pd;
444
445	/*
446	 * Get provider table entries matching name and instance
447	 * for hardware providers that are in a usable state.
448	 * Logical providers not included. NULL name matches
449	 * all hardware providers.
450	 */
451	rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
452	    name, instance, B_FALSE);
453	if (rv != CRYPTO_SUCCESS)
454		return (rv);
455
456	if (provider_count == 0)
457		return (CRYPTO_ARGUMENTS_BAD);
458
459	/* Count all mechanisms supported by all providers */
460	max_count = 0;
461	for (i = 0; i < provider_count; i++)
462		max_count += provider_array[i]->pd_mech_list_count;
463
464	if (max_count == 0) {
465		mech_names = NULL;
466		goto out;
467	}
468
469	/* Allocate space and copy mech names */
470	mech_names = kmem_alloc(max_count * sizeof (crypto_mech_name_t),
471	    KM_SLEEP);
472
473	k = 0;
474	for (i = 0; i < provider_count; i++) {
475		pd = provider_array[i];
476		for (j = 0; j < pd->pd_mech_list_count; j++) {
477			/* check for duplicate */
478			if (duplicate(&pd->pd_mechanisms[j].cm_mech_name[0],
479			    mech_names, k))
480				continue;
481			bcopy(&pd->pd_mechanisms[j].cm_mech_name[0],
482			    &mech_names[k][0], sizeof (crypto_mech_name_t));
483			k++;
484		}
485	}
486
487	/* resize */
488	if (k != max_count) {
489		resized_array =
490		    kmem_alloc(k * sizeof (crypto_mech_name_t), KM_SLEEP);
491		bcopy(mech_names, resized_array,
492		    k * sizeof (crypto_mech_name_t));
493		kmem_free(mech_names,
494		    max_count * sizeof (crypto_mech_name_t));
495		mech_names = resized_array;
496	}
497
498out:
499	kcf_free_provider_tab(provider_count, provider_array);
500	*count = k;
501	*array = mech_names;
502
503	return (CRYPTO_SUCCESS);
504}
505
506/*
507 * Given a kernel software provider name, return a list of mechanisms
508 * it supports.
509 * Called from the CRYPTO_GET_SOFT_INFO ioctl.
510 */
511int
512crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
513{
514	ddi_modhandle_t modh = NULL;
515	kcf_provider_desc_t *provider;
516	int rv;
517
518	provider = kcf_prov_tab_lookup_by_name(name);
519	if (provider == NULL) {
520		char *tmp;
521		int name_len;
522
523		/* strlen("crypto/") + NULL terminator == 8 */
524		name_len = strlen(name);
525		tmp = kmem_alloc(name_len + 8, KM_SLEEP);
526		bcopy("crypto/", tmp, 7);
527		bcopy(name, &tmp[7], name_len);
528		tmp[name_len + 7] = '\0';
529
530		modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
531		kmem_free(tmp, name_len + 8);
532
533		if (modh == NULL) {
534			return (CRYPTO_ARGUMENTS_BAD);
535		}
536
537		provider = kcf_prov_tab_lookup_by_name(name);
538		if (provider == NULL) {
539			return (CRYPTO_ARGUMENTS_BAD);
540		}
541	}
542
543	rv = dup_mech_names(provider, array, count, KM_SLEEP);
544	KCF_PROV_REFRELE(provider);
545	if (modh != NULL)
546		(void) ddi_modclose(modh);
547	return (rv);
548}
549
550
551/*
552 * Change the mechanism list for a provider.
553 * If "direction" is CRYPTO_MECH_ADDED, add new mechanisms.
554 * If "direction" is CRYPTO_MECH_REMOVED, remove the mechanism list.
555 * Called from crypto_load_dev_disabled().
556 */
557static void
558kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count,
559    crypto_mech_name_t *array, crypto_event_change_t direction)
560{
561	crypto_notify_event_change_t ec;
562	crypto_mech_info_t *mi;
563	kcf_prov_mech_desc_t *pmd;
564	char *mech;
565	int i, j, n;
566
567	ASSERT(direction == CRYPTO_MECH_ADDED ||
568	    direction == CRYPTO_MECH_REMOVED);
569
570	if (provider == NULL) {
571		/*
572		 * Nothing to add or remove from the tables since
573		 * the provider isn't registered.
574		 */
575		return;
576	}
577
578	for (i = 0; i < count; i++) {
579		if (array[i][0] == '\0')
580			continue;
581
582		mech = &array[i][0];
583
584		n = provider->pd_mech_list_count;
585		for (j = 0; j < n; j++) {
586			mi = &provider->pd_mechanisms[j];
587			if (strncmp(mi->cm_mech_name, mech,
588			    CRYPTO_MAX_MECH_NAME) == 0)
589				break;
590		}
591		if (j == n)
592			continue;
593
594		switch (direction) {
595		case CRYPTO_MECH_ADDED:
596			(void) kcf_add_mech_provider(j, provider, &pmd);
597			break;
598
599		case CRYPTO_MECH_REMOVED:
600			kcf_remove_mech_provider(mech, provider);
601			break;
602		}
603
604		/* Inform interested clients of the event */
605		ec.ec_provider_type = provider->pd_prov_type;
606		ec.ec_change = direction;
607
608		(void) strncpy(ec.ec_mech_name, mech, CRYPTO_MAX_MECH_NAME);
609		kcf_walk_ntfylist(CRYPTO_EVENT_MECHS_CHANGED, &ec);
610	}
611}
612
613/*
614 * If a mech name in the second array (prev_array) is also in the
615 * first array, then a NULL character is written into the first byte
616 * of the mech name in the second array.  This effectively removes
617 * the mech name from the second array.
618 */
619static void
620kcf_compare_mechs(uint_t count, crypto_mech_name_t *array, uint_t prev_count,
621    crypto_mech_name_t *prev_array)
622{
623	int i, j;
624
625	for (i = 0; i < prev_count; i++) {
626		for (j = 0; j < count; j++) {
627			if (strncmp(&prev_array[i][0], &array[j][0],
628			    CRYPTO_MAX_MECH_NAME) == 0) {
629				prev_array[i][0] = '\0';
630			}
631		}
632	}
633}
634
635/*
636 * Called from CRYPTO_LOAD_DEV_DISABLED ioctl.
637 * If new_count is 0, then completely remove the entry.
638 */
639int
640crypto_load_dev_disabled(char *name, uint_t instance, uint_t new_count,
641    crypto_mech_name_t *new_array)
642{
643	kcf_provider_desc_t *provider = NULL;
644	kcf_provider_desc_t **provider_array;
645	crypto_mech_name_t *prev_array;
646	uint_t provider_count, prev_count;
647	int i, rv = CRYPTO_SUCCESS;
648
649	/*
650	 * Remove the policy entry if new_count is 0, otherwise put disabled
651	 * mechanisms into policy table.
652	 */
653	if (new_count == 0) {
654		kcf_policy_remove_by_dev(name, instance, &prev_count,
655		    &prev_array);
656	} else if ((rv = kcf_policy_load_dev_disabled(name, instance, new_count,
657	    new_array, &prev_count, &prev_array)) != CRYPTO_SUCCESS) {
658		return (rv);
659	}
660
661	/*
662	 * Get provider table entries matching name and instance
663	 * for providers that are are in a usable or unverified state.
664	 */
665	rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
666	    name, instance, B_TRUE);
667	if (rv != CRYPTO_SUCCESS)
668		return (rv);
669
670	for (i = 0; i < provider_count; i++) {
671		provider = provider_array[i];
672
673		/* previously disabled mechanisms may become enabled */
674		if (prev_array != NULL) {
675			kcf_compare_mechs(new_count, new_array,
676			    prev_count, prev_array);
677			kcf_change_mechs(provider, prev_count, prev_array,
678			    CRYPTO_MECH_ADDED);
679		}
680
681		kcf_change_mechs(provider, new_count, new_array,
682		    CRYPTO_MECH_REMOVED);
683	}
684
685	kcf_free_provider_tab(provider_count, provider_array);
686	crypto_free_mech_list(prev_array, prev_count);
687	return (rv);
688}
689
690/*
691 * Called from CRYPTO_LOAD_SOFT_DISABLED ioctl.
692 * If new_count is 0, then completely remove the entry.
693 */
694int
695crypto_load_soft_disabled(char *name, uint_t new_count,
696    crypto_mech_name_t *new_array)
697{
698	kcf_provider_desc_t *provider = NULL;
699	crypto_mech_name_t *prev_array;
700	uint_t prev_count = 0;
701	int rv;
702
703	provider = kcf_prov_tab_lookup_by_name(name);
704	if (provider != NULL) {
705		mutex_enter(&provider->pd_lock);
706		/*
707		 * Check if any other thread is disabling or removing
708		 * this provider. We return if this is the case.
709		 */
710		if (provider->pd_state >= KCF_PROV_DISABLED) {
711			mutex_exit(&provider->pd_lock);
712			KCF_PROV_REFRELE(provider);
713			return (CRYPTO_BUSY);
714		}
715		provider->pd_state = KCF_PROV_DISABLED;
716		mutex_exit(&provider->pd_lock);
717
718		undo_register_provider(provider, B_TRUE);
719		KCF_PROV_REFRELE(provider);
720		if (provider->pd_kstat != NULL)
721			KCF_PROV_REFRELE(provider);
722
723		/* Wait till the existing requests complete. */
724		while (kcf_get_refcnt(provider, B_TRUE) > 0) {
725			/* wait 1 second and try again. */
726			delay(1 * drv_usectohz(1000000));
727		}
728	}
729
730	if (new_count == 0) {
731		kcf_policy_remove_by_name(name, &prev_count, &prev_array);
732		crypto_free_mech_list(prev_array, prev_count);
733		rv = CRYPTO_SUCCESS;
734		goto out;
735	}
736
737	/* put disabled mechanisms into policy table */
738	if ((rv = kcf_policy_load_soft_disabled(name, new_count, new_array,
739	    &prev_count, &prev_array)) == CRYPTO_SUCCESS) {
740		crypto_free_mech_list(prev_array, prev_count);
741	}
742
743out:
744	if (provider != NULL) {
745		redo_register_provider(provider);
746		if (provider->pd_kstat != NULL)
747			KCF_PROV_REFHOLD(provider);
748		mutex_enter(&provider->pd_lock);
749		provider->pd_state = KCF_PROV_READY;
750		mutex_exit(&provider->pd_lock);
751	} else if (rv == CRYPTO_SUCCESS) {
752		/*
753		 * There are some cases where it is useful to kCF clients
754		 * to have a provider whose mechanism is enabled now to be
755		 * available. So, we attempt to load it here.
756		 *
757		 * The check, new_count < prev_count, ensures that we do this
758		 * only in the case where a mechanism(s) is now enabled.
759		 * This check assumes that enable and disable are separate
760		 * administrative actions and are not done in a single action.
761		 */
762		if ((new_count < prev_count) &&
763		    (modload("crypto", name) != -1)) {
764			struct modctl *mcp;
765			boolean_t load_again = B_FALSE;
766
767			if ((mcp = mod_hold_by_name(name)) != NULL) {
768				mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;
769
770				/* memory pressure may have unloaded module */
771				if (!mcp->mod_installed)
772					load_again = B_TRUE;
773				mod_release_mod(mcp);
774
775				if (load_again)
776					(void) modload("crypto", name);
777			}
778		}
779	}
780
781	return (rv);
782}
783
784/* called from the CRYPTO_LOAD_SOFT_CONFIG ioctl */
785int
786crypto_load_soft_config(caddr_t name, uint_t count, crypto_mech_name_t *array)
787{
788	return (add_soft_config(name, count, array));
789}
790
791/*
792 * Unload a kernel software crypto module.
793 * Called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl.
794 */
795int
796crypto_unload_soft_module(caddr_t name)
797{
798	int error;
799	modid_t id;
800	kcf_provider_desc_t *provider;
801	struct modctl *mcp;
802
803	/* verify that 'name' refers to a registered crypto provider */
804	if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
805		return (CRYPTO_UNKNOWN_PROVIDER);
806
807	/*
808	 * We save the module id and release the reference. We need to
809	 * do this as modunload() calls unregister which waits for the
810	 * refcnt to drop to zero.
811	 */
812	id = provider->pd_module_id;
813	KCF_PROV_REFRELE(provider);
814
815	if ((mcp = mod_hold_by_name(name)) != NULL) {
816		mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
817		mod_release_mod(mcp);
818	}
819
820	if ((error = modunload(id)) != 0) {
821		return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
822	}
823
824	return (CRYPTO_SUCCESS);
825}
826
827/*
828 * Free the list of kernel hardware crypto providers.
829 * Called by get_dev_list() for the CRYPTO_GET_DEV_LIST ioctl.
830 */
831void
832crypto_free_dev_list(crypto_dev_list_entry_t *array, uint_t count)
833{
834	if (count == 0 || array == NULL)
835		return;
836
837	kmem_free(array, count * sizeof (crypto_dev_list_entry_t));
838}
839
840/*
841 * Returns duplicate array of mechanisms.  The array is allocated and
842 * must be freed by the caller.
843 */
844static int
845dup_mech_names(kcf_provider_desc_t *provider, crypto_mech_name_t **array,
846    uint_t *count, int kmflag)
847{
848	crypto_mech_name_t *mech_names;
849	uint_t n;
850	uint_t i;
851
852	if ((n = provider->pd_mech_list_count) == 0) {
853		*count = 0;
854		*array = NULL;
855		return (CRYPTO_SUCCESS);
856	}
857
858	mech_names = kmem_alloc(n * sizeof (crypto_mech_name_t), kmflag);
859	if (mech_names == NULL)
860		return (CRYPTO_HOST_MEMORY);
861
862	for (i = 0; i < n; i++) {
863		bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
864		    &mech_names[i][0], sizeof (crypto_mech_name_t));
865	}
866
867	*count = n;
868	*array = mech_names;
869	return (CRYPTO_SUCCESS);
870}
871
872/*
873 * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
874 */
875boolean_t
876is_mech_disabled_byname(crypto_provider_type_t prov_type, char *pd_name,
877    uint_t pd_instance, crypto_mech_name_t mech_name)
878{
879	kcf_policy_desc_t *policy;
880	uint_t i;
881
882	ASSERT(prov_type == CRYPTO_SW_PROVIDER ||
883	    prov_type == CRYPTO_HW_PROVIDER);
884
885	switch (prov_type) {
886	case CRYPTO_SW_PROVIDER:
887		policy = kcf_policy_lookup_by_name(pd_name);
888		/* no policy for provider - so mechanism can't be disabled */
889		if (policy == NULL)
890			return (B_FALSE);
891		break;
892
893	case CRYPTO_HW_PROVIDER:
894		policy = kcf_policy_lookup_by_dev(pd_name, pd_instance);
895		/* no policy for provider - so mechanism can't be disabled */
896		if (policy == NULL)
897			return (B_FALSE);
898		break;
899	}
900
901	mutex_enter(&policy->pd_mutex);
902	for (i = 0; i < policy->pd_disabled_count; i ++) {
903		if (strncmp(mech_name, &policy->pd_disabled_mechs[i][0],
904		    CRYPTO_MAX_MECH_NAME) == 0) {
905			mutex_exit(&policy->pd_mutex);
906			KCF_POLICY_REFRELE(policy);
907			return (B_TRUE);
908		}
909	}
910	mutex_exit(&policy->pd_mutex);
911	KCF_POLICY_REFRELE(policy);
912	return (B_FALSE);
913}
914
915/*
916 * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
917 *
918 * This is a wrapper routine around is_mech_disabled_byname() above and
919 * takes a pointer kcf_provider_desc structure as argument.
920 */
921boolean_t
922is_mech_disabled(kcf_provider_desc_t *provider, crypto_mech_name_t name)
923{
924	kcf_provider_list_t *e;
925	kcf_provider_desc_t *pd;
926	boolean_t found = B_FALSE;
927	uint_t count, i;
928
929	if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
930		return (is_mech_disabled_byname(provider->pd_prov_type,
931		    provider->pd_name, provider->pd_instance, name));
932	}
933
934	/*
935	 * Lock the logical provider just in case one of its hardware
936	 * provider members unregisters.
937	 */
938	mutex_enter(&provider->pd_lock);
939	for (e = provider->pd_provider_list; e != NULL; e = e->pl_next) {
940
941		pd = e->pl_provider;
942		ASSERT(pd->pd_prov_type == CRYPTO_HW_PROVIDER);
943
944		/* find out if mechanism is offered by hw provider */
945		count = pd->pd_mech_list_count;
946		for (i = 0; i < count; i++) {
947			if (strncmp(&pd->pd_mechanisms[i].cm_mech_name[0],
948			    name, MAXNAMELEN) == 0) {
949				break;
950			}
951		}
952		if (i == count)
953			continue;
954
955		found = !is_mech_disabled_byname(pd->pd_prov_type,
956		    pd->pd_name, pd->pd_instance, name);
957
958		if (found)
959			break;
960	}
961	mutex_exit(&provider->pd_lock);
962	/*
963	 * If we found the mechanism, then it means it is still enabled for
964	 * at least one hardware provider, so the mech can't be disabled
965	 * for the logical provider.
966	 */
967	return (!found);
968}
969
970/*
971 * Builds array of permitted mechanisms.  The array is allocated and
972 * must be freed by the caller.
973 */
974int
975crypto_build_permitted_mech_names(kcf_provider_desc_t *provider,
976    crypto_mech_name_t **array, uint_t *count, int kmflag)
977{
978	crypto_mech_name_t *mech_names, *p;
979	uint_t i;
980	uint_t scnt = provider->pd_mech_list_count;
981	uint_t dcnt = 0;
982
983	/*
984	 * Compute number of 'permitted mechanisms', which is
985	 * 'supported mechanisms' - 'disabled mechanisms'.
986	 */
987	for (i = 0; i < scnt; i++) {
988		if (is_mech_disabled(provider,
989		    &provider->pd_mechanisms[i].cm_mech_name[0])) {
990			dcnt++;
991		}
992	}
993
994	/* all supported mechanisms have been disabled */
995	if (scnt == dcnt) {
996		*count = 0;
997		*array = NULL;
998		return (CRYPTO_SUCCESS);
999	}
1000
1001	mech_names = kmem_alloc((scnt - dcnt) * sizeof (crypto_mech_name_t),
1002	    kmflag);
1003	if (mech_names == NULL)
1004		return (CRYPTO_HOST_MEMORY);
1005
1006	/* build array of permitted mechanisms */
1007	for (i = 0, p = mech_names; i < scnt; i++) {
1008		if (!is_mech_disabled(provider,
1009		    &provider->pd_mechanisms[i].cm_mech_name[0])) {
1010			bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
1011			    p++, sizeof (crypto_mech_name_t));
1012		}
1013	}
1014
1015	*count = scnt - dcnt;
1016	*array = mech_names;
1017	return (CRYPTO_SUCCESS);
1018}
1019
1020/*
1021 * Free memory for elements in a kcf_soft_config_entry_t.  This entry must
1022 * have been previously removed from the soft_config_list linked list.
1023 */
1024static void
1025free_soft_config_entry(kcf_soft_conf_entry_t *p)
1026{
1027	kmem_free(p->ce_name, strlen(p->ce_name) + 1);
1028	crypto_free_mech_list(p->ce_mechs, p->ce_count);
1029	kmem_free(p, sizeof (kcf_soft_conf_entry_t));
1030}
1031
1032/*
1033 * Store configuration information for software providers in a linked list.
1034 * If the list already contains an entry for the specified provider
1035 * and the specified mechanism list has at least one mechanism, then
1036 * the mechanism list for the provider is updated. If the mechanism list
1037 * is empty, the entry for the provider is removed.
1038 *
1039 * Called from kcf_soft_config_init() (to initially populate the list
1040 * with default kernel providers) and from crypto_load_soft_config() for
1041 * the CRYPTO_LOAD_SOFT_CONFIG ioctl (for third-party kernel modules).
1042 *
1043 * Important note: the array argument must be allocated memory
1044 * since it is consumed in soft_config_list.
1045 *
1046 * Parameters:
1047 * name		Provider name to add or remove.
1048 * count	Number of mechanisms to add.
1049 *		If 0, then remove provider from the list (instead of add).
1050 * array	An array of "count" mechanism names (use only if count > 0).
1051 */
1052static int
1053add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
1054{
1055	static uint_t soft_config_count = 0;
1056	kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
1057	size_t name_len;
1058
1059	/*
1060	 * Allocate storage for a new entry.
1061	 * Free later if an entry already exists.
1062	 */
1063	name_len = strlen(name) + 1;
1064	new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
1065	new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
1066	(void) strcpy(new_entry->ce_name, name);
1067
1068	mutex_enter(&soft_config_mutex);
1069
1070	/* Search to see if provider already in soft_config_list */
1071	for (p = soft_config_list; p != NULL; p = p->ce_next) {
1072		if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) { /* found */
1073			entry = p;
1074			break;
1075		}
1076		prev = p;
1077	}
1078
1079	if (entry == NULL) { /* new provider (not in soft_config_list) */
1080		if (count == 0) { /* free memory--no entry exists to remove */
1081			mutex_exit(&soft_config_mutex);
1082			kmem_free(new_entry->ce_name, name_len);
1083			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1084			return (CRYPTO_SUCCESS);
1085		}
1086
1087		if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) { /* full */
1088			mutex_exit(&soft_config_mutex);
1089			kmem_free(new_entry->ce_name, name_len);
1090			kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1091			cmn_err(CE_WARN, "out of soft_config_list entries");
1092			return (CRYPTO_FAILED);
1093		}
1094
1095		/* add new provider to head of list */
1096		new_entry->ce_next = soft_config_list;
1097		soft_config_list = new_entry;
1098		soft_config_count++;
1099		entry = new_entry;
1100
1101	} else { /* mechanism already in soft_config_list */
1102		kmem_free(new_entry->ce_name, name_len);
1103		kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1104	}
1105
1106	if (count == 0) { /* remove provider entry from soft_config_list */
1107		if (prev == NULL) {
1108			/* entry to remove is at the head of the list */
1109			soft_config_list = entry->ce_next;
1110		} else {
1111			prev->ce_next = entry->ce_next;
1112		}
1113		soft_config_count--;
1114		mutex_exit(&soft_config_mutex);
1115
1116		/* free entry */
1117		free_soft_config_entry(entry);
1118
1119	} else { /* add provider entry to soft_config_list */
1120		/*
1121		 * Don't replace a mechanism list if it's already present.
1122		 * This is because the default entries for Software providers
1123		 * are more up-to-date than possibly stale entries in kcf.conf.
1124		 * If an entry is to be deleted, the proper way to do it is
1125		 * to add it to the disablelist (with cryptoadm(1M)),
1126		 * instead of removing it from the supportedlist.
1127		 */
1128		if (entry->ce_mechs == NULL) { /* add new mechanisms */
1129			entry->ce_mechs = array;
1130			entry->ce_count = count;
1131			mutex_exit(&soft_config_mutex);
1132		} else { /* ignore replacement mechanism list */
1133			mutex_exit(&soft_config_mutex);
1134			crypto_free_mech_list(array, count);
1135		}
1136	}
1137
1138	return (CRYPTO_SUCCESS);
1139}
1140
1141/*
1142 * This function removes a module entry from the soft_config_list.
1143 *
1144 * This comes in handy if FIPS 140 is enabled, but fails to validate.  At
1145 * which point when the kernel reports its' supported modules, it shows only
1146 * those that are not within the boundary
1147 */
1148void
1149remove_soft_config(char *name)
1150{
1151	kcf_soft_conf_entry_t *p, *entry = NULL, *prev = NULL;
1152
1153	mutex_enter(&soft_config_mutex);
1154	/* Search for provider in soft_config_list */
1155	for (p = soft_config_list; p != NULL; p = p->ce_next) {
1156		if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) {
1157			entry = p;
1158			break;
1159		}
1160		prev = p;
1161	}
1162
1163	if (prev == NULL) {
1164		/* entry to remove is at the head of the list */
1165		soft_config_list = entry->ce_next;
1166	} else {
1167		prev->ce_next = entry->ce_next;
1168	}
1169
1170	mutex_exit(&soft_config_mutex);
1171
1172	/* free entry */
1173	free_soft_config_entry(entry);
1174}
1175
1176/*
1177 * This routine searches the soft_config_list for the first entry that
1178 * has the specified mechanism in its mechanism list.  If found,
1179 * a buffer containing the name of the software module that implements
1180 * the mechanism is allocated and stored in 'name'.
1181 */
1182int
1183get_sw_provider_for_mech(crypto_mech_name_t mech, char **name)
1184{
1185	kcf_soft_conf_entry_t *p, *next;
1186	char tmp_name[MAXNAMELEN];
1187	size_t name_len = 0;
1188	int i;
1189
1190	mutex_enter(&soft_config_mutex);
1191	p = soft_config_list;
1192	while (p != NULL) {
1193		next = p->ce_next;
1194		for (i = 0; i < p->ce_count; i++) {
1195			if (strncmp(mech, &p->ce_mechs[i][0],
1196			    CRYPTO_MAX_MECH_NAME) == 0) {
1197				name_len = strlen(p->ce_name) + 1;
1198				bcopy(p->ce_name, tmp_name, name_len);
1199				break;
1200			}
1201		}
1202		p = next;
1203	}
1204	mutex_exit(&soft_config_mutex);
1205
1206	if (name_len == 0)
1207		return (CRYPTO_FAILED);
1208
1209	*name = kmem_alloc(name_len, KM_SLEEP);
1210	bcopy(tmp_name, *name, name_len);
1211	return (CRYPTO_SUCCESS);
1212}
1213