in source/pkcs11.c [833:971]
int aws_pkcs11_lib_find_private_key(
struct aws_pkcs11_lib *pkcs11_lib,
CK_SESSION_HANDLE session_handle,
const struct aws_string *match_label,
CK_OBJECT_HANDLE *out_key_handle,
CK_KEY_TYPE *out_key_type) {
/* gets set true after everything succeeds */
bool success = false;
/* gets set true after search initialized.
* indicates that C_FindObjectsFinal() must be run before function ends */
bool must_finalize_search = false;
/* set up search attributes */
CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
CK_ULONG num_attributes = 1;
CK_ATTRIBUTE attributes[2] = {
{
.type = CKA_CLASS,
.pValue = &key_class,
.ulValueLen = sizeof(key_class),
},
};
if (match_label != NULL) {
if (match_label->len > ULONG_MAX) {
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11,
"id=%p session=%lu: private key label is too long",
(void *)pkcs11_lib,
session_handle);
aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
goto clean_up;
}
CK_ATTRIBUTE *attr = &attributes[num_attributes++];
attr->type = CKA_LABEL;
attr->pValue = (void *)match_label->bytes;
attr->ulValueLen = (CK_ULONG)match_label->len;
}
/* initialize search */
CK_RV rv = pkcs11_lib->function_list->C_FindObjectsInit(session_handle, attributes, num_attributes);
if (rv != CKR_OK) {
s_raise_ck_session_error(pkcs11_lib, "C_FindObjectsInit", session_handle, rv);
goto clean_up;
}
must_finalize_search = true;
/* get search results.
* note that we're asking for 2 objects max, so we can fail if we find more than one */
CK_OBJECT_HANDLE found_objects[2] = {0};
CK_ULONG num_found = 0;
rv = pkcs11_lib->function_list->C_FindObjects(session_handle, found_objects, 2 /*max*/, &num_found);
if (rv != CKR_OK) {
s_raise_ck_session_error(pkcs11_lib, "C_FindObjects", session_handle, rv);
goto clean_up;
}
if ((num_found == 0) || (found_objects[0] == CK_INVALID_HANDLE)) {
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11,
"id=%p session=%lu: Failed to find private key on PKCS#11 token which matches search criteria",
(void *)pkcs11_lib,
session_handle);
aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
goto clean_up;
}
if (num_found > 1) {
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11,
"id=%p session=%lu: Failed to choose private key, multiple objects on PKCS#11 token match search criteria",
(void *)pkcs11_lib,
session_handle);
aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
goto clean_up;
}
/* key found */
CK_OBJECT_HANDLE key_handle = found_objects[0];
/* query key-type */
CK_KEY_TYPE key_type = 0;
CK_ATTRIBUTE key_attributes[] = {
{
.type = CKA_KEY_TYPE,
.pValue = &key_type,
.ulValueLen = sizeof(key_type),
},
};
rv = pkcs11_lib->function_list->C_GetAttributeValue(
session_handle, key_handle, key_attributes, AWS_ARRAY_SIZE(key_attributes));
if (rv != CKR_OK) {
s_raise_ck_session_error(pkcs11_lib, "C_GetAttributeValue", session_handle, rv);
goto clean_up;
}
switch (key_type) {
case CKK_RSA:
break;
default:
AWS_LOGF_ERROR(
AWS_LS_IO_PKCS11,
"id=%p session=%lu: PKCS#11 private key type %s (0x%08lX) is currently unsupported",
(void *)pkcs11_lib,
session_handle,
s_ckk_str(key_type),
key_type);
aws_raise_error(AWS_ERROR_PKCS11_KEY_TYPE_UNSUPPORTED);
goto clean_up;
}
/* Success! */
AWS_LOGF_TRACE(
AWS_LS_IO_PKCS11,
"id=%p session=%lu: Found private key. type=%s",
(void *)pkcs11_lib,
session_handle,
s_ckk_str(key_type));
*out_key_handle = key_handle;
*out_key_type = key_type;
success = true;
clean_up:
if (must_finalize_search) {
rv = pkcs11_lib->function_list->C_FindObjectsFinal(session_handle);
/* don't bother reporting error if we were already failing */
if ((rv != CKR_OK) && (success == true)) {
s_raise_ck_session_error(pkcs11_lib, "C_FindObjectsFinal", session_handle, rv);
success = false;
}
}
return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
}