PEM_X509_INFO_read_bio_ex(): Generalize to allow parsing any type of private key

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14647)
This commit is contained in:
Dr. David von Oheimb 2021-03-22 16:23:24 +01:00 committed by Dr. David von Oheimb
parent c1fd710297
commit 4957d95208
4 changed files with 54 additions and 73 deletions

View File

@ -22,6 +22,7 @@
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include "crypto/evp.h"
#ifndef OPENSSL_NO_STDIO #ifndef OPENSSL_NO_STDIO
STACK_OF(X509_INFO) STACK_OF(X509_INFO)
@ -54,7 +55,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
const char *propq) const char *propq)
{ {
X509_INFO *xi = NULL; X509_INFO *xi = NULL;
char *name = NULL, *header = NULL; char *name = NULL, *header = NULL, *str;
void *pp; void *pp;
unsigned char *data = NULL; unsigned char *data = NULL;
const unsigned char *p; const unsigned char *p;
@ -90,22 +91,9 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
} }
ERR_clear_last_mark(); ERR_clear_last_mark();
start: start:
if ((strcmp(name, PEM_STRING_X509) == 0) || if (strcmp(name, PEM_STRING_X509) == 0
(strcmp(name, PEM_STRING_X509_OLD) == 0)) { || strcmp(name, PEM_STRING_X509_OLD) == 0
d2i = (D2I_OF(void)) d2i_X509; || strcmp(name, PEM_STRING_X509_TRUSTED) == 0) {
if (xi->x509 != NULL) {
if (!sk_X509_INFO_push(ret, xi))
goto err;
if ((xi = X509_INFO_new()) == NULL)
goto err;
goto start;
}
xi->x509 = X509_new_ex(libctx, propq);
if (xi->x509 == NULL)
goto err;
pp = &(xi->x509);
} else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
d2i = (D2I_OF(void)) d2i_X509_AUX;
if (xi->x509 != NULL) { if (xi->x509 != NULL) {
if (!sk_X509_INFO_push(ret, xi)) if (!sk_X509_INFO_push(ret, xi))
goto err; goto err;
@ -113,6 +101,10 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err; goto err;
goto start; goto start;
} }
if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0))
d2i = (D2I_OF(void)) d2i_X509_AUX;
else
d2i = (D2I_OF(void)) d2i_X509;
xi->x509 = X509_new_ex(libctx, propq); xi->x509 = X509_new_ex(libctx, propq);
if (xi->x509 == NULL) if (xi->x509 == NULL)
goto err; goto err;
@ -127,8 +119,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
goto start; goto start;
} }
pp = &(xi->crl); pp = &(xi->crl);
} else if (strcmp(name, PEM_STRING_RSA) == 0) { } else if ((str = strstr(name, PEM_STRING_PKCS8INF)) != NULL) {
d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
if (xi->x_pkey != NULL) { if (xi->x_pkey != NULL) {
if (!sk_X509_INFO_push(ret, xi)) if (!sk_X509_INFO_push(ret, xi))
goto err; goto err;
@ -136,65 +127,25 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
goto err; goto err;
goto start; goto start;
} }
if (str == name || strcmp(name, PEM_STRING_PKCS8) == 0) {
xi->enc_data = NULL; ptype = EVP_PKEY_NONE;
xi->enc_len = 0; } else {
/* chop " PRIVATE KEY" */
xi->x_pkey = X509_PKEY_new(); *--str = '\0';
if (xi->x_pkey == NULL) ptype = evp_pkey_name2type(name);
goto err;
ptype = EVP_PKEY_RSA;
pp = &xi->x_pkey->dec_pkey;
if ((int)strlen(header) > 10) /* assume encrypted */
raw = 1;
} else
#ifndef OPENSSL_NO_DSA
if (strcmp(name, PEM_STRING_DSA) == 0) {
d2i = (D2I_OF(void)) d2i_DSAPrivateKey;
if (xi->x_pkey != NULL) {
if (!sk_X509_INFO_push(ret, xi))
goto err;
if ((xi = X509_INFO_new()) == NULL)
goto err;
goto start;
} }
xi->enc_data = NULL; xi->enc_data = NULL;
xi->enc_len = 0; xi->enc_len = 0;
d2i = (D2I_OF(void)) d2i_AutoPrivateKey;
xi->x_pkey = X509_PKEY_new(); xi->x_pkey = X509_PKEY_new();
if (xi->x_pkey == NULL) if (xi->x_pkey == NULL)
goto err; goto err;
ptype = EVP_PKEY_DSA;
pp = &xi->x_pkey->dec_pkey; pp = &xi->x_pkey->dec_pkey;
if ((int)strlen(header) > 10) /* assume encrypted */ if ((int)strlen(header) > 10 /* assume encrypted */
|| strcmp(name, PEM_STRING_PKCS8) == 0)
raw = 1; raw = 1;
} else } else { /* unknown */
#endif
#ifndef OPENSSL_NO_EC
if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
d2i = (D2I_OF(void)) d2i_ECPrivateKey;
if (xi->x_pkey != NULL) {
if (!sk_X509_INFO_push(ret, xi))
goto err;
if ((xi = X509_INFO_new()) == NULL)
goto err;
goto start;
}
xi->enc_data = NULL;
xi->enc_len = 0;
xi->x_pkey = X509_PKEY_new();
if (xi->x_pkey == NULL)
goto err;
ptype = EVP_PKEY_EC;
pp = &xi->x_pkey->dec_pkey;
if ((int)strlen(header) > 10) /* assume encrypted */
raw = 1;
} else
#endif
{
d2i = NULL; d2i = NULL;
pp = NULL; pp = NULL;
} }
@ -225,8 +176,6 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
xi->enc_len = (int)len; xi->enc_len = (int)len;
data = NULL; data = NULL;
} }
} else {
/* unknown */
} }
OPENSSL_free(name); OPENSSL_free(name);
name = NULL; name = NULL;

View File

@ -27,7 +27,7 @@ PEM_X509_INFO_read_ex() loads the B<X509_INFO> objects from a file I<fp>.
PEM_X509_INFO_read_bio_ex loads the B<X509_INFO> objects using a bio I<bp>. PEM_X509_INFO_read_bio_ex loads the B<X509_INFO> objects using a bio I<bp>.
Each of the loaded B<X509_INFO> objects can contain a CRL, a certificate, Each of the loaded B<X509_INFO> objects can contain a CRL, a certificate,
and/or an RSA/DSA/EC private key. and/or a private key.
The elements are read sequentially, and as far as they are of different type than The elements are read sequentially, and as far as they are of different type than
the elements read before, they are combined into the same B<X509_INFO> object. the elements read before, they are combined into the same B<X509_INFO> object.

View File

@ -0,0 +1,30 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIuH8X1xWl9ygCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCw27UHDuBtxWa928AXEEb1BIIE
0A/aH/nMGoifA4TKpLg1SobskugzWV7+N2qh3j9LZrz6GxB9jR64JBx8+eKBu5lv
VeMp/cIuGZscJ56QFZ01tTEyIiP1eeD68eQol2n7KEwk9DKkR2QbQuLDOaR4voqM
rm02uehLnNPJ7d81CrgfqIRi5OF4cWVV20jN7pQMxn8KqW4OYPdOrV1i6mTnsbNz
M5hL9YMud4wppWwA93MLD4TGvQBQSTvreYtLNy1atq1uK4k2KZh2tw/CTNiCo47R
N6Ft+CDJblikodpj/a6ZPJ84qBMonTbc7IMvkeWP0mnzA25ohOW7RfhgWzz/mfx3
/ypX8xqLd8JzmdRFOcc5MFdVcYPmgFzFVtEJ0bBZx6WCW+6OszLkt/7p7raRKirA
/zJJSBmEvQKvwtZ6I/rG6SqMFiTseRuWq0sXa1NX2zlH9y+g68K+7Bt5816l93WD
p0GQgWxXV2J+QJ3fGvxMdQG7qmGWx6dc6yZkFw9e94sTHH74fShTv53OekCgWg2B
58pFBTK9NGtiG5LawtDKMqlYcSKvfqjvKwDokQS104DwM+om0QBLTH+RRxh05jYv
2hx1uwSXoo8oO+AYaYsEQE8z7mYxQr5Ea1gKbtyYPE0Eo5rrH9fYzXN8A1LH7wbL
ywQIZq/lthuJGarTPCFjoHrPW9O+FiQBLsn5Ej2VVm2MQpS3v6m7SnHTWBaPZvkq
GEGw/MZiwkzyULsg7zRKfnNhYBfxdg+gmwIR6x1e4vT6hAFjZbvn1eOlFTLqIBpE
XQCqxaITtW6bCEhvl/c0AKkAWM39XEs/ff1giYza+6SLgLQObHApp+Q/Hk3PaUDq
Wnm/5w8IyQcGDAik0f6JqbQ+licBk5lHlOifO0GFKqePlKLY/Mvx9al2UflzOydG
u9BpXx8sLooLuyycXFhgpZZLp19+79KgPm+ZrXKlKKwTDQwuB+eGxr2wKWCbJb2y
gmnBCtml5apTQx+l630GldMjkhwxOSZJoXy6XKQew85L/J9Jknta3bjGbyL2lEeW
/gfT+L6WrmG3Hf4xGhpkkx6UITzujJbE2/YyxJ+sXlRuYd4ld0Hfn6Ihsajknj8G
jvLb77FvgNndf5SXlqU3sMGcOPizQkMr/AmtHPzBLT8O6OxpeAOWzG3jOvznRsmZ
27nmW4cM/6t/86PvnAssPETFcrC3GqFYWnzdVaWunCz5zn4xIot3633VGR1lbxX4
kTQLBzgBjKuajgVim5Q4obfaqnJEvHkbJaAFJg0y6uId2RIzYo5/onHrVOQR5ulB
qyR8YJjWu3pyq8t5q9Iw3L+pWDOh4AH7/ay0IBu/qxapvybqEXyol3kAJIsY0AKZ
Y5dPA4duWjW0MHNDgliAssKr2t3CTALU9nrBVX1fEPR4Y05JZ9f4OIueu/IGdDIE
snLdqtkY0sOTma9FhKDv1RwsumT/UfOqUJ3ZSJCaKgE/RnzS3YN+j5BYv788micZ
S9nl5KX+q/VSVXxial0nxkGiqs73mASF5JP4iarRihSntGMvn4PPB7Oid5SVLrqk
JFFy7pjL8xuERx0hlShUl2q8/C3DSi0u+QkIhNrUBKZRADzNDkJcfWmKwbhq7HPp
ghzvaDrFtH/4o8t7kd+TVdKjnS0cna43Sj94w3J5/y5Y
-----END ENCRYPTED PRIVATE KEY-----

View File

@ -12,7 +12,7 @@ use OpenSSL::Test::Utils;
setup("test_x509_check_cert_pkey"); setup("test_x509_check_cert_pkey");
plan tests => 9; plan tests => 11;
sub src_file { sub src_file {
return srctop_file("test", "certs", shift); return srctop_file("test", "certs", shift);
@ -60,4 +60,6 @@ ok(run(test(["x509_check_cert_pkey_test",
src_file("wrongkey.pem"), "req", "failed"]))); src_file("wrongkey.pem"), "req", "failed"])));
test_PEM_X509_INFO_read("root-cert.pem", "1"); test_PEM_X509_INFO_read("root-cert.pem", "1");
test_PEM_X509_INFO_read("root-key.pem", "1");
test_PEM_X509_INFO_read("key-pass-12345.pem", "1");
test_PEM_X509_INFO_read("cyrillic_crl.utf8", "1"); test_PEM_X509_INFO_read("cyrillic_crl.utf8", "1");