]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix EVP_PKEY_print_private() so that it works with non default providers.
authorslontis <shane.lontis@oracle.com>
Wed, 20 Nov 2024 01:39:35 +0000 (12:39 +1100)
committerTomas Mraz <tomas@openssl.org>
Fri, 29 Nov 2024 16:15:19 +0000 (17:15 +0100)
At some point in time it was decided that the EC keymanagers ec_export()
function would only allow the selection to be both the public + private
parts. If just the private element is selected it returns an error.
Many openssl commandline apps use EVP_PKEY_print_private() which passes
EVP_PKEY_PRIVATE_KEY to the encoder. This selection propagates to
encoder_construct_pkey(). For external providers (such as the fips
provider this will call the keymanagers export() with the selection set
to just the private part.

So we either need to
1) change the selection in EVP_PKEY_print_private() or
2) modify the selection used in the export used in
   encoder_construct_pkey
3) Change the ec_export to allow this.

I have chosen 2) but I am not sure if this is the correct thing to do
or whether it should conditionally do this when the output_type ==
'text'.

Issue was reported by Ilia Okomin (Oracle).

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26004)

(cherry picked from commit 79c98fc6ccab49f02528e06cc046ac61f841a753)

crypto/encode_decode/encoder_pkey.c
test/recipes/04-test_encoder_decoder.t

index 7b9584953d9727ccb03045394e07840af1d2add4..af18bcd38529c8a87a2bf6f85082fa23b456a984 100644 (file)
@@ -189,9 +189,13 @@ encoder_construct_pkey(OSSL_ENCODER_INSTANCE *encoder_inst, void *arg)
         const OSSL_PROVIDER *e_prov = OSSL_ENCODER_get0_provider(encoder);
 
         if (k_prov != e_prov) {
+            int selection = data->selection;
+
+            if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+                selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
             data->encoder_inst = encoder_inst;
 
-            if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, data->selection,
+            if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, selection,
                                     &encoder_import_cb, data))
                 return NULL;
             data->obj = data->constructed_obj;
index 19541610a9a9b97184228146d4371816581c58df..3587ed84700df1065f1af367b292630c4d7c35df 100644 (file)
@@ -25,9 +25,26 @@ my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
 my $rsa_key = srctop_file("test", "certs", "ee-key.pem");
 my $pss_key = srctop_file("test", "certs", "ca-pss-key.pem");
 
-plan tests => ($no_fips ? 0 : 1) + 2;     # FIPS install test + test
+plan tests => ($no_fips ? 0 : 3) + 2;     # FIPS install test + test
 
 my $conf = srctop_file("test", "default.cnf");
+
+# Check if the specified pattern occurs in the given file
+# Returns 1 if the pattern is found and 0 if not
+sub find_line_file {
+    my ($key, $file) = @_;
+
+    open(my $in, $file) or return -1;
+    while (my $line = <$in>) {
+        if ($line =~ /$key/) {
+            close($in);
+            return 1;
+        }
+    }
+    close($in);
+    return 0;
+}
+
 ok(run(test(["endecode_test", "-rsa", $rsa_key,
                               "-pss", $pss_key,
                               "-config", $conf,
@@ -47,5 +64,13 @@ unless ($no_fips) {
                                   "-pss", $pss_key,
                                   "-config", $conf,
                                   "-provider", "fips"])));
+SKIP: {
+    skip "EC disabled", 2 if disabled("ec");
+    ok(run(app([ 'openssl', 'genpkey', '-algorithm', 'EC',
+                 '-pkeyopt', 'group:P-256', '-text',
+                 '-config', $conf, '-provider', 'fips', '-out', 'ec.txt' ])),
+       'Print a FIPS provider EC private key');
+    ok(find_line_file('NIST CURVE: P-256', 'ec.txt') == 1,
+       'Printing an FIPS provider EC private key');
 }