Prune low-level ASN.1 parse errors from error queue in der2key_decode() etc.
Also adds error output tests on loading key files with unsupported algorithms to 30-test_evp.t Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/13023)
This commit is contained in:
parent
9032c2c11b
commit
66066e1bba
@ -172,10 +172,8 @@ static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
|
|||||||
|
|
||||||
eckey = eckey_type2param(ptype, pval, libctx, propq);
|
eckey = eckey_type2param(ptype, pval, libctx, propq);
|
||||||
|
|
||||||
if (!eckey) {
|
if (!eckey)
|
||||||
ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* We have parameters now set public key */
|
/* We have parameters now set public key */
|
||||||
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
|
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
|
||||||
@ -224,22 +222,19 @@ static int eckey_priv_decode_with_libctx(EVP_PKEY *pkey,
|
|||||||
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
|
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
|
||||||
|
|
||||||
eckey = eckey_type2param(ptype, pval, libctx, propq);
|
eckey = eckey_type2param(ptype, pval, libctx, propq);
|
||||||
|
|
||||||
if (eckey == NULL)
|
if (eckey == NULL)
|
||||||
goto ecliberr;
|
goto err;
|
||||||
|
|
||||||
/* We have parameters now set private key */
|
/* We have parameters now set private key */
|
||||||
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
|
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
|
||||||
ECerr(0, EC_R_DECODE_ERROR);
|
ECerr(0, EC_R_DECODE_ERROR);
|
||||||
goto ecerr;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ecliberr:
|
err:
|
||||||
ECerr(0, ERR_R_EC_LIB);
|
|
||||||
ecerr:
|
|
||||||
EC_KEY_free(eckey);
|
EC_KEY_free(eckey);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -472,10 +467,8 @@ static int old_ec_priv_decode(EVP_PKEY *pkey,
|
|||||||
{
|
{
|
||||||
EC_KEY *ec;
|
EC_KEY *ec;
|
||||||
|
|
||||||
if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) {
|
if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL)
|
||||||
ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
#include <openssl/params.h>
|
#include <openssl/params.h>
|
||||||
#include <openssl/provider.h>
|
#include <openssl/provider.h>
|
||||||
|
#include <openssl/evperr.h>
|
||||||
|
#include <openssl/ecerr.h>
|
||||||
|
#include <openssl/x509err.h>
|
||||||
#include "internal/passphrase.h"
|
#include "internal/passphrase.h"
|
||||||
#include "crypto/decoder.h"
|
#include "crypto/decoder.h"
|
||||||
#include "encoder_local.h"
|
#include "encoder_local.h"
|
||||||
@ -424,7 +427,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
|
|||||||
BIO *bio = data->bio;
|
BIO *bio = data->bio;
|
||||||
long loc;
|
long loc;
|
||||||
size_t i;
|
size_t i;
|
||||||
int ok = 0;
|
int err, ok = 0;
|
||||||
/* For recursions */
|
/* For recursions */
|
||||||
struct decoder_process_data_st new_data;
|
struct decoder_process_data_st new_data;
|
||||||
|
|
||||||
@ -532,6 +535,16 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
|
|||||||
&new_data.ctx->pwdata);
|
&new_data.ctx->pwdata);
|
||||||
if (ok)
|
if (ok)
|
||||||
break;
|
break;
|
||||||
|
err = ERR_peek_last_error();
|
||||||
|
if ((ERR_GET_LIB(err) == ERR_LIB_EVP
|
||||||
|
&& ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM)
|
||||||
|
#ifndef OPENSSL_NO_EC
|
||||||
|
|| (ERR_GET_LIB(err) == ERR_LIB_EC
|
||||||
|
&& ERR_GET_REASON(err) == EC_R_UNKNOWN_GROUP)
|
||||||
|
#endif
|
||||||
|
|| (ERR_GET_LIB(err) == ERR_LIB_X509
|
||||||
|
&& ERR_GET_REASON(err) == X509_R_UNSUPPORTED_ALGORITHM))
|
||||||
|
break; /* fatal error; preserve it on the error queue and stop */
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
@ -41,10 +41,8 @@ EVP_PKEY *EVP_PKCS82PKEY_with_libctx(const PKCS8_PRIV_KEY_INFO *p8,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pkey->ameth->priv_decode_with_libctx != NULL) {
|
if (pkey->ameth->priv_decode_with_libctx != NULL) {
|
||||||
if (!pkey->ameth->priv_decode_with_libctx(pkey, p8, libctx, propq)) {
|
if (!pkey->ameth->priv_decode_with_libctx(pkey, p8, libctx, propq))
|
||||||
EVPerr(0, EVP_R_PRIVATE_KEY_DECODE_ERROR);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
} else if (pkey->ameth->priv_decode != NULL) {
|
} else if (pkey->ameth->priv_decode != NULL) {
|
||||||
if (!pkey->ameth->priv_decode(pkey, p8)) {
|
if (!pkey->ameth->priv_decode(pkey, p8)) {
|
||||||
EVPerr(0, EVP_R_PRIVATE_KEY_DECODE_ERROR);
|
EVPerr(0, EVP_R_PRIVATE_KEY_DECODE_ERROR);
|
||||||
|
@ -88,6 +88,7 @@ static int try_pkcs12(struct extracted_param_data_st *, OSSL_STORE_INFO **,
|
|||||||
\
|
\
|
||||||
if (ERR_GET_LIB(err) == ERR_LIB_ASN1 \
|
if (ERR_GET_LIB(err) == ERR_LIB_ASN1 \
|
||||||
&& (ERR_GET_REASON(err) == ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE \
|
&& (ERR_GET_REASON(err) == ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE \
|
||||||
|
|| ERR_GET_REASON(err) == ASN1_R_NO_MATCHING_CHOICE_TYPE \
|
||||||
|| ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)) \
|
|| ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)) \
|
||||||
ERR_pop_to_mark(); \
|
ERR_pop_to_mark(); \
|
||||||
else \
|
else \
|
||||||
|
@ -41,12 +41,12 @@ static int x509_pubkey_decode(EVP_PKEY **pk, const X509_PUBKEY *key);
|
|||||||
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||||
void *exarg)
|
void *exarg)
|
||||||
{
|
{
|
||||||
|
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
|
||||||
|
|
||||||
if (operation == ASN1_OP_FREE_POST) {
|
if (operation == ASN1_OP_FREE_POST) {
|
||||||
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
|
|
||||||
EVP_PKEY_free(pubkey->pkey);
|
EVP_PKEY_free(pubkey->pkey);
|
||||||
} else if (operation == ASN1_OP_D2I_POST) {
|
} else if (operation == ASN1_OP_D2I_POST) {
|
||||||
/* Attempt to decode public key and cache in pubkey structure. */
|
/* Attempt to decode public key and cache in pubkey structure. */
|
||||||
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
|
|
||||||
EVP_PKEY_free(pubkey->pkey);
|
EVP_PKEY_free(pubkey->pkey);
|
||||||
pubkey->pkey = NULL;
|
pubkey->pkey = NULL;
|
||||||
/*
|
/*
|
||||||
@ -55,8 +55,10 @@ static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
|||||||
* will return an appropriate error.
|
* will return an appropriate error.
|
||||||
*/
|
*/
|
||||||
ERR_set_mark();
|
ERR_set_mark();
|
||||||
if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1)
|
if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1) {
|
||||||
|
ERR_clear_last_mark();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
ERR_pop_to_mark();
|
ERR_pop_to_mark();
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -180,10 +182,8 @@ static int x509_pubkey_decode(EVP_PKEY **ppkey, const X509_PUBKEY *key)
|
|||||||
* future we could have different return codes for decode
|
* future we could have different return codes for decode
|
||||||
* errors and fatal errors such as malloc failure.
|
* errors and fatal errors such as malloc failure.
|
||||||
*/
|
*/
|
||||||
if (!pkey->ameth->pub_decode(pkey, key)) {
|
if (!pkey->ameth->pub_decode(pkey, key))
|
||||||
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED);
|
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -30,6 +30,25 @@
|
|||||||
#include "prov/providercommonerr.h"
|
#include "prov/providercommonerr.h"
|
||||||
#include "endecoder_local.h"
|
#include "endecoder_local.h"
|
||||||
|
|
||||||
|
#define SET_ERR_MARK() ERR_set_mark()
|
||||||
|
#define CLEAR_ERR_MARK() \
|
||||||
|
do { \
|
||||||
|
int err = ERR_peek_last_error(); \
|
||||||
|
\
|
||||||
|
if (ERR_GET_LIB(err) == ERR_LIB_ASN1 \
|
||||||
|
&& (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG \
|
||||||
|
|| ERR_GET_REASON(err) == ASN1_R_UNSUPPORTED_TYPE \
|
||||||
|
|| ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR)) \
|
||||||
|
ERR_pop_to_mark(); \
|
||||||
|
else \
|
||||||
|
ERR_clear_last_mark(); \
|
||||||
|
} while(0)
|
||||||
|
#define RESET_ERR_MARK() \
|
||||||
|
do { \
|
||||||
|
CLEAR_ERR_MARK(); \
|
||||||
|
SET_ERR_MARK(); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
|
static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
|
||||||
unsigned char **data, long *len)
|
unsigned char **data, long *len)
|
||||||
{
|
{
|
||||||
@ -165,9 +184,9 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin,
|
|||||||
long new_der_len;
|
long new_der_len;
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
void *key = NULL;
|
void *key = NULL;
|
||||||
int err, ok = 0;
|
int ok = 0;
|
||||||
|
|
||||||
ERR_set_mark();
|
SET_ERR_MARK();
|
||||||
if (!read_der(ctx->provctx, cin, &der, &der_len))
|
if (!read_der(ctx->provctx, cin, &der, &der_len))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -180,16 +199,19 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin,
|
|||||||
der = new_der;
|
der = new_der;
|
||||||
der_len = new_der_len;
|
der_len = new_der_len;
|
||||||
}
|
}
|
||||||
|
RESET_ERR_MARK();
|
||||||
|
|
||||||
derp = der;
|
derp = der;
|
||||||
pkey = d2i_PrivateKey_ex(ctx->desc->type, NULL, &derp, der_len,
|
pkey = d2i_PrivateKey_ex(ctx->desc->type, NULL, &derp, der_len,
|
||||||
libctx, NULL);
|
libctx, NULL);
|
||||||
if (pkey == NULL) {
|
if (pkey == NULL) {
|
||||||
|
RESET_ERR_MARK();
|
||||||
derp = der;
|
derp = der;
|
||||||
pkey = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, NULL);
|
pkey = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkey == NULL) {
|
if (pkey == NULL) {
|
||||||
|
RESET_ERR_MARK();
|
||||||
derp = der;
|
derp = der;
|
||||||
pkey = d2i_KeyParams(ctx->desc->type, NULL, &derp, der_len);
|
pkey = d2i_KeyParams(ctx->desc->type, NULL, &derp, der_len);
|
||||||
}
|
}
|
||||||
@ -198,13 +220,7 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin,
|
|||||||
* Prune low-level ASN.1 parse errors from error queue, assuming that
|
* Prune low-level ASN.1 parse errors from error queue, assuming that
|
||||||
* this is called by decoder_process() in a loop trying several formats.
|
* this is called by decoder_process() in a loop trying several formats.
|
||||||
*/
|
*/
|
||||||
err = ERR_peek_last_error();
|
CLEAR_ERR_MARK();
|
||||||
if (ERR_GET_LIB(err) == ERR_LIB_ASN1
|
|
||||||
&& (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG
|
|
||||||
|| ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR))
|
|
||||||
ERR_pop_to_mark();
|
|
||||||
else
|
|
||||||
ERR_clear_last_mark();
|
|
||||||
|
|
||||||
if (pkey != NULL) {
|
if (pkey != NULL) {
|
||||||
/*
|
/*
|
||||||
|
20
test/certs/server-dsa-pubkey.pem
Normal file
20
test/certs/server-dsa-pubkey.pem
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIDSDCCAjoGByqGSM44BAEwggItAoIBAQD+P3LcpaA+AYu9M1gSsHi8fixl7VPC
|
||||||
|
sKK96oaH7/ZJqvOD0TdASkn+4Td8SPvkc+KG2bBbmp39FCxGpa4d8CRLKVbIHAFt
|
||||||
|
aKHIDFuMlPuFnsiaU0uWN/s3lROhAHWrTiODhehFM+NiPrAOJmtXQURBoeQ07t4H
|
||||||
|
oyKz7sUyTF2qotw1JDvBRb6JXw+13Z2a1iZGJopLZN3RicvoHee3rYEsM5AHMS3c
|
||||||
|
ntYX2NhQUHjiQ451iL2OkFJtVeaUoX5JV6KYSzz4lzNlYwJfF/Tzac/+l1aFA1ND
|
||||||
|
bNFcQ1UC0JXscKeT/J2Wo8kRwpx042UKaayw5jkOv3GndgKCOaCe29UrAiEAh8hM
|
||||||
|
JV/kKTLolNr6kV87KV8eTaJfrnSRS2E3ToOhWH0CggEBAOd/YKl8svYqvJtThaOs
|
||||||
|
mVETeXwEvz/MLqpj4hZr029Oqps7z6OmeZ2er7aldxC5+BKMxCfPlhFo0iQ9XITp
|
||||||
|
+J7UqS3qrRZqAnxMjd6VmEGXKWOoeAc0CpEzR1QNkjKodzgstQj5oYbiiPG0SgCt
|
||||||
|
BV4I1b/IuKzkjcLxQaF+8Rob/lzLBwA6pFjZNa6FcDjthmtH2pC+zI760sv05rbZ
|
||||||
|
GcXDj8G0SLsvbkrfiRIn/8LkgBpoTWpKfa8BmvYtt9WI/CYkbeQYIwM9sXUPwRSD
|
||||||
|
1VONSg5bXTW3Sxmzy3Yfy9RYt+suMKzi78oSv81e5BoL1D2HtfxSAFQbiJU3kipx
|
||||||
|
vhsDggEGAAKCAQEArDidnkCegHb/itBTFeyGsebv+I8Z93V3jGcKPOs3s1wqB/+H
|
||||||
|
RL5ERlhQOq/lfYPigUFKhfC8tlCVAM+MtUDqXCzqAkomw0yX8oVkp9plswxHKlqj
|
||||||
|
zKr6PWLOJGp/NDBAL1ZcUzHB1omvmkUHy9pYiapVVNUuUdL2Z5EvDze8jQoiR0k9
|
||||||
|
zgMKiH+MyCfV0tLo8W8djFJPlIM9Ypa7DH4fazcEfRuzq1jvK/uX4+HWmg3Nswdh
|
||||||
|
5eysb++RqtJSUBtGT3tAQY59WjBf2nXMG0nkZGkT7TCJ6icvNdbSl1AlAGMV/nZN
|
||||||
|
3PFsFH17L8uMUYS7V5PWiqQTxe5COHqpGumo9A==
|
||||||
|
-----END PUBLIC KEY-----
|
@ -110,7 +110,8 @@ push @defltfiles, qw(evppkey_sm2.txt) unless $no_sm2;
|
|||||||
plan tests =>
|
plan tests =>
|
||||||
($no_fips ? 0 : 1) # FIPS install test
|
($no_fips ? 0 : 1) # FIPS install test
|
||||||
+ (scalar(@configs) * scalar(@files))
|
+ (scalar(@configs) * scalar(@files))
|
||||||
+ scalar(@defltfiles);
|
+ scalar(@defltfiles)
|
||||||
|
+ 3; # error output tests
|
||||||
|
|
||||||
unless ($no_fips) {
|
unless ($no_fips) {
|
||||||
my $infile = bldtop_file('providers', platform->dso('fips'));
|
my $infile = bldtop_file('providers', platform->dso('fips'));
|
||||||
@ -139,3 +140,38 @@ foreach my $f ( @defltfiles ) {
|
|||||||
data_file("$f")])),
|
data_file("$f")])),
|
||||||
"running evp_test -config $conf $f");
|
"running evp_test -config $conf $f");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub test_errors { # actually tests diagnostics of OSSL_STORE
|
||||||
|
my ($expected, $key, @opts) = @_;
|
||||||
|
my $infile = srctop_file('test', 'certs', $key);
|
||||||
|
my @args = qw(openssl pkey -in);
|
||||||
|
push(@args, $infile, @opts);
|
||||||
|
my $tmpfile = 'out.txt';
|
||||||
|
my $res = !run(app([@args], stderr => $tmpfile));
|
||||||
|
my $found = 0;
|
||||||
|
open(my $in, '<', $tmpfile) or die "Could not open file $tmpfile";
|
||||||
|
while(<$in>) {
|
||||||
|
print; # this may help debugging
|
||||||
|
$res &&= !m/asn1 encoding/; # output must not include ASN.1 parse errors
|
||||||
|
$found = 1 if m/$expected/; # output must include $expected
|
||||||
|
}
|
||||||
|
close $in;
|
||||||
|
# $tmpfile is kept to help with investigation in case of failure
|
||||||
|
return $res && $found;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "DSA not disabled", 2 if !disabled("dsa");
|
||||||
|
|
||||||
|
ok(test_errors("unsupported algorithm", "server-dsa-key.pem"),
|
||||||
|
"error loading unsupported dsa private key");
|
||||||
|
ok(test_errors("unsupported algorithm", "server-dsa-pubkey.pem", "-pubin"),
|
||||||
|
"error loading unsupported dsa public key");
|
||||||
|
}
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "sm2 not disabled", 1 if !disabled("sm2");
|
||||||
|
|
||||||
|
ok(test_errors("unknown group|unsupported algorithm", "sm2.key"),
|
||||||
|
"error loading unsupported sm2 private key");
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user