mirror of https://github.com/openssl/openssl.git
Change PBES2 KDF default salt length to 16 bytes.
The PKCS5 (RFC 8018) standard uses a 64 bit salt length for PBE, and recommends a minimum of 64 bits for PBES2. For FIPS compliance PBKDF2 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 salt length. 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:
parent
61cfc22b60
commit
3859a02725
10
CHANGES.md
10
CHANGES.md
|
@ -25,6 +25,16 @@ OpenSSL 3.2
|
||||||
|
|
||||||
### Changes between 3.1 and 3.2 [xx XXX xxxx]
|
### Changes between 3.1 and 3.2 [xx XXX xxxx]
|
||||||
|
|
||||||
|
* Changed the default salt length used by PBES2 KDF's (PBKDF2 and scrypt)
|
||||||
|
from 8 bytes to 16 bytes.
|
||||||
|
The PKCS5 (RFC 8018) standard uses a 64 bit salt length for PBE, and
|
||||||
|
recommends a minimum of 64 bits for PBES2. For FIPS compliance PBKDF2
|
||||||
|
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.
|
||||||
|
|
||||||
|
*Shane Lontis*
|
||||||
|
|
||||||
* Changed the default value of the `ess_cert_id_alg` configuration
|
* Changed the default value of the `ess_cert_id_alg` configuration
|
||||||
option which is used to calculate the TSA's public key certificate
|
option which is used to calculate the TSA's public key certificate
|
||||||
identifier. The default algorithm is updated to be sha256 instead
|
identifier. The default algorithm is updated to be sha256 instead
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <openssl/asn1t.h>
|
#include <openssl/asn1t.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
#include "crypto/evp.h"
|
||||||
|
|
||||||
/* PKCS#5 password based encryption structure */
|
/* PKCS#5 password based encryption structure */
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!saltlen)
|
if (!saltlen)
|
||||||
saltlen = PKCS5_SALT_LEN;
|
saltlen = PKCS5_DEFAULT_PBE1_SALT_LEN;
|
||||||
if (saltlen < 0)
|
if (saltlen < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "internal/cryptlib.h"
|
#include "internal/cryptlib.h"
|
||||||
#include "crypto/asn1.h"
|
#include "crypto/asn1.h"
|
||||||
|
#include "crypto/evp.h"
|
||||||
#include <openssl/asn1t.h>
|
#include <openssl/asn1t.h>
|
||||||
#include <openssl/core.h>
|
#include <openssl/core.h>
|
||||||
#include <openssl/core_names.h>
|
#include <openssl/core_names.h>
|
||||||
|
@ -196,7 +197,7 @@ X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (saltlen == 0)
|
if (saltlen == 0)
|
||||||
saltlen = PKCS5_SALT_LEN;
|
saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN;
|
||||||
if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
|
if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!saltlen)
|
if (!saltlen)
|
||||||
saltlen = PKCS5_SALT_LEN;
|
saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN;
|
||||||
|
|
||||||
/* This will either copy salt or grow the buffer */
|
/* This will either copy salt or grow the buffer */
|
||||||
if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) {
|
if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) {
|
||||||
|
|
|
@ -127,6 +127,12 @@ associated parameters for the PBKDF2 algorithm.
|
||||||
PKCS5_pbe_set0_algor() and PKCS5_pbe_set0_algor_ex() set the PBE algorithm OID and
|
PKCS5_pbe_set0_algor() and PKCS5_pbe_set0_algor_ex() set the PBE algorithm OID and
|
||||||
parameters into the supplied B<X509_ALGOR>.
|
parameters into the supplied B<X509_ALGOR>.
|
||||||
|
|
||||||
|
If I<salt> is NULL, then I<saltlen> specifies the size in bytes of the random salt to
|
||||||
|
generate. If I<saltlen> is 0 then a default size is used.
|
||||||
|
For PBE related functions such as PKCS5_pbe_set_ex() the default salt length is 8 bytes.
|
||||||
|
For PBE2 related functions that use PBKDF2 such as PKCS5_pbkdf2_set(),
|
||||||
|
PKCS5_pbe2_set_scrypt() and PKCS5_pbe2_set() the default salt length is 16 bytes.
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
|
|
||||||
The *_keyivgen() functions are typically used in PKCS#12 to encrypt objects.
|
The *_keyivgen() functions are typically used in PKCS#12 to encrypt objects.
|
||||||
|
@ -165,9 +171,13 @@ PKCS5_pbkdf2_set_ex() were added in OpenSSL 3.0.
|
||||||
From OpenSSL 3.0 the PBKDF1 algorithm used in PKCS5_PBE_keyivgen() and
|
From OpenSSL 3.0 the PBKDF1 algorithm used in PKCS5_PBE_keyivgen() and
|
||||||
PKCS5_PBE_keyivgen_ex() has been moved to the legacy provider as an EVP_KDF.
|
PKCS5_PBE_keyivgen_ex() has been moved to the legacy provider as an EVP_KDF.
|
||||||
|
|
||||||
|
In OpenSSL 3.2 the default salt length changed from 8 bytes to 16 bytes for PBE2
|
||||||
|
related functions such as PKCS5_pbe2_set().
|
||||||
|
This is required for PBKDF2 FIPS compliance.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
|
|
@ -16,6 +16,15 @@
|
||||||
# include "internal/refcount.h"
|
# include "internal/refcount.h"
|
||||||
# include "crypto/ecx.h"
|
# include "crypto/ecx.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default PKCS5 PBE KDF salt lengths
|
||||||
|
* In RFC 8018, PBE1 uses 8 bytes (64 bits) for its salt length.
|
||||||
|
* It also specifies to use at least 8 bytes for PBES2.
|
||||||
|
* The NIST requirement for PBKDF2 is 128 bits so we use this as the
|
||||||
|
* default for PBE2 (scrypt and HKDF2)
|
||||||
|
*/
|
||||||
|
# define PKCS5_DEFAULT_PBE1_SALT_LEN PKCS5_SALT_LEN
|
||||||
|
# define PKCS5_DEFAULT_PBE2_SALT_LEN 16
|
||||||
/*
|
/*
|
||||||
* Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag
|
* Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag
|
||||||
* values in evp.h
|
* values in evp.h
|
||||||
|
|
|
@ -25,7 +25,7 @@ my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
|
||||||
|
|
||||||
plan tests =>
|
plan tests =>
|
||||||
($no_fips ? 0 : 5) # Extra FIPS related tests
|
($no_fips ? 0 : 5) # Extra FIPS related tests
|
||||||
+ 15;
|
+ 16;
|
||||||
|
|
||||||
# We want to know that an absurdly small number of bits isn't support
|
# We want to know that an absurdly small number of bits isn't support
|
||||||
is(run(app([ 'openssl', 'genpkey', '-out', 'genrsatest.pem',
|
is(run(app([ 'openssl', 'genpkey', '-out', 'genrsatest.pem',
|
||||||
|
@ -106,6 +106,13 @@ ok(run(app([ 'openssl', 'rsa', '-check', '-in', 'genrsatest.pem', '-noout' ])),
|
||||||
ok(run(app([ 'openssl', 'rsa', '-in', 'genrsatest.pem', '-out', 'genrsatest-enc.pem',
|
ok(run(app([ 'openssl', 'rsa', '-in', 'genrsatest.pem', '-out', 'genrsatest-enc.pem',
|
||||||
'-aes256', '-passout', 'pass:x' ])),
|
'-aes256', '-passout', 'pass:x' ])),
|
||||||
"rsa encrypt");
|
"rsa encrypt");
|
||||||
|
# Check the default salt length for PBKDF2 is 16 bytes
|
||||||
|
# We expect the output to be of the form "0:d=0 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:FAC7F37508E6B7A805BF4B13861B3687"
|
||||||
|
# i.e. 2 byte header + 16 byte salt.
|
||||||
|
ok(run(app(([ 'openssl', 'asn1parse',
|
||||||
|
'-in', 'genrsatest-enc.pem',
|
||||||
|
'-offset', '34', '-length', '18']))),
|
||||||
|
"Check the default size of the PBKDF2 PARAM 'salt length' is 16");
|
||||||
ok(run(app([ 'openssl', 'rsa', '-in', 'genrsatest-enc.pem', '-passin', 'pass:x' ])),
|
ok(run(app([ 'openssl', 'rsa', '-in', 'genrsatest-enc.pem', '-passin', 'pass:x' ])),
|
||||||
"rsa decrypt");
|
"rsa decrypt");
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,58 @@ use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips is_nofips/;
|
||||||
|
|
||||||
setup("test_pkcs8");
|
setup("test_pkcs8");
|
||||||
|
|
||||||
plan tests => 3;
|
plan tests => 9;
|
||||||
|
|
||||||
|
ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
|
||||||
|
'-in', srctop_file('test', 'certs', 'pc5-key.pem'),
|
||||||
|
'-out', 'pbkdf2_default_saltlen.pem',
|
||||||
|
'-passout', 'pass:password']))),
|
||||||
|
"Convert a private key to PKCS5 v2.0 format using PBKDF2 with the default saltlen");
|
||||||
|
|
||||||
|
# We expect the output to be of the form "0:d=0 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:FAC7F37508E6B7A805BF4B13861B3687"
|
||||||
|
# i.e. 2 byte header + 16 byte salt.
|
||||||
|
ok(run(app(([ 'openssl', 'asn1parse',
|
||||||
|
'-in', 'pbkdf2_default_saltlen.pem',
|
||||||
|
'-offset', '34', '-length', '18']))),
|
||||||
|
"Check the default size of the PBKDF2 PARAM 'salt length' is 16");
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "scrypt is not supported by this OpenSSL build", 2
|
||||||
|
if disabled("scrypt");
|
||||||
|
|
||||||
|
ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
|
||||||
|
'-in', srctop_file('test', 'certs', 'pc5-key.pem'),
|
||||||
|
'-scrypt',
|
||||||
|
'-out', 'scrypt_default_saltlen.pem',
|
||||||
|
'-passout', 'pass:password']))),
|
||||||
|
"Convert a private key to PKCS5 v2.0 format using scrypt with the default saltlen");
|
||||||
|
|
||||||
|
# We expect the output to be of the form "0:d=0 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:FAC7F37508E6B7A805BF4B13861B3687"
|
||||||
|
# i.e. 2 byte header + 16 byte salt.
|
||||||
|
ok(run(app(([ 'openssl', 'asn1parse',
|
||||||
|
'-in', 'scrypt_default_saltlen.pem',
|
||||||
|
'-offset', '34', '-length', '18']))),
|
||||||
|
"Check the default size of the SCRYPT PARAM 'salt length' = 16");
|
||||||
|
}
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "legacy provider is not supported by this OpenSSL build", 2
|
||||||
|
if disabled('legacy') || disabled("des");
|
||||||
|
|
||||||
|
ok(run(app(([ 'openssl', 'pkcs8', '-topk8',
|
||||||
|
'-in', srctop_file('test', 'certs', 'pc5-key.pem'),
|
||||||
|
'-v1', "PBE-MD5-DES",
|
||||||
|
'-provider', 'legacy',
|
||||||
|
'-provider', 'default',
|
||||||
|
'-out', 'pbe1.pem',
|
||||||
|
'-passout', 'pass:password']))),
|
||||||
|
"Convert a private key to PKCS5 v1.5 format using pbeWithMD5AndDES-CBC with the default saltlen");
|
||||||
|
|
||||||
|
ok(run(app(([ 'openssl', 'asn1parse',
|
||||||
|
'-in', 'pbe1.pem',
|
||||||
|
'-offset', '19', '-length', '10']))),
|
||||||
|
"Check the default size of the PBE PARAM 'salt length' = 8");
|
||||||
|
};
|
||||||
|
|
||||||
SKIP: {
|
SKIP: {
|
||||||
skip "SM2, SM3 or SM4 is not supported by this OpenSSL build", 3
|
skip "SM2, SM3 or SM4 is not supported by this OpenSSL build", 3
|
||||||
|
|
Loading…
Reference in New Issue