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