]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
APPS/pkcs8: fix case where infile and outfile are the same
authorDr. David von Oheimb <dev@ddvo.net>
Fri, 27 Sep 2024 05:58:33 +0000 (07:58 +0200)
committerTomas Mraz <tomas@openssl.org>
Fri, 4 Oct 2024 10:09:33 +0000 (12:09 +0200)
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25552)

apps/pkcs8.c
doc/man1/openssl-pkcs8.pod.in
test/recipes/25-test_pkcs8.t

index 7b5e79966bacc04e917739b3a2c352e5220b4b21..22978afb9093e4e9d3a2c4569457d8c0ac041d64 100644 (file)
@@ -227,9 +227,6 @@ int pkcs8_main(int argc, char **argv)
                           informat == FORMAT_UNDEF ? FORMAT_PEM : informat);
     if (in == NULL)
         goto end;
-    out = bio_open_owner(outfile, outformat, private);
-    if (out == NULL)
-        goto end;
 
     if (topk8) {
         pkey = load_key(infile, informat, 1, passin, e, "key");
@@ -240,6 +237,8 @@ int pkcs8_main(int argc, char **argv)
             ERR_print_errors(bio_err);
             goto end;
         }
+        if ((out = bio_open_owner(outfile, outformat, private)) == NULL)
+            goto end;
         if (nocrypt) {
             assert(private);
             if (outformat == FORMAT_PEM) {
@@ -361,6 +360,9 @@ int pkcs8_main(int argc, char **argv)
     }
 
     assert(private);
+    out = bio_open_owner(outfile, outformat, private);
+    if (out == NULL)
+        goto end;
     if (outformat == FORMAT_PEM) {
         if (traditional)
             PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0,
index 08c3272a70afc8ff0fa8ed2a3032277d9633e38a..db089d6777d76420a1c989a635c3f93bc45575c7 100644 (file)
@@ -79,9 +79,9 @@ key is written.
 
 =item B<-in> I<filename>
 
-This specifies the input filename to read a key from or standard input if this
+This specifies the input file to read a key from or standard input if this
 option is not specified. If the key is encrypted a pass phrase will be
-prompted for.
+prompted for unless B<-passin> is given.
 
 =item B<-passin> I<arg>, B<-passout> I<arg>
 
@@ -91,10 +91,14 @@ see L<openssl-passphrase-options(1)>.
 
 =item B<-out> I<filename>
 
-This specifies the output filename to write a key to or standard output by
-default. If any encryption options are set then a pass phrase will be
-prompted for. The output filename should B<not> be the same as the input
-filename.
+This specifies the output file to write a key to or standard output by default.
+The output filename can be the same as the input filename,
+which leads to replacing the file contents.
+Note that file I/O is not atomic. The output file is truncated and then written.
+
+If any encryption options are set and B<-passout> is not given
+then a pass phrase will be prompted for.
+When password input is interrupted, the output file is not touched.
 
 =item B<-iter> I<count>
 
index 93cb7629bf9c234b5693b10c2c1a4dc62cfb5a23..a0f8644744827e87185f9be37dcff36fb4dade2a 100644 (file)
@@ -10,15 +10,29 @@ use strict;
 use warnings;
 
 use OpenSSL::Test::Utils;
-use File::Compare qw(compare_text);
+use File::Copy;
+use File::Compare qw(compare_text compare);
 use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips is_nofips/;
 
 setup("test_pkcs8");
 
-plan tests => 15;
+plan tests => 18;
+
+my $pc5_key = srctop_file('test', 'certs', 'pc5-key.pem');
+
+my $inout = 'inout.pem';
+copy($pc5_key, $inout);
+ok(run(app(['openssl', 'pkcs8', '-topk8', '-in', $inout,
+            '-out', $inout, '-passout', 'pass:password'])),
+   "identical infile and outfile, to PKCS#8");
+ok(run(app(['openssl', 'pkcs8', '-in', $inout,
+            '-out', $inout, '-passin', 'pass:password'])),
+   "identical infile and outfile, from PKCS#8");
+is(compare($pc5_key, $inout), 0,
+   "Same file contents after converting forth and back");
 
 ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-              '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+              '-in', $pc5_key,
               '-out', 'pbkdf2_default_saltlen.pem',
               '-passout', 'pass:password']))),
    "Convert a private key to PKCS5 v2.0 format using PBKDF2 with the default saltlen");
@@ -35,7 +49,7 @@ SKIP: {
         if disabled("scrypt");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-                  '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+                  '-in', $pc5_key,
                   '-scrypt',
                   '-out', 'scrypt_default_saltlen.pem',
                   '-passout', 'pass:password']))),
@@ -49,7 +63,7 @@ SKIP: {
        "Check the default size of the SCRYPT PARAM 'salt length' = 16");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-                  '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+                  '-in', $pc5_key,
                   '-scrypt',
                   '-saltlen', '8',
                   '-out', 'scrypt_64bit_saltlen.pem',
@@ -69,7 +83,7 @@ SKIP: {
         if disabled('legacy') || disabled("des");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-                  '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+                  '-in', $pc5_key,
                   '-v1', "PBE-MD5-DES",
                   '-provider', 'legacy',
                   '-provider', 'default',
@@ -83,7 +97,7 @@ SKIP: {
        "Check the default size of the PBE PARAM 'salt length' = 8");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-                  '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+                  '-in', $pc5_key,
                   '-v1', "PBE-MD5-DES",
                   '-saltlen', '16',
                   '-provider', 'legacy',
@@ -100,7 +114,7 @@ SKIP: {
 
 
 ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
-              '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+              '-in', $pc5_key,
               '-saltlen', '8',
               '-out', 'pbkdf2_64bit_saltlen.pem',
               '-passout', 'pass:password']))),