Skip to content

Commit

Permalink
Fix EVP_PKEY_print_private() so that it works with non default provid…
Browse files Browse the repository at this point in the history
…ers.

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 <[email protected]>
Reviewed-by: Tomas Mraz <[email protected]>
(Merged from openssl#26004)

(cherry picked from commit 79c98fc)
  • Loading branch information
slontis authored and t8m committed Nov 29, 2024
1 parent 6f667f4 commit a9c16d4
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
6 changes: 5 additions & 1 deletion crypto/encode_decode/encoder_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
27 changes: 26 additions & 1 deletion test/recipes/04-test_encoder_decoder.t
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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');
}

0 comments on commit a9c16d4

Please sign in to comment.