aboutsummaryrefslogtreecommitdiff
path: root/src/secp256k1/examples/examples_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/secp256k1/examples/examples_util.h')
-rw-r--r--src/secp256k1/examples/examples_util.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/secp256k1/examples/examples_util.h b/src/secp256k1/examples/examples_util.h
new file mode 100644
index 0000000000..a52b1fa115
--- /dev/null
+++ b/src/secp256k1/examples/examples_util.h
@@ -0,0 +1,102 @@
+/*************************************************************************
+ * Copyright (c) 2020-2021 Elichai Turkel *
+ * Distributed under the CC0 software license, see the accompanying file *
+ * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *
+ *************************************************************************/
+
+/*
+ * This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems.
+ * It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below.
+ *
+ * Platform randomness sources:
+ * 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
+ * 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
+ * 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
+ * OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom
+ * Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+ */
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <ntstatus.h>
+#include <bcrypt.h>
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/random.h>
+#elif defined(__OpenBSD__)
+#include <unistd.h>
+#else
+#error "Couldn't identify the OS"
+#endif
+
+#include <stddef.h>
+#include <limits.h>
+#include <stdio.h>
+
+
+/* Returns 1 on success, and 0 on failure. */
+static int fill_random(unsigned char* data, size_t size) {
+#if defined(_WIN32)
+ NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (res != STATUS_SUCCESS || size > ULONG_MAX) {
+ return 0;
+ } else {
+ return 1;
+ }
+#elif defined(__linux__) || defined(__FreeBSD__)
+ /* If `getrandom(2)` is not available you should fallback to /dev/urandom */
+ ssize_t res = getrandom(data, size, 0);
+ if (res < 0 || (size_t)res != size ) {
+ return 0;
+ } else {
+ return 1;
+ }
+#elif defined(__APPLE__) || defined(__OpenBSD__)
+ /* If `getentropy(2)` is not available you should fallback to either
+ * `SecRandomCopyBytes` or /dev/urandom */
+ int res = getentropy(data, size);
+ if (res == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+#endif
+ return 0;
+}
+
+static void print_hex(unsigned char* data, size_t size) {
+ size_t i;
+ printf("0x");
+ for (i = 0; i < size; i++) {
+ printf("%02x", data[i]);
+ }
+ printf("\n");
+}
+
+#if defined(_MSC_VER)
+// For SecureZeroMemory
+#include <Windows.h>
+#endif
+/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
+static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
+#if defined(_MSC_VER)
+ /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
+ SecureZeroMemory(ptr, len);
+#elif defined(__GNUC__)
+ /* We use a memory barrier that scares the compiler away from optimizing out the memset.
+ *
+ * Quoting Adam Langley <agl@google.com> in commit ad1907fe73334d6c696c8539646c21b11178f20f
+ * in BoringSSL (ISC License):
+ * As best as we can tell, this is sufficient to break any optimisations that
+ * might try to eliminate "superfluous" memsets.
+ * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
+ * pretty efficient, because the compiler can still implement the memset() efficently,
+ * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
+ * Yang et al. (USENIX Security 2017) for more background.
+ */
+ memset(ptr, 0, len);
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
+#else
+ void *(*volatile const volatile_memset)(void *, int, size_t) = memset;
+ volatile_memset(ptr, 0, len);
+#endif
+}