csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1 (docs.ppad.tech/csecp256k1).
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

examples_util.h (4479B)


      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 }