3410 pk11_get_digest(pflist, current_slot, current_slot_n_digest, |
3349 pk11_get_digest(pflist, current_slot, current_slot_n_digest, |
3411 local_digest_nids, &digests[i]); |
3350 local_digest_nids, &digests[i]); |
3412 } |
3351 } |
3413 } |
3352 } |
3414 |
3353 |
3415 #ifdef SOLARIS_HW_SLOT_SELECTION |
|
3416 /* |
|
3417 * It would be great if we could use pkcs11_kernel directly since this library |
|
3418 * offers hardware slots only. That's the easiest way to achieve the situation |
|
3419 * where we use the hardware accelerators when present and OpenSSL native code |
|
3420 * otherwise. That presumes the fact that OpenSSL native code is faster than the |
|
3421 * code in the soft token. It's a logical assumption - Crypto Framework has some |
|
3422 * inherent overhead so going there for the software implementation of a |
|
3423 * mechanism should be logically slower in contrast to the OpenSSL native code, |
|
3424 * presuming that both implementations are of similar speed. For example, the |
|
3425 * soft token for AES is roughly three times slower than OpenSSL for 64 byte |
|
3426 * blocks and still 20% slower for 8KB blocks. So, if we want to ship products |
|
3427 * that use the PKCS#11 engine by default, we must somehow avoid that regression |
|
3428 * on machines without hardware acceleration. That's why switching to the |
|
3429 * pkcs11_kernel library seems like a very good idea. |
|
3430 * |
|
3431 * The problem is that OpenSSL built with SunStudio is roughly 2x slower for |
|
3432 * asymmetric operations (RSA/DSA/DH) than the soft token built with the same |
|
3433 * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 |
|
3434 * library, we would have had a performance regression on machines without |
|
3435 * hardware acceleration for asymmetric operations for all applications that use |
|
3436 * the PKCS#11 engine. There is one such application - Apache web server since |
|
3437 * it's shipped configured to use the PKCS#11 engine by default. Having said |
|
3438 * that, we can't switch to the pkcs11_kernel library now and have to come with |
|
3439 * a solution that, on non-accelerated machines, uses the OpenSSL native code |
|
3440 * for all symmetric ciphers and digests while it uses the soft token for |
|
3441 * asymmetric operations. |
|
3442 * |
|
3443 * This is the idea: dlopen() pkcs11_kernel directly and find out what |
|
3444 * mechanisms are there. We don't care about duplications (more slots can |
|
3445 * support the same mechanism), we just want to know what mechanisms can be |
|
3446 * possibly supported in hardware on that particular machine. As said before, |
|
3447 * pkcs11_kernel will show you hardware providers only. |
|
3448 * |
|
3449 * Then, we rely on the fact that since we use libpkcs11 library we will find |
|
3450 * the metaslot. When we go through the metaslot's mechanisms for symmetric |
|
3451 * ciphers and digests, we check that any found mechanism is in the table |
|
3452 * created using the pkcs11_kernel library. So, as a result we have two arrays |
|
3453 * of mechanisms that were advertised as supported in hardware which was the |
|
3454 * goal of that whole exercise. Thus, we can use libpkcs11 but avoid soft token |
|
3455 * code for symmetric ciphers and digests. See pk11_choose_slots() for more |
|
3456 * information. |
|
3457 * |
|
3458 * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined |
|
3459 * the code won't be used. |
|
3460 */ |
|
3461 #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) |
|
3462 static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; |
|
3463 #else |
|
3464 static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; |
|
3465 #endif |
|
3466 |
|
3467 /* |
|
3468 * Check hardware capabilities of the machines. The output are two lists, |
|
3469 * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware |
|
3470 * providers together. They are not sorted and may contain duplicate mechanisms. |
|
3471 */ |
|
3472 static int check_hw_mechanisms(void) |
|
3473 { |
|
3474 int i; |
|
3475 CK_RV rv; |
|
3476 void *handle; |
|
3477 CK_C_GetFunctionList p; |
|
3478 CK_TOKEN_INFO token_info; |
|
3479 CK_ULONG ulSlotCount = 0; |
|
3480 int n_cipher = 0, n_digest = 0; |
|
3481 CK_FUNCTION_LIST_PTR pflist = NULL; |
|
3482 CK_SLOT_ID_PTR pSlotList = NULL_PTR; |
|
3483 int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; |
|
3484 int hw_ctable_size, hw_dtable_size; |
|
3485 |
|
3486 DEBUG_SLOT_SEL("%s: SOLARIS_HW_SLOT_SELECTION code running\n", |
|
3487 PK11_DBG); |
|
3488 /* |
|
3489 * Use RTLD_GROUP to limit the pkcs11_kernel provider to its own |
|
3490 * symbols, which prevents it from mistakenly accessing C_* functions |
|
3491 * from the top-level PKCS#11 library. |
|
3492 */ |
|
3493 if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY | RTLD_GROUP)) == NULL) |
|
3494 { |
|
3495 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); |
|
3496 goto err; |
|
3497 } |
|
3498 |
|
3499 if ((p = (CK_C_GetFunctionList)dlsym(handle, |
|
3500 PK11_GET_FUNCTION_LIST)) == NULL) |
|
3501 { |
|
3502 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); |
|
3503 goto err; |
|
3504 } |
|
3505 |
|
3506 /* get the full function list from the loaded library */ |
|
3507 if (p(&pflist) != CKR_OK) |
|
3508 { |
|
3509 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); |
|
3510 goto err; |
|
3511 } |
|
3512 |
|
3513 rv = pflist->C_Initialize(NULL_PTR); |
|
3514 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) |
|
3515 { |
|
3516 PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, |
|
3517 PK11_R_INITIALIZE, rv); |
|
3518 goto err; |
|
3519 } |
|
3520 |
|
3521 if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) |
|
3522 { |
|
3523 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); |
|
3524 goto err; |
|
3525 } |
|
3526 |
|
3527 /* no slots, set the hw mechanism tables as empty */ |
|
3528 if (ulSlotCount == 0) |
|
3529 { |
|
3530 DEBUG_SLOT_SEL("%s: no hardware mechanisms found\n", PK11_DBG); |
|
3531 hw_cnids = OPENSSL_malloc(sizeof (int)); |
|
3532 hw_dnids = OPENSSL_malloc(sizeof (int)); |
|
3533 if (hw_cnids == NULL || hw_dnids == NULL) |
|
3534 { |
|
3535 PK11err(PK11_F_CHECK_HW_MECHANISMS, |
|
3536 PK11_R_MALLOC_FAILURE); |
|
3537 return (0); |
|
3538 } |
|
3539 /* this means empty tables */ |
|
3540 hw_cnids[0] = NID_undef; |
|
3541 hw_dnids[0] = NID_undef; |
|
3542 return (1); |
|
3543 } |
|
3544 |
|
3545 pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); |
|
3546 if (pSlotList == NULL) |
|
3547 { |
|
3548 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); |
|
3549 goto err; |
|
3550 } |
|
3551 |
|
3552 /* Get the slot list for processing */ |
|
3553 if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) |
|
3554 { |
|
3555 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); |
|
3556 goto err; |
|
3557 } |
|
3558 |
|
3559 /* |
|
3560 * We don't care about duplicate mechanisms in multiple slots and also |
|
3561 * reserve one slot for the terminal NID_undef which we use to stop the |
|
3562 * search. |
|
3563 */ |
|
3564 hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; |
|
3565 hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; |
|
3566 tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); |
|
3567 tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); |
|
3568 if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) |
|
3569 { |
|
3570 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); |
|
3571 goto err; |
|
3572 } |
|
3573 |
|
3574 /* |
|
3575 * Do not use memset since we should not rely on the fact that NID_undef |
|
3576 * is zero now. |
|
3577 */ |
|
3578 for (i = 0; i < hw_ctable_size; ++i) |
|
3579 tmp_hw_cnids[i] = NID_undef; |
|
3580 for (i = 0; i < hw_dtable_size; ++i) |
|
3581 tmp_hw_dnids[i] = NID_undef; |
|
3582 |
|
3583 DEBUG_SLOT_SEL("%s: provider: %s\n", PK11_DBG, pkcs11_kernel); |
|
3584 DEBUG_SLOT_SEL("%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); |
|
3585 DEBUG_SLOT_SEL("%s: now looking for mechs supported in hw\n", |
|
3586 PK11_DBG); |
|
3587 |
|
3588 for (i = 0; i < ulSlotCount; i++) |
|
3589 { |
|
3590 if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) |
|
3591 continue; |
|
3592 |
|
3593 DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG, |
|
3594 token_info.label); |
|
3595 |
|
3596 /* |
|
3597 * We are filling the hw mech tables here. Global tables are |
|
3598 * still NULL so all mechanisms are put into tmp tables. |
|
3599 */ |
|
3600 pk11_find_symmetric_ciphers(pflist, pSlotList[i], |
|
3601 &n_cipher, tmp_hw_cnids); |
|
3602 pk11_find_digests(pflist, pSlotList[i], |
|
3603 &n_digest, tmp_hw_dnids); |
|
3604 } |
|
3605 |
|
3606 /* |
|
3607 * Since we are part of a library (libcrypto.so), calling this function |
|
3608 * may have side-effects. Also, C_Finalize() is triggered by |
|
3609 * dlclose(3C). |
|
3610 */ |
|
3611 #if 0 |
|
3612 pflist->C_Finalize(NULL); |
|
3613 #endif |
|
3614 OPENSSL_free(pSlotList); |
|
3615 (void) dlclose(handle); |
|
3616 hw_cnids = tmp_hw_cnids; |
|
3617 hw_dnids = tmp_hw_dnids; |
|
3618 |
|
3619 DEBUG_SLOT_SEL("%s: hw mechs check complete\n", PK11_DBG); |
|
3620 return (1); |
|
3621 |
|
3622 err: |
|
3623 if (pSlotList != NULL) |
|
3624 OPENSSL_free(pSlotList); |
|
3625 if (tmp_hw_cnids != NULL) |
|
3626 OPENSSL_free(tmp_hw_cnids); |
|
3627 if (tmp_hw_dnids != NULL) |
|
3628 OPENSSL_free(tmp_hw_dnids); |
|
3629 |
|
3630 return (0); |
|
3631 } |
|
3632 |
|
3633 /* |
|
3634 * Check presence of a NID in the table of NIDs unless the mechanism is |
|
3635 * supported directly in a CPU instruction set. The table may be NULL (i.e., |
|
3636 * non-existent). |
|
3637 */ |
|
3638 static int nid_in_table(int nid, int *nid_table) |
|
3639 { |
|
3640 int i = 0; |
|
3641 |
|
3642 /* |
|
3643 * Special case first. NULL means that we are initializing a new table. |
|
3644 */ |
|
3645 if (nid_table == NULL) |
|
3646 return (1); |
|
3647 |
|
3648 /* |
|
3649 * the table is never full, there is always at least one |
|
3650 * NID_undef. |
|
3651 */ |
|
3652 while (nid_table[i] != NID_undef) |
|
3653 { |
|
3654 if (nid_table[i++] == nid) |
|
3655 { |
|
3656 DEBUG_SLOT_SEL(" (NID %d in hw table, idx %d)", nid, i); |
|
3657 return (1); |
|
3658 } |
|
3659 } |
|
3660 |
|
3661 return (0); |
|
3662 } |
|
3663 |
|
3664 #endif /* SOLARIS_HW_SLOT_SELECTION */ |
|
3665 |
|
3666 #endif /* OPENSSL_NO_HW_PK11 */ |
3354 #endif /* OPENSSL_NO_HW_PK11 */ |
3667 #endif /* OPENSSL_NO_HW */ |
3355 #endif /* OPENSSL_NO_HW */ |