Commit cb9a902175 for openssl.org

commit cb9a9021752b0c3499fccbb965e1e525b357a0f0
Author: Neil Horman <nhorman@openssl.org>
Date:   Tue Jul 14 13:00:59 2026 -0400

    Fix dsaparams decoding from DER files

    The tests addded in commit d8a7e8e uncovered an odd error case.

    https://github.com/openssl/openssl/actions/runs/29303845665/job/86993085732

    Is failing when attempting to read in a der file converting from a
    corresponding PEM file containing DSA parameters.

    Interestingly The problem was only occuring when:
    1) The input was a DER file
    and
    2) Blake2 was not configured

    Doing some tracing of the decoder operation showed that this is occuring
    because the OSSL_STORE lookup used to find the proper decoder uses a
    "first successful decode wins" approach, after which the loading code
    checks to see if the decoded type matches the expected key type.

    When decoding PEM, this isn't a problem, as the PEM armoring gives the
    decoder a hint as to why type of data the input file is.

    But with DER, there is no such hint, and we're at the mercy of whichever
    decoder happens to decode the data correctly first.  Normally it works
    just fine, but when features are disabled or enabled, the order in which
    the decoders are attempted may change, affecting the outcome.  In this
    particular case, disabling blake2 caused the DHX decoder to be attempted
    first, which decodes the input der file without issue.  That in turn
    caused the subsequent EVP_PKEY_is_a check to fail (as we were expecting
    a DSA key), and so the test fails.

    Fortunately, the code that the dsaparam applet uses to do this decode
    provides a keytype hint, which we can use to guide the decode process.
    keep the old store lookup method around in case anyone doesn't pass a
    uri that is a file path or provide a keytype, but if we do both those
    things, we can use OSSL_DECODER_CTX_new_for_pkey to specifically tell
    the decoder that we want to decode the input data as the expected type
    (in this case a DSA key).

    Fixes #31944

    Reviewed-by: Milan Broz <mbroz@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Tim Hudson <tjh@openssl.org>
    MergeDate: Thu Jul 16 15:28:32 2026
    (Merged from https://github.com/openssl/openssl/pull/31954)

diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index 128c40d086..36fcb20e2a 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -40,6 +40,7 @@
 #include <openssl/ssl.h>
 #include <openssl/core_names.h>
 #include <openssl/encoder.h>
+#include <openssl/decoder.h>
 #include "s_apps.h"
 #include "apps.h"

@@ -605,20 +606,46 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
     int suppress_decode_errors)
 {
     EVP_PKEY *params = NULL;
+    OSSL_DECODER_CTX *dctx = NULL;
+    BIO *file_bio = BIO_new_file(uri, "rb");
+    OSSL_LIB_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();

     if (desc == NULL)
         desc = "key parameters";
-    (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
-        suppress_decode_errors,
-        NULL, NULL, &params, NULL, NULL, NULL, NULL, NULL);
-    if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
-        ERR_print_errors(bio_err);
-        BIO_printf(bio_err,
-            "Unable to load %s from %s (unexpected parameters type)\n",
-            desc, uri);
-        EVP_PKEY_free(params);
-        params = NULL;
+    /*
+     * Use the store lookup path for anything that is not DER/ASN1 format
+     * Or if we are unable to opens the uri as a file.
+     */
+    if (format != FORMAT_ASN1 || file_bio == NULL) {
+        (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
+            suppress_decode_errors,
+            NULL, NULL, &params, NULL, NULL, NULL, NULL, NULL);
+        if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
+            ERR_print_errors(bio_err);
+            BIO_printf(bio_err,
+                "Unable to load %s from %s (unexpected parameters type)\n",
+                desc, uri);
+            EVP_PKEY_free(params);
+            params = NULL;
+        }
+    } else {
+        dctx = OSSL_DECODER_CTX_new_for_pkey(&params, NULL, NULL, keytype,
+            OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
+            libctx, propq);
+        if (dctx == NULL) {
+            ERR_print_errors(bio_err);
+            BIO_printf(bio_err, "Unable to allocate decoder context\n");
+        } else {
+            if (!OSSL_DECODER_from_bio(dctx, file_bio)) {
+                ERR_print_errors(bio_err);
+                BIO_printf(bio_err, "Unable to decode file %s\n", uri);
+            }
+        }
     }
+
+    BIO_free(file_bio);
+    OSSL_DECODER_CTX_free(dctx);
     return params;
 }