PEM_X509_INFO_read_bio_ex(): Generalize to allow parsing any type of private key
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Mon, 22 Mar 2021 15:23:24 +0000 (16:23 +0100)
committerDr. David von Oheimb <dev@ddvo.net>
Thu, 8 Apr 2021 13:18:58 +0000 (15:18 +0200)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14647)

crypto/pem/pem_info.c
doc/man3/PEM_X509_INFO_read_bio_ex.pod
test/certs/key-pass-12345.pem [new file with mode: 0644]
test/recipes/60-test_x509_check_cert_pkey.t

index 2714009103c48838295f3449e1132b8b2e72a952..cd75a95e2a25d3448ae21864f809624e642f5291 100644 (file)
@@ -22,6 +22,7 @@
 #include <openssl/pem.h>
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
+#include "crypto/evp.h"
 
 #ifndef OPENSSL_NO_STDIO
 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)
 {
     X509_INFO *xi = NULL;
-    char *name = NULL, *header = NULL;
+    char *name = NULL, *header = NULL, *str;
     void *pp;
     unsigned char *data = NULL;
     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();
  start:
-        if ((strcmp(name, PEM_STRING_X509) == 0) ||
-            (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
-            d2i = (D2I_OF(void)) d2i_X509;
-            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 (strcmp(name, PEM_STRING_X509) == 0
+                || strcmp(name, PEM_STRING_X509_OLD) == 0
+                || strcmp(name, PEM_STRING_X509_TRUSTED) == 0) {
             if (xi->x509 != NULL) {
                 if (!sk_X509_INFO_push(ret, xi))
                     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 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);
             if (xi->x509 == NULL)
                 goto err;
@@ -127,30 +119,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
                 goto start;
             }
             pp = &(xi->crl);
-        } else if (strcmp(name, PEM_STRING_RSA) == 0) {
-            d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
-            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_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;
+        } else if ((str = strstr(name, PEM_STRING_PKCS8INF)) != NULL) {
             if (xi->x_pkey != NULL) {
                 if (!sk_X509_INFO_push(ret, xi))
                     goto err;
@@ -158,43 +127,25 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk,
                     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_DSA;
-            pp = &xi->x_pkey->dec_pkey;
-            if ((int)strlen(header) > 10) /* assume encrypted */
-                raw = 1;
-        } else
-#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;
+            if (str == name || strcmp(name, PEM_STRING_PKCS8) == 0) {
+                ptype = EVP_PKEY_NONE;
+            } else {
+                /* chop " PRIVATE KEY" */
+                *--str = '\0';
+                ptype = evp_pkey_name2type(name);
             }
-
             xi->enc_data = NULL;
             xi->enc_len = 0;
 
+            d2i = (D2I_OF(void)) d2i_AutoPrivateKey;
             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 */
+            if ((int)strlen(header) > 10 /* assume encrypted */
+                   || strcmp(name, PEM_STRING_PKCS8) == 0)
                 raw = 1;
-        } else
-#endif
-        {
+        } else { /* unknown */
             d2i = 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;
                 data = NULL;
             }
-        } else {
-            /* unknown */
         }
         OPENSSL_free(name);
         name = NULL;
index f0add6537f9f6405b1df3d838ba1f95dbdc3699e..cdff0561e9d815248cb607724ff9071605657fb8 100644 (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>.
 
 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 read before, they are combined into the same B<X509_INFO> object.
diff --git a/test/certs/key-pass-12345.pem b/test/certs/key-pass-12345.pem
new file mode 100644 (file)
index 0000000..e1aabfe
--- /dev/null
@@ -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-----
index 2c0f2e40097ed4b95004f4d0005f01629b3f4fea..d7c83acb80755d8f1e6ef7ed52ecbc4f4a691a9e 100644 (file)
@@ -12,7 +12,7 @@ use OpenSSL::Test::Utils;
 
 setup("test_x509_check_cert_pkey");
 
-plan tests => 9;
+plan tests => 11;
 
 sub src_file {
     return srctop_file("test", "certs", shift);
@@ -60,4 +60,6 @@ ok(run(test(["x509_check_cert_pkey_test",
              src_file("wrongkey.pem"), "req", "failed"])));
 
 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");