in source/pkcs11.c [619:753]
int aws_pkcs11_lib_find_slot_with_token(
struct aws_pkcs11_lib *pkcs11_lib,
const uint64_t *match_slot_id,
const struct aws_string *match_token_label,
CK_SLOT_ID *out_slot_id) {
CK_SLOT_ID *slot_id_array = NULL; /* array of IDs */
CK_SLOT_ID *candidate = NULL; /* points to ID in slot_id_array */
CK_TOKEN_INFO info;
AWS_ZERO_STRUCT(info);
bool success = false;
/* query number of slots with tokens */
CK_ULONG num_slots = 0;
CK_RV rv = pkcs11_lib->function_list->C_GetSlotList(CK_TRUE /*tokenPresent*/, NULL /*pSlotList*/, &num_slots);
if (rv != CKR_OK) {
s_raise_ck_error(pkcs11_lib, "C_GetSlotList", rv);
goto clean_up;
}
if (num_slots == 0) {
AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "id=%p: No PKCS#11 tokens present in any slot", (void *)pkcs11_lib);
aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
goto clean_up;
}
AWS_LOGF_TRACE(
AWS_LS_IO_PKCS11, "id=%p: Found %lu slots with tokens. Picking one...", (void *)pkcs11_lib, num_slots);
/* allocate space for slot IDs */
slot_id_array = aws_mem_calloc(pkcs11_lib->allocator, num_slots, sizeof(CK_SLOT_ID));
/* query all slot IDs */
rv = pkcs11_lib->function_list->C_GetSlotList(CK_TRUE /*tokenPresent*/, slot_id_array, &num_slots);
if (rv != CKR_OK) {
s_raise_ck_error(pkcs11_lib, "C_GetSlotList", rv);
goto clean_up;
}
for (size_t i = 0; i < num_slots; ++i) {
CK_SLOT_ID slot_id_i = slot_id_array[i];
/* if specific slot_id requested, and this isn't it, then skip */
if ((match_slot_id != NULL) && (*match_slot_id != slot_id_i)) {
AWS_LOGF_TRACE(
AWS_LS_IO_PKCS11,
"id=%p: Ignoring PKCS#11 token because slot %lu doesn't match %" PRIu64,
(void *)pkcs11_lib,
slot_id_i,
*match_slot_id);
continue;
}
/* query token info */
CK_TOKEN_INFO token_info_i;
AWS_ZERO_STRUCT(token_info_i);
rv = pkcs11_lib->function_list->C_GetTokenInfo(slot_id_i, &token_info_i);
if (rv != CKR_OK) {
s_raise_ck_error(pkcs11_lib, "C_GetTokenInfo", rv);
goto clean_up;
}
/* if specific token label requested, and this isn't it, then skip */
if (match_token_label != NULL) {
struct aws_byte_cursor label_i = s_trim_padding(token_info_i.label, sizeof(token_info_i.label));
if (aws_string_eq_byte_cursor(match_token_label, &label_i) == false) {
AWS_LOGF_TRACE(
AWS_LS_IO_PKCS11,
"id=%p: Ignoring PKCS#11 token in slot %lu because label '" PRInSTR "' doesn't match '%s'",
(void *)pkcs11_lib,
slot_id_i,
AWS_BYTE_CURSOR_PRI(label_i),
aws_string_c_str(match_token_label));
continue;
}
}
/* this slot is a candidate! */
/* be sure there's only one candidate */
if (candidate != NULL) {
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11,
"id=%p: Failed to choose PKCS#11 token, multiple tokens match search criteria",
(void *)pkcs11_lib);
aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
goto clean_up;
}
/* the new candidate! */
candidate = &slot_id_array[i];
memcpy(&info, &token_info_i, sizeof(CK_TOKEN_INFO));
}
if (candidate == NULL) {
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11, "id=%p: Failed to find PKCS#11 token which matches search criteria", (void *)pkcs11_lib);
aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
goto clean_up;
}
/* success! */
AWS_LOGF_DEBUG(
AWS_LS_IO_PKCS11,
"id=%p: Selected PKCS#11 token. slot:%lu label:'" PRInSTR "' manufacturerID:'" PRInSTR "' model:'" PRInSTR
"' serialNumber:'" PRInSTR "' flags:0x%08lX sessionCount:%lu/%lu rwSessionCount:%lu/%lu"
" freePublicMemory:%lu/%lu freePrivateMemory:%lu/%lu"
" hardwareVersion:%" PRIu8 ".%" PRIu8 " firmwareVersion:%" PRIu8 ".%" PRIu8,
(void *)pkcs11_lib,
*candidate,
AWS_BYTE_CURSOR_PRI(s_trim_padding(info.label, sizeof(info.label))),
AWS_BYTE_CURSOR_PRI(s_trim_padding(info.manufacturerID, sizeof(info.manufacturerID))),
AWS_BYTE_CURSOR_PRI(s_trim_padding(info.model, sizeof(info.model))),
AWS_BYTE_CURSOR_PRI(s_trim_padding(info.serialNumber, sizeof(info.serialNumber))),
info.flags,
info.ulSessionCount,
info.ulMaxSessionCount,
info.ulRwSessionCount,
info.ulMaxRwSessionCount,
info.ulFreePublicMemory,
info.ulTotalPublicMemory,
info.ulFreePrivateMemory,
info.ulTotalPrivateMemory,
info.hardwareVersion.major,
info.hardwareVersion.minor,
info.firmwareVersion.major,
info.firmwareVersion.minor);
*out_slot_id = *candidate;
success = true;
clean_up:
aws_mem_release(pkcs11_lib->allocator, slot_id_array);
return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
}