ecparam keygen does not use configured seed source in FIPS provider
New reproducer
./config --with-rand-seed=none enable-jitter enable-fips --with-jitter-include=jitter/ --with-jitter-lib=jitter/ -DOPENSSL_DEFAULT_SEED_SRC=JITTER
make
make tests
....
lots of failures to get drbg and entropy
....
What's happening:
https://github.com/openssl/openssl/blob/d292c363b92bd92d0a8c8f2fe99b283307dbb6fb/crypto/rand/prov_seed.c#L50
size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx,
unsigned char **pout, int entropy,
size_t min_len, size_t max_len)
{
EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx);
if (rng != NULL && evp_rand_can_seed(rng))
return evp_rand_get_seed(rng, pout, entropy, min_len, max_len,
0, NULL, 0);
else
return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len);
}
Essentially if the primary drbg has never been created on the provider-core side, there will never be seed created on the provider-core side.
If the first call to get entropy is coming from the fips provider, in ossl_rand_get_user_entropy rng will be NULL, and thus ossl_rand_get_entropy will be used. And if one configures it without any getrandom() capability, one can observe failures.
It seems to me that a 'creating' seed would be desired here. I am attempting to add that, but that too causes failures.
Alternatively it would be nice to init seed => if for example custom seed was specified in the config file. Or somehow do it automatically upon creating new context; after configs loaded; after providers loaded; init primary drbg & seed; then return the default context for things to work.
Old steps
On master branch eaf4da97c9b9c09a407b9f1a47ad7dd99c05884c
- Configure and build openssl with debug, fips, jitter (opt-in)
./config enable-fips enable-jitter --with-jitter-include=jitter/ --with-jitter-lib=jitter/ --debug
make -j10
- Tweak test config file for base and fips to opt into jitter entropy source, like it is done in default and jitter
diff --git a/test/fips-and-base.cnf b/test/fips-and-base.cnf
index f233f83062..8bda7dcb31 100644
--- a/test/fips-and-base.cnf
+++ b/test/fips-and-base.cnf
@@ -7,6 +7,7 @@ config_diagnostics = 1
[openssl_init]
providers = provider_sect
+random = random
# You MUST uncomment the following line to operate in a FIPS approved manner,
# It is commented out here purely for testing purposes.
#alg_section = evp_properties
@@ -20,3 +21,6 @@ base = base_sect
[base_sect]
activate = 1
+
+[random]
+seed = JITTER
- Create gdb batch command script to aid with debugging - it runs openssl to generate P-256 private key, with breakpoints for syscall_random() and jitter functions. With seed source set to jitter it is expected that sycall_random is never used.
cat <<EOF >openssl.gdb
set pagination off
set logging file gdb.log
set logging on
set width 0
set height 0
set verbose off
set breakpoint pending on
break get_jitter_random_value
commands 1
continue
end
break syscall_random
commands 2
bt
continue
end
run list -providers
run ecparam -name prime256v1 -genkey
EOF
- Run above gdb script against default-and-jitter configuration like so:
$ ./util/wrap.pl -jitter gdb --batch --command ./openssl.gdb ./apps/openssl
Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.
Function "get_jitter_random_value" not defined.
Breakpoint 1 (get_jitter_random_value) pending.
Function "syscall_random" not defined.
Breakpoint 2 (syscall_random) pending.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Providers:
default
name: OpenSSL Default Provider
version: 3.5.0
status: active
[Inferior 1 (process 623981) exited normally]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, get_jitter_random_value (s=0x5555556c1b10, buf=0x5555556e7b80 "", len=48) at providers/implementations/rands/seed_src_jitter.c:84
84 struct rand_data *jitter_ec = NULL;
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPonYAxUzDG7877C5u3v76+OC+4/ycvFV4L5I08s2BVnoAoGCCqGSM49
AwEHoUQDQgAE/9ryFLAbKDYq2vMuTBCpg1BhaOty++y2cIbOXySCqvN5GaW299Zv
vsK5nHu4v/1eJeapUjdEdsnXrcKx9YFWnw==
-----END EC PRIVATE KEY-----
[Inferior 1 (process 623985) exited normally]
Observe that a random key is generated, and that the only breakpoint that hit was get_jitter_random_value. All is good.
- Rerun with the patched fips config file that opts into jitter entropy, and observe that jitter entropy is not used
$ ./util/wrap.pl -fips gdb --batch --command ./openssl.gdb ./apps/openssl
Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.
Function "get_jitter_random_value" not defined.
Breakpoint 1 (get_jitter_random_value) pending.
Function "syscall_random" not defined.
Breakpoint 2 (syscall_random) pending.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Providers:
base
name: OpenSSL Base Provider
version: 3.5.0
status: active
fips
name: OpenSSL FIPS Provider
version: 3.5.0
status: active
[Inferior 1 (process 624171) exited normally]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 2, syscall_random (buf=0x5555556f8100, buflen=48) at providers/implementations/rands/seeding/rand_unix.c:355
355 if (getentropy != NULL) {
#0 syscall_random (buf=0x5555556f8100, buflen=48) at providers/implementations/rands/seeding/rand_unix.c:355
#1 0x00007ffff7aa43aa in ossl_pool_acquire_entropy (pool=0x5555556cdd80) at providers/implementations/rands/seeding/rand_unix.c:642
#2 0x00007ffff797e74d in ossl_rand_get_entropy (ctx=0x7ffff7c66640 <default_context_int>, pout=0x7fffffffcfa8, entropy=256, min_len=48, max_len=4294967294) at crypto/rand/prov_seed.c:33
#3 0x00007ffff797e81f in ossl_rand_get_user_entropy (ctx=0x7ffff7c66640 <default_context_int>, pout=0x7fffffffcfa8, entropy=256, min_len=48, max_len=4294967294) at crypto/rand/prov_seed.c:54
#4 0x00007ffff78938f1 in rand_get_user_entropy (handle=0x5555556aa9e0, pout=0x7fffffffcfa8, entropy=256, min_len=48, max_len=4294967294) at crypto/provider_core.c:2126
#5 0x00007ffff6fe49de in ossl_prov_get_entropy (prov_ctx=0x5555556b0790, pout=0x7fffffffcfa8, entropy=256, min_len=48, max_len=4294967294) at providers/common/provider_seeding.c:88
#6 0x00007ffff6e590a0 in crng_test_get_seed (vcrngt=0x5555556f7e30, pout=0x7fffffffcfa8, entropy=256, min_len=48, max_len=4294967294, prediction_resistance=0, adin=0x7fffffffcf38 "@\315lUUU", adin_len=8) at providers/implementations/rands/fips_crng_test.c:296
#7 0x00007ffff6fe6c97 in get_entropy (drbg=0x5555556ccd40, pout=0x7fffffffcfa8, entropy=384, min_len=48, max_len=4294967294, prediction_resistance=0) at providers/implementations/rands/drbg.c:238
#8 0x00007ffff6fe7506 in ossl_prov_drbg_instantiate (drbg=0x5555556ccd40, strength=0, prediction_resistance=0, pers=0x7ffff703ce70 <ossl_pers_string> "OpenSSL NIST SP 800-90A DRBG", perslen=29) at providers/implementations/rands/drbg.c:438
#9 0x00007ffff6e554c7 in drbg_ctr_instantiate_wrapper (vdrbg=0x5555556ccd40, strength=0, prediction_resistance=0, pstr=0x0, pstr_len=0, params=0x7fffffffd170) at providers/implementations/rands/drbg_ctr.c:343
#10 0x00007ffff6ed8164 in evp_rand_instantiate_locked (ctx=0x5555556f7d70, strength=0, prediction_resistance=0, pstr=0x0, pstr_len=0, params=0x7fffffffd170) at crypto/evp/evp_rand.c:517
#11 0x00007ffff6ed81c3 in EVP_RAND_instantiate (ctx=0x5555556f7d70, strength=0, prediction_resistance=0, pstr=0x0, pstr_len=0, params=0x7fffffffd170) at crypto/evp/evp_rand.c:530
#12 0x00007ffff6fbb1d8 in rand_new_drbg (libctx=0x5555556af4c0, parent=0x5555556f7dc0, reseed_interval=65536, reseed_time_interval=420) at crypto/rand/rand_lib.c:704
#13 0x00007ffff6fbb6f9 in RAND_get0_private (ctx=0x5555556af4c0) at crypto/rand/rand_lib.c:861
#14 0x00007ffff6fba7ec in RAND_priv_bytes_ex (ctx=0x5555556af4c0, buf=0x5555556f7930 "\367k:", num=32, strength=0) at crypto/rand/rand_lib.c:353
#15 0x00007ffff6e88046 in bnrand (flag=PRIVATE, rnd=0x5555556f7d30, bits=256, top=-1, bottom=0, strength=0, ctx=0x5555556e46e0) at crypto/bn/bn_rand.c:49
#16 0x00007ffff6e8858c in bnrand_range (flag=PRIVATE, r=0x5555556f7d30, range=0x5555556f7d50, strength=0, ctx=0x5555556e46e0) at crypto/bn/bn_rand.c:187
#17 0x00007ffff6e88680 in BN_priv_rand_range_ex (r=0x5555556f7d30, range=0x5555556f7d50, strength=0, ctx=0x5555556e46e0) at crypto/bn/bn_rand.c:219
#18 0x00007ffff6eb3190 in ec_generate_key (eckey=0x5555556e2750, pairwise_test=0) at crypto/ec/ec_key.c:354
#19 0x00007ffff6eb3398 in ossl_ec_key_simple_generate_key (eckey=0x5555556e2750) at crypto/ec/ec_key.c:444
#20 0x00007ffff6eb2ddf in ossl_ec_key_gen (eckey=0x5555556e2750) at crypto/ec/ec_key.c:233
#21 0x00007ffff6eb2d4f in EC_KEY_generate_key (eckey=0x5555556e2750) at crypto/ec/ec_key.c:219
#22 0x00007ffff6e4ce46 in ec_gen (genctx=0x5555556e6c20, osslcb=0x7ffff785398a <ossl_callback_to_pkey_gencb>, cbarg=0x5555556abe10) at providers/implementations/keymgmt/ec_kmgmt.c:1330
#23 0x00007ffff7844f94 in evp_keymgmt_gen (keymgmt=0x5555556ebad0, genctx=0x5555556e6c20, cb=0x7ffff785398a <ossl_callback_to_pkey_gencb>, cbarg=0x5555556abe10) at crypto/evp/keymgmt_meth.c:446
#24 0x00007ffff7843a74 in evp_keymgmt_util_gen (target=0x5555556e5ca0, keymgmt=0x5555556ebad0, genctx=0x5555556e6c20, cb=0x7ffff785398a <ossl_callback_to_pkey_gencb>, cbarg=0x5555556abe10) at crypto/evp/keymgmt_lib.c:518
#25 0x00007ffff7853c4e in EVP_PKEY_generate (ctx=0x5555556abe10, ppkey=0x7fffffffd708) at crypto/evp/pmeth_gn.c:189
#26 0x00007ffff7853f45 in EVP_PKEY_keygen (ctx=0x5555556abe10, ppkey=0x7fffffffd708) at crypto/evp/pmeth_gn.c:274
#27 0x00005555555c379b in ecparam_main (argc=4, argv=0x7fffffffdaa0) at apps/ecparam.c:230
#28 0x00005555555d6b45 in do_cmd (prog=0x5555556e8800, argc=4, argv=0x7fffffffdaa0) at apps/openssl.c:428
#29 0x00005555555d66cd in main (argc=4, argv=0x7fffffffdaa0) at apps/openssl.c:309
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAJamBhBfvIC46y9vmUfE+GeY8i0yqmHCfknrmouVnZBoAoGCCqGSM49
AwEHoUQDQgAESRsmBiXEvDMHDnXHXxKBNCf0Ii3tlx+fhmIA7zyhj5XC57E9+5Ox
PQYSJOmLXwVn44K0sCluQqwngD3rR1ZeXw==
-----END EC PRIVATE KEY-----
[Inferior 1 (process 624174) exited normally]
And observe that rand_get_user_entropy() callback used seed-src rather than configured jitter seed source, as if the thread is not started; and crypto global RNG did not get started.
Note this seems to only affect ecparams; as openssl rand and openssl genrsa and openssl genpkey -algorithm ed25519 in the above openssl gdb script all operate correctly; initialise global drbg with correct jitter seed source. But not for ECDSA keys.
Will this be addressed for the 3.5 release?
#24498 should have addressed this. If not, we're likely out of time for 3.5.
I will re-test this thanks!
@paulidale
With c0eb5c57f77c5a158b989285b1344297e0186235 from February 24 which contains d46667284d193ceb3242ebf17422e62b1c837c60 appears to still exhibit the property of calling OS getrandom.
Do I need to somehow create an automated github workflow integration tests that shows this, to help with debugging/developing fix for this?
That would be great. Debugging this code isn't easy...
Ok, I have a more straight forward reproducer, just a set of config options, and then running all the tests shows the issue.