random.h (2866B)
1 /************************************************************************* 2 * Copyright (c) 2020-2021 Elichai Turkel * 3 * Distributed under the CC0 software license, see the accompanying file * 4 * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * 5 *************************************************************************/ 6 7 /* 8 * This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems. 9 * It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below. 10 * 11 * Platform randomness sources: 12 * Linux -> `getrandom(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. http://man7.org/linux/man-pages/man2/getrandom.2.html, https://linux.die.net/man/4/urandom 13 * macOS -> `getentropy(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. https://www.unix.com/man-page/mojave/2/getentropy, https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man4/random.4.auto.html 14 * FreeBSD -> `getrandom(2)`(`sys/random.h`), if not available `kern.arandom` should be used. https://www.freebsd.org/cgi/man.cgi?query=getrandom, https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 15 * OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom 16 * Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom 17 */ 18 19 #if defined(_WIN32) 20 #include <windows.h> 21 #include <ntstatus.h> 22 #include <bcrypt.h> 23 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) 24 //#include <sys/random.h> 25 #include <Security/SecRandom.h> 26 #elif defined(__OpenBSD__) 27 #include <unistd.h> 28 #else 29 #error "Couldn't identify the OS" 30 #endif 31 32 #include <stddef.h> 33 #include <limits.h> 34 #include <stdio.h> 35 36 37 /* Returns 1 on success, and 0 on failure. */ 38 static int fill_random(unsigned char* data, size_t size) { 39 #if defined(_WIN32) 40 NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG); 41 if (res != STATUS_SUCCESS || size > ULONG_MAX) { 42 return 0; 43 } else { 44 return 1; 45 } 46 #elif defined(__linux__) || defined(__FreeBSD__) 47 /* If `getrandom(2)` is not available you should fallback to /dev/urandom */ 48 ssize_t res = getrandom(data, size, 0); 49 if (res < 0 || (size_t)res != size ) { 50 return 0; 51 } else { 52 return 1; 53 } 54 #elif defined(__APPLE__) || defined(__OpenBSD__) 55 /* If `getentropy(2)` is not available you should fallback to either 56 * `SecRandomCopyBytes` or /dev/urandom */ 57 int res = SecRandomCopyBytes(kSecRandomDefault, size, data); 58 if (res == 0) { 59 return 1; 60 } else { 61 return 0; 62 } 63 #endif 64 return 0; 65 } 66