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 2009 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 kcf_lock_withpad_t *mp; 126 127 /* 128 * Count the maximum possible mechanisms that can come from the 129 * hint list. 130 */ 131 mutex_enter(&soft_config_mutex); 132 p = soft_config_list; 133 while (p != NULL) { 134 count += p->ce_count; 135 p = p->ce_next; 136 } 137 mutex_exit(&soft_config_mutex); 138 139 /* First let's count'em, for mem allocation */ 140 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 141 me_tab_size = kcf_mech_tabs_tab[cl].met_size; 142 me_tab = kcf_mech_tabs_tab[cl].met_tab; 143 for (i = 0; i < me_tab_size; i++) { 144 me = &me_tab[i]; 145 mp = &me_mutexes[CPU_SEQID]; 146 mutex_enter(&mp->kl_lock); 147 if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) { 148 ASSERT(me->me_hw_prov_chain != NULL); 149 count++; 150 } 151 mutex_exit(&mp->kl_lock); 152 } 153 } 154 155 /* 156 * Allocate a buffer to hold the mechanisms from 157 * mech tabs and mechanisms from the hint list. 158 */ 159 n = count * CRYPTO_MAX_MECH_NAME; 160 161 again: 162 count = 0; 163 tmp_mech_name_tab = kmem_zalloc(n, kmflag); 164 if (tmp_mech_name_tab == NULL) { 165 *countp = 0; 166 return (NULL); 167 } 168 169 /* 170 * Second round, fill in the table 171 */ 172 173 mech_name = (char *)tmp_mech_name_tab; 174 end = mech_name + n; 175 176 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) { 177 me_tab_size = kcf_mech_tabs_tab[cl].met_size; 178 me_tab = kcf_mech_tabs_tab[cl].met_tab; 179 for (i = 0; i < me_tab_size; i++) { 180 me = &me_tab[i]; 181 mp = &me_mutexes[CPU_SEQID]; 182 mutex_enter(&mp->kl_lock); 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(&mp->kl_lock); 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(&mp->kl_lock); 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 /* Check the input */ 323 if (nf == NULL || !(event_mask & (CRYPTO_EVENT_MECHS_CHANGED | 324 CRYPTO_EVENT_PROVIDER_REGISTERED | 325 CRYPTO_EVENT_PROVIDER_UNREGISTERED))) { 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 * events do not happen frequently. We have to revisit this 415 * code if we add a new event that happens often. 416 */ 417 goto retry; 418 } 419 420 mutex_exit(&nep->kn_lock); 421 422 /* Free the element */ 423 mutex_destroy(&nep->kn_lock); 424 cv_destroy(&nep->kn_cv); 425 kmem_free(nep, sizeof (kcf_ntfy_elem_t)); 426 427 mutex_exit(&ntfy_list_lock); 428 } 429 430 /* 431 * We walk the notification list and do the callbacks. 432 */ 433 void 434 kcf_walk_ntfylist(uint32_t event, void *event_arg) 435 { 436 kcf_ntfy_elem_t *nep; 437 int nelem = 0; 438 439 mutex_enter(&ntfy_list_lock); 440 441 /* 442 * Count how many clients are on the notification list. We need 443 * this count to ensure that clients which joined the list after we 444 * have started this walk, are not wrongly notified. 445 */ 446 for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next) 447 nelem++; 448 449 for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) { 450 nelem--; 451 452 /* 453 * Check if this client is interested in the 454 * event. 455 */ 456 if (!(nep->kn_event_mask & event)) 457 continue; 458 459 mutex_enter(&nep->kn_lock); 460 nep->kn_state = NTFY_RUNNING; 461 mutex_exit(&nep->kn_lock); 462 mutex_exit(&ntfy_list_lock); 463 464 /* 465 * We invoke the callback routine with no locks held. Another 466 * client could have joined the list meanwhile. This is fine 467 * as we maintain nelem as stated above. The NULL check in the 468 * for loop guards against shrinkage. Also, any callers of 469 * crypto_unnotify_events() at this point cv_wait till kn_state 470 * changes to NTFY_WAITING. Hence, nep is assured to be valid. 471 */ 472 (*nep->kn_func)(event, event_arg); 473 474 mutex_enter(&nep->kn_lock); 475 nep->kn_state = NTFY_WAITING; 476 cv_broadcast(&nep->kn_cv); 477 mutex_exit(&nep->kn_lock); 478 479 mutex_enter(&ntfy_list_lock); 480 } 481 482 mutex_exit(&ntfy_list_lock); 483 } 484 485 /* 486 * crypto_key_check() 487 * 488 * Arguments: 489 * . mech: the mechanism to check the key with. 490 * . key: the key to check for validity and weakness. 491 * 492 * Description: 493 * Checks the validity and strength of the key for the mechanism. 494 * CRYPTO_KEY_REFERENCE is not supported for this routine. 495 * If more than one provider is capable of key checking for the mechanism, 496 * then run the key through them all. 497 * A conservative approach is adopted here: New weak keys may be 498 * discovered with more recent providers. If at least one provider is 499 * not happy with a key, then it is no good. 500 * 501 * Context: 502 * Process and interruption. 503 */ 504 int 505 crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key) 506 { 507 int error; 508 kcf_mech_entry_t *me; 509 kcf_provider_desc_t *pd; 510 kcf_prov_mech_desc_t *prov_chain; 511 kcf_lock_withpad_t *mp; 512 513 /* when mech is a valid mechanism, me will be its mech_entry */ 514 if ((mech == NULL) || (key == NULL) || 515 (key->ck_format == CRYPTO_KEY_REFERENCE)) 516 return (CRYPTO_ARGUMENTS_BAD); 517 518 if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) { 519 /* error is one of the KCF_INVALID_MECH_XXX's */ 520 return (CRYPTO_MECHANISM_INVALID); 521 } 522 523 mp = &me_mutexes[CPU_SEQID]; 524 mutex_enter(&mp->kl_lock); 525 526 /* First let the software provider check this key */ 527 if (me->me_sw_prov != NULL) { 528 pd = me->me_sw_prov->pm_prov_desc; 529 KCF_PROV_REFHOLD(pd); 530 531 if ((KCF_PROV_KEY_OPS(pd) != NULL) && 532 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 533 crypto_mechanism_t lmech; 534 535 mutex_exit(&mp->kl_lock); 536 lmech = *mech; 537 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 538 error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 539 540 if (error != CRYPTO_SUCCESS) { 541 KCF_PROV_REFRELE(pd); 542 return (error); 543 } 544 545 mutex_enter(&mp->kl_lock); 546 } 547 KCF_PROV_REFRELE(pd); 548 } 549 550 prov_chain = me->me_hw_prov_chain; 551 while (prov_chain != NULL) { 552 pd = prov_chain->pm_prov_desc; 553 KCF_PROV_REFHOLD(pd); 554 555 if ((KCF_PROV_KEY_OPS(pd) != NULL) && 556 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) { 557 crypto_mechanism_t lmech; 558 559 mutex_exit(&mp->kl_lock); 560 lmech = *mech; 561 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, 562 &lmech); 563 error = KCF_PROV_KEY_CHECK(pd, &lmech, key); 564 565 if (error != CRYPTO_SUCCESS) { 566 KCF_PROV_REFRELE(pd); 567 return (error); 568 } 569 mutex_enter(&mp->kl_lock); 570 } 571 KCF_PROV_REFRELE(pd); 572 prov_chain = prov_chain->pm_next; 573 } 574 575 mutex_exit(&mp->kl_lock); 576 577 /* All are happy with this key */ 578 return (CRYPTO_SUCCESS); 579 } 580 581 int 582 crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech, 583 crypto_key_t *key) 584 { 585 kcf_provider_desc_t *pd = provider; 586 kcf_provider_desc_t *real_provider = pd; 587 crypto_mechanism_t lmech; 588 int rv; 589 590 ASSERT(KCF_PROV_REFHELD(pd)); 591 592 if ((mech == NULL) || (key == NULL) || 593 (key->ck_format == CRYPTO_KEY_REFERENCE)) 594 return (CRYPTO_ARGUMENTS_BAD); 595 596 /* no logical providers currently support the key check */ 597 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 598 return (CRYPTO_NOT_SUPPORTED); 599 } 600 601 lmech = *mech; 602 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 603 rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key); 604 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 605 KCF_PROV_REFRELE(real_provider); 606 607 return (rv); 608 } 609 610 /* 611 * Initialize the specified crypto_mechanism_info_t structure for 612 * the specified mechanism provider descriptor. Used by 613 * crypto_get_all_mech_info(). 614 */ 615 static void 616 init_mechanism_info(crypto_mechanism_info_t *mech_info, 617 kcf_prov_mech_desc_t *pmd) 618 { 619 crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask; 620 621 /* min/max key sizes */ 622 mech_info->mi_keysize_unit = pmd->pm_mech_info.cm_mech_flags & 623 (CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_KEYSIZE_UNIT_IN_BYTES); 624 mech_info->mi_min_key_size = 625 (size_t)pmd->pm_mech_info.cm_min_key_length; 626 mech_info->mi_max_key_size = 627 (size_t)pmd->pm_mech_info.cm_max_key_length; 628 629 /* usage flag */ 630 mech_info->mi_usage = 0; 631 if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC)) 632 mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT; 633 if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC)) 634 mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT; 635 if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC)) 636 mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC; 637 } 638 639 /* 640 * Return the mechanism info for the specified mechanism. 641 */ 642 int 643 crypto_get_all_mech_info(crypto_mech_type_t mech_type, 644 crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos, 645 int km_flag) 646 { 647 uint_t ninfos, cur_info; 648 kcf_mech_entry_t *me; 649 int rv; 650 kcf_prov_mech_desc_t *hwp; 651 crypto_mechanism_info_t *infos; 652 size_t infos_size; 653 kcf_lock_withpad_t *mp; 654 655 /* get to the mech entry corresponding to the specified mech type */ 656 if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) { 657 return (rv); 658 } 659 660 /* compute the number of key size ranges to return */ 661 mp = &me_mutexes[CPU_SEQID]; 662 mutex_enter(&mp->kl_lock); 663 again: 664 ninfos = PROV_COUNT(me); 665 mutex_exit(&mp->kl_lock); 666 667 if (ninfos == 0) { 668 infos = NULL; 669 rv = CRYPTO_SUCCESS; 670 goto bail; 671 } 672 infos_size = ninfos * sizeof (crypto_mechanism_info_t); 673 infos = kmem_alloc(infos_size, km_flag); 674 if (infos == NULL) { 675 rv = CRYPTO_HOST_MEMORY; 676 goto bail; 677 } 678 679 mutex_enter(&mp->kl_lock); 680 if (ninfos != PROV_COUNT(me)) { 681 kmem_free(infos, infos_size); 682 goto again; 683 } 684 685 /* populate array of crypto mechanism infos */ 686 cur_info = 0; 687 688 /* software provider, if present */ 689 if (me->me_sw_prov != NULL) 690 init_mechanism_info(&infos[cur_info++], me->me_sw_prov); 691 692 /* hardware providers */ 693 for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next) 694 init_mechanism_info(&infos[cur_info++], hwp); 695 696 mutex_exit(&mp->kl_lock); 697 ASSERT(cur_info == ninfos); 698 bail: 699 *mech_infos = infos; 700 *num_mech_infos = ninfos; 701 return (rv); 702 } 703 704 /* 705 * Frees the array of mechanism infos previously allocated by 706 * crypto_get_all_mech_info(). 707 */ 708 void 709 crypto_free_all_mech_info(crypto_mechanism_info_t *mech_infos, uint_t count) 710 { 711 if ((mech_infos != NULL) && (count > 0)) 712 kmem_free(mech_infos, count * sizeof (crypto_mechanism_info_t)); 713 } 714 715 /* 716 * memcmp_pad_max() is a specialized version of memcmp() which 717 * compares two pieces of data up to a maximum length. If the 718 * the two data match up the maximum length, they are considered 719 * matching. Trailing blanks do not cause the match to fail if 720 * one of the data is shorter. 721 * 722 * Examples of matches: 723 * "one" | 724 * "one " | 725 * ^maximum length 726 * 727 * "Number One | X" (X is beyond maximum length) 728 * "Number One " | 729 * ^maximum length 730 * 731 * Examples of mismatches: 732 * " one" 733 * "one" 734 * 735 * "Number One X|" 736 * "Number One |" 737 * ^maximum length 738 */ 739 static int 740 memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz) 741 { 742 uint_t len, extra_len; 743 char *marker; 744 745 /* No point in comparing anything beyond max_sz */ 746 if (d1_len > max_sz) 747 d1_len = max_sz; 748 if (d2_len > max_sz) 749 d2_len = max_sz; 750 751 /* Find shorter of the two data. */ 752 if (d1_len <= d2_len) { 753 len = d1_len; 754 extra_len = d2_len; 755 marker = d2; 756 } else { /* d1_len > d2_len */ 757 len = d2_len; 758 extra_len = d1_len; 759 marker = d1; 760 } 761 762 /* Have a match in the shortest length of data? */ 763 if (memcmp(d1, d2, len) != 0) 764 /* CONSTCOND */ 765 return (!0); 766 767 /* If the rest of longer data is nulls or blanks, call it a match. */ 768 while (len < extra_len) 769 if (!isspace(marker[len++])) 770 /* CONSTCOND */ 771 return (!0); 772 return (0); 773 } 774 775 /* 776 * Obtain ext info for specified provider and see if it matches. 777 */ 778 static boolean_t 779 match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial, 780 crypto_provider_ext_info_t *ext_info) 781 { 782 int rv; 783 784 rv = crypto_get_provinfo(pd, ext_info); 785 ASSERT(rv != CRYPTO_NOT_SUPPORTED); 786 if (rv != CRYPTO_SUCCESS) 787 return (B_FALSE); 788 789 if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL, 790 label, strlen(label), CRYPTO_EXT_SIZE_LABEL)) 791 return (B_FALSE); 792 793 if (manuf != NULL) { 794 if (memcmp_pad_max(ext_info->ei_manufacturerID, 795 CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf), 796 CRYPTO_EXT_SIZE_MANUF)) 797 return (B_FALSE); 798 } 799 800 if (serial != NULL) { 801 if (memcmp_pad_max(ext_info->ei_serial_number, 802 CRYPTO_EXT_SIZE_SERIAL, serial, strlen(serial), 803 CRYPTO_EXT_SIZE_SERIAL)) 804 return (B_FALSE); 805 } 806 return (B_TRUE); 807 } 808 809 /* 810 * Find a provider based on its label, manufacturer ID, and serial number. 811 */ 812 crypto_provider_t 813 crypto_get_provider(char *label, char *manuf, char *serial) 814 { 815 kcf_provider_desc_t **provider_array, *pd; 816 crypto_provider_ext_info_t *ext_info; 817 uint_t count; 818 int i; 819 820 /* manuf and serial are optional */ 821 if (label == NULL) 822 return (NULL); 823 824 if (kcf_get_slot_list(&count, &provider_array, B_FALSE) 825 != CRYPTO_SUCCESS) 826 return (NULL); 827 828 if (count == 0) 829 return (NULL); 830 831 ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP); 832 833 for (i = 0; i < count; i++) { 834 pd = provider_array[i]; 835 if (match_ext_info(pd, label, manuf, serial, ext_info)) { 836 KCF_PROV_REFHOLD(pd); 837 break; 838 } 839 } 840 if (i == count) 841 pd = NULL; 842 843 kcf_free_provider_tab(count, provider_array); 844 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t)); 845 return (pd); 846 } 847 848 /* 849 * Get the provider information given a provider handle. The caller 850 * needs to allocate the space for the argument, info. 851 */ 852 int 853 crypto_get_provinfo(crypto_provider_t hndl, crypto_provider_ext_info_t *info) 854 { 855 int rv; 856 kcf_req_params_t params; 857 kcf_provider_desc_t *pd; 858 kcf_provider_desc_t *real_provider; 859 860 pd = (kcf_provider_desc_t *)hndl; 861 rv = kcf_get_hardware_provider_nomech( 862 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info), 863 CHECK_RESTRICT_FALSE, pd, &real_provider); 864 865 if (rv == CRYPTO_SUCCESS && real_provider != NULL) { 866 ASSERT(real_provider == pd || 867 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 868 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO, 869 0, NULL, 0, NULL, 0, NULL, info, pd); 870 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 871 B_FALSE); 872 KCF_PROV_REFRELE(real_provider); 873 } 874 875 return (rv); 876 } 877 878 void 879 crypto_release_provider(crypto_provider_t provider) 880 { 881 KCF_PROV_REFRELE((kcf_provider_desc_t *)provider); 882 } 883