github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/examples/examples_util.h (about)

     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. */
    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(__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  
    72  static 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. */
    86  static 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  }