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 } 975