hcrypto-pkcs11: check mechanism flags

Before committing to a PKCS#11 mechanism, check that it can provide the
required encryption or digest services by validating the flags returned by
C_GetMechanismInfo().
This commit is contained in:
Luke Howard
2019-05-18 14:16:37 +10:00
committed by Jeffrey Altman
parent dc791c8fcf
commit 5c70e5015e

View File

@@ -158,7 +158,9 @@ p11_module_init(void)
}
static CK_RV
p11_session_init(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE_PTR phSession)
p11_session_init(CK_MECHANISM_TYPE mechanismType,
CK_SESSION_HANDLE_PTR phSession,
CK_FLAGS *pFlags)
{
CK_RV rv;
CK_ULONG i, ulSlotCount = 0;
@@ -168,6 +170,8 @@ p11_session_init(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE_PTR phSessio
if (phSession != NULL)
*phSession = CK_INVALID_HANDLE;
*pFlags = 0;
rv = p11_module_init();
if (rv != CKR_OK)
goto cleanup;
@@ -198,8 +202,10 @@ p11_session_init(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE_PTR phSessio
*/
for (i = 0; i < ulSlotCount; i++) {
rv = p11_module->C_GetMechanismInfo(pSlotList[i], mechanismType, &info);
if (rv == CKR_OK)
break;
if (rv == CKR_OK) {
*pFlags = info.flags;
break;
}
}
if (i == ulSlotCount) {
@@ -220,9 +226,16 @@ cleanup:
}
static int
p11_mech_available_p(CK_MECHANISM_TYPE mechanismType)
p11_mech_available_p(CK_MECHANISM_TYPE mechanismType, CK_FLAGS reqFlags)
{
return p11_session_init(mechanismType, NULL) == CKR_OK;
CK_RV rv;
CK_FLAGS flags;
rv = p11_session_init(mechanismType, NULL, &flags);
if (rv != CKR_OK)
return 0;
return (flags & reqFlags) == reqFlags;
}
static CK_KEY_TYPE
@@ -287,6 +300,7 @@ p11_key_init(EVP_CIPHER_CTX *ctx,
ctx->cipher->iv_len
};
struct pkcs11_cipher_ctx *p11ctx = (struct pkcs11_cipher_ctx *)ctx->cipher_data;
CK_FLAGS flags;
rv = CKR_OK;
@@ -294,9 +308,14 @@ p11_key_init(EVP_CIPHER_CTX *ctx,
p11_cleanup(ctx); /* refresh session with new key */
if (p11ctx->hSession == CK_INVALID_HANDLE) {
rv = p11_session_init(mechanismType, &p11ctx->hSession);
rv = p11_session_init(mechanismType, &p11ctx->hSession, &flags);
if (rv != CKR_OK)
goto cleanup;
if ((flags & (CKF_ENCRYPT|CKF_DECRYPT)) != (CKF_ENCRYPT|CKF_DECRYPT)) {
rv = CKR_MECHANISM_INVALID;
goto cleanup;
}
}
if (key != NULL) {
@@ -373,19 +392,26 @@ p11_md_hash_init(CK_MECHANISM_TYPE mechanismType, EVP_MD_CTX *ctx)
{
struct pkcs11_md_ctx *p11ctx = (struct pkcs11_md_ctx *)ctx;
CK_RV rv;
CK_FLAGS flags;
CK_MECHANISM mechanism = { mechanismType, NULL, 0 };
if (p11ctx->hSession != CK_INVALID_HANDLE)
p11_md_cleanup(ctx);
rv = p11_session_init(mechanismType, &p11ctx->hSession);
if (rv == CKR_OK) {
CK_MECHANISM mechanism = { mechanismType, NULL, 0 };
rv = p11_session_init(mechanismType, &p11ctx->hSession, &flags);
if (rv != CKR_OK)
goto cleanup;
assert(p11_module != NULL);
rv = p11_module->C_DigestInit(p11ctx->hSession, &mechanism);
if ((flags & CKF_DIGEST) != CKF_DIGEST) {
rv = CKR_MECHANISM_INVALID;
goto cleanup;
}
assert(p11_module != NULL);
rv = p11_module->C_DigestInit(p11ctx->hSession, &mechanism);
cleanup:
return rv == CKR_OK;
}
@@ -459,7 +485,7 @@ p11_md_cleanup(EVP_MD_CTX *ctx)
const EVP_CIPHER * \
hc_EVP_pkcs11_##name(void) \
{ \
if (p11_mech_available_p(mechanismType)) \
if (p11_mech_available_p(mechanismType, CKF_ENCRYPT|CKF_DECRYPT)) \
return &pkcs11_##name; \
else \
return NULL; \
@@ -509,7 +535,7 @@ p11_md_cleanup(EVP_MD_CTX *ctx)
p11_md_cleanup \
}; \
\
if (p11_mech_available_p(mechanismType)) \
if (p11_mech_available_p(mechanismType, CKF_DIGEST)) \
return &name; \
else \
return NULL; \