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 d7c61f3
Showing 1 changed file with 80 additions and 2 deletions.
82 changes: 80 additions & 2 deletions std/random.d
Original file line number Diff line number Diff line change
Expand Up @@ -1772,11 +1772,53 @@ 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 $(I cryptographically-secure pseudo-random
number generator (CSPRNG)) or $(I pseudo-random number generator (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 CSPRNG.
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) PRNG engines.
Returns:
A single unsigned integer seed value, different on each successive call
Note:
Expand All @@ -1788,7 +1830,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 +1897,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 d7c61f3

Please sign in to comment.