Skip to content

Commit 20b2d00

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

File tree

1 file changed

+78
-2
lines changed

1 file changed

+78
-2
lines changed

std/random.d

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,11 +1772,51 @@ 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;
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 (CS-)PRNG where available and implemented
1799+
(currently `arc4random` on applicable BSD systems or `getrandom` on Linux) to
1800+
generate “high quality” pseudo-random numbers – if possible.
1801+
As a consequence, calling it may block under certain circumstances (typically
1802+
during early boot when the system's entropy pool has not yet been
1803+
initialized).
1804+
1805+
On x86 CPU models which support the `RDRAND` instruction, that will be used
1806+
when no more specialized randomness source is implemented.
1807+
1808+
In the future, further platform-specific PRNGs may be incorporated.
1809+
1810+
Warning:
1811+
$(B This function must not be used for cryptographic purposes.)
1812+
Despite being implemented for certain targets, there are no guarantees
1813+
that it sources its randomness from a cryptographically-secure PRNG.
1814+
The implementation also includes a fallback option that provides very little
1815+
randomness and is used when no better source of randomness is available or
1816+
integrated on the target system.
1817+
As written earlier, this function only aims to provide randomness for seeding
1818+
ordinary (non-cryptographic) RNG engines.
1819+
17801820
Returns:
17811821
A single unsigned integer seed value, different on each successive call
17821822
Note:
@@ -1788,7 +1828,25 @@ how excellent the source of entropy is.
17881828
*/
17891829
@property uint unpredictableSeed() @trusted nothrow @nogc
17901830
{
1791-
version (AnyARC4Random)
1831+
version (linux)
1832+
{
1833+
uint buffer;
1834+
1835+
/*
1836+
getrandom(2):
1837+
If the _urandom_ source has been initialized, reads of up to
1838+
256 bytes will always return as many bytes as requested and
1839+
will not be interrupted by signals. No such guarantees apply
1840+
for larger buffer sizes.
1841+
*/
1842+
static assert(buffer.sizeof <= 256);
1843+
1844+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1845+
assert(status == buffer.sizeof);
1846+
1847+
return buffer;
1848+
}
1849+
else version (AnyARC4Random)
17921850
{
17931851
return arc4random();
17941852
}
@@ -1837,7 +1895,25 @@ if (isUnsigned!UIntType)
18371895
/// ditto
18381896
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391897
{
1840-
version (AnyARC4Random)
1898+
version (linux)
1899+
{
1900+
UIntType buffer;
1901+
1902+
/*
1903+
getrandom(2):
1904+
If the _urandom_ source has been initialized, reads of up to
1905+
256 bytes will always return as many bytes as requested and
1906+
will not be interrupted by signals. No such guarantees apply
1907+
for larger buffer sizes.
1908+
*/
1909+
static assert(buffer.sizeof <= 256);
1910+
1911+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1912+
assert(status == buffer.sizeof);
1913+
1914+
return buffer;
1915+
}
1916+
else version (AnyARC4Random)
18411917
{
18421918
static if (UIntType.sizeof <= uint.sizeof)
18431919
{

0 commit comments

Comments
 (0)