-
Notifications
You must be signed in to change notification settings - Fork 31
Random: add DRBG reseed support #130
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |
| # pylint: disable=redefined-outer-name | ||
|
|
||
| import pytest | ||
| from wolfcrypt._ffi import lib as _lib | ||
| from wolfcrypt.random import Random | ||
|
|
||
|
|
||
|
|
@@ -38,13 +39,47 @@ def test_bytes(rng): | |
| assert len(rng.bytes(8)) == 8 | ||
| assert len(rng.bytes(128)) == 128 | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def rng_nonce(): | ||
| return Random(b"abcdefghijklmnopqrstuv") | ||
|
|
||
|
|
||
| def test_nonce_byte(rng_nonce): | ||
| assert len(rng_nonce.byte()) == 1 | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("length", (1, 8, 128)) | ||
| def test_nonce_bytes(rng_nonce, length): | ||
| assert len(rng_nonce.bytes(length)) == length | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not _lib.HASHDRBG_ENABLED, reason="Reseeding only available with hash-DRBG") | ||
|
dgarske marked this conversation as resolved.
|
||
| @pytest.mark.parametrize("seed_size", [0, 1, 32, 1000]) | ||
| def test_reseed_sizes(rng, seed_size): | ||
| """ | ||
| Test that reseeding the random number generator works, for various seed sizes. | ||
| """ | ||
| # Create seed of required length. | ||
| seed = bytes(x % 256 for x in range(seed_size)) | ||
| assert len(seed) == seed_size | ||
| rng.reseed(seed) | ||
| # Pull some bytes from the random number generator to test that it still works. | ||
| rng.bytes(32) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not _lib.HASHDRBG_ENABLED, reason="Reseeding only available with hash-DRBG") | ||
|
dgarske marked this conversation as resolved.
|
||
| def test_reseed_multiple(rng): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] test_reseed_multiple is non-deterministic The test derives both the per-iteration seed size and the final byte count from live RNG output ( Fix: Use fixed, explicit seed sizes and byte counts so the test is deterministic and reproducible; keep the loop to prove consecutive reseeds work. |
||
| """ | ||
| Test that consecutive reseeding of the random number generator works. | ||
| """ | ||
| # Using our own rng for getting random seed sizes. | ||
| for _ in range(10): | ||
| # Create seed using random seed size for each call. | ||
| seed_size = ord(rng.byte()) | ||
| seed = bytes(x % 256 for x in range(seed_size)) | ||
| rng.reseed(seed) | ||
|
|
||
| # Pull some bytes from the random number generator to test that it still works. | ||
| num_bytes = ord(rng.byte()) | ||
| rng.bytes(num_bytes) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,3 +77,13 @@ def bytes(self, length: int) -> __builtins__.bytes: | |
| raise WolfCryptApiError("RNG generate block error", ret) | ||
|
|
||
| return _ffi.buffer(result, length)[:] | ||
|
|
||
| if _lib.HASHDRBG_ENABLED: | ||
|
dgarske marked this conversation as resolved.
|
||
| def reseed(self, seed: __builtins__.bytes) -> None: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] reseed() accepts bytes only with no input normalization
Fix: Optional: either leave as-is to match Random.init's bytes-only convention, or run |
||
| """ | ||
| Reseed the DRBG with the provided seed material. | ||
| """ | ||
| assert self.native_object is not None | ||
| ret = _lib.wc_RNG_DRBG_Reseed(self.native_object, seed, len(seed)) | ||
| if ret < 0: # pragma: no cover | ||
| raise WolfCryptApiError("RNG reseed error", ret) | ||
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.
🟠 [Medium] HASHDRBG feature not detected on Windows non-FIPS build; reseed() silently unavailable
The new detection
features["HASHDRBG"] = 1 if "#define HAVE_HASHDRBG" in defines else 0does a literal, exact-line match against the defines pulled fromoptions.h/user_settings.h. On Linux/macOS the autotools build emits#define HAVE_HASHDRBGinto the generatedoptions.h(verified inlib/wolfssl/.../include/wolfssl/options.h), so detection works. On Windows non-FIPS the build copieswindows/non_fips/user_settings.has the sole defines source, and that file does NOT contain#define HAVE_HASHDRBG— Hash-DRBG is left enabled implicitly via wolfSSL's defaultsettings.h(noWC_NO_HASHDRBG). As a result,features["HASHDRBG"]evaluates to 0 on Windows non-FIPS even thoughwc_RNG_DRBG_Reseedis actually compiled into the library. ConsequentlyHASHDRBG_ENABLEDis 0,wc_RNG_DRBG_Reseedis omitted from the cdef, andRandom.reseed()is never defined on the default Windows build — the very feature this PR adds ships as unavailable there. Notewindows/fips_ready/user_settings.h:17already definesHAVE_HASHDRBG, andwindows/non_fips/user_settings.h:23already listsHAVE_HKDFfor exactly this reason, so the omission looks accidental.Fix: Add
#define HAVE_HASHDRBGtowindows/non_fips/user_settings.h(mirroring the existingHAVE_HKDFdefine and the fips_ready variant) so the new detection fires andreseed()is exposed on the default Windows build. Alternatively, document that reseed is Linux/macOS-only for now.