Skip to content

Commit

Permalink
Make unpredictableSeed use getrandom (syscall) on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
0xEAB committed Jan 19, 2025
1 parent 1b24204 commit 83cb01f
Showing 1 changed file with 78 additions and 2 deletions.
80 changes: 78 additions & 2 deletions std/random.d
Original file line number Diff line number Diff line change
Expand Up @@ -1772,11 +1772,51 @@ else
}
}

version (linux)
{
// `getrandom()` was introduced in Linux 3.17.

// Shim for missing bindings in druntime
version (none)
import core.sys.linux.sys.random : getrandom;
else
{
import core.sys.posix.sys.types : ssize_t;
extern extern(C) ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc;
}
}

/**
A "good" seed for initializing random number engines. Initializing
with $(D_PARAM unpredictableSeed) makes engines generate different
random number sequences every run.
This function utilizes the system (CS-)PRNG where available and implemented
(currently `arc4random` on applicable BSD systems or `getrandom` on Linux) to
generate “high quality” pseudo-random numbers – if possible.
As a consequence, calling it may block under certain circumstances (typically
during early boot when the system's entropy pool has not yet been
initialized).
On x86 CPU models which support the `RDRAND` instruction, that will be used
when no more specialized randomness source is implemented.
In the future, further platform-specific PRNGs may be incorporated.
Warning:
$(B This function must not be used for cryptographic purposes.)
Despite being implemented for certain targets, there are no guarantees
that it sources its randomness from a cryptographically-secure PRNG.
The implementation also includes a fallback option that provides very little
randomness and is used when no better source of randomness is available or
integrated on the target system.
As written earlier, this function only aims to provide randomness for seeding
ordinary (non-cryptographic) RNG engines.
Returns:
A single unsigned integer seed value, different on each successive call
Note:
Expand All @@ -1788,7 +1828,25 @@ how excellent the source of entropy is.
*/
@property uint unpredictableSeed() @trusted nothrow @nogc
{
version (AnyARC4Random)
version (linux)
{
uint buffer;

/*
getrandom(2):
If the _urandom_ source has been initialized, reads of up to
256 bytes will always return as many bytes as requested and
will not be interrupted by signals. No such guarantees apply
for larger buffer sizes.
*/
static assert(buffer.sizeof <= 256);

const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
assert(status == buffer.sizeof);

return buffer;
}
else version (AnyARC4Random)
{
return arc4random();
}
Expand Down Expand Up @@ -1837,7 +1895,25 @@ if (isUnsigned!UIntType)
/// ditto
@property UIntType unpredictableSeed() @nogc nothrow @trusted
{
version (AnyARC4Random)
version (linux)
{
UIntType buffer;

/*
getrandom(2):
If the _urandom_ source has been initialized, reads of up to
256 bytes will always return as many bytes as requested and
will not be interrupted by signals. No such guarantees apply
for larger buffer sizes.
*/
static assert(buffer.sizeof <= 256);

const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
assert(status == buffer.sizeof);

return buffer;
}
else version (AnyARC4Random)
{
static if (UIntType.sizeof <= uint.sizeof)
{
Expand Down

0 comments on commit 83cb01f

Please sign in to comment.