17761944 pk11_choose_slots() in the PKCS#11 engine should be split into more functions
authorjenny.yung@oracle.com <jenny.yung@oracle.com>
Fri, 13 Dec 2013 10:42:29 -0800
changeset 1597 392a401c6d27
parent 1596 59869c4257d0
child 1598 3223461a4c41
17761944 pk11_choose_slots() in the PKCS#11 engine should be split into more functions
components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.c
components/openssl/openssl-1.0.1/engines/pkcs11/e_pk11.c
--- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.c	Fri Dec 13 07:45:20 2013 -0800
+++ b/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.c	Fri Dec 13 10:42:29 2013 -0800
@@ -310,6 +310,14 @@
 static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
 
 static int pk11_choose_slots(int *any_slot_found);
+static void pk11_choose_rand_slot(CK_TOKEN_INFO token_info,
+    CK_SLOT_ID current_slot);
+static void pk11_choose_pubkey_slot(CK_MECHANISM_INFO mech_info,
+    CK_TOKEN_INFO token_info, CK_SLOT_ID current_slot, CK_RV rv,
+    int best_number_of_mechs, CK_SLOT_ID best_pubkey_slot_sofar);
+static void pk11_choose_cipher_digest(int *local_cipher_nids,
+    int *local_digest_nids, CK_FUNCTION_LIST_PTR pflist,
+    CK_SLOT_ID current_slot);
 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
     CK_SLOT_ID current_slot, int *current_slot_n_cipher,
     int *local_cipher_nids);
@@ -3022,16 +3030,8 @@
 	int i;
 	CK_RV rv;
 	CK_SLOT_ID best_pubkey_slot_sofar;
-#ifdef DEBUG_SLOT_SELECTION
-	CK_SLOT_ID best_cd_slot_sofar;
-#endif
-	int slot_n_cipher = -1;
-	int slot_n_digest = -1;
 	CK_SLOT_ID current_slot = 0;
-	int current_slot_n_cipher = 0;
-	int current_slot_n_digest = 0;
 	int best_number_of_mechs = 0;
-	int current_number_of_mechs = 0;
 	int local_cipher_nids[PK11_CIPHER_MAX];
 	int local_digest_nids[PK11_DIGEST_MAX];
 
@@ -3078,9 +3078,6 @@
 	pubkey_SLOTID = pSlotList[0];
 	for (i = 0; i < ulSlotCount; i++)
 		{
-		CK_BBOOL slot_has_rsa = CK_FALSE;
-		CK_BBOOL slot_has_dsa = CK_FALSE;
-		CK_BBOOL slot_has_dh = CK_FALSE;
 		current_slot = pSlotList[i];
 
 		DEBUG_SLOT_SEL("%s: == checking slot: %d ==\n", PK11_DBG,
@@ -3091,144 +3088,13 @@
 
 		DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG,
 		    token_info.label);
-
-		DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG);
-
-		if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random)
-			{
-			DEBUG_SLOT_SEL(
-			    "%s: this token has CKF_RNG flag\n", PK11_DBG);
-			pk11_have_random = CK_TRUE;
-			rand_SLOTID = current_slot;
-			}
-
-		DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG);
-		current_number_of_mechs = 0;
-
-#ifndef OPENSSL_NO_RSA
-		/*
-		 * Check if this slot is capable of signing and
-		 * verifying with CKM_RSA_PKCS.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
-			&mech_info);
-
-		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-				(mech_info.flags & CKF_VERIFY)))
-			{
-			/*
-			 * Check if this slot is capable of encryption,
-			 * decryption, sign, and verify with CKM_RSA_X_509.
-			 */
-			rv = pFuncList->C_GetMechanismInfo(current_slot,
-			    CKM_RSA_X_509, &mech_info);
-
-			if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-			    (mech_info.flags & CKF_VERIFY) &&
-			    (mech_info.flags & CKF_ENCRYPT) &&
-			    (mech_info.flags & CKF_VERIFY_RECOVER) &&
-			    (mech_info.flags & CKF_DECRYPT)))
-				{
-				slot_has_rsa = CK_TRUE;
-				current_number_of_mechs++;
-				}
-			}
-#endif	/* OPENSSL_NO_RSA */
-
-#ifndef OPENSSL_NO_DSA
-		/*
-		 * Check if this slot is capable of signing and
-		 * verifying with CKM_DSA.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
-			&mech_info);
-		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-		    (mech_info.flags & CKF_VERIFY)))
-			{
-			slot_has_dsa = CK_TRUE;
-			current_number_of_mechs++;
-			}
-
-#endif	/* OPENSSL_NO_DSA */
-
-#ifndef OPENSSL_NO_DH
-		/*
-		 * Check if this slot is capable of DH key generataion and
-		 * derivation.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot,
-		    CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
-
-		if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
-			{
-			rv = pFuncList->C_GetMechanismInfo(current_slot,
-				CKM_DH_PKCS_DERIVE, &mech_info);
-			if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
-				{
-				slot_has_dh = CK_TRUE;
-				current_number_of_mechs++;
-				}
-			}
-#endif	/* OPENSSL_NO_DH */
-
-		if (current_number_of_mechs > best_number_of_mechs)
-			{
-			best_pubkey_slot_sofar = current_slot;
-			pk11_have_rsa = slot_has_rsa;
-			pk11_have_dsa = slot_has_dsa;
-			pk11_have_dh = slot_has_dh;
-			best_number_of_mechs = current_number_of_mechs;
-			/*
-			 * Cache the flags for later use. We might need those if
-			 * RSA keys by reference feature is used.
-			 */
-			pubkey_token_flags = token_info.flags;
-			DEBUG_SLOT_SEL("%s: pubkey flags changed to "
-			    "%lu.\n", PK11_DBG, pubkey_token_flags);
-			}
-
-		DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG);
-
-		current_slot_n_cipher = 0;
-		current_slot_n_digest = 0;
-		(void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
-		(void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
-
-		pk11_find_symmetric_ciphers(pFuncList, current_slot,
-		    &current_slot_n_cipher, local_cipher_nids);
-
-		pk11_find_digests(pFuncList, current_slot,
-		    &current_slot_n_digest, local_digest_nids);
-
-		DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG,
-			current_slot_n_cipher);
-		DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG,
-			current_slot_n_digest);
-
-		/*
-		 * If the current slot supports more ciphers/digests than
-		 * the previous best one we change the current best to this one,
-		 * otherwise leave it where it is.
-		 */
-		if ((current_slot_n_cipher + current_slot_n_digest) >
-		    (slot_n_cipher + slot_n_digest))
-			{
-			DEBUG_SLOT_SEL("%s: changing best slot to %d\n",
-				PK11_DBG, current_slot);
-			SLOTID = current_slot;
-#ifdef DEBUG_SLOT_SELECTION
-			best_cd_slot_sofar = current_slot;
-#endif
-			cipher_count = slot_n_cipher = current_slot_n_cipher;
-			digest_count = slot_n_digest = current_slot_n_digest;
-			(void) memcpy(cipher_nids, local_cipher_nids,
-			    sizeof (local_cipher_nids));
-			(void) memcpy(digest_nids, local_digest_nids,
-			    sizeof (local_digest_nids));
-			}
-
-		DEBUG_SLOT_SEL("%s: best cipher/digest slot so far: %d\n",
-			PK11_DBG, best_cd_slot_sofar);
+		pk11_choose_rand_slot(token_info, current_slot);
+
+		pk11_choose_pubkey_slot(mech_info, token_info, current_slot,
+			rv, best_number_of_mechs, best_pubkey_slot_sofar);
+
+		pk11_choose_cipher_digest(&local_cipher_nids,
+			&local_digest_nids, pFuncList, current_slot);
 		}
 
 	if (best_number_of_mechs == 0)
@@ -3263,6 +3129,156 @@
 	return (1);
 	}
 
+static void pk11_choose_rand_slot(CK_TOKEN_INFO token_info,
+    CK_SLOT_ID current_slot)
+	{
+	DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG);
+
+	if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random)
+		{
+		DEBUG_SLOT_SEL(
+		    "%s: this token has CKF_RNG flag\n", PK11_DBG);
+		pk11_have_random = CK_TRUE;
+		rand_SLOTID = current_slot;
+		}
+	}
+
+static void pk11_choose_pubkey_slot(CK_MECHANISM_INFO mech_info,
+    CK_TOKEN_INFO token_info, CK_SLOT_ID current_slot, CK_RV rv,
+    int best_number_of_mechs, CK_SLOT_ID best_pubkey_slot_sofar)
+	{
+	CK_BBOOL slot_has_rsa = CK_FALSE;
+	CK_BBOOL slot_has_dsa = CK_FALSE;
+	CK_BBOOL slot_has_dh = CK_FALSE;
+	int current_number_of_mechs = 0;
+	DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG);
+
+#ifndef OPENSSL_NO_RSA
+	/*
+	 * Check if this slot is capable of signing and
+	 * verifying with CKM_RSA_PKCS.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
+		&mech_info);
+
+	if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+			(mech_info.flags & CKF_VERIFY)))
+		{
+		/*
+		 * Check if this slot is capable of encryption,
+		 * decryption, sign, and verify with CKM_RSA_X_509.
+		 */
+		rv = pFuncList->C_GetMechanismInfo(current_slot,
+			CKM_RSA_X_509, &mech_info);
+
+		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+		    (mech_info.flags & CKF_VERIFY) &&
+		    (mech_info.flags & CKF_ENCRYPT) &&
+		    (mech_info.flags & CKF_VERIFY_RECOVER) &&
+		    (mech_info.flags & CKF_DECRYPT)))
+			{
+			slot_has_rsa = CK_TRUE;
+			current_number_of_mechs++;
+			}
+		}
+#endif  /* OPENSSL_NO_RSA */
+
+#ifndef OPENSSL_NO_DSA
+	/*
+	 * Check if this slot is capable of signing and
+	 * verifying with CKM_DSA.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
+		&mech_info);
+	if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+	    (mech_info.flags & CKF_VERIFY)))
+		{
+		slot_has_dsa = CK_TRUE;
+		current_number_of_mechs++;
+		}
+
+#endif  /* OPENSSL_NO_DSA */
+
+#ifndef OPENSSL_NO_DH
+	/*
+	 * Check if this slot is capable of DH key generataion and
+	 * derivation.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot,
+	    CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
+
+	if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
+		{
+		rv = pFuncList->C_GetMechanismInfo(current_slot,
+			CKM_DH_PKCS_DERIVE, &mech_info);
+		if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
+			{
+			slot_has_dh = CK_TRUE;
+			current_number_of_mechs++;
+			}
+		}
+#endif  /* OPENSSL_NO_DH */
+
+	if (current_number_of_mechs > best_number_of_mechs)
+		{
+		best_pubkey_slot_sofar = current_slot;
+		pk11_have_rsa = slot_has_rsa;
+		pk11_have_dsa = slot_has_dsa;
+		pk11_have_dh = slot_has_dh;
+		best_number_of_mechs = current_number_of_mechs;
+		/*
+		 * Cache the flags for later use. We might need those if
+		 * RSA keys by reference feature is used.
+		 */
+		pubkey_token_flags = token_info.flags;
+		DEBUG_SLOT_SEL("%s: pubkey flags changed to "
+		    "%lu.\n", PK11_DBG, pubkey_token_flags);
+		}
+	}
+
+static void pk11_choose_cipher_digest(int *local_cipher_nids,
+    int *local_digest_nids, CK_FUNCTION_LIST_PTR pflist,
+    CK_SLOT_ID current_slot)
+	{
+	int current_slot_n_cipher = 0;
+	int current_slot_n_digest = 0;
+
+	DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG);
+
+	(void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
+	(void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
+
+	pk11_find_symmetric_ciphers(pFuncList, current_slot,
+	    &current_slot_n_cipher, local_cipher_nids);
+
+	pk11_find_digests(pFuncList, current_slot,
+	    &current_slot_n_digest, local_digest_nids);
+
+	DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG,
+		current_slot_n_cipher);
+	DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG,
+		current_slot_n_digest);
+
+	/*
+	 * If the current slot supports more ciphers/digests than
+	 * the previous best one we change the current best to this one,
+	 * otherwise leave it where it is.
+	 */
+	if ((current_slot_n_cipher + current_slot_n_digest) >
+	    (cipher_count + digest_count))
+		{
+		DEBUG_SLOT_SEL("%s: changing best slot to %d\n",
+			PK11_DBG, current_slot);
+		SLOTID = current_slot;
+		cipher_count = current_slot_n_cipher;
+		digest_count = current_slot_n_digest;
+		(void) memcpy(cipher_nids, local_cipher_nids,
+			sizeof (local_cipher_nids));
+		(void) memcpy(digest_nids, local_digest_nids,
+			sizeof (local_digest_nids));
+		}
+	}
+
 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
     int slot_id, int *current_slot_n_cipher, int *local_cipher_nids,
     PK11_CIPHER *cipher)
--- a/components/openssl/openssl-1.0.1/engines/pkcs11/e_pk11.c	Fri Dec 13 07:45:20 2013 -0800
+++ b/components/openssl/openssl-1.0.1/engines/pkcs11/e_pk11.c	Fri Dec 13 10:42:29 2013 -0800
@@ -317,6 +317,14 @@
 static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
 
 static int pk11_choose_slots(int *any_slot_found);
+static void pk11_choose_rand_slot(CK_TOKEN_INFO token_info,
+    CK_SLOT_ID current_slot);
+static void pk11_choose_pubkey_slot(CK_MECHANISM_INFO mech_info,
+    CK_TOKEN_INFO token_info, CK_SLOT_ID current_slot, CK_RV rv,
+    int best_number_of_mechs, CK_SLOT_ID best_pubkey_slot_sofar);
+static void pk11_choose_cipher_digest(int *local_cipher_nids,
+    int *local_digest_nids, CK_FUNCTION_LIST_PTR pflist,
+    CK_SLOT_ID current_slot);
 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist,
     CK_SLOT_ID current_slot, int *current_slot_n_cipher,
     int *local_cipher_nids);
@@ -3028,16 +3036,8 @@
 	int i;
 	CK_RV rv;
 	CK_SLOT_ID best_pubkey_slot_sofar;
-#ifdef DEBUG_SLOT_SELECTION
-	CK_SLOT_ID best_cd_slot_sofar;
-#endif
-	int slot_n_cipher = -1;
-	int slot_n_digest = -1;
 	CK_SLOT_ID current_slot = 0;
-	int current_slot_n_cipher = 0;
-	int current_slot_n_digest = 0;
 	int best_number_of_mechs = 0;
-	int current_number_of_mechs = 0;
 	int local_cipher_nids[PK11_CIPHER_MAX];
 	int local_digest_nids[PK11_DIGEST_MAX];
 
@@ -3084,9 +3084,6 @@
 	pubkey_SLOTID = pSlotList[0];
 	for (i = 0; i < ulSlotCount; i++)
 		{
-		CK_BBOOL slot_has_rsa = CK_FALSE;
-		CK_BBOOL slot_has_dsa = CK_FALSE;
-		CK_BBOOL slot_has_dh = CK_FALSE;
 		current_slot = pSlotList[i];
 		DEBUG_SLOT_SEL("%s: == checking slot: %d ==\n", PK11_DBG,
 		    current_slot);
@@ -3097,143 +3094,13 @@
 		DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG,
 		    token_info.label);
 
-		DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG);
-
-		if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random)
-			{
-			DEBUG_SLOT_SEL(
-			    "%s: this token has CKF_RNG flag\n", PK11_DBG);
-			pk11_have_random = CK_TRUE;
-			rand_SLOTID = current_slot;
-			}
-
-		DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG);
-
-		current_number_of_mechs = 0;
-#ifndef OPENSSL_NO_RSA
-		/*
-		 * Check if this slot is capable of signing and
-		 * verifying with CKM_RSA_PKCS.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
-			&mech_info);
-
-		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-				(mech_info.flags & CKF_VERIFY)))
-			{
-			/*
-			 * Check if this slot is capable of encryption,
-			 * decryption, sign, and verify with CKM_RSA_X_509.
-			 */
-			rv = pFuncList->C_GetMechanismInfo(current_slot,
-			    CKM_RSA_X_509, &mech_info);
-
-			if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-			    (mech_info.flags & CKF_VERIFY) &&
-			    (mech_info.flags & CKF_ENCRYPT) &&
-			    (mech_info.flags & CKF_VERIFY_RECOVER) &&
-			    (mech_info.flags & CKF_DECRYPT)))
-				{
-				slot_has_rsa = CK_TRUE;
-				current_number_of_mechs++;
-				}
-			}
-#endif	/* OPENSSL_NO_RSA */
-
-#ifndef OPENSSL_NO_DSA
-		/*
-		 * Check if this slot is capable of signing and
-		 * verifying with CKM_DSA.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
-			&mech_info);
-		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
-		    (mech_info.flags & CKF_VERIFY)))
-			{
-			slot_has_dsa = CK_TRUE;
-			current_number_of_mechs++;
-			}
-
-#endif	/* OPENSSL_NO_DSA */
-
-#ifndef OPENSSL_NO_DH
-		/*
-		 * Check if this slot is capable of DH key generataion and
-		 * derivation.
-		 */
-		rv = pFuncList->C_GetMechanismInfo(current_slot,
-		    CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
-
-		if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
-			{
-			rv = pFuncList->C_GetMechanismInfo(current_slot,
-				CKM_DH_PKCS_DERIVE, &mech_info);
-			if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
-				{
-				slot_has_dh = CK_TRUE;
-				current_number_of_mechs++;
-				}
-			}
-#endif	/* OPENSSL_NO_DH */
-
-		if (current_number_of_mechs > best_number_of_mechs)
-			{
-			best_pubkey_slot_sofar = current_slot;
-			pk11_have_rsa = slot_has_rsa;
-			pk11_have_dsa = slot_has_dsa;
-			pk11_have_dh = slot_has_dh;
-			best_number_of_mechs = current_number_of_mechs;
-			/*
-			 * Cache the flags for later use. We might need those if
-			 * RSA keys by reference feature is used.
-			 */
-			pubkey_token_flags = token_info.flags;
-			DEBUG_SLOT_SEL("%s: pubkey flags changed to "
-			    "%lu.\n", PK11_DBG, pubkey_token_flags);
-			}
-
-		DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG);
-
-		current_slot_n_cipher = 0;
-		current_slot_n_digest = 0;
-		(void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
-		(void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
-
-		pk11_find_symmetric_ciphers(pFuncList, current_slot,
-		    &current_slot_n_cipher, local_cipher_nids);
-
-		pk11_find_digests(pFuncList, current_slot,
-		    &current_slot_n_digest, local_digest_nids);
-
-		DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG,
-			current_slot_n_cipher);
-		DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG,
-			current_slot_n_digest);
-
-		/*
-		 * If the current slot supports more ciphers/digests than
-		 * the previous best one we change the current best to this one,
-		 * otherwise leave it where it is.
-		 */
-		if ((current_slot_n_cipher + current_slot_n_digest) >
-		    (slot_n_cipher + slot_n_digest))
-			{
-			DEBUG_SLOT_SEL("%s: changing best slot to %d\n",
-				PK11_DBG, current_slot);
-			SLOTID = current_slot;
-#ifdef DEBUG_SLOT_SELECTION
-			best_cd_slot_sofar = current_slot;
-#endif
-			cipher_count = slot_n_cipher = current_slot_n_cipher;
-			digest_count = slot_n_digest = current_slot_n_digest;
-			(void) memcpy(cipher_nids, local_cipher_nids,
-			    sizeof (local_cipher_nids));
-			(void) memcpy(digest_nids, local_digest_nids,
-			    sizeof (local_digest_nids));
-			}
-
-		DEBUG_SLOT_SEL("%s: best cipher/digest slot so far: %d\n",
-			PK11_DBG, best_cd_slot_sofar);
+		pk11_choose_rand_slot(token_info, current_slot);
+
+		pk11_choose_pubkey_slot(mech_info, token_info, current_slot,
+			rv, best_number_of_mechs, best_pubkey_slot_sofar);
+
+		pk11_choose_cipher_digest(&local_cipher_nids,
+			&local_digest_nids, pFuncList, current_slot);
 		}
 
 	if (best_number_of_mechs == 0)
@@ -3268,6 +3135,153 @@
 	return (1);
 	}
 
+static void pk11_choose_rand_slot(CK_TOKEN_INFO token_info,
+    CK_SLOT_ID current_slot)
+	{
+	DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG);
+	if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random)
+		{
+		DEBUG_SLOT_SEL("%s: this token has CKF_RNG flag\n", PK11_DBG);
+		pk11_have_random = CK_TRUE;
+		rand_SLOTID = current_slot;
+		}
+	}
+
+static void pk11_choose_pubkey_slot(CK_MECHANISM_INFO mech_info,
+    CK_TOKEN_INFO token_info, CK_SLOT_ID current_slot, CK_RV rv,
+    int best_number_of_mechs, CK_SLOT_ID best_pubkey_slot_sofar)
+	{
+	CK_BBOOL slot_has_rsa = CK_FALSE;
+	CK_BBOOL slot_has_dsa = CK_FALSE;
+	CK_BBOOL slot_has_dh = CK_FALSE;
+	int current_number_of_mechs = 0;
+
+	DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG);
+
+#ifndef OPENSSL_NO_RSA
+	/*
+	 * Check if this slot is capable of signing and
+	 * verifying with CKM_RSA_PKCS.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
+		&mech_info);
+
+	if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+			(mech_info.flags & CKF_VERIFY)))
+		{
+		/*
+		 * Check if this slot is capable of encryption,
+		 * decryption, sign, and verify with CKM_RSA_X_509.
+		 */
+		rv = pFuncList->C_GetMechanismInfo(current_slot,
+		    CKM_RSA_X_509, &mech_info);
+
+		if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+		    (mech_info.flags & CKF_VERIFY) &&
+		    (mech_info.flags & CKF_ENCRYPT) &&
+		    (mech_info.flags & CKF_VERIFY_RECOVER) &&
+		    (mech_info.flags & CKF_DECRYPT)))
+			{
+			slot_has_rsa = CK_TRUE;
+			current_number_of_mechs++;
+			}
+		}
+#endif  /* OPENSSL_NO_RSA */
+
+#ifndef OPENSSL_NO_DSA
+	/*
+	 * Check if this slot is capable of signing and
+	 * verifying with CKM_DSA.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
+		&mech_info);
+	if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
+	    (mech_info.flags & CKF_VERIFY)))
+		{
+		slot_has_dsa = CK_TRUE;
+		current_number_of_mechs++;
+		}
+#endif  /* OPENSSL_NO_DSA */
+
+#ifndef OPENSSL_NO_DH
+	/*
+	 * Check if this slot is capable of DH key generataion and
+	 * derivation.
+	 */
+	rv = pFuncList->C_GetMechanismInfo(current_slot,
+	    CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
+
+	if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
+		{
+		rv = pFuncList->C_GetMechanismInfo(current_slot,
+			CKM_DH_PKCS_DERIVE, &mech_info);
+		if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
+			{
+			slot_has_dh = CK_TRUE;
+			current_number_of_mechs++;
+			}
+		}
+#endif  /* OPENSSL_NO_DH */
+
+	if (current_number_of_mechs > best_number_of_mechs)
+		{
+		best_pubkey_slot_sofar = current_slot;
+		pk11_have_rsa = slot_has_rsa;
+		pk11_have_dsa = slot_has_dsa;
+		pk11_have_dh = slot_has_dh;
+		best_number_of_mechs = current_number_of_mechs;
+		/*
+		 * Cache the flags for later use. We might need those if
+		 * RSA keys by reference feature is used.
+		 */
+		pubkey_token_flags = token_info.flags;
+		DEBUG_SLOT_SEL("%s: pubkey flags changed to "
+		    "%lu.\n", PK11_DBG, pubkey_token_flags);
+		}
+	}
+
+static void pk11_choose_cipher_digest(int *local_cipher_nids,
+    int *local_digest_nids, CK_FUNCTION_LIST_PTR pflist,
+    CK_SLOT_ID current_slot)
+	{
+	int current_slot_n_cipher = 0;
+	int current_slot_n_digest = 0;
+
+	DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG);
+
+	(void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids));
+	(void) memset(local_digest_nids, 0, sizeof (local_digest_nids));
+
+	pk11_find_symmetric_ciphers(pFuncList, current_slot,
+	    &current_slot_n_cipher, local_cipher_nids);
+
+	pk11_find_digests(pFuncList, current_slot,
+	    &current_slot_n_digest, local_digest_nids);
+
+	DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG,
+		current_slot_n_cipher);
+	DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG,
+		current_slot_n_digest);
+	/*
+	 * If the current slot supports more ciphers/digests than
+	 * the previous best one we change the current best to this one,
+	 * otherwise leave it where it is.
+	 */
+	if ((current_slot_n_cipher + current_slot_n_digest) >
+	    (cipher_count + digest_count))
+		{
+		DEBUG_SLOT_SEL("%s: changing best slot to %d\n",
+			PK11_DBG, current_slot);
+		SLOTID = current_slot;
+		cipher_count = current_slot_n_cipher;
+		digest_count = current_slot_n_digest;
+		(void) memcpy(cipher_nids, local_cipher_nids,
+			sizeof (local_cipher_nids));
+		(void) memcpy(digest_nids, local_digest_nids,
+			sizeof (local_digest_nids));
+		}
+	}
+
 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist,
     int slot_id, int *current_slot_n_cipher, int *local_cipher_nids,
     PK11_CIPHER *cipher)