[openssl] master update

Matt Caswell matt at openssl.org
Thu Feb 18 16:18:33 UTC 2021


The branch master has been updated
       via  70793dbbb983b0f95da30b79e8c8744289062499 (commit)
       via  3a2171f6aa0f72ca95210fa80d92214315d1e744 (commit)
      from  3262300a2c2351c6706f37b89fef015430988a31 (commit)


- Log -----------------------------------------------------------------
commit 70793dbbb983b0f95da30b79e8c8744289062499
Author: Matt Caswell <matt at openssl.org>
Date:   Sat Feb 13 14:24:15 2021 +0000

    Pass the object type and data structure from the pem2der decoder
    
    The pem2der decoder can infer certain information about the endoded der
    data based on the PEM headers. This information should be passed to the
    next decoders in the chain to ensure we end up loading the correct type of
    thing.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14191)

commit 3a2171f6aa0f72ca95210fa80d92214315d1e744
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Feb 11 16:32:58 2021 +0000

    Don't forget the type of thing we are loading
    
    The apps helper function load_key_certs_crls() is a general purpose
    function for loading different types of objects from a given URI. It
    sets up an OSSL_STORE and calls OSSL_STORE_expect() so that the store
    knows what type of thing to expect to load. Unfortunately this wasn't
    working and was always setting "expect" to 0 - which means "anything".
    
    Fixes #13709
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14191)

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

Summary of changes:
 apps/lib/apps.c                                    | 37 +++++++++----
 crypto/store/store_result.c                        | 10 +++-
 .../implementations/encode_decode/decode_pem2der.c | 64 +++++++++++++++++-----
 test/recipes/20-test_cli_fips.t                    | 59 ++++++++++++++++----
 4 files changed, 132 insertions(+), 38 deletions(-)

diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index f53f1b2003..7c1015737d 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -730,11 +730,11 @@ int load_key_certs_crls(const char *uri, int maybe_stdin,
         return 0;
     }
 
-    if (pcerts != NULL && *pcerts == NULL
-            && (*pcerts = sk_X509_new_null()) == NULL) {
-        BIO_printf(bio_err, "Out of memory loading");
-        goto end;
-    } else {
+    if (pcerts != NULL) {
+        if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
+            BIO_printf(bio_err, "Out of memory loading");
+            goto end;
+        }
         cnt_expectations++;
         expect = OSSL_STORE_INFO_CERT;
     }
@@ -743,11 +743,11 @@ int load_key_certs_crls(const char *uri, int maybe_stdin,
         cnt_expectations++;
         expect = OSSL_STORE_INFO_CRL;
     }
-    if (pcrls != NULL && *pcrls == NULL
-            && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
-        BIO_printf(bio_err, "Out of memory loading");
-        goto end;
-    } else {
+    if (pcrls != NULL) {
+        if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
+            BIO_printf(bio_err, "Out of memory loading");
+            goto end;
+        }
         cnt_expectations++;
         expect = OSSL_STORE_INFO_CRL;
     }
@@ -787,8 +787,21 @@ int load_key_certs_crls(const char *uri, int maybe_stdin,
         OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
         int type, ok = 1;
 
-        if (info == NULL)
-            break;
+        /*
+         * This can happen (for example) if we attempt to load a file with
+         * multiple different types of things in it - but the thing we just
+         * tried to load wasn't one of the ones we wanted, e.g. if we're trying
+         * to load a certificate but the file has both the private key and the
+         * 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;
+        }
+
         type = OSSL_STORE_INFO_get_type(info);
         switch (type) {
         case OSSL_STORE_INFO_PKEY:
diff --git a/crypto/store/store_result.c b/crypto/store/store_result.c
index b79126e1cb..64b0e814b3 100644
--- a/crypto/store/store_result.c
+++ b/crypto/store/store_result.c
@@ -62,6 +62,7 @@
 struct extracted_param_data_st {
     int object_type;
     const char *data_type;
+    const char *data_structure;
     const char *utf8_data;
     const void *octet_data;
     size_t octet_data_size;
@@ -128,6 +129,10 @@ int ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg)
                                             &helper_data.octet_data_size)
         && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.utf8_data))
         return 0;
+    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
+    if (p != NULL
+        && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure))
+        return 0;
     p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE);
     if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref,
                                                       &helper_data.ref_size))
@@ -274,8 +279,9 @@ static EVP_PKEY *try_key_value(struct extracted_param_data_st *data,
     }
 
     decoderctx =
-        OSSL_DECODER_CTX_new_for_pkey(&pk, "DER", NULL, data->data_type,
-                                      selection, libctx, propq);
+        OSSL_DECODER_CTX_new_for_pkey(&pk, "DER", data->data_structure,
+                                      data->data_type, selection, libctx,
+                                      propq);
     (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg);
 
     /* No error if this couldn't be decoded */
diff --git a/providers/implementations/encode_decode/decode_pem2der.c b/providers/implementations/encode_decode/decode_pem2der.c
index 73973e13ff..895015a56b 100644
--- a/providers/implementations/encode_decode/decode_pem2der.c
+++ b/providers/implementations/encode_decode/decode_pem2der.c
@@ -17,6 +17,7 @@
 
 #include <openssl/core_dispatch.h>
 #include <openssl/core_names.h>
+#include <openssl/core_object.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/params.h>
@@ -114,20 +115,23 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                           OSSL_CALLBACK *data_cb, void *data_cbarg,
                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
 {
-    /* Strings to peal off the pem name */
-    static const char *pealable_pem_name_endings[] = {
+    /* Strings to peel off the pem name */
+    static struct peelablee_pem_name_endings_st {
+        const char *ending;
+        const char *data_structure;
+    } peelable_pem_name_endings[] = {
         /*
          * These entries should be in longest to shortest order to avoid
          * mixups.
          */
-        "ENCRYPTED PRIVATE KEY",
-        "PRIVATE KEY",
-        "PUBLIC KEY",
-        "PARAMETERS"
+        { "ENCRYPTED PRIVATE KEY", "pkcs8" },
+        { "PRIVATE KEY", "pkcs8" },
+        { "PUBLIC KEY", "SubjectPublicKeyInfo" },
+        { "PARAMETERS", NULL }
 
         /*
          * Libcrypto currently only supports decoding keys with provider side
-         * decoders, so we don't try to peal any other PEM name.  That's an
+         * decoders, so we don't try to peel any other PEM name.  That's an
          * exercise for when libcrypto starts to treat other types of objects
          * via providers.
          */
@@ -138,6 +142,8 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
     unsigned char *der = NULL;
     long der_len = 0;
     int ok = 0;
+    int objtype = OSSL_OBJECT_UNKNOWN;
+    const char *data_structure = NULL;
 
     if (read_pem(ctx->provctx, cin, &pem_name, &pem_header,
                  &der, &der_len) <= 0)
@@ -166,15 +172,15 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
      * no further purpose.
      */
     for (i = 0, pem_name_len = strlen(pem_name);
-         i < OSSL_NELEM(pealable_pem_name_endings);
+         i < OSSL_NELEM(peelable_pem_name_endings);
          i++) {
-        size_t peal_len = strlen(pealable_pem_name_endings[i]);
+        size_t peel_len = strlen(peelable_pem_name_endings[i].ending);
         size_t pem_name_offset;
 
-        if (peal_len <= pem_name_len) {
-            pem_name_offset = pem_name_len - peal_len;
+        if (peel_len <= pem_name_len) {
+            pem_name_offset = pem_name_len - peel_len;
             if (strcmp(pem_name + pem_name_offset,
-                       pealable_pem_name_endings[i]) == 0) {
+                       peelable_pem_name_endings[i].ending) == 0) {
 
                 do {
                     pem_name[pem_name_offset] = '\0';
@@ -185,21 +191,53 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                     OPENSSL_free(pem_name);
                     pem_name = NULL;
                 }
+                /* All of these peelable endings are for EVP_PKEYs */
+                objtype = OSSL_OBJECT_PKEY;
+                if (pem_name == NULL) {
+                    data_structure = peelable_pem_name_endings[i].data_structure;
+                    if (data_structure == NULL)
+                        goto end;
+                } else {
+                    /*
+                     * If there is an algorithm name prefix then it is a
+                     * type-specific data structure
+                     */
+                    data_structure = "type-specific";
+                }
                 break;
             }
         }
     }
 
+    /* If we don't know the object type yet check if it's one we know about */
+    if (objtype == OSSL_OBJECT_UNKNOWN) {
+        if (strcmp(pem_name, PEM_STRING_X509) == 0
+                || strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0
+                || strcmp(pem_name, PEM_STRING_X509_OLD) == 0)
+            objtype = OSSL_OBJECT_CERT;
+        else if (strcmp(pem_name, PEM_STRING_X509_CRL) == 0)
+            objtype = OSSL_OBJECT_CRL;
+    }
+
     {
-        OSSL_PARAM params[3], *p = params;
+        OSSL_PARAM params[5], *p = params;
 
         if (pem_name != NULL)
             *p++ =
                 OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
                                                  pem_name, 0);
+
+        /* We expect this to be read only so casting away the const is ok */
+        if (data_structure != NULL)
+            *p++ =
+                OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
+                                                 (char *)data_structure, 0);
         *p++ =
             OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
                                               der, der_len);
+        *p++ =
+            OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
+
         *p = OSSL_PARAM_construct_end();
 
         ok = data_cb(params, data_cbarg);
diff --git a/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t
index 364c9d2bde..591b497027 100644
--- a/test/recipes/20-test_cli_fips.t
+++ b/test/recipes/20-test_cli_fips.t
@@ -64,11 +64,27 @@ ok(run(app(['openssl', 'list', '-asymcipher-algorithms', '-verbose'])),
 ok(run(app(['openssl', 'list', '-key-managers', '-verbose', '-select', 'DSA' ])),
    "provider listing of one item in the keymanager");
 
+sub pubfrompriv {
+    my $prefix = shift;
+    my $key = shift;
+    my $pub_key = shift;
+    my $type = shift;
+
+    ok(run(app(['openssl', 'pkey',
+                '-in', $key,
+                '-pubout',
+                '-out', $pub_key])),
+        $prefix.': '."Create the public key with $type parameters");
+
+}
+
 my $tsignverify_count = 8;
 sub tsignverify {
     my $prefix = shift;
     my $fips_key = shift;
+    my $fips_pub_key = shift;
     my $nonfips_key = shift;
+    my $nonfips_pub_key = shift;
     my $fips_sigfile = $prefix.'.fips.sig';
     my $nonfips_sigfile = $prefix.'.nonfips.sig';
     my $sigfile = '';
@@ -88,7 +104,7 @@ sub tsignverify {
     $testtext = $prefix.': '.
         'Verify something with a FIPS key';
     ok(run(app(['openssl', 'dgst', '-sha256',
-                '-verify', $fips_key,
+                '-verify', $fips_pub_key,
                 '-signature', $sigfile,
                 $tbs_data])),
        $testtext);
@@ -97,7 +113,7 @@ sub tsignverify {
         'Verify a valid signature against the wrong data with a FIPS key'.
         ' (should fail)';
     ok(!run(app(['openssl', 'dgst', '-sha256',
-                 '-verify', $fips_key,
+                 '-verify', $fips_pub_key,
                  '-signature', $sigfile,
                  $bogus_data])),
        $testtext);
@@ -118,7 +134,7 @@ sub tsignverify {
         'Verify something with a non-FIPS key'.
         ' with the default provider';
     ok(run(app(['openssl', 'dgst', '-sha256',
-                '-verify', $nonfips_key,
+                '-verify', $nonfips_pub_key,
                 '-signature', $sigfile,
                 $tbs_data])),
        $testtext);
@@ -138,7 +154,7 @@ sub tsignverify {
         'Verify something with a non-FIPS key'.
         ' (should fail)';
     ok(!run(app(['openssl', 'dgst', '-sha256',
-                 '-verify', $nonfips_key,
+                 '-verify', $nonfips_pub_key,
                  '-signature', $sigfile,
                  $tbs_data])),
        $testtext);
@@ -147,7 +163,7 @@ sub tsignverify {
         'Verify a valid signature against the wrong data with a non-FIPS key'.
         ' (should fail)';
     ok(!run(app(['openssl', 'dgst', '-sha256',
-                 '-verify', $nonfips_key,
+                 '-verify', $nonfips_pub_key,
                  '-signature', $sigfile,
                  $bogus_data])),
        $testtext);
@@ -161,12 +177,14 @@ SKIP : {
         my $testtext_prefix = 'EC';
         my $a_fips_curve = 'prime256v1';
         my $fips_key = $testtext_prefix.'.fips.priv.pem';
+        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
         my $a_nonfips_curve = 'brainpoolP256r1';
         my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
+        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
         my $testtext = '';
         my $curvename = '';
 
-        plan tests => 3 + $tsignverify_count;
+        plan tests => 5 + $tsignverify_count;
 
         $ENV{OPENSSL_CONF} = $defaultconf;
         $curvename = $a_nonfips_curve;
@@ -177,6 +195,8 @@ SKIP : {
                     '-out', $nonfips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
+
         $ENV{OPENSSL_CONF} = $fipsconf;
 
         $curvename = $a_fips_curve;
@@ -187,6 +207,8 @@ SKIP : {
                     '-out', $fips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
+
         $curvename = $a_nonfips_curve;
         $testtext = $testtext_prefix.': '.
             'Generate a key with a non-FIPS algorithm'.
@@ -196,7 +218,8 @@ SKIP : {
                      '-out', $testtext_prefix.'.'.$curvename.'.priv.pem'])),
            $testtext);
 
-        tsignverify($testtext_prefix, $fips_key, $nonfips_key);
+        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, $nonfips_key,
+                    $nonfips_pub_key);
     };
 }
 
@@ -207,10 +230,12 @@ SKIP: {
     subtest RSA => sub {
         my $testtext_prefix = 'RSA';
         my $fips_key = $testtext_prefix.'.fips.priv.pem';
+        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
         my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
+        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
         my $testtext = '';
 
-        plan tests => 3 + $tsignverify_count;
+        plan tests => 5 + $tsignverify_count;
 
         $ENV{OPENSSL_CONF} = $defaultconf;
         $testtext = $testtext_prefix.': '.
@@ -220,6 +245,8 @@ SKIP: {
                     '-out', $nonfips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
+
         $ENV{OPENSSL_CONF} = $fipsconf;
 
         $testtext = $testtext_prefix.': '.
@@ -229,6 +256,8 @@ SKIP: {
                     '-out', $fips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
+
         $testtext = $testtext_prefix.': '.
             'Generate a key with a non-FIPS algorithm'.
             ' (should fail)';
@@ -237,7 +266,8 @@ SKIP: {
                      '-out', $testtext_prefix.'.fail.priv.pem'])),
            $testtext);
 
-        tsignverify($testtext_prefix, $fips_key, $nonfips_key);
+        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, $nonfips_key,
+                    $nonfips_pub_key);
     };
 }
 
@@ -248,12 +278,14 @@ SKIP : {
     subtest DSA => sub {
         my $testtext_prefix = 'DSA';
         my $fips_key = $testtext_prefix.'.fips.priv.pem';
+        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
         my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
+        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
         my $testtext = '';
         my $fips_param = $testtext_prefix.'.fips.param.pem';
         my $nonfips_param = $testtext_prefix.'.nonfips.param.pem';
 
-        plan tests => 6 + $tsignverify_count;
+        plan tests => 8 + $tsignverify_count;
 
         $ENV{OPENSSL_CONF} = $defaultconf;
 
@@ -295,6 +327,8 @@ SKIP : {
                     '-out', $nonfips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
+
         $ENV{OPENSSL_CONF} = $fipsconf;
 
         $testtext = $testtext_prefix.': '.
@@ -305,6 +339,8 @@ SKIP : {
                     '-out', $fips_key])),
            $testtext);
 
+        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
+
         $testtext = $testtext_prefix.': '.
             'Generate a key with non-FIPS parameters'.
             ' (should fail)';
@@ -314,6 +350,7 @@ SKIP : {
                      '-out', $testtext_prefix.'.fail.priv.pem'])),
            $testtext);
 
-        tsignverify($testtext_prefix, $fips_key, $nonfips_key);
+        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, $nonfips_key,
+                    $nonfips_pub_key);
     };
 }


More information about the openssl-commits mailing list