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 <ae@cy.md> 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 /// Fill `buf` with random data. 41 void genRandom(ubyte[] buf) 42 { 43 HCRYPTPROV hCryptProv; 44 wenforce(CryptAcquireContext(&hCryptProv, null, null, PROV_RSA_FULL, 0), "CryptAcquireContext"); 45 scope(exit) wenforce(CryptReleaseContext(hCryptProv, 0), "CryptReleaseContext"); 46 wenforce(CryptGenRandom(hCryptProv, buf.length.to!DWORD, buf.ptr), "CryptGenRandom"); 47 } 48 } 49 else 50 version (SecureARC4Random) 51 { 52 extern(C) private @nogc nothrow 53 { 54 void arc4random_buf(scope void* buf, size_t nbytes) @system; 55 } 56 57 /// Fill `buf` with random data. 58 void genRandom(ubyte[] buf) 59 { 60 arc4random_buf(buf.ptr, buf.length); 61 } 62 } 63 else 64 version (Posix) 65 { 66 import std.stdio; 67 import std.exception; 68 69 /// Fill `buf` with random data. 70 void genRandom(ubyte[] buf) 71 { 72 auto f = File("/dev/urandom"); 73 auto result = f.rawRead(buf); 74 enforce(result.length == buf.length, "Couldn't read enough random bytes"); 75 } 76 }