-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reorganise reseeding #1941
Reorganise reseeding #1941
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## randomness_generation #1941 +/- ##
=========================================================
+ Coverage 78.46% 78.57% +0.10%
=========================================================
Files 585 585
Lines 97061 98008 +947
Branches 13920 13922 +2
=========================================================
+ Hits 76160 77010 +850
- Misses 20282 20380 +98
+ Partials 619 618 -1 ☔ View full report in Codecov by Sentry. |
crypto/fipsmodule/rand/new_rand.c
Outdated
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN], | ||
size_t personalization_string_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why take the string length if you're requiring a specific size? You don't take a size for the seed. Also do we need a compiler flag to enforce this? I tried passing in a huge array for seed/personalization string and nothing complained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because you might not use the personalization string in which case personalization_string_len
would be 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency CTR_DRBG_reseed doesn't define the argument in this way. Should we just make them both consistent?
const uint8_t *additional_data,
size_t additional_data_len
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just use the name personalization_string
to mean both additional data and personalization string. the latter is the name used in SP800-90A for the extra input for reseeding, while the latter is the name used for the extra input for initial seeding. I renamed stuff. now use "extra entropy" as a general name and flip to either "personalization string" or "additional data" depending on context.
crypto/fipsmodule/rand/new_rand.c
Outdated
// must_reseed_before_generate is 1 if we must reseed before invoking the | ||
// CTR-DRBG generate function CTR_DRBG_generate(). | ||
int must_reseed_before_generate = 0; | ||
|
||
// Ensure the CTR-DRBG state is safe to use. | ||
if (rand_ensure_ctr_drbg_uniqueness(state) == 1) { | ||
rand_ctr_drbg_reseed(state); | ||
must_reseed_before_generate = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is all of this checked up here and not down around 267?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it doesn't have to be checked iteratively. So, preventing redundant work.
crypto/fipsmodule/rand/new_rand.c
Outdated
// CTR-DRBG generate function CTR_DRBG_generate(). | ||
int must_reseed_before_generate = 0; | ||
|
||
// Ensure the CTR-DRBG state is safe to use. | ||
if (rand_ensure_ctr_drbg_uniqueness(state) == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP: It's not immediately obvious what this function does when reading the name, I had to look up what this function does when reading this. What about is_uniqueness_broken
or need_to_reseed_for_uniqueness
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to rand_check_ctr_drbg_uniqueness
and also flipped the return value: 0
is now "bad"and
1` is "good"
|
||
must_reseed_before_generate = 0; | ||
|
||
// TODO: unlock here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you planning to lock up on 253 to unlock here and then lock again on 279? Is the only important part to lock in rand_ctr_drbg_reseed? Could that handle the locking inside that function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to synchronise access to the CTR-DRBG with the global memory manager that can also mutate the state.
line 253 and 304 wraps the critical code under the while-loop. The powerpc then necessitates the unlock-lock cycle if needing to reseed due to reseed interval - but only if that condition ever becomes true. I don't want to handle that in a child function because then a post-condition to that function will be that the lock as already been acquired otherwise unlocking will fail and abort the process.
// Should be able to perform kCtrDrbgReseedInterval-2 generate calls before a | ||
// reseed is emitted. Requesting | ||
// CTR_DRBG_MAX_GENERATE_LENGTH * (kCtrDrbgReseedInterval-2) + 1 would require | ||
// quite a large buffer. Instead iterate until we need | ||
// 5 iterations and request 5 * CTR_DRBG_MAX_GENERATE_LENGTH+1, which is a | ||
// much smaller buffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are you trying to test here that isn't covered in the first section?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it's sorta the same thing. Just trying to make sure to exercise multiple iterations of the while-loop that calls the CTR_DRBG_generate()
function.
uint8_t seed[CTR_DRBG_ENTROPY_LEN]; | ||
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN]; | ||
size_t personalization_string_len = 0; | ||
rand_get_ctr_drbg_seed_entropy(state->entropy_source, seed, | ||
personalization_string, &personalization_string_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get why you moved this out of this function. Also it's only used in one spot, does it make more sense to just put this all in RAND_bytes_core?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to decouple the two operations 1) gathering entropy 2) using that entropy to reseed. rand_get_ctr_drbg_seed_entropy()
is used twice. rand_ctr_drbg_reseed()
is now only used once, but I still like to factor out a wrapper for reseeding. I think it makes reading the core function easier.
crypto/fipsmodule/rand/new_rand.c
Outdated
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN], | ||
size_t personalization_string_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency CTR_DRBG_reseed doesn't define the argument in this way. Should we just make them both consistent?
const uint8_t *additional_data,
size_t additional_data_len
static void rand_ctr_drbg_reseed(struct rand_thread_local_state *state, | ||
uint8_t seed[CTR_DRBG_ENTROPY_LEN], | ||
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN], | ||
size_t personalization_string_len) { | ||
|
||
GUARD_PTR_ABORT(state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should seed
and personalization_string
be guarded for NULL or do we enforce that earlier on higher in the function call stack? Since these are just passed as pointers technically, not sure if the compiler would catch these otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only use array types when calling these functions. so in practice no problem.
if (must_reseed_before_generate == 1 || | ||
(state->generate_calls_since_seed + 1) > kCtrDrbgReseedInterval) { | ||
|
||
must_reseed_before_generate = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe move this to after reseeding is done.
72f0a9f
into
aws:randomness_generation
To avoid synchronisation issues for codepoints that reads/mutates the ctr-drbg state in aws#1919, we must reorganise the reseed logic. This decouples the code that reads/mutates the ctr-drbg state and the code that gathers entropy. The latter is not an issue. The former will later be wrapped as critical code needing synchronisation as part of the global zeroisation.
Call-outs:
To avoid synchronisation issues for codepoints that reads/mutates the ctr-drbg state in #1919, we must reorganise the reseed logic. This decouples the code that reads/mutates the ctr-drbg state and the code that gathers entropy. The latter is not an issue. The former will later be wrapped as critical code needing synchronisation as part of the global zeroisation.
Testing:
Added new tests that verifies we can predict the time of reseeding based on the configured reseed bound.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.