Bitcoin Core 28.99.0
P2P Digital Currency
examples_util.h
Go to the documentation of this file.
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/*
21 * The defined WIN32_NO_STATUS macro disables return code definitions in
22 * windows.h, which avoids "macro redefinition" MSVC warnings in ntstatus.h.
23 */
24#define WIN32_NO_STATUS
25#include <windows.h>
26#undef WIN32_NO_STATUS
27#include <ntstatus.h>
28#include <bcrypt.h>
29#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
30#include <sys/random.h>
31#elif defined(__OpenBSD__)
32#include <unistd.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. */
43static 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(__linux__) || defined(__FreeBSD__)
52 /* If `getrandom(2)` is not available you should fallback to /dev/urandom */
53 ssize_t res = getrandom(data, size, 0);
54 if (res < 0 || (size_t)res != size ) {
55 return 0;
56 } else {
57 return 1;
58 }
59#elif defined(__APPLE__) || defined(__OpenBSD__)
60 /* If `getentropy(2)` is not available you should fallback to either
61 * `SecRandomCopyBytes` or /dev/urandom */
62 int res = getentropy(data, size);
63 if (res == 0) {
64 return 1;
65 } else {
66 return 0;
67 }
68#endif
69 return 0;
70}
71
72static void print_hex(unsigned char* data, size_t size) {
73 size_t i;
74 printf("0x");
75 for (i = 0; i < size; i++) {
76 printf("%02x", data[i]);
77 }
78 printf("\n");
79}
80
81#if defined(_MSC_VER)
82// For SecureZeroMemory
83#include <Windows.h>
84#endif
85/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
86static void secure_erase(void *ptr, size_t len) {
87#if defined(_MSC_VER)
88 /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
89 SecureZeroMemory(ptr, len);
90#elif defined(__GNUC__)
91 /* We use a memory barrier that scares the compiler away from optimizing out the memset.
92 *
93 * Quoting Adam Langley <agl@google.com> in commit ad1907fe73334d6c696c8539646c21b11178f20f
94 * in BoringSSL (ISC License):
95 * As best as we can tell, this is sufficient to break any optimisations that
96 * might try to eliminate "superfluous" memsets.
97 * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
98 * pretty efficient, because the compiler can still implement the memset() efficiently,
99 * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
100 * Yang et al. (USENIX Security 2017) for more background.
101 */
102 memset(ptr, 0, len);
103 __asm__ __volatile__("" : : "r"(ptr) : "memory");
104#else
105 void *(*volatile const volatile_memset)(void *, int, size_t) = memset;
106 volatile_memset(ptr, 0, len);
107#endif
108}
static int fill_random(unsigned char *data, size_t size)
Definition: examples_util.h:43
static void secure_erase(void *ptr, size_t len)
Definition: examples_util.h:86
static void print_hex(unsigned char *data, size_t size)
Definition: examples_util.h:72
void printf(FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1096