Skip to content

Commit 5a80f7d

Browse files
committed
Make unpredictableSeed use BCryptGenRandom (CNG) on Windows
1 parent f2c49d3 commit 5a80f7d

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

std/random.d

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,27 @@ version (linux)
17901790
}
17911791
}
17921792

1793+
version (Windows)
1794+
{
1795+
pragma(lib, "Bcrypt.lib");
1796+
1797+
private bool bcryptGenRandom(T)(out T result) @trusted
1798+
{
1799+
import core.sys.windows.windef : PUCHAR, ULONG;
1800+
import core.sys.windows.ntdef : NTSTATUS, NT_SUCCESS;
1801+
import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;
1802+
1803+
const gotRandom = BCryptGenRandom(
1804+
null,
1805+
cast(PUCHAR) &result,
1806+
ULONG(T.sizeof),
1807+
BCRYPT_USE_SYSTEM_PREFERRED_RNG,
1808+
);
1809+
1810+
return NT_SUCCESS(gotRandom);
1811+
}
1812+
}
1813+
17931814
/**
17941815
A "good" seed for initializing random number engines. Initializing
17951816
with $(D_PARAM unpredictableSeed) makes engines generate different
@@ -1798,8 +1819,8 @@ random number sequences every run.
17981819
This function utilizes the system $(I cryptographically-secure pseudo-random
17991820
number generator (CSPRNG)) or $(I pseudo-random number generator (PRNG))
18001821
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.
1822+
systems, `getrandom` on Linux or `BCryptGenRandom` on Windows) to generate
1823+
“high quality” pseudo-random numbers – if possible.
18031824
As a consequence, calling it may block under certain circumstances (typically
18041825
during early boot when the system's entropy pool has not yet been
18051826
initialized).
@@ -1848,6 +1869,18 @@ how excellent the source of entropy is.
18481869

18491870
return buffer;
18501871
}
1872+
else version (Windows)
1873+
{
1874+
uint result;
1875+
if (!bcryptGenRandom!uint(result))
1876+
{
1877+
version (none)
1878+
return fallbackSeed();
1879+
else
1880+
assert(false, "BCryptGenRandom() failed.");
1881+
}
1882+
return result;
1883+
}
18511884
else version (AnyARC4Random)
18521885
{
18531886
return arc4random();
@@ -1915,6 +1948,18 @@ if (isUnsigned!UIntType)
19151948

19161949
return buffer;
19171950
}
1951+
else version (Windows)
1952+
{
1953+
UIntType result;
1954+
if (!bcryptGenRandom!UIntType(result))
1955+
{
1956+
version (none)
1957+
return fallbackSeed();
1958+
else
1959+
assert(false, "BCryptGenRandom() failed.");
1960+
}
1961+
return result;
1962+
}
19181963
else version (AnyARC4Random)
19191964
{
19201965
static if (UIntType.sizeof <= uint.sizeof)

0 commit comments

Comments
 (0)