EVP: If a key can't be exported to provider, fallback to legacy
authorRichard Levitte <levitte@openssl.org>
Tue, 7 Jan 2020 10:49:08 +0000 (11:49 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 8 Jan 2020 21:30:54 +0000 (22:30 +0100)
Currently, the operations that do try to export a legacy key to
providers will fail if the export failed.  It makes more sense to
simply use the legacy method instead, as a fallback for things not
being implemented (yet) in a provider.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10771)

crypto/evp/exchange.c
crypto/evp/m_sigver.c
crypto/evp/pmeth_fn.c

index 189c1c0f454f4193fb1780c98dbee0088eadd68f..3e7c00103c7a358ae688b037ae1d8257f6ac96b8 100644 (file)
@@ -208,10 +208,9 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 
     if (ctx->pkey != NULL) {
         provkey = evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
-        if (provkey == NULL) {
-            EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-            goto err;
-        }
+        /* If export failed, legacy may be able to pick it up */
+        if (provkey == NULL)
+            goto legacy;
     }
     ctx->op.kex.exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
     if (ctx->op.kex.exchprovctx == NULL) {
@@ -227,7 +226,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
     return 0;
 
  legacy:
-    if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
+    if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
         EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
         return -2;
     }
@@ -261,10 +260,9 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
     }
 
     provkey = evp_keymgmt_export_to_provider(peer, ctx->keymgmt, 0);
-    if (provkey == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
+    /* If export failed, legacy may be able to pick it up */
+    if (provkey == NULL)
+        goto legacy;
     return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
 
  legacy:
index 7a21f680b974a91aad1597a52d5c07fc0f2dfab4..9d12e9b96adecdc370e349ff5963604607225866 100644 (file)
@@ -104,6 +104,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
 
     locpctx->op.sig.signature = signature;
 
+    provkey =
+        evp_keymgmt_export_to_provider(locpctx->pkey, locpctx->keymgmt, 0);
+    /* If export failed, legacy may be able to pick it up */
+    if (provkey == NULL)
+        goto legacy;
+
     locpctx->operation = ver ? EVP_PKEY_OP_VERIFYCTX
                              : EVP_PKEY_OP_SIGNCTX;
 
@@ -113,13 +119,6 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
         ERR_raise(ERR_LIB_EVP,  EVP_R_INITIALIZATION_ERROR);
         goto err;
     }
-    provkey =
-        evp_keymgmt_export_to_provider(locpctx->pkey, locpctx->keymgmt, 0);
-    if (provkey == NULL) {
-        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
-        goto err;
-    }
-
     if (type != NULL) {
         ctx->reqdigest = type;
     } else {
@@ -156,6 +155,11 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     return 0;
 
  legacy:
+    if (ctx->pctx->pmeth == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
     if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {
 
         if (type == NULL) {
index 638619051ed0391d59ff4e979b59c7ded90866cc..0ce4ff95221cd7538768c4caf4adff617f979189 100644 (file)
@@ -367,10 +367,9 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
     if (ctx->pkey != NULL) {
         provkey =
             evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
-        if (provkey == NULL) {
-            EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-            goto err;
-        }
+        /* If export failed, legacy may be able to pick it up */
+        if (provkey == NULL)
+            goto legacy;
     }
     ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov));
     if (ctx->op.sig.sigprovctx == NULL) {
@@ -617,10 +616,9 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
 
     if (ctx->pkey != NULL) {
         provkey = evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0);
-        if (provkey == NULL) {
-            EVPerr(0, EVP_R_INITIALIZATION_ERROR);
-            goto err;
-        }
+        /* If export failed, legacy may be able to pick it up */
+        if (provkey == NULL)
+            goto legacy;
     }
     ctx->op.ciph.ciphprovctx = cipher->newctx(ossl_provider_ctx(cipher->prov));
     if (ctx->op.ciph.ciphprovctx == NULL) {