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