]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Added a 'saltlen' option to the openssl pkcs8 command line app.
authorslontis <shane.lontis@oracle.com>
Thu, 31 Aug 2023 07:49:55 +0000 (17:49 +1000)
committerPauli <pauli@openssl.org>
Mon, 4 Sep 2023 04:15:34 +0000 (14:15 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21858)

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

index e3932245f39db33292dd0745aac923fec391bea5..7b5e79966bacc04e917739b3a2c352e5220b4b21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -17,6 +17,9 @@
 #include <openssl/evp.h>
 #include <openssl/pkcs12.h>
 
+#define STR(a) XSTR(a)
+#define XSTR(a) #a
+
 typedef enum OPTION_choice {
     OPT_COMMON,
     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
@@ -26,6 +29,7 @@ typedef enum OPTION_choice {
 #endif
     OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
     OPT_TRADITIONAL,
+    OPT_SALTLEN,
     OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
@@ -53,7 +57,8 @@ const OPTIONS pkcs8_options[] = {
     {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"},
     {"iter", OPT_ITER, 'p', "Specify the iteration count"},
     {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
-
+    {"saltlen", OPT_SALTLEN, 'p', "Specify the salt length (in bytes)"},
+    {OPT_MORE_STR, 0, 0, "Default: 8 (For PBE1) or 16 (for PBE2)"},
 #ifndef OPENSSL_NO_SCRYPT
     OPT_SECTION("Scrypt"),
     {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"},
@@ -88,6 +93,7 @@ int pkcs8_main(int argc, char **argv)
 #ifndef OPENSSL_NO_SCRYPT
     long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
 #endif
+    int saltlen = 0; /* A value of zero chooses the default */
 
     prog = opt_init(argc, argv, pkcs8_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -189,6 +195,10 @@ int pkcs8_main(int argc, char **argv)
                 goto opthelp;
             break;
 #endif
+        case OPT_SALTLEN:
+            if (!opt_int(opt_arg(), &saltlen))
+                goto opthelp;
+            break;
         }
     }
 
@@ -245,14 +255,14 @@ int pkcs8_main(int argc, char **argv)
             if (cipher) {
 #ifndef OPENSSL_NO_SCRYPT
                 if (scrypt_N && scrypt_r && scrypt_p)
-                    pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL,
+                    pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, saltlen, NULL,
                                                 scrypt_N, scrypt_r, scrypt_p);
                 else
 #endif
-                    pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL,
+                    pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, saltlen, NULL,
                                             pbe_nid);
             } else {
-                pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0);
+                pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, saltlen);
             }
             if (pbe == NULL) {
                 BIO_printf(bio_err, "Error setting PBE algorithm\n");
index 2af61203e9a75f7f03e90cd842202ac4709af55d..bf87c590c79b7b672b6ad104a85c730a1a767678 100644 (file)
@@ -27,6 +27,7 @@ B<openssl> B<pkcs8>
 [B<-scrypt_N> I<N>]
 [B<-scrypt_r> I<r>]
 [B<-scrypt_p> I<p>]
+[B<-saltlen> I<size>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
 
@@ -148,6 +149,12 @@ B<-scrypt_p> and B<-v2> options.
 
 Sets the scrypt I<N>, I<r> or I<p> parameters.
 
+=item B<-saltlen>
+
+Sets the length (in bytes) of the salt to use for the PBE algorithm.
+If this value is not specified, the default for PBES2 is 16 (128 bits)
+and 8 (64 bits) for PBES1.
+
 {- $OpenSSL::safe::opt_r_item -}
 
 {- $OpenSSL::safe::opt_engine_item -}
index 7a06be19e4e59c1cc955ebfb25acd95c434ba00e..2f7ea1e1ae0c2ffa425726203cc3033d5aa97acf 100644 (file)
@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips is_nofips/;
 
 setup("test_pkcs8");
 
-plan tests => 9;
+plan tests => 15;
 
 ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
               '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
@@ -31,7 +31,7 @@ ok(run(app(([ 'openssl', 'asn1parse',
    "Check the default size of the PBKDF2 PARAM 'salt length' is 16");
 
 SKIP: {
-    skip "scrypt is not supported by this OpenSSL build", 2
+    skip "scrypt is not supported by this OpenSSL build", 4
         if disabled("scrypt");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
@@ -47,10 +47,25 @@ SKIP: {
                   '-in', 'scrypt_default_saltlen.pem',
                   '-offset', '34', '-length', '18']))),
        "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'),
+                  '-scrypt',
+                  '-saltlen', '8',
+                  '-out', 'scrypt_64bit_saltlen.pem',
+                  '-passout', 'pass:password']))),
+       "Convert a private key to PKCS5 v2.0 format using scrypt with a salt length of 8 bytes");
+
+# We expect the output to be of the form "0:d=0  hl=2 l=   8 prim: OCTET STRING      [HEX DUMP]:3C1147976A2B61CA"
+# i.e. 2 byte header + 8 byte salt.
+    ok(run(app(([ 'openssl', 'asn1parse',
+                  '-in', 'scrypt_64bit_saltlen.pem',
+                  '-offset', '34', '-length', '10']))),
+       "Check the size of the SCRYPT PARAM 'salt length' is 8");
 }
 
 SKIP: {
-    skip "legacy provider is not supported by this OpenSSL build", 2
+    skip "legacy provider is not supported by this OpenSSL build", 4
         if disabled('legacy') || disabled("des");
 
     ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
@@ -66,8 +81,39 @@ SKIP: {
                   '-in', 'pbe1.pem',
                   '-offset', '19', '-length', '10']))),
        "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'),
+                  '-v1', "PBE-MD5-DES",
+                  '-saltlen', '16',
+                  '-provider', 'legacy',
+                  '-provider', 'default',
+                  '-out', 'pbe1_128bitsalt.pem',
+                  '-passout', 'pass:password']))),
+       "Convert a private key to PKCS5 v1.5 format using pbeWithMD5AndDES-CBC with the 16 byte saltlen");
+
+    ok(run(app(([ 'openssl', 'asn1parse',
+                  '-in', 'pbe1_128bitsalt.pem',
+                  '-offset', '19', '-length', '18']))),
+       "Check the size of the PBE PARAM 'salt length' = 16");
 };
 
+
+ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
+              '-in', srctop_file('test', 'certs', 'pc5-key.pem'),
+              '-saltlen', '8',
+              '-out', 'pbkdf2_64bit_saltlen.pem',
+              '-passout', 'pass:password']))),
+   "Convert a private key to PKCS5 v2.0 format using pbkdf2 with a salt length of 8 bytes");
+
+# We expect the output to be of the form "0:d=0  hl=2 l=   8 prim: OCTET STRING      [HEX DUMP]:3C1147976A2B61CA"
+# i.e. 2 byte header + 8 byte salt.
+ok(run(app(([ 'openssl', 'asn1parse',
+              '-in', 'pbkdf2_64bit_saltlen.pem',
+              '-offset', '34', '-length', '10']))),
+   "Check the size of the PBKDF2 PARAM 'salt length' is 8");
+
+
 SKIP: {
     skip "SM2, SM3 or SM4 is not supported by this OpenSSL build", 3
         if disabled("sm2") || disabled("sm3") || disabled("sm4");