Skip to content

Commit d7c61f3

Browse files
committed
Make unpredictableSeed use getrandom (syscall) on Linux
1 parent 1b24204 commit d7c61f3

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

std/random.d

+80-2
Original file line numberDiff line numberDiff line change
@@ -1772,11 +1772,53 @@ else
17721772
}
17731773
}
17741774

1775+
version (linux)
1776+
{
1777+
// `getrandom()` was introduced in Linux 3.17.
1778+
1779+
// Shim for missing bindings in druntime
1780+
version (none)
1781+
import core.sys.linux.sys.random : getrandom;
1782+
else
1783+
{
1784+
import core.sys.posix.sys.types : ssize_t;
1785+
extern extern(C) ssize_t getrandom(
1786+
void* buf,
1787+
size_t buflen,
1788+
uint flags,
1789+
) @system nothrow @nogc;
1790+
}
1791+
}
1792+
17751793
/**
17761794
A "good" seed for initializing random number engines. Initializing
17771795
with $(D_PARAM unpredictableSeed) makes engines generate different
17781796
random number sequences every run.
17791797
1798+
This function utilizes the system $(I cryptographically-secure pseudo-random
1799+
number generator (CSPRNG)) or $(I pseudo-random number generator (PRNG))
1800+
where available and implemented (currently `arc4random` on applicable BSD
1801+
systems or `getrandom` on Linux) to generate “high quality” pseudo-random
1802+
numbers – if possible.
1803+
As a consequence, calling it may block under certain circumstances (typically
1804+
during early boot when the system's entropy pool has not yet been
1805+
initialized).
1806+
1807+
On x86 CPU models which support the `RDRAND` instruction, that will be used
1808+
when no more specialized randomness source is implemented.
1809+
1810+
In the future, further platform-specific PRNGs may be incorporated.
1811+
1812+
Warning:
1813+
$(B This function must not be used for cryptographic purposes.)
1814+
Despite being implemented for certain targets, there are no guarantees
1815+
that it sources its randomness from a CSPRNG.
1816+
The implementation also includes a fallback option that provides very little
1817+
randomness and is used when no better source of randomness is available or
1818+
integrated on the target system.
1819+
As written earlier, this function only aims to provide randomness for seeding
1820+
ordinary (non-cryptographic) PRNG engines.
1821+
17801822
Returns:
17811823
A single unsigned integer seed value, different on each successive call
17821824
Note:
@@ -1788,7 +1830,25 @@ how excellent the source of entropy is.
17881830
*/
17891831
@property uint unpredictableSeed() @trusted nothrow @nogc
17901832
{
1791-
version (AnyARC4Random)
1833+
version (linux)
1834+
{
1835+
uint buffer;
1836+
1837+
/*
1838+
getrandom(2):
1839+
If the _urandom_ source has been initialized, reads of up to
1840+
256 bytes will always return as many bytes as requested and
1841+
will not be interrupted by signals. No such guarantees apply
1842+
for larger buffer sizes.
1843+
*/
1844+
static assert(buffer.sizeof <= 256);
1845+
1846+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1847+
assert(status == buffer.sizeof);
1848+
1849+
return buffer;
1850+
}
1851+
else version (AnyARC4Random)
17921852
{
17931853
return arc4random();
17941854
}
@@ -1837,7 +1897,25 @@ if (isUnsigned!UIntType)
18371897
/// ditto
18381898
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391899
{
1840-
version (AnyARC4Random)
1900+
version (linux)
1901+
{
1902+
UIntType buffer;
1903+
1904+
/*
1905+
getrandom(2):
1906+
If the _urandom_ source has been initialized, reads of up to
1907+
256 bytes will always return as many bytes as requested and
1908+
will not be interrupted by signals. No such guarantees apply
1909+
for larger buffer sizes.
1910+
*/
1911+
static assert(buffer.sizeof <= 256);
1912+
1913+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1914+
assert(status == buffer.sizeof);
1915+
1916+
return buffer;
1917+
}
1918+
else version (AnyARC4Random)
18411919
{
18421920
static if (UIntType.sizeof <= uint.sizeof)
18431921
{

0 commit comments

Comments
 (0)