From 129c22840ee73c0c6cb1e5ed629fa361b688e537 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 18 Mar 2020 14:46:33 +0000 Subject: [PATCH] Fix EVP_PKEY_new_mac_key() EVP_PKEY_new_mac_key() was failing if the specified MAC was not available in the default provider - even though that MAC is never actually needed to successfully complete the function. The resulting EVP_PKEY can then be used in some non-default libctx which *does* have the MAC loaded. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/11360) --- crypto/evp/pkey_mac.c | 83 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/crypto/evp/pkey_mac.c b/crypto/evp/pkey_mac.c index c664a87cb1..7430b62b0b 100644 --- a/crypto/evp/pkey_mac.c +++ b/crypto/evp/pkey_mac.c @@ -53,19 +53,25 @@ static int pkey_mac_init(EVP_PKEY_CTX *ctx) int nid = ctx->pmeth->pkey_id; EVP_MAC *mac = EVP_MAC_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propquery); - if (mac == NULL) { - EVPerr(EVP_F_PKEY_MAC_INIT, EVP_R_FETCH_FAILED); - return 0; - } + /* + * mac == NULL may actually be ok in some situations. In an + * EVP_PKEY_new_mac_key() call a temporary EVP_PKEY_CTX is created with + * default libctx. We don't actually need the underlying MAC to be present + * to successfully set the key in that case. The resulting EVP_PKEY could + * then be used in some other libctx where the MAC *is* present + */ + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE); return 0; } - hctx->ctx = EVP_MAC_CTX_new(mac); - if (hctx->ctx == NULL) { - OPENSSL_free(hctx); - return 0; + if (mac != NULL) { + hctx->ctx = EVP_MAC_CTX_new(mac); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } } if (nid == EVP_PKEY_CMAC) { @@ -87,6 +93,13 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) MAC_PKEY_CTX *sctx, *dctx; sctx = EVP_PKEY_CTX_get_data(src); + + if (sctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (sctx->ctx->data == NULL) return 0; @@ -146,7 +159,7 @@ static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx) MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx); if (hctx != NULL) { - EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx); + EVP_MAC *mac = hctx->ctx != NULL ? EVP_MAC_CTX_mac(hctx->ctx) : NULL; switch (hctx->type) { case MAC_TYPE_RAW: @@ -181,8 +194,15 @@ static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) break; case MAC_TYPE_MAC: { - EVP_MAC_CTX *cmkey = EVP_MAC_CTX_dup(hctx->ctx); + EVP_MAC_CTX *cmkey; + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + + cmkey = EVP_MAC_CTX_dup(hctx->ctx); if (cmkey == NULL) return 0; if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx))) @@ -224,6 +244,12 @@ static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) hctx->type == MAC_TYPE_RAW && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0; + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (set_key) { if (!EVP_MAC_is_a(EVP_MAC_CTX_mac(hctx->ctx), OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))))) @@ -289,6 +315,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ciphname, 0); params[params_n] = OSSL_PARAM_construct_end(); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (!EVP_MAC_CTX_set_params(hctx->ctx, params) || !EVP_MAC_init(hctx->ctx)) return 0; @@ -340,6 +374,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + if (!EVP_MAC_CTX_set_params(hctx->ctx, params)) return 0; @@ -376,6 +418,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) p2, p1); params[params_n] = OSSL_PARAM_construct_end(); + if (hctx->ctx == NULL) { + /* + * This actually means the fetch failed during the init call + */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + return EVP_MAC_CTX_set_params(hctx->ctx, params); } break; @@ -388,6 +438,12 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_DIGESTINIT: switch (hctx->type) { case MAC_TYPE_RAW: + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + /* Ensure that we have attached the implementation */ if (!EVP_MAC_init(hctx->ctx)) return 0; @@ -459,6 +515,13 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx, type, value, strlen(value) + 1, NULL)) return 0; params[1] = OSSL_PARAM_construct_end(); + + if (hctx->ctx == NULL) { + /* This actually means the fetch failed during the init call */ + EVPerr(0, EVP_R_FETCH_FAILED); + return 0; + } + ok = EVP_MAC_CTX_set_params(hctx->ctx, params); OPENSSL_free(params[0].data); return ok; -- 2.25.1