nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

random.h (3500B)


      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(__ANDROID__)
     24 #include <fcntl.h>
     25 #include <unistd.h>
     26 #include <errno.h>
     27 #elif defined(__linux__) || defined(__FreeBSD__)
     28 #include <sys/random.h>
     29 #elif defined(__OpenBSD__)
     30 #include <unistd.h>
     31 #elif defined(__APPLE__)
     32 #include <Security/SecRandom.h>
     33 #else
     34 #error "Couldn't identify the OS"
     35 #endif
     36 
     37 #include <stddef.h>
     38 #include <limits.h>
     39 #include <stdio.h>
     40 
     41 
     42 /* Returns 1 on success, and 0 on failure. */
     43 static int fill_random(unsigned char* data, size_t size) {
     44 #if defined(_WIN32)
     45     NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
     46     if (res != STATUS_SUCCESS || size > ULONG_MAX) {
     47         return 0;
     48     } else {
     49         return 1;
     50     }
     51 #elif defined(__ANDROID__)
     52     int fd = open("/dev/urandom", O_RDONLY);
     53     if (fd < 0) {
     54         return 0; // Failed to open /dev/urandom
     55     }
     56     ssize_t read_bytes = 0;
     57     while (size > 0) {
     58         read_bytes = read(fd, data, size);
     59         if (read_bytes <= 0) {
     60             if (errno == EINTR) {
     61                 continue; // If interrupted by signal, try again
     62             }
     63             close(fd);
     64             return 0; // Failed to read
     65         }
     66         data += read_bytes;
     67         size -= read_bytes;
     68     }
     69     close(fd);
     70     return 1;
     71 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
     72     /* If `getrandom(2)` is not available you should fallback to /dev/urandom */
     73     ssize_t res = getrandom(data, size, 0);
     74     if (res < 0 || (size_t)res != size ) {
     75         return 0;
     76     } else {
     77         return 1;
     78     }
     79 #elif defined(__APPLE__) 
     80     /* If `getentropy(2)` is not available you should fallback to either
     81      * `SecRandomCopyBytes` or /dev/urandom */
     82     int res = SecRandomCopyBytes(kSecRandomDefault, size, data);
     83     if (res == 0) {
     84         return 1;
     85     } else {
     86         return 0;
     87     }
     88 #endif
     89     return 0;
     90 }
     91