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