Added 'saltlen' option to the OpenSSL enc command line app.

This allows PBKDF2 to change the saltlen to something other than the
new default value of 16. Previously this app hardwired the salt length
to a maximum of 8 bytes. Non PBKDF2 mode uses EVP_BytesToKey()
internally, which is documented to only allow 8 bytes.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21858)
This commit is contained in:
slontis 2023-08-31 17:51:46 +10:00 committed by Pauli
parent 9f679bdc71
commit e3994583a1
5 changed files with 58 additions and 12 deletions

View File

@ -32,6 +32,9 @@ OpenSSL 3.2
requires a salt length of 128 bits. This affects OpenSSL command line
applications such as "genrsa" and "pkcs8" and API's such as
PEM_write_bio_PrivateKey() that are reliant on the default value.
The additional commandline option 'saltlen' has been added to the
OpenSSL command line applications for "pkcs8" and "enc" to allow the
salt length to be set to a non default value.
*Shane Lontis*

View File

@ -49,7 +49,7 @@ typedef enum OPTION_choice {
OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
OPT_R_ENUM, OPT_PROV_ENUM
OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
@ -100,6 +100,8 @@ const OPTIONS enc_options[] = {
{OPT_MORE_STR, 0, 0,
"Use -iter to change the iteration count from " STR(PBKDF2_ITER_DEFAULT)},
{"none", OPT_NONE, '-', "Don't encrypt"},
{"saltlen", OPT_SALTLEN, 'p', "Specify the PBKDF2 salt length (in bytes)"},
{OPT_MORE_STR, 0, 0, "Default: 16"},
#ifndef OPENSSL_NO_ZLIB
{"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"},
#endif
@ -132,7 +134,8 @@ int enc_main(int argc, char **argv)
int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY;
int ret = 1, inl, nopad = 0;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
unsigned char *buff = NULL, salt[EVP_MAX_IV_LENGTH];
int saltlen = 0;
int pbkdf2 = 0;
int iter = 0;
long n;
@ -293,6 +296,12 @@ int enc_main(int argc, char **argv)
iter = opt_int_arg();
pbkdf2 = 1;
break;
case OPT_SALTLEN:
if (!opt_int(opt_arg(), &saltlen))
goto opthelp;
if (saltlen > (int)sizeof(salt))
saltlen = (int)sizeof(salt);
break;
case OPT_PBKDF2:
pbkdf2 = 1;
if (iter == 0) /* do not overwrite a chosen value */
@ -317,6 +326,8 @@ int enc_main(int argc, char **argv)
goto opthelp;
if (!app_RAND_load())
goto end;
if (saltlen == 0 || pbkdf2 == 0)
saltlen = PKCS5_SALT_LEN;
/* Get the cipher name, either from progname (if set) or flag. */
if (!opt_cipher(ciphername, &cipher))
@ -496,13 +507,13 @@ int enc_main(int argc, char **argv)
if (nosalt) {
sptr = NULL;
} else {
if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) {
if (hsalt != NULL && !set_hex(hsalt, salt, saltlen)) {
BIO_printf(bio_err, "invalid hex salt value\n");
goto end;
}
if (enc) { /* encryption */
if (hsalt == NULL) {
if (RAND_bytes(salt, sizeof(salt)) <= 0) {
if (RAND_bytes(salt, saltlen) <= 0) {
BIO_printf(bio_err, "RAND_bytes failed\n");
goto end;
}
@ -515,7 +526,7 @@ int enc_main(int argc, char **argv)
sizeof(magic) - 1) != sizeof(magic) - 1
|| BIO_write(wbio,
(char *)salt,
sizeof(salt)) != sizeof(salt))) {
saltlen) != saltlen)) {
BIO_printf(bio_err, "error writing output file\n");
goto end;
}
@ -528,7 +539,7 @@ int enc_main(int argc, char **argv)
}
if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */
if (BIO_read(rbio, salt,
sizeof(salt)) != sizeof(salt)) {
saltlen) != saltlen) {
BIO_printf(bio_err, "error reading input file\n");
goto end;
}
@ -550,7 +561,8 @@ int enc_main(int argc, char **argv)
int iklen = EVP_CIPHER_get_key_length(cipher);
int ivlen = EVP_CIPHER_get_iv_length(cipher);
/* not needed if HASH_UPDATE() is fixed : */
int islen = (sptr != NULL ? sizeof(salt) : 0);
int islen = (sptr != NULL ? saltlen : 0);
if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen,
iter, dgst, iklen+ivlen, tmpkeyiv)) {
BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n");
@ -646,7 +658,7 @@ int enc_main(int argc, char **argv)
if (printkey) {
if (!nosalt) {
printf("salt=");
for (i = 0; i < (int)sizeof(salt); i++)
for (i = 0; i < (int)saltlen; i++)
printf("%02X", salt[i]);
printf("\n");
}

View File

@ -31,6 +31,7 @@ B<openssl> B<enc>|I<cipher>
[B<-md> I<digest>]
[B<-iter> I<count>]
[B<-pbkdf2>]
[B<-saltlen> I<size>]
[B<-p>]
[B<-P>]
[B<-bufsize> I<number>]
@ -132,6 +133,15 @@ This option enables the use of PBKDF2 algorithm to derive the key.
Use PBKDF2 algorithm with a default iteration count of 10000
unless otherwise specified by the B<-iter> command line option.
=item B<-saltlen>
Set the salt length to use when using the B<-pbkdf2> option.
For compatibility reasons, the default is 8 bytes.
The maximum value is currently 16 bytes.
If the B<-pbkdf2> option is not used, then this option is ignored
and a fixed salt length of 8 is used. The salt length used when
encrypting must also be used when decrypting.
=item B<-nosalt>
Don't use a salt in the key derivation routines. This option B<SHOULD NOT> be
@ -147,7 +157,8 @@ encrypting, this is the default.
The actual salt to use: this must be represented as a string of hex digits.
If this option is used while encrypting, the same exact value will be needed
again during decryption.
again during decryption. This salt may be truncated or zero padded to
match the salt length (See B<-saltlen>).
=item B<-K> I<key>
@ -465,9 +476,11 @@ The B<-list> option was added in OpenSSL 1.1.1e.
The B<-ciphers> and B<-engine> options were deprecated in OpenSSL 3.0.
The B<-saltlen> option was added in OpenSSL 3.2.
=head1 COPYRIGHT
Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2000-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

View File

@ -41,7 +41,7 @@ my @ciphers =
|rc2|rc4|seed)/x} @ciphers
if disabled("legacy");
plan tests => 2 + (scalar @ciphers)*2;
plan tests => 5 + (scalar @ciphers)*2;
SKIP: {
skip "Problems getting ciphers...", 1 + scalar(@ciphers)
@ -72,4 +72,22 @@ plan tests => 2 + (scalar @ciphers)*2;
&& compare_text($test,$clearfile) == 0, $t);
}
}
ok(run(app([$cmd, "enc", "-in", $test, "-aes256", "-pbkdf2", "-out",
"salted_default.cipher", "-pass", "pass:password"]))
&& run(app([$cmd, "enc", "-d", "-in", "salted_default.cipher", "-aes256", "-pbkdf2",
"-saltlen", "8", "-out", "salted_default.clear", "-pass", "pass:password"]))
&& compare_text($test,"salted_default.clear") == 0,
"Check that the default salt length of 8 bytes is used for PKDF2");
ok(!run(app([$cmd, "enc", "-d", "-in", "salted_default.cipher", "-aes256", "-pbkdf2",
"-saltlen", "16", "-out", "salted_fail.clear", "-pass", "pass:password"])),
"Check the decrypt fails if the saltlen is incorrect");
ok(run(app([$cmd, "enc", "-in", $test, "-aes256", "-pbkdf2", "-saltlen", "16",
"-out", "salted.cipher", "-pass", "pass:password"]))
&& run(app([$cmd, "enc", "-d", "-in", "salted.cipher", "-aes256", "-pbkdf2",
"-saltlen", "16", "-out", "salted.clear", "-pass", "pass:password"]))
&& compare_text($test,"salted.clear") == 0,
"Check that we can still use a salt length of 16 bytes for PKDF2");
}

View File

@ -81,7 +81,7 @@ 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",