1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/sunddi.h> 31 #include <sys/disp.h> 32 #include <sys/modctl.h> 33 #include <sys/sysmacros.h> 34 #include <sys/crypto/common.h> 35 #include <sys/crypto/api.h> 36 #include <sys/crypto/impl.h> 37 #include <sys/crypto/sched_impl.h> 38 39 #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \ 40 ((ch) == '\t') || ((ch) == '\f')) 41 42 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 43 #define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f) 44 #define CRYPTO_PROVIDER_OFFSET(f) \ 45 offsetof(crypto_provider_management_ops_t, f) 46 47 /* Miscellaneous exported entry points */ 48 49 /* 50 * All event subscribers are put on a list. kcf_notify_list_lock 51 * protects changes to this list. 52 * 53 * The following locking order is maintained in the code - The 54 * global kcf_notify_list_lock followed by the individual lock 55 * in a kcf_ntfy_elem structure (kn_lock). 56 */ 57 kmutex_t ntfy_list_lock; 58 kcondvar_t ntfy_list_cv; /* cv the service thread waits on */ 59 static kcf_ntfy_elem_t *ntfy_list_head; 60 static kcf_ntfy_elem_t *ntfy_list_tail; 61 62 /* count all the hardware and software providers */ 63 #define PROV_COUNT(me) \ 64 (((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov) 65 66 /* 67 * crypto_mech2id() 68 * 69 * Arguments: 70 * . mechname: A null-terminated string identifying the mechanism name. 71 * 72 * Description: 73 * Walks the mechanisms tables, looking for an entry that matches the 74 * mechname. Once it find it, it builds the 64-bit mech_type and returns 75 * it. If there are no hardware or software providers for the mechanism, 76 * but there is an unloaded software provider, this routine will attempt 77 * to load it. 78 * 79 * Context: 80 * Process and interruption. 81 * 82 * Returns: 83 * The unique mechanism identified by 'mechname', if found. 84 * CRYPTO_MECH_INVALID otherwise. 85 */ 86 crypto_mech_type_t 87 crypto_mech2id(char *mechname) 88 { 89 return (crypto_mech2id_common(mechname, B_TRUE)); 90 } 91 92 /* 93 * crypto_get_mech_list() 94 * 95 * Arguments: 96 * . countp: pointer to contain the number of mech names returned 97 * . kmflag: memory allocation flag. 98 * 99 * Description: 100 * Allocates an array of crypto_mech_name_t containing all the mechanisms 101 * currently available on the system. Sets *countp with the number of 102 * mechanism names returned. 103 * 104 * We get a list of mech names which have a hardware provider by walking 105 * all the mechanism tables. We merge them with mech names obtained from 106 * the hint list. A mech name in the hint list is considered only if it 107 * is not disabled for the provider. Note that the hint list contains only 108 * software providers and the mech names supported by them. 109 * 110 * Context: 111 * Process and interruption. kmflag should be KM_NOSLEEP when called 112 * from an interruption context. 113 * 114 * Returns: 115 * The array of the crypto_mech_t allocated. 116 * NULL otherwise. 117 */ 118 crypto_mech_name_t * 119 crypto_get_mech_list(uint_t *countp, int kmflag) 120 { 121 uint_t count = 0, me_tab_size, i, j; 122 kcf_ops_class_t cl; 123 kcf_mech_entry_t *me, *me_tab; 124 crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab; 125 char *mech_name, *hint_mech, *end; 126 kcf_soft_conf_entry_t *p; 127 size_t n; 128 129 /* 130 * Count the maximum possible mechanisms that can come from the 131 * hint list. 132 */ 133 mutex_enter(&soft_config_mutex); 134 p = soft_config_list; 135 while (p != NULL) { 136 count += p->ce_count; 137 p = p->ce_next; 138 } 139 mutex_exit(&soft_config_mutex); 140 141 /* First let's count'em, for mem allocation */ 142 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 143 me_tab_size = kcf_mech_tabs_tab[cl].met_size; 144 me_tab = kcf_mech_tabs_tab[cl].met_tab; 145 for (i = 0; i < me_tab_size; i++) { 146 me = &me_tab[i]; 147 mutex_enter(&(me->me_mutex)); 148 if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) { 149 ASSERT(me->me_hw_prov_chain != NULL); 150 count++; 151 } 152 mutex_exit(&(me->me_mutex)); 153 } 154 } 155 156 /* 157 * Allocate a buffer to hold the mechanisms from 158 * mech tabs and mechanisms from the hint list. 159 */ 160 n = count * CRYPTO_MAX_MECH_NAME; 161 162 again: 163 count = 0; 164 tmp_mech_name_tab = kmem_zalloc(n, kmflag); 165 if (tmp_mech_name_tab == NULL) { 166 *countp = 0; 167 return (NULL); 168 } 169 170 /* 171 * Second round, fill in the table 172 */ 173 174 mech_name = (char *)tmp_mech_name_tab; 175 end = mech_name + n; 176 177 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 178 me_tab_size = kcf_mech_tabs_tab[cl].met_size; 179 me_tab = kcf_mech_tabs_tab[cl].met_tab; 180 for (i = 0; i < me_tab_size; i++) { 181 me = &me_tab[i]; 182 mutex_enter(&(me->me_mutex)); 183 if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) { 184 ASSERT(me->me_hw_prov_chain != NULL); 185 if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) { 186 mutex_exit(&(me->me_mutex)); 187 kmem_free(tmp_mech_name_tab, n); 188 n = n << 1; 189 goto again; 190 } 191 (void) strncpy(mech_name, me->me_name, 192 CRYPTO_MAX_MECH_NAME); 193 194 mech_name += CRYPTO_MAX_MECH_NAME; 195 count++; 196 } 197 mutex_exit(&(me->me_mutex)); 198 } 199 } 200 201 /* 202 * Search tmp_mech_name_tab for each mechanism in the hint list. We 203 * have to add any new mechanisms found in the hint list. Note that we 204 * should not modload the providers here as it will be too early. It 205 * may be the case that the caller never uses a provider. 206 */ 207 mutex_enter(&soft_config_mutex); 208 p = soft_config_list; 209 while (p != NULL) { 210 for (i = 0; i < p->ce_count; i++) { 211 hint_mech = p->ce_mechs[i]; 212 213 /* Do not consider the mechanism if it is disabled. */ 214 if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER, 215 p->ce_name, 0, hint_mech)) 216 continue; 217 218 /* 219 * There may be duplicate mechanisms in the hint list. 220 * So, we need to search all the entries that have been 221 * added so far. That number would be count. 222 */ 223 for (j = 0; j < count; j++) { 224 if (strcmp(hint_mech, 225 tmp_mech_name_tab[j]) == 0) 226 break; 227 } 228 229 if (j == count) { /* This is a new one. Add it. */ 230 ASSERT((char *)&tmp_mech_name_tab[count] == 231 mech_name); 232 if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) { 233 mutex_exit(&soft_config_mutex); 234 kmem_free(tmp_mech_name_tab, n); 235 n = n << 1; 236 goto again; 237 } 238 (void) strncpy(tmp_mech_name_tab[count], 239 hint_mech, CRYPTO_MAX_MECH_NAME); 240 mech_name += CRYPTO_MAX_MECH_NAME; 241 count++; 242 } 243 } 244 p = p->ce_next; 245 } 246 mutex_exit(&soft_config_mutex); 247 248 /* 249 * Check if we have consumed all of the space. We are done if 250 * this is the case. 251 */ 252 ASSERT(mech_name <= end); 253 if (mech_name == end) { 254 mech_name_tab = tmp_mech_name_tab; 255 goto done; 256 } 257 258 /* 259 * Allocate a buffer of the right size now that we have the 260 * correct count. 261 */ 262 mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag); 263 if (mech_name_tab == NULL) { 264 kmem_free(tmp_mech_name_tab, n); 265 *countp = 0; 266 return (NULL); 267 } 268 269 bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME); 270 kmem_free(tmp_mech_name_tab, n); 271 272 done: 273 *countp = count; 274 return (mech_name_tab); 275 } 276 277 /* 278 * crypto_free_mech_list() 279 * 280 * Arguments: 281 * . mech_names: An array of crypto_mech_name_t previously allocated by 282 * crypto_get_mech_list. 283 * . count: the number of mech names in mech_names 284 * 285 * Description: 286 * Frees the the mech_names array. 287 * 288 * Context: 289 * Process and interruption. 290 */ 291 void 292 crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count) 293 { 294 if ((mech_names != NULL) && (count > 0)) 295 kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME); 296 } 297 298 /* 299 * crypto_notify_events() 300 * 301 * Arguments: 302 * . nf: Callback function to invoke when event occurs. 303 * . event_mask: Mask of events. 304 * 305 * Description: 306 * Allocates a new element and inserts it in to the notification 307 * list. 308 * 309 * Context: 310 * Process context. 311 * 312 * Returns: 313 * A handle is returned if the client is put on the notification list. 314 * NULL is returned otherwise. 315 */ 316 crypto_notify_handle_t 317 crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask) 318 { 319 kcf_ntfy_elem_t *nep; 320 crypto_notify_handle_t hndl; 321 322 /* 323 * The only valid value for event_mask is CRYPTO_EVENT_PROVIDERS_CHANGE. 324 */ 325 if (nf == NULL || !(event_mask & CRYPTO_EVENT_PROVIDERS_CHANGE)) { 326 return (NULL); 327 } 328 329 nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP); 330 mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL); 331 cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL); 332 nep->kn_state = NTFY_WAITING; 333 nep->kn_func = nf; 334 nep->kn_event_mask = event_mask; 335 336 mutex_enter(&ntfy_list_lock); 337 if (ntfy_list_head == NULL) { 338 ntfy_list_head = ntfy_list_tail = nep; 339 } else { 340 ntfy_list_tail->kn_next = nep; 341 nep->kn_prev = ntfy_list_tail; 342 ntfy_list_tail = nep; 343 } 344 345 hndl = (crypto_notify_handle_t)nep; 346 mutex_exit(&ntfy_list_lock); 347 348 return (hndl); 349 } 350 351 /* 352 * crypto_unnotify_events() 353 * 354 * Arguments: 355 * . hndl - Handle returned from an earlier crypto_notify_events(). 356 * 357 * Description: 358 * Removes the element specified by hndl from the notification list. 359 * We wait for the notification routine to complete, if the routine 360 * is currently being called. We also free the element. 361 * 362 * Context: 363 * Process context. 364 */ 365 void 366 crypto_unnotify_events(crypto_notify_handle_t hndl) 367 { 368 kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl; 369 370 if (hndl == NULL) 371 return; 372 373 retry: 374 mutex_enter(&ntfy_list_lock); 375 mutex_enter(&nep->kn_lock); 376 377 if (nep->kn_state == NTFY_WAITING) { 378 kcf_ntfy_elem_t *nextp = nep->kn_next; 379 kcf_ntfy_elem_t *prevp = nep->kn_prev; 380 381 if (nextp != NULL) 382 nextp->kn_prev = prevp; 383 else 384 ntfy_list_tail = prevp; 385 386 if (prevp != NULL) 387 prevp->kn_next = nextp; 388 else 389 ntfy_list_head = nextp; 390 } else { 391 ASSERT(nep->kn_state == NTFY_RUNNING); 392 393 /* 394 * We have to drop this lock as the client might call 395 * crypto_notify_events() in the callback routine resulting 396 * in a deadlock. 397 */ 398 mutex_exit(&ntfy_list_lock); 399 400 /* 401 * Another thread is working on this element. We will wait 402 * for that thread to signal us when done. No other thread 403 * will free this element. So, we can be sure it stays valid 404 * after the wait. 405 */ 406 while (nep->kn_state == NTFY_RUNNING) 407 cv_wait(&nep->kn_cv, &nep->kn_lock); 408 mutex_exit(&nep->kn_lock); 409 410 /* 411 * We have to remove the element from the notification list. 412 * So, start over and do the work (acquire locks etc.). This is 413 * safe (i.e. We won't be in this routine forever) as the 414 * CRYPTO_EVENT_PROVIDERS_CHANGE event does not happen 415 * frequently. We have to revisit this code if we 416 * add a new event that happens often. 417 */ 418 goto retry; 419 } 420 421 mutex_exit(&nep->kn_lock); 422 423 /* Free the element */ 424 mutex_destroy(&nep->kn_lock); 425 cv_destroy(&nep->kn_cv); 426 kmem_free(nep, sizeof (kcf_ntfy_elem_t)); 427 428 mutex_exit(&ntfy_list_lock); 429 } 430 431 /* 432 * This routine is called from crypto_register_provider() and 433 * crypto_unregister_provider() with the CRYPTO_EVENT_PROVIDERS_CHANGE event. 434 * 435 * We walk the notification list and do the callbacks. 436 */ 437 void 438 kcf_walk_ntfylist(uint32_t event, void *event_arg) 439 { 440 kcf_ntfy_elem_t *nep; 441 int nelem = 0; 442 443 mutex_enter(&ntfy_list_lock); 444 445 /* 446 * Count how many clients are on the notification list. We need 447 * this count to ensure that clients which joined the list after we 448 * have started this walk, are not wrongly notified. 449 */ 450 for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next) 451 nelem++; 452 453 for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) { 454 nelem--; 455 456 /* 457 * Check if this client is interested in the 458 * event. 459 */ 460 if (!(nep->kn_event_mask & event)) 461 continue; 462 463 mutex_enter(&nep->kn_lock); 464 nep->kn_state = NTFY_RUNNING; 465 mutex_exit(&nep->kn_lock); 466 mutex_exit(&ntfy_list_lock); 467 468 /* 469 * We invoke the callback routine with no locks held. Another 470 * client could have joined the list meanwhile. This is fine 471 * as we maintain nelem as stated above. The NULL check in the 472 * for loop guards against shrinkage. Also, any callers of 473 * crypto_unnotify_events() at this point cv_wait till kn_state 474 * changes to NTFY_WAITING. Hence, nep is assured to be valid. 475 */ 476 (*nep->kn_func)(event, event_arg); 477 478 mutex_enter(&nep->kn_lock); 479 nep->kn_state = NTFY_WAITING; 480 cv_broadcast(&nep->kn_cv); 481 mutex_exit(&nep->kn_lock); 482 483 mutex_enter(&ntfy_list_lock); 484 } 485 486 mutex_exit(&ntfy_list_lock); 487 } 488 489 /* 490 * crypto_key_check() 491 * 492 * Arguments: 493 * . mech: the mechanism to check the key with. 494 * . key: the key to check for validity and weakness. 495 * 496 * Description: 497 * Checks the validity and strength of the key for the mechanism. 498 * CRYPTO_KEY_REFERENCE is not supported for this routine. 499 * If more than one provider is capable of key checking for the mechanism, 500 * then run the key through them all. 501 * A conservative approach is adopted here: New weak keys may be 502 * discovered with more recent providers. If at least one provider is 503 * not happy with a key, then it is no good. 504 * 505 * Context: 506 * Process and interruption. 507 */ 508 int 509 crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key) 510 { 511 int error; 512 kcf_mech_entry_t *me; 513 kcf_provider_desc_t *pd; 514 kcf_prov_mech_desc_t *prov_chain; 515 516 /* when mech is a valid mechanism, me will be its mech_entry */ 517 if ((mech == NULL) || (key == NULL) || 518 (key->ck_format == CRYPTO_KEY_REFERENCE)) 519 return (CRYPTO_ARGUMENTS_BAD); 520 521 if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) { 522 /* error is one of the KCF_INVALID_MECH_XXX's */ 523 return (CRYPTO_MECHANISM_INVALID); 524 } 525 526 mutex_enter(&me->me_mutex); 527 528 /* First let the software provider check this key */ 529 if (me->me_sw_prov != NULL) { 530 pd = me->me_sw_prov->pm_prov_desc; 531 KCF_PROV_REFHOLD(pd); 532 533 if ((KCF_PROV_KEY_OPS(pd) != NULL) && 534 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 535 crypto_mechanism_t lmech; 536 537 mutex_exit(&me->me_mutex); 538 lmech = *mech; 539 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 540 error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 541 542 if (error != CRYPTO_SUCCESS) { 543 KCF_PROV_REFRELE(pd); 544 return (error); 545 } 546 547 mutex_enter(&me->me_mutex); 548 } 549 KCF_PROV_REFRELE(pd); 550 } 551 552 prov_chain = me->me_hw_prov_chain; 553 while (prov_chain != NULL) { 554 pd = prov_chain->pm_prov_desc; 555 KCF_PROV_REFHOLD(pd); 556 557 if ((KCF_PROV_KEY_OPS(pd) != NULL) && 558 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 559 crypto_mechanism_t lmech; 560 561 mutex_exit(&me->me_mutex); 562 lmech = *mech; 563 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, 564 &lmech); 565 error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 566 567 if (error != CRYPTO_SUCCESS) { 568 KCF_PROV_REFRELE(pd); 569 return (error); 570 } 571 mutex_enter(&me->me_mutex); 572 } 573 KCF_PROV_REFRELE(pd); 574 prov_chain = prov_chain->pm_next; 575 } 576 577 mutex_exit(&me->me_mutex); 578 579 /* All are happy with this key */ 580 return (CRYPTO_SUCCESS); 581 } 582 583 int 584 crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech, 585 crypto_key_t *key) 586 { 587 kcf_provider_desc_t *pd = provider; 588 kcf_provider_desc_t *real_provider = pd; 589 crypto_mechanism_t lmech; 590 int rv; 591 592 ASSERT(KCF_PROV_REFHELD(pd)); 593 594 if ((mech == NULL) || (key == NULL) || 595 (key->ck_format == CRYPTO_KEY_REFERENCE)) 596 return (CRYPTO_ARGUMENTS_BAD); 597 598 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 599 rv = kcf_get_hardware_provider(mech->cm_type, 600 CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops), 601 CRYPTO_KEY_OFFSET(key_check), CHECK_RESTRICT_FALSE, 602 pd, &real_provider); 603 604 if (rv != CRYPTO_SUCCESS) 605 return (rv); 606 } 607 608 lmech = *mech; 609 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 610 rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key); 611 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 612 KCF_PROV_REFRELE(real_provider); 613 614 return (rv); 615 } 616 617 /* 618 * Initialize the specified crypto_mechanism_info_t structure for 619 * the specified mechanism provider descriptor. Used by 620 * crypto_get_all_mech_info(). 621 */ 622 static void 623 init_mechanism_info(crypto_mechanism_info_t *mech_info, 624 kcf_prov_mech_desc_t *pmd) 625 { 626 crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask; 627 628 /* min/max key sizes */ 629 mech_info->mi_keysize_unit = 630 pmd->pm_mech_info.cm_keysize_unit; 631 mech_info->mi_min_key_size = 632 (size_t)pmd->pm_mech_info.cm_min_key_length; 633 mech_info->mi_max_key_size = 634 (size_t)pmd->pm_mech_info.cm_max_key_length; 635 636 /* usage flag */ 637 mech_info->mi_usage = 0; 638 if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC)) 639 mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT; 640 if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC)) 641 mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT; 642 if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC)) 643 mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC; 644 } 645 646 /* 647 * Return the mechanism info for the specified mechanism. 648 */ 649 int 650 crypto_get_all_mech_info(crypto_mech_type_t mech_type, 651 crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos, 652 int km_flag) 653 { 654 uint_t ninfos, cur_info; 655 kcf_mech_entry_t *me; 656 int rv; 657 kcf_prov_mech_desc_t *hwp; 658 crypto_mechanism_info_t *infos; 659 size_t infos_size; 660 661 /* get to the mech entry corresponding to the specified mech type */ 662 if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) { 663 return (rv); 664 } 665 666 /* compute the number of key size ranges to return */ 667 mutex_enter(&me->me_mutex); 668 again: 669 ninfos = PROV_COUNT(me); 670 mutex_exit(&me->me_mutex); 671 672 if (ninfos == 0) { 673 infos = NULL; 674 rv = CRYPTO_SUCCESS; 675 goto bail; 676 } 677 infos_size = ninfos * sizeof (crypto_mechanism_info_t); 678 infos = kmem_alloc(infos_size, km_flag); 679 if (infos == NULL) { 680 rv = CRYPTO_HOST_MEMORY; 681 goto bail; 682 } 683 684 mutex_enter(&me->me_mutex); 685 if (ninfos != PROV_COUNT(me)) { 686 kmem_free(infos, infos_size); 687 goto again; 688 } 689 690 /* populate array of crypto mechanism infos */ 691 cur_info = 0; 692 693 /* software provider, if present */ 694 if (me->me_sw_prov != NULL) 695 init_mechanism_info(&infos[cur_info++], me->me_sw_prov); 696 697 /* hardware providers */ 698 for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next) 699 init_mechanism_info(&infos[cur_info++], hwp); 700 701 mutex_exit(&me->me_mutex); 702 ASSERT(cur_info == ninfos); 703 bail: 704 *mech_infos = infos; 705 *num_mech_infos = ninfos; 706 return (rv); 707 } 708 709 /* 710 * memcmp_pad_max() is a specialized version of memcmp() which 711 * compares two pieces of data up to a maximum length. If the 712 * the two data match up the maximum length, they are considered 713 * matching. Trailing blanks do not cause the match to fail if 714 * one of the data is shorter. 715 * 716 * Examples of matches: 717 * "one" | 718 * "one " | 719 * ^maximum length 720 * 721 * "Number One | X" (X is beyond maximum length) 722 * "Number One " | 723 * ^maximum length 724 * 725 * Examples of mismatches: 726 * " one" 727 * "one" 728 * 729 * "Number One X|" 730 * "Number One |" 731 * ^maximum length 732 */ 733 static int 734 memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz) 735 { 736 uint_t len, extra_len; 737 char *marker; 738 739 /* No point in comparing anything beyond max_sz */ 740 if (d1_len > max_sz) 741 d1_len = max_sz; 742 if (d2_len > max_sz) 743 d2_len = max_sz; 744 745 /* Find shorter of the two data. */ 746 if (d1_len <= d2_len) { 747 len = d1_len; 748 extra_len = d2_len; 749 marker = d2; 750 } else { /* d1_len > d2_len */ 751 len = d2_len; 752 extra_len = d1_len; 753 marker = d1; 754 } 755 756 /* Have a match in the shortest length of data? */ 757 if (memcmp(d1, d2, len) != 0) 758 /* CONSTCOND */ 759 return (!0); 760 761 /* If the rest of longer data is nulls or blanks, call it a match. */ 762 while (len < extra_len) 763 if (!isspace(marker[len++])) 764 /* CONSTCOND */ 765 return (!0); 766 return (0); 767 } 768 769 /* 770 * Obtain ext info for specified provider and see if it matches. 771 */ 772 static boolean_t 773 match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial, 774 crypto_provider_ext_info_t *ext_info) 775 { 776 kcf_provider_desc_t *real_provider; 777 int rv; 778 kcf_req_params_t params; 779 780 (void) kcf_get_hardware_provider_nomech( 781 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info), 782 CHECK_RESTRICT_FALSE, pd, &real_provider); 783 784 if (real_provider != NULL) { 785 ASSERT(real_provider == pd || 786 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 787 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO, 788 0, NULL, 0, NULL, 0, NULL, ext_info, pd); 789 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 790 B_FALSE); 791 ASSERT(rv != CRYPTO_NOT_SUPPORTED); 792 KCF_PROV_REFRELE(real_provider); 793 } 794 795 if (rv != CRYPTO_SUCCESS) 796 return (B_FALSE); 797 798 if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL, 799 label, strlen(label), CRYPTO_EXT_SIZE_LABEL)) 800 return (B_FALSE); 801 802 if (manuf != NULL) { 803 if (memcmp_pad_max(ext_info->ei_manufacturerID, 804 CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf), 805 CRYPTO_EXT_SIZE_MANUF)) 806 return (B_FALSE); 807 } 808 809 if (serial != NULL) { 810 if (memcmp_pad_max(ext_info->ei_serial_number, 811 CRYPTO_EXT_SIZE_SERIAL, label, strlen(label), 812 CRYPTO_EXT_SIZE_SERIAL)) 813 return (B_FALSE); 814 } 815 return (B_TRUE); 816 } 817 818 /* 819 * Find a provider based on its label, manufacturer ID, and serial number. 820 */ 821 crypto_provider_t 822 crypto_get_provider(char *label, char *manuf, char *serial) 823 { 824 kcf_provider_desc_t **provider_array, *pd; 825 crypto_provider_ext_info_t *ext_info; 826 uint_t count; 827 int i; 828 829 /* manuf and serial are optional */ 830 if (label == NULL) 831 return (NULL); 832 833 if (kcf_get_slot_list(&count, &provider_array, B_FALSE) 834 != CRYPTO_SUCCESS) 835 return (NULL); 836 837 if (count == 0) 838 return (NULL); 839 840 ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP); 841 842 for (i = 0; i < count; i++) { 843 pd = provider_array[i]; 844 if (match_ext_info(pd, label, manuf, serial, ext_info)) { 845 KCF_PROV_REFHOLD(pd); 846 break; 847 } 848 } 849 if (i == count) 850 pd = NULL; 851 852 kcf_free_provider_tab(count, provider_array); 853 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t)); 854 return (pd); 855 } 856 857 void 858 crypto_release_provider(crypto_provider_t provider) 859 { 860 KCF_PROV_REFRELE((kcf_provider_desc_t *)provider); 861 } 862