components/openssl/openssl-fips-140/engines/pkcs11/e_pk11.c
changeset 5694 501423159f9d
parent 4822 1fb8a14c6702
equal deleted inserted replaced
5693:dfccef2e9955 5694:501423159f9d
     1 /*
     1 /*
     2  * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
     3  */
     3  */
     4 
     4 
     5 /* crypto/engine/e_pk11.c */
     5 /* crypto/engine/e_pk11.c */
     6 /*
     6 /*
     7  * This product includes software developed by the OpenSSL Project for
     7  * This product includes software developed by the OpenSSL Project for
   101 
   101 
   102 /* label for debug messages printed on stderr */
   102 /* label for debug messages printed on stderr */
   103 #define	PK11_DBG	"PKCS#11 ENGINE DEBUG"
   103 #define	PK11_DBG	"PKCS#11 ENGINE DEBUG"
   104 /* prints a lot of debug messages on stderr about slot selection process */
   104 /* prints a lot of debug messages on stderr about slot selection process */
   105 #undef	DEBUG_SLOT_SELECTION
   105 #undef	DEBUG_SLOT_SELECTION
   106 /*
       
   107  * Solaris specific code. See comment at check_hw_mechanisms() for more
       
   108  * information.
       
   109  */
       
   110 #if defined(__SVR4) && defined(__sun)
       
   111 #define	SOLARIS_HW_SLOT_SELECTION
       
   112 #endif
       
   113 
   106 
   114 #ifdef DEBUG_SLOT_SELECTION
   107 #ifdef DEBUG_SLOT_SELECTION
   115 #define	DEBUG_SLOT_SEL(...) fprintf(stderr, __VA_ARGS__)
   108 #define	DEBUG_SLOT_SEL(...) fprintf(stderr, __VA_ARGS__)
   116 #else
   109 #else
   117 #define	DEBUG_SLOT_SEL(...)
   110 #define	DEBUG_SLOT_SEL(...)
   133  * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
   126  * We use this lock to prevent multiple C_Login()s, guard getpassphrase(),
   134  * uri_struct manipulation, and static token info. All of that is used by the
   127  * uri_struct manipulation, and static token info. All of that is used by the
   135  * RSA keys by reference feature.
   128  * RSA keys by reference feature.
   136  */
   129  */
   137 pthread_mutex_t *uri_lock = NULL;
   130 pthread_mutex_t *uri_lock = NULL;
   138 
       
   139 #ifdef	SOLARIS_HW_SLOT_SELECTION
       
   140 /*
       
   141  * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel
       
   142  * library. See comment at check_hw_mechanisms() for more information.
       
   143  */
       
   144 int *hw_cnids;
       
   145 int *hw_dnids;
       
   146 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
   147 
   131 
   148 /* PKCS#11 session caches and their locks for all operation types */
   132 /* PKCS#11 session caches and their locks for all operation types */
   149 static PK11_CACHE session_cache[OP_MAX];
   133 static PK11_CACHE session_cache[OP_MAX];
   150 
   134 
   151 /*
   135 /*
   334     int *current_slot_n_digest, int *local_digest_nids,
   318     int *current_slot_n_digest, int *local_digest_nids,
   335     PK11_DIGEST *digest);
   319     PK11_DIGEST *digest);
   336 
   320 
   337 static int pk11_init_all_locks(void);
   321 static int pk11_init_all_locks(void);
   338 static void pk11_free_all_locks(void);
   322 static void pk11_free_all_locks(void);
   339 
       
   340 #ifdef	SOLARIS_HW_SLOT_SELECTION
       
   341 static int check_hw_mechanisms(void);
       
   342 static int nid_in_table(int nid, int *nid_table);
       
   343 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
   344 
   323 
   345 #define	TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type)	\
   324 #define	TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type)	\
   346 	{								\
   325 	{								\
   347 	if (uselock)							\
   326 	if (uselock)							\
   348 		LOCK_OBJSTORE(alg_type);				\
   327 		LOCK_OBJSTORE(alg_type);				\
  1181 			PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
  1160 			PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
  1182 			goto err;
  1161 			goto err;
  1183 			}
  1162 			}
  1184 		}
  1163 		}
  1185 
  1164 
  1186 #ifdef	SOLARIS_HW_SLOT_SELECTION
       
  1187 	if (check_hw_mechanisms() == 0)
       
  1188 		goto err;
       
  1189 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
  1190 
       
  1191 	/* get the C_GetFunctionList function from the loaded library */
  1165 	/* get the C_GetFunctionList function from the loaded library */
  1192 	p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
  1166 	p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
  1193 		PK11_GET_FUNCTION_LIST);
  1167 		PK11_GET_FUNCTION_LIST);
  1194 	if (!p)
  1168 	if (!p)
  1195 		{
  1169 		{
  1616 		 * process. If we are here then we must have found at least one
  1590 		 * process. If we are here then we must have found at least one
  1617 		 * usable slot before so we don't need to check any_slot_found.
  1591 		 * usable slot before so we don't need to check any_slot_found.
  1618 		 * See pk11_library_init()'s usage of this function for more
  1592 		 * See pk11_library_init()'s usage of this function for more
  1619 		 * information.
  1593 		 * information.
  1620 		 */
  1594 		 */
  1621 #ifdef	SOLARIS_HW_SLOT_SELECTION
       
  1622 		if (check_hw_mechanisms() == 0)
       
  1623 			goto err;
       
  1624 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
  1625 		if (pk11_choose_slots(NULL) == 0)
  1595 		if (pk11_choose_slots(NULL) == 0)
  1626 			goto err;
  1596 			goto err;
  1627 
  1597 
  1628 		/* Open the global_session for the new process */
  1598 		/* Open the global_session for the new process */
  1629 		rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
  1599 		rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
  3123 	DEBUG_SLOT_SEL("%s: digest_count %d\n", PK11_DBG, digest_count);
  3093 	DEBUG_SLOT_SEL("%s: digest_count %d\n", PK11_DBG, digest_count);
  3124 
  3094 
  3125 	if (pSlotList != NULL)
  3095 	if (pSlotList != NULL)
  3126 		OPENSSL_free(pSlotList);
  3096 		OPENSSL_free(pSlotList);
  3127 
  3097 
  3128 #ifdef  SOLARIS_HW_SLOT_SELECTION
       
  3129 	OPENSSL_free(hw_cnids);
       
  3130 	OPENSSL_free(hw_dnids);
       
  3131 #endif  /* SOLARIS_HW_SLOT_SELECTION */
       
  3132 
       
  3133 	if (any_slot_found != NULL)
  3098 	if (any_slot_found != NULL)
  3134 		*any_slot_found = 1;
  3099 		*any_slot_found = 1;
  3135 	return (1);
  3100 	return (1);
  3136 	}
  3101 	}
  3137 
  3102 
  3319 			    " match mech range <%lu-%lu>\n",
  3284 			    " match mech range <%lu-%lu>\n",
  3320 			    cipher->min_key_len, cipher->max_key_len,
  3285 			    cipher->min_key_len, cipher->max_key_len,
  3321 			    mech_info.ulMinKeySize, mech_info.ulMaxKeySize);
  3286 			    mech_info.ulMinKeySize, mech_info.ulMaxKeySize);
  3322 			return;
  3287 			return;
  3323 			}
  3288 			}
  3324 #ifdef  SOLARIS_HW_SLOT_SELECTION
  3289 		DEBUG_SLOT_SEL(" usable\n");
  3325 		if (nid_in_table(cipher->nid, hw_cnids))
  3290 		local_cipher_nids[(*current_slot_n_cipher)++] = cipher->nid;
  3326 #endif  /* SOLARIS_HW_SLOT_SELECTION */
       
  3327 			{
       
  3328 			DEBUG_SLOT_SEL(" usable\n");
       
  3329 			local_cipher_nids[(*current_slot_n_cipher)++] =
       
  3330 			    cipher->nid;
       
  3331 			}
       
  3332 #ifdef  SOLARIS_HW_SLOT_SELECTION
       
  3333 		else
       
  3334 			{
       
  3335 			DEBUG_SLOT_SEL(
       
  3336 			    " rejected, software implementation only\n");
       
  3337 			}
       
  3338 #endif  /* SOLARIS_HW_SLOT_SELECTION */
       
  3339 		}
  3291 		}
  3340 	else
  3292 	else
  3341 		{
  3293 		{
  3342 		DEBUG_SLOT_SEL(" unusable\n");
  3294 		DEBUG_SLOT_SEL(" unusable\n");
  3343 		}
  3295 		}
  3360 		return;
  3312 		return;
  3361 		}
  3313 		}
  3362 
  3314 
  3363 	if (mech_info.flags & CKF_DIGEST)
  3315 	if (mech_info.flags & CKF_DIGEST)
  3364 		{
  3316 		{
  3365 #ifdef	SOLARIS_HW_SLOT_SELECTION
  3317 		DEBUG_SLOT_SEL(" usable\n");
  3366 		if (nid_in_table(digest->nid, hw_dnids))
  3318 		local_digest_nids[(*current_slot_n_digest)++] = digest->nid;
  3367 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
  3368 			{
       
  3369 			DEBUG_SLOT_SEL(" usable\n");
       
  3370 			local_digest_nids[(*current_slot_n_digest)++] =
       
  3371 			    digest->nid;
       
  3372 			}
       
  3373 #ifdef	SOLARIS_HW_SLOT_SELECTION
       
  3374 		else
       
  3375 			{
       
  3376 			DEBUG_SLOT_SEL(
       
  3377 			    " rejected, software implementation only\n");
       
  3378 			}
       
  3379 #endif	/* SOLARIS_HW_SLOT_SELECTION */
       
  3380 		}
  3319 		}
  3381 	else
  3320 	else
  3382 		{
  3321 		{
  3383 		DEBUG_SLOT_SEL(" unusable\n");
  3322 		DEBUG_SLOT_SEL(" unusable\n");
  3384 		}
  3323 		}
  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 */