]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fail if we fail to fetch the EVP_KEYMGMT
authorMatt Caswell <matt@openssl.org>
Wed, 13 May 2020 16:17:35 +0000 (17:17 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 28 May 2020 16:01:47 +0000 (17:01 +0100)
If we failed to fetch an EVP_KEYMGMT then we were falling back to legacy.
This is because some algorithms (such as MACs and KDFs used via an old
style EVP_PKEY) have not been transferred to providers.

Unfortunately this means that you cannot stop some algorithms from being
used by not loading the provider.

For example if you wanted to prevent RSA from being used, you might expect
to just not load any providers that make it available. Unfortunately that
doesn't work because we simply fall back to legacy if we fail to fetch
the EVP_KEYMGMT.

Instead we should fail *unless* the key type is one of those legacy key
types that we have not transferred.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11826)

crypto/evp/pmeth_lib.c
test/evp_test.c

index 355565de6323f1ae00f105f85e1f694c2b4ec73a..ea8bdec388633ac87db949f150483fcc436b33a1 100644 (file)
@@ -137,6 +137,40 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
 }
 #endif /* FIPS_MODULE */
 
+static int is_legacy_alg(int id, const char *keytype)
+{
+#ifndef FIPS_MODULE
+    /* Certain EVP_PKEY keytypes are only available in legacy form */
+    if (id == -1) {
+        id = OBJ_sn2nid(keytype);
+        if (id == NID_undef)
+            id = OBJ_ln2nid(keytype);
+        if (id == NID_undef)
+            return  0;
+    }
+    switch (id) {
+    /*
+     * TODO(3.0): Remove SM2 and DHX when they are converted to have provider
+     * support
+     */
+    case EVP_PKEY_SM2:
+    case EVP_PKEY_DHX:
+    case EVP_PKEY_SCRYPT:
+    case EVP_PKEY_TLS1_PRF:
+    case EVP_PKEY_HKDF:
+    case EVP_PKEY_CMAC:
+    case EVP_PKEY_HMAC:
+    case EVP_PKEY_SIPHASH:
+    case EVP_PKEY_POLY1305:
+        return 1;
+    default:
+        return 0;
+    }
+#else
+    return 0;
+#endif
+}
+
 static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
                                  EVP_PKEY *pkey, ENGINE *e,
                                  const char *keytype, const char *propquery,
@@ -228,10 +262,20 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
      * implementation.
      */
     if (e == NULL && keytype != NULL) {
-        /* This could fail so ignore errors */
-        ERR_set_mark();
+        int legacy = is_legacy_alg(id, keytype);
+
+        if (legacy) {
+            /* This could fail so ignore errors */
+            ERR_set_mark();
+        }
+
         keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
-        ERR_pop_to_mark();
+        if (legacy) {
+            ERR_pop_to_mark();
+        } else if (keymgmt == NULL) {
+            EVPerr(EVP_F_INT_CTX_NEW, EVP_R_FETCH_FAILED);
+            return NULL;
+        }
     }
 
     ret = OPENSSL_zalloc(sizeof(*ret));
index 813218a42a214d0ff5f4d534af8c1f1dd6d9456e..6ed5bafba6067e8098aa31191f1c0ab8ab89ca39 100644 (file)
@@ -2995,7 +2995,8 @@ static int key_unsupported(void)
     long err = ERR_peek_error();
 
     if (ERR_GET_LIB(err) == ERR_LIB_EVP
-            && ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM) {
+            && (ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM
+                || ERR_GET_REASON(err) == EVP_R_FETCH_FAILED)) {
         ERR_clear_error();
         return 1;
     }