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