1 /**
2  * Interface to the OS CSPRNG.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.sys.osrng;
15 
16 import std.conv : to;
17 
18 version (CRuntime_Bionic)
19 	version = SecureARC4Random; // ChaCha20
20 version (OSX)
21 	version = SecureARC4Random; // AES
22 version (OpenBSD)
23 	version = SecureARC4Random; // ChaCha20
24 version (NetBSD)
25 	version = SecureARC4Random; // ChaCha20
26 
27 // Not SecureARC4Random:
28 // CRuntime_UClibc (ARC4)
29 // FreeBSD (ARC4)
30 // DragonFlyBSD (ARC4)
31 
32 version (Windows)
33 {
34 	import ae.sys.windows;
35 
36 	import ae.sys.windows.imports;
37 	mixin(importWin32!q{wincrypt});
38 	mixin(importWin32!q{windef});
39 
40 	void genRandom(ubyte[] buf)
41 	{
42 		HCRYPTPROV hCryptProv;
43 		wenforce(CryptAcquireContext(&hCryptProv, null, null, PROV_RSA_FULL, 0), "CryptAcquireContext");
44 		scope(exit) wenforce(CryptReleaseContext(hCryptProv, 0), "CryptReleaseContext");
45 		wenforce(CryptGenRandom(hCryptProv, buf.length.to!DWORD, buf.ptr), "CryptGenRandom");
46 	}
47 }
48 else
49 version (SecureARC4Random)
50 {
51 	extern(C) private @nogc nothrow
52 	{
53 		void arc4random_buf(scope void* buf, size_t nbytes) @system;
54 	}
55 
56 	void genRandom(ubyte[] buf)
57 	{
58 		arc4random_buf(buf.ptr, buf.length);
59 	}
60 }
61 else
62 version (Posix)
63 {
64 	import std.stdio;
65 	import std.exception;
66 
67 	void genRandom(ubyte[] buf)
68 	{
69 		auto f = File("/dev/urandom");
70 		auto result = f.rawRead(buf);
71 		enforce(result.length == buf.length, "Couldn't read enough random bytes");
72 	}
73 }