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, ¶ms, 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, ¶ms, 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(¶ms, 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;
}