/// <summary>
/// Obtains a list of all slots where token that matches PKCS#11 URI is present
/// </summary>
/// <param name="pkcs11Uri">PKCS#11 URI</param>
/// <param name="pkcs11">Low level PKCS#11 wrapper</param>
/// <param name="tokenPresent">Flag indicating whether the list obtained includes only those slots with a token present (true), or all slots (false)</param>
/// <param name="slotList">List of slots matching PKCS#11 URI</param>
/// <returns>CKR_OK if successful; any other value otherwise</returns>
public static CKR GetMatchingSlotList(Pkcs11Uri pkcs11Uri, Pkcs11 pkcs11, bool tokenPresent, out uint[] slotList)
{
if (pkcs11Uri == null)
throw new ArgumentNullException("pkcs11Uri");
if (pkcs11 == null)
throw new ArgumentNullException("pkcs11");
List<uint> matchingSlots = new List<uint>();
// Get library information
CK_INFO libraryInfo = new CK_INFO();
CKR rv = pkcs11.C_GetInfo(ref libraryInfo);
if (rv != CKR.CKR_OK)
{
slotList = new uint[0];
return rv;
}
// Check whether library matches URI
if (!Matches(pkcs11Uri, libraryInfo))
{
slotList = new uint[0];
return CKR.CKR_OK;
}
// Get number of slots in first call
uint slotCount = 0;
rv = pkcs11.C_GetSlotList(false, null, ref slotCount);
if (rv != CKR.CKR_OK)
{
slotList = new uint[0];
return rv;
}
if (slotCount < 1)
{
slotList = new uint[0];
return CKR.CKR_OK;
}
// Allocate array for slot IDs
uint[] slots = new uint[slotCount];
// Get slot IDs in second call
rv = pkcs11.C_GetSlotList(tokenPresent, slots, ref slotCount);
if (rv != CKR.CKR_OK)
{
slotList = new uint[0];
return rv;
}
// Shrink array if needed
if (slots.Length != slotCount)
Array.Resize(ref slots, Convert.ToInt32(slotCount));
// Match slots with Pkcs11Uri
foreach (uint slot in slots)
{
CK_SLOT_INFO slotInfo = new CK_SLOT_INFO();
rv = pkcs11.C_GetSlotInfo(slot, ref slotInfo);
if (rv != CKR.CKR_OK)
{
slotList = new uint[0];
return rv;
}
// Check whether slot matches URI
if (Matches(pkcs11Uri, slotInfo, slot))
{
if ((slotInfo.Flags & CKF.CKF_TOKEN_PRESENT) == CKF.CKF_TOKEN_PRESENT)
{
CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO();
rv = pkcs11.C_GetTokenInfo(slot, ref tokenInfo);
if (rv != CKR.CKR_OK)
{
slotList = new uint[0];
return rv;
}
// Check whether token matches URI
if (Matches(pkcs11Uri, tokenInfo))
matchingSlots.Add(slot);
}
else
{
if (!tokenPresent && Pkcs11UriSharedUtils.Matches(pkcs11Uri, null, null, null, null))
matchingSlots.Add(slot);
}
}
}
slotList = matchingSlots.ToArray();
return CKR.CKR_OK;
}