[openssl] master update

tomas at openssl.org tomas at openssl.org
Fri Jul 2 13:34:34 UTC 2021


The branch master has been updated
       via  5cffc49f7213c718ebcc2c1236cdd8c2fae7fb28 (commit)
       via  d82d1d11d4dafc97875969329a5100242441744d (commit)
       via  e58087842cf74164809977872eb2f7a62490d8dd (commit)
       via  bb8a24503c309e353fb25f341de3ed27f7003f77 (commit)
       via  66a7c9f34b46edd462d647ae2febe8276bb9b4f7 (commit)
       via  fbbd425336144455f4a976acd7b890352ef7ed38 (commit)
      from  92d7120c60cea7c9e0219921c2cc2320346218b2 (commit)


- Log -----------------------------------------------------------------
commit 5cffc49f7213c718ebcc2c1236cdd8c2fae7fb28
Author: Tomas Mraz <tomas at openssl.org>
Date:   Wed Jun 30 18:02:24 2021 +0200

    PEM_read_...: document that garbage and other PEM data is skipped
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

commit d82d1d11d4dafc97875969329a5100242441744d
Author: Tomas Mraz <tomas at openssl.org>
Date:   Wed Jun 30 16:11:17 2021 +0200

    load_key_certs_crls: Avoid reporting any spurious errors
    
    When there is other PEM data in between certs the OSSL_STORE_load
    returns NULL and reports error. Avoid printing that error unless
    there was nothing read at all.
    
    Fixes #15945
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

commit e58087842cf74164809977872eb2f7a62490d8dd
Author: Tomas Mraz <tomas at openssl.org>
Date:   Tue Jun 29 17:18:34 2021 +0200

    test_pem_reading: Test loading a key from a file with multiple PEM data
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

commit bb8a24503c309e353fb25f341de3ed27f7003f77
Author: Tomas Mraz <tomas at openssl.org>
Date:   Tue Jun 29 16:44:00 2021 +0200

    load_pkey_pem: Check for spurious errors when loading
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

commit 66a7c9f34b46edd462d647ae2febe8276bb9b4f7
Author: Tomas Mraz <tomas at openssl.org>
Date:   Tue Jun 29 16:24:59 2021 +0200

    pem_read_bio_key: Add passphrase caching to avoid asking for password twice
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

commit fbbd425336144455f4a976acd7b890352ef7ed38
Author: Tomas Mraz <tomas at openssl.org>
Date:   Tue Jun 29 15:46:25 2021 +0200

    pem_read_bio_key_decoder: Avoid spurious error on unknown PEM data
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15949)

-----------------------------------------------------------------------

Summary of changes:
 apps/lib/apps.c                      | 12 ++---
 crypto/pem/pem_pkey.c                | 38 ++++++++++++---
 doc/man3/PEM_read_bio_PrivateKey.pod |  4 ++
 test/certs/cert-key-cert.pem         | 90 ++++++++++++++++++++++++++++++++++++
 test/pemtest.c                       | 16 +++++++
 test/recipes/04-test_pem_reading.t   | 24 ++++++----
 test/recipes/80-test_pkcs12.t        | 23 ++++++++-
 test/testutil/load.c                 | 14 ++++--
 8 files changed, 193 insertions(+), 28 deletions(-)
 create mode 100644 test/certs/cert-key-cert.pem

diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index dfbc3ec522..a767023197 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -871,9 +871,6 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
     OSSL_PARAM itp[2];
     const OSSL_PARAM *params = NULL;
 
-    if (suppress_decode_errors)
-        ERR_set_mark();
-
     if (ppkey != NULL) {
         *ppkey = NULL;
         cnt_expectations++;
@@ -971,10 +968,6 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
          * certificate in it. We just retry until eof.
          */
         if (info == NULL) {
-            if (OSSL_STORE_error(ctx)) {
-                ERR_print_errors(bio_err);
-                ERR_clear_error();
-            }
             continue;
         }
 
@@ -1078,8 +1071,9 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
         BIO_printf(bio_err, "\n");
         ERR_print_errors(bio_err);
     }
-    if (suppress_decode_errors)
-        ERR_pop_to_mark();
+    if (suppress_decode_errors || failed == NULL)
+        /* clear any spurious errors */
+        ERR_clear_error();
     return failed == NULL;
 }
 
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index ca6b2a2132..f9346486dd 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -11,7 +11,6 @@
 #define OPENSSL_SUPPRESS_DEPRECATED
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/objects.h>
 #include <openssl/evp.h>
@@ -22,6 +21,8 @@
 #include <openssl/dh.h>
 #include <openssl/decoder.h>
 #include <openssl/ui.h>
+#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
 #include "crypto/asn1.h"
 #include "crypto/x509.h"
 #include "crypto/evp.h"
@@ -55,11 +56,24 @@ static EVP_PKEY *pem_read_bio_key_decoder(BIO *bp, EVP_PKEY **x,
     if (!OSSL_DECODER_CTX_set_pem_password_cb(dctx, cb, u))
         goto err;
 
+    ERR_set_mark();
     while (!OSSL_DECODER_from_bio(dctx, bp) || pkey == NULL)
-        if (BIO_eof(bp) != 0 || (newpos = BIO_tell(bp)) < 0 || newpos <= pos)
+        if (BIO_eof(bp) != 0 || (newpos = BIO_tell(bp)) < 0 || newpos <= pos) {
+            ERR_clear_last_mark();
             goto err;
-        else
+        } else {
+            if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_UNSUPPORTED) {
+                /* unsupported PEM data, try again */
+                ERR_pop_to_mark();
+                ERR_set_mark();
+            } else {
+                /* other error, bail out */
+                ERR_clear_last_mark();
+                goto err;
+            }
             pos = newpos;
+        }
+    ERR_pop_to_mark();
 
     if (!evp_keymgmt_util_has(pkey, selection)) {
         EVP_PKEY_free(pkey);
@@ -195,9 +209,10 @@ static EVP_PKEY *pem_read_bio_key(BIO *bp, EVP_PKEY **x,
                                   const char *propq,
                                   int selection)
 {
-    EVP_PKEY *ret;
+    EVP_PKEY *ret = NULL;
     BIO *new_bio = NULL;
     int pos;
+    struct ossl_passphrase_data_st pwdata = { 0 };
 
     if ((pos = BIO_tell(bp)) < 0) {
         new_bio = BIO_new(BIO_f_readbuffer());
@@ -207,17 +222,28 @@ static EVP_PKEY *pem_read_bio_key(BIO *bp, EVP_PKEY **x,
         pos = BIO_tell(bp);
     }
 
+    if (cb == NULL)
+        cb = PEM_def_callback;
+
+    if (!ossl_pw_set_pem_password_cb(&pwdata, cb, u)
+        || !ossl_pw_enable_passphrase_caching(&pwdata))
+        goto err;
+
     ERR_set_mark();
-    ret = pem_read_bio_key_decoder(bp, x, cb, u, libctx, propq, selection);
+    ret = pem_read_bio_key_decoder(bp, x, ossl_pw_pem_password, &pwdata,
+                                   libctx, propq, selection);
     if (ret == NULL
         && (BIO_seek(bp, pos) < 0
-            || (ret = pem_read_bio_key_legacy(bp, x, cb, u,
+            || (ret = pem_read_bio_key_legacy(bp, x,
+                                              ossl_pw_pem_password, &pwdata,
                                               libctx, propq,
                                               selection)) == NULL))
         ERR_clear_last_mark();
     else
         ERR_pop_to_mark();
 
+ err:
+    ossl_pw_clear_passphrase_data(&pwdata);
     if (new_bio != NULL) {
         BIO_pop(new_bio);
         BIO_free(new_bio);
diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod
index 9df61892fd..4ed1b8c703 100644
--- a/doc/man3/PEM_read_bio_PrivateKey.pod
+++ b/doc/man3/PEM_read_bio_PrivateKey.pod
@@ -358,6 +358,10 @@ will be used.
 
 =head1 NOTES
 
+The PEM reading functions will skip any extraneous content or PEM data of
+a different type than they expect. This allows for example having a certificate
+(or multiple certificates) and a key in the PEM format in a single file.
+
 The old B<PrivateKey> write routines are retained for compatibility.
 New applications should write private keys using the
 PEM_write_bio_PKCS8PrivateKey() or PEM_write_PKCS8PrivateKey() routines
diff --git a/test/certs/cert-key-cert.pem b/test/certs/cert-key-cert.pem
new file mode 100644
index 0000000000..bf6fd9c34b
--- /dev/null
+++ b/test/certs/cert-key-cert.pem
@@ -0,0 +1,90 @@
+Some garbage at the beginning
+-----BEGIN CERTIFICATE-----
+MIIEzDCCA7QCCQCgxkRox+YljjANBgkqhkiG9w0BAQsFADCCASYxYzBhBgNVBAgM
+WlRoZSBHcmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVs
+ZCBOYW1lcyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0G
+A1UEBwwWVG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2
+b2xlbnQgU29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlw
+aHJhc2lzMT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlk
+ZW50aWFyeSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwHhcN
+MTcwMjIzMjAyNTM2WhcNMTcwMzI1MjAyNTM2WjCCASYxYzBhBgNVBAgMWlRoZSBH
+cmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVsZCBOYW1l
+cyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0GA1UEBwwW
+VG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2b2xlbnQg
+U29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlwaHJhc2lz
+MT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlkZW50aWFy
+eSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7MOIrqH+ZIJiZdroKMrelKMSvvRKg2MEg
+j/sx9TaHHqrKys4AiL4Rq/ybQEigFC6G8mpZWbBrU+vN2SLr1ZsPftCHIY12LF56
+0WLYTYNqDgF5BdCZCrjJ2hhN+XwML2tgYdWioV/Eey8SJSqUskf03MpcwnLbVfSp
+hwmowqNfiEFFqPBCf7E8IVarGWctbMpvlMbAM5owhMev/Ccmqqt81NFkb1WVejvN
+5v/JKv243/Xedf4I7ZJv7zKeswoP9piFzWHXCd9SIVzWqF77u/crHufIhoEa7NkZ
+hSC2aosQF619iKnfk0nqWaLDJ182CCXkHERoQC7q9X2IGLDLoA0XAgMBAAEwDQYJ
+KoZIhvcNAQELBQADggEBAKbtLx+YlCGRCBmYn3dfYF+BIvK/b/e0DKNhDKhb4s9J
+ywlJ4qnAB48tgPx0q+ZB+EdMYRqCwyvXJxEdZ7PsCdUeU6xI2ybkhSdUUfQbYem3
+aYRG+yukGzazySQJs8lGqxBlRMFl/FGCg+oSQ/I32eGf8micDskj2zkAJtCkUPHX
+30YrWMfOwW1r2xYr2mBNXbNWXJhW/sIg5u8aa9fcALeuQcMXkbsbVoPmC5aLdiVZ
+rvUFoJ8DPg0aYYwj64RwU0B5HW/7jKhQ25FgKVAzLGrgYx1DivkM7UQGdWYnU8IA
+A8S89gRjGk2hnkeagWas3dxqTTpgJDhprgWzyKa9hII=
+-----END CERTIFICATE-----
+Some garbage in the middle
+And more
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7MOIrqH+ZIJiZ
+droKMrelKMSvvRKg2MEgj/sx9TaHHqrKys4AiL4Rq/ybQEigFC6G8mpZWbBrU+vN
+2SLr1ZsPftCHIY12LF560WLYTYNqDgF5BdCZCrjJ2hhN+XwML2tgYdWioV/Eey8S
+JSqUskf03MpcwnLbVfSphwmowqNfiEFFqPBCf7E8IVarGWctbMpvlMbAM5owhMev
+/Ccmqqt81NFkb1WVejvN5v/JKv243/Xedf4I7ZJv7zKeswoP9piFzWHXCd9SIVzW
+qF77u/crHufIhoEa7NkZhSC2aosQF619iKnfk0nqWaLDJ182CCXkHERoQC7q9X2I
+GLDLoA0XAgMBAAECggEAcEBMIGoWuji1ybFMtrjbL4tXBxuWhCX3ChPNSpQFctmN
+Cba7+c4GTIqaHG9cHcJ8dCgCZjpGdNYKXZKMQmgBaDVfzujr76WDsprFb3hsCbkE
+YRJ/mIa5cTH7ySaGoLf+5/lDJxcmWqiT/YmUEz8lr0yHfUCNp8HPyalUvYKafbos
+5BiXs8lr4XQ/vxL0CtVQx+5T8pmgU6CmP1jjgBqV4Y9RPewSmPNhxKAqm82JYMND
+9evNHNpZmDpwTMygwwL0oJ0DV0nq0uqzuk1ORcp7YIph7IFGcdi4n7Y4Y2U6B8Ok
+ITY684qpcXgy+qO1A8AwDEJ34wiIWb8Mi8S84KdTIQKBgQDhHmCdpWKzwLETlHQR
+V9wT3ulySmxG0t8kSgNOFRVUZNXQ0ij2v8rOJ7R0QzJ+kCqvdxJ5QHNlUFKkOFMA
+SnSy098iEz5skwRhHof7ZNa3U6oRRSauUcZcThWL+z14nhTIC1m99KpACV6fl3jj
+MVEYYpG6n7jZ0wKUGMStxT1q9QKBgQDU3pOgNLnFasMIujvXI3ARSK6xIpkBTq89
+n6pmn9XeMWs/H6wQRO5wpUXbg+/3/d4tnezrDG9Lg5aPV8ca/zJ7IP8iNyLnhiUY
+c9O6hKAW1fxddt9megzBDvsBgRzhytnv3OSpM+idgtsJ7Tvkevmt4K5j6gitpJpb
+1A1erknoWwKBgCM5zKZ+bZ5xBYRp02uvUtmtJNxkduLyNkaIalH6jJbjHG4LpKtP
+wZ1Wqy8SIMGbL4K7YCGnCyeMVRIrWhmOjQo6iwza9AarTqEf1OlqkwqmxdLj/jSC
+yUZCVa7MxoasPdY7qHRH56gTj0HrwtfSLL1jFyibu6IiGaIw6f3DAmRNAoGAL2sx
+iYOVSnPg5GXQBLnBMih1ucHSQadMhDa4F8pNMwThNhuREcK5NuCqMh8u6phj0NeY
+Ojf35uN2O5I7KTll/mW4T9/mZ5rLUqoipS78FnoukId1dneDtdHnektPqsCsUbFs
+QoDstYG713dAW0JFskUVs+4jZsL/G6ueGtRKZHcCgYEA27sBEJtHGLAgEUGSlwSA
+acmaIlKpF3EMImgWhlzRN3JC7+z8HJAhoHTxQUdnWfJt2Xl4Z+WmXvv+E7U9ofH7
+kH8fbLcaxwvylPm4hAMlhtL3EqnRDSL4hfZHBrqqf3C0Kv+C8naNxzeCNG6iHxcp
+3c7vY4BXTz0dGBGHml6qu5Y=
+-----END PRIVATE KEY-----
+More garbage in the middle
+And more
+-----BEGIN CERTIFICATE-----
+MIIEzDCCA7QCCQCgxkRox+YljjANBgkqhkiG9w0BAQsFADCCASYxYzBhBgNVBAgM
+WlRoZSBHcmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVs
+ZCBOYW1lcyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0G
+A1UEBwwWVG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2
+b2xlbnQgU29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlw
+aHJhc2lzMT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlk
+ZW50aWFyeSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwHhcN
+MTcwMjIzMjAyNTM2WhcNMTcwMzI1MjAyNTM2WjCCASYxYzBhBgNVBAgMWlRoZSBH
+cmVhdCBTdGF0ZSBvZiBMb25nLVdpbmRlZCBDZXJ0aWZpY2F0ZSBGaWVsZCBOYW1l
+cyBXaGVyZWJ5IHRvIEluY3JlYXNlIHRoZSBPdXRwdXQgU2l6ZTEfMB0GA1UEBwwW
+VG9vbWFueWNoYXJhY3RlcnN2aWxsZTFIMEYGA1UECgw/VGhlIEJlbmV2b2xlbnQg
+U29jaWV0eSBvZiBMb3F1YWNpb3VzIGFuZCBQbGVvbmFzdGljIFBlcmlwaHJhc2lz
+MT0wOwYDVQQLDDRFbmRvcnNlbWVudCBvZiBWb3VjaHNhZmUnZCBFdmlkZW50aWFy
+eSBDZXJ0aWZpY2F0aW9uMRUwEwYDVQQDDAxjZXJ0LmV4YW1wbGUwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7MOIrqH+ZIJiZdroKMrelKMSvvRKg2MEg
+j/sx9TaHHqrKys4AiL4Rq/ybQEigFC6G8mpZWbBrU+vN2SLr1ZsPftCHIY12LF56
+0WLYTYNqDgF5BdCZCrjJ2hhN+XwML2tgYdWioV/Eey8SJSqUskf03MpcwnLbVfSp
+hwmowqNfiEFFqPBCf7E8IVarGWctbMpvlMbAM5owhMev/Ccmqqt81NFkb1WVejvN
+5v/JKv243/Xedf4I7ZJv7zKeswoP9piFzWHXCd9SIVzWqF77u/crHufIhoEa7NkZ
+hSC2aosQF619iKnfk0nqWaLDJ182CCXkHERoQC7q9X2IGLDLoA0XAgMBAAEwDQYJ
+KoZIhvcNAQELBQADggEBAKbtLx+YlCGRCBmYn3dfYF+BIvK/b/e0DKNhDKhb4s9J
+ywlJ4qnAB48tgPx0q+ZB+EdMYRqCwyvXJxEdZ7PsCdUeU6xI2ybkhSdUUfQbYem3
+aYRG+yukGzazySQJs8lGqxBlRMFl/FGCg+oSQ/I32eGf8micDskj2zkAJtCkUPHX
+30YrWMfOwW1r2xYr2mBNXbNWXJhW/sIg5u8aa9fcALeuQcMXkbsbVoPmC5aLdiVZ
+rvUFoJ8DPg0aYYwj64RwU0B5HW/7jKhQ25FgKVAzLGrgYx1DivkM7UQGdWYnU8IA
+A8S89gRjGk2hnkeagWas3dxqTTpgJDhprgWzyKa9hII=
+-----END CERTIFICATE-----
+Some garbage at the end
diff --git a/test/pemtest.c b/test/pemtest.c
index 8c9e04297a..444603f253 100644
--- a/test/pemtest.c
+++ b/test/pemtest.c
@@ -28,6 +28,8 @@ static TESTDATA b64_pem_data[] = {
 
 static const char *pemtype = "PEMTESTDATA";
 
+static char *pemfile;
+
 static int test_b64(int idx)
 {
     BIO *b = BIO_new(BIO_s_mem());
@@ -83,9 +85,23 @@ static int test_invalid(void)
     return 1;
 }
 
+static int test_cert_key_cert(void)
+{
+    EVP_PKEY *key;
+
+    if (!TEST_ptr(key = load_pkey_pem(pemfile, NULL)))
+        return 0;
+
+    EVP_PKEY_free(key);
+    return 1;
+}
+
 int setup_tests(void)
 {
+    if (!TEST_ptr(pemfile = test_get_argument(0)))
+        return 0;
     ADD_ALL_TESTS(test_b64, OSSL_NELEM(b64_pem_data));
     ADD_TEST(test_invalid);
+    ADD_TEST(test_cert_key_cert);
     return 1;
 }
diff --git a/test/recipes/04-test_pem_reading.t b/test/recipes/04-test_pem_reading.t
index f69121cd37..9698289a8b 100644
--- a/test/recipes/04-test_pem_reading.t
+++ b/test/recipes/04-test_pem_reading.t
@@ -80,7 +80,7 @@ my %dsa_expected = (
     "dsa.pem" => 1
 );
 
-plan tests =>  scalar keys(%cert_expected) + scalar keys(%dsa_expected) + 2;
+plan tests =>  scalar keys(%cert_expected) + scalar keys(%dsa_expected) + 4;
 
 foreach my $input (keys %cert_expected) {
     my @common = ($cmd, "x509", "-text", "-noout", "-inform", "PEM", "-in");
@@ -101,12 +101,18 @@ SKIP: {
         is((scalar @match > 0 ? 1 : 0), $dsa_expected{$input});
     }
 }
-SKIP: {
-    skip "RSA support disabled, skipping...", 1 unless !disabled("rsa");
-    my @common = ($cmd, "pkey", "-inform", "PEM", "-noout", "-text", "-in");
-    my @data = run(app([@common, data_file("beermug.pem")], stderr => undef), capture => 1);
-    my @match = grep /00:a0:3a:21:14:5d:cd:b6:d5:a0:3e:49:23:c1:3a:/, @data;
-    ok(scalar @match > 0 ? 1 : 0);
-}
 
-ok(run(test(["pemtest"])), "running pemtest");
+my @common = ($cmd, "pkey", "-inform", "PEM", "-noout", "-text", "-in");
+my @data = run(app([@common, data_file("beermug.pem")], stderr => undef), capture => 1);
+my @match = grep /00:a0:3a:21:14:5d:cd:b6:d5:a0:3e:49:23:c1:3a:/, @data;
+ok(scalar @match > 0 ? 1 : 0);
+my $certkeycert = srctop_file("test", "certs", "cert-key-cert.pem");
+ at data = run(app([@common, $certkeycert], stderr => "outerr.txt"), capture => 1);
+open DATA, "outerr.txt";
+ at match = grep /:error:/, <DATA>;
+close DATA;
+ok(scalar @match > 0 ? 0 : 1);
+ at match = grep /70:40:4c:20:6a:16:ba:38:b5:c9:b1:4c:b6:b8:db:/, @data;
+ok(scalar @match > 0 ? 1 : 0);
+
+ok(run(test(["pemtest", $certkeycert])), "running pemtest");
diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t
index c85437f1a8..52c70cb0f7 100644
--- a/test/recipes/80-test_pkcs12.t
+++ b/test/recipes/80-test_pkcs12.t
@@ -54,7 +54,7 @@ if (eval { require Win32::API; 1; }) {
 }
 $ENV{OPENSSL_WIN32_UTF8}=1;
 
-plan tests => 7;
+plan tests => 10;
 
 # Test different PKCS#12 formats
 ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats");
@@ -78,6 +78,7 @@ my @path = qw(test certs);
 my $outfile1 = "out1.p12";
 my $outfile2 = "out2.p12";
 my $outfile3 = "out3.p12";
+my $outfile4 = "out4.p12";
 
 # Test the -chain option with -untrusted
 ok(run(app(["openssl", "pkcs12", "-export", "-chain",
@@ -113,4 +114,24 @@ SKIP: {
     "test_pkcs12_passcerts_legacy");
 }
 
+# Test export of PEM file with both cert and key
+# -nomac necessary to avoid legacy provider requirement
+ok(run(app(["openssl", "pkcs12", "-export",
+        "-inkey", srctop_file(@path, "cert-key-cert.pem"),
+        "-in", srctop_file(@path, "cert-key-cert.pem"),
+        "-passout", "pass:v3-certs",
+        "-nomac", "-out", $outfile4], stderr => "outerr.txt")),
+   "test_export_pkcs12_cert_key_cert");
+open DATA, "outerr.txt";
+my @match = grep /:error:/, <DATA>;
+close DATA;
+ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr_empty");
+
+ok(run(app(["openssl", "pkcs12",
+            "-in", $outfile4,
+            "-passin", "pass:v3-certs",
+            "-nomacver", "-nodes"])),
+  "test_import_pkcs12_cert_key_cert");
+
+
 SetConsoleOutputCP($savedcp) if (defined($savedcp));
diff --git a/test/testutil/load.c b/test/testutil/load.c
index be30d7e053..d776a7f167 100644
--- a/test/testutil/load.c
+++ b/test/testutil/load.c
@@ -73,9 +73,17 @@ EVP_PKEY *load_pkey_pem(const char *file, OSSL_LIB_CTX *libctx)
 
     if (!TEST_ptr(file) || !TEST_ptr(bio = BIO_new(BIO_s_file())))
         return NULL;
-    if (TEST_int_gt(BIO_read_filename(bio, file), 0))
-        (void)TEST_ptr(key = PEM_read_bio_PrivateKey_ex(bio, NULL, NULL, NULL,
-                                                        libctx, NULL));
+    if (TEST_int_gt(BIO_read_filename(bio, file), 0)) {
+        unsigned long err = ERR_peek_error();
+
+        if (TEST_ptr(key = PEM_read_bio_PrivateKey_ex(bio, NULL, NULL, NULL,
+                                                      libctx, NULL))
+            && err != ERR_peek_error()) {
+            TEST_info("Spurious error from reading PEM");
+            EVP_PKEY_free(key);
+            key = NULL;
+        }
+    }
 
     BIO_free(bio);
     return key;


More information about the openssl-commits mailing list