Merge pull request #130 from mjdemilliano/add-hashdrbg-reseed
Random: add DRBG reseed supportpull/137/head
commit
905682a036
|
|
@ -391,6 +391,9 @@ def get_features(local_wolfssl, features):
|
|||
features["ML_DSA_NO_CTX"] = 1 if have_mldsa_no_context_support else 0
|
||||
features["ML_KEM"] = 1 if '#define WOLFSSL_HAVE_MLKEM' in defines else 0
|
||||
features["HKDF"] = 1 if "#define HAVE_HKDF" in defines else 0
|
||||
# Unlike the other fatures, HASHDRBG is enabled by default in random.h, unless WC_NO_HASHDRBG or
|
||||
# CUSTOM_RAND_GENERATE_BLOCK is defined.
|
||||
features["HASHDRBG"] = 0 if ("#define WC_NO_HASHDRBG" in defines or "#define CUSTOM_RAND_GENERATE_BLOCK" in defines) else 1
|
||||
|
||||
if '#define HAVE_FIPS' in defines:
|
||||
if not fips:
|
||||
|
|
@ -511,6 +514,7 @@ def build_ffi(local_wolfssl, features):
|
|||
int ML_DSA_ENABLED = {features["ML_DSA"]};
|
||||
int ML_DSA_NO_CTX_ENABLED = {features["ML_DSA_NO_CTX"]};
|
||||
int HKDF_ENABLED = {features["HKDF"]};
|
||||
int HASHDRBG_ENABLED = {features["HASHDRBG"]};
|
||||
"""
|
||||
|
||||
ffibuilder.set_source( "wolfcrypt._ffi", init_source_string,
|
||||
|
|
@ -553,6 +557,7 @@ def build_ffi(local_wolfssl, features):
|
|||
extern int ML_DSA_ENABLED;
|
||||
extern int ML_DSA_NO_CTX_ENABLED;
|
||||
extern int HKDF_ENABLED;
|
||||
extern int HASHDRBG_ENABLED;
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned int word32;
|
||||
|
|
@ -567,6 +572,10 @@ def build_ffi(local_wolfssl, features):
|
|||
int wc_RNG_GenerateByte(WC_RNG*, byte*);
|
||||
int wc_FreeRng(WC_RNG*);
|
||||
"""
|
||||
if features["HASHDRBG"]:
|
||||
cdef += """
|
||||
int wc_RNG_DRBG_Reseed(WC_RNG*, const byte*, word32);
|
||||
"""
|
||||
|
||||
if features["ERROR_STRINGS"]:
|
||||
cdef += """
|
||||
|
|
@ -1390,6 +1399,7 @@ def main(ffibuilder):
|
|||
"ML_DSA": 1,
|
||||
"ML_DSA_NO_CTX": 0,
|
||||
"HKDF": 1,
|
||||
"HASHDRBG": 1,
|
||||
}
|
||||
|
||||
# Ed448 requires SHAKE256, which isn't part of the Windows build, yet.
|
||||
|
|
|
|||
|
|
@ -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,44 @@ 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")
|
||||
@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")
|
||||
def test_reseed_multiple(rng):
|
||||
"""
|
||||
Test that consecutive reseeding of the random number generator works.
|
||||
"""
|
||||
for _ in range(10):
|
||||
# Create seed of typical size. Testing with various seed sizes done in `test_reseed_sizes`.
|
||||
seed = bytes(x % 256 for x in range(32))
|
||||
rng.reseed(seed)
|
||||
|
||||
# Pull some bytes from the random number generator to test that it still works.
|
||||
rng.bytes(100)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#endif
|
||||
|
||||
#define WOLFCRYPT_ONLY
|
||||
#define HAVE_HASHDRBG
|
||||
#define WOLFSSL_AESGCM_STREAM
|
||||
#define HAVE_AESGCM
|
||||
#define GCM_TABLE_4BIT
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ SHA256_ENABLED: int
|
|||
SHA384_ENABLED: int
|
||||
SHA512_ENABLED: int
|
||||
WC_RNG_SEED_CB_ENABLED: int
|
||||
HASHDRBG_ENABLED: int
|
||||
|
||||
# Error codes
|
||||
WC_FAILURE: int
|
||||
|
|
@ -331,6 +332,7 @@ def wc_GetErrorString(error: int) -> FFI.CData: ...
|
|||
def wc_InitRngNonce_ex(rng: RNG, nonce: bytes, nonce_size: int, heap: FFI.CData, device_id: int) -> int: ...
|
||||
def wc_RNG_GenerateByte(rng: RNG, buffer: FFI.CData) -> int: ...
|
||||
def wc_RNG_GenerateBlock(rng: RNG, buffer: FFI.CData, len: int) -> int: ...
|
||||
def wc_RNG_DRBG_Reseed(rng: RNG, seed: bytes, seed_size: int) -> int: ...
|
||||
def wc_FreeRng(rng: RNG) -> None: ...
|
||||
|
||||
DerBufferPtr: TypeAlias = FFI.CData
|
||||
|
|
|
|||
|
|
@ -82,3 +82,13 @@ class Random:
|
|||
raise WolfCryptApiError("RNG generate block error", ret)
|
||||
|
||||
return _ffi.buffer(result, length)[:]
|
||||
|
||||
if _lib.HASHDRBG_ENABLED:
|
||||
def reseed(self, seed: __builtins__.bytes) -> None:
|
||||
"""
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue