diff options
Diffstat (limited to 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand')
8 files changed, 855 insertions, 0 deletions
diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/CMakeLists.txt b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/CMakeLists.txt new file mode 100644 index 000000000..f7c11f1c1 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(../../include) + +if (${ARCH} STREQUAL "x86_64") + set( + RAND_ARCH_SOURCES + + rdrand-x86_64.${ASM_EXT} + ) +endif() + +add_library( + rand + + OBJECT + + deterministic.c + fuchsia.c + rand.c + urandom.c + windows.c + + ${RAND_ARCH_SOURCES} +) + +perlasm(rdrand-x86_64.${ASM_EXT} asm/rdrand-x86_64.pl) diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/asm/rdrand-x86_64.pl b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/asm/rdrand-x86_64.pl new file mode 100644 index 000000000..c32a55c4b --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/asm/rdrand-x86_64.pl @@ -0,0 +1,75 @@ +#!/usr/bin/env perl + +# Copyright (c) 2015, Google Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +print<<___; +.text + +# CRYPTO_rdrand writes eight bytes of random data from the hardware RNG to +# |out|. It returns one on success or zero on hardware failure. +# int CRYPTO_rdrand(uint8_t out[8]); +.globl CRYPTO_rdrand +.type CRYPTO_rdrand,\@function,1 +.align 16 +CRYPTO_rdrand: + xorq %rax, %rax + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + # An add-with-carry of zero effectively sets %rax to the carry flag. + adcq %rax, %rax + movq %rcx, 0(%rdi) + retq + +# CRYPTO_rdrand_multiple8_buf fills |len| bytes at |buf| with random data from +# the hardware RNG. The |len| argument must be a multiple of eight. It returns +# one on success and zero on hardware failure. +# int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); +.globl CRYPTO_rdrand_multiple8_buf +.type CRYPTO_rdrand_multiple8_buf,\@function,2 +.align 16 +CRYPTO_rdrand_multiple8_buf: + test %rsi, %rsi + jz .Lout + movq \$8, %rdx +.Lloop: + # This is rdrand %rcx. It sets rcx to a random value and sets the carry + # flag on success. + .byte 0x48, 0x0f, 0xc7, 0xf1 + jnc .Lerr + movq %rcx, 0(%rdi) + addq %rdx, %rdi + subq %rdx, %rsi + jnz .Lloop +.Lout: + movq \$1, %rax + retq +.Lerr: + xorq %rax, %rax + retq +___ + +close STDOUT; # flush diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/deterministic.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/deterministic.c new file mode 100644 index 000000000..d96a50534 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/deterministic.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <openssl/rand.h> + +#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) + +#include <string.h> + +#include <openssl/chacha.h> + +#include "internal.h" +#include "../internal.h" + + +/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured. + * + * TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is + * ever used in a multi-threaded program, replace this with a thread-local. (A + * mutex would not be deterministic.) */ +static uint64_t g_num_calls = 0; + +void RAND_reset_for_fuzzing(void) { g_num_calls = 0; } + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + static const uint8_t kZeroKey[32]; + + uint8_t nonce[12]; + OPENSSL_memset(nonce, 0, sizeof(nonce)); + OPENSSL_memcpy(nonce, &g_num_calls, sizeof(g_num_calls)); + + OPENSSL_memset(out, 0, requested); + CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0); + g_num_calls++; +} + +#endif /* BORINGSSL_UNSAFE_DETERMINISTIC_MODE */ diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/fuchsia.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/fuchsia.c new file mode 100644 index 000000000..2e138d0ab --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/fuchsia.c @@ -0,0 +1,43 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <openssl/rand.h> + +#if defined(OPENSSL_FUCHSIA) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) + +#include <limits.h> +#include <stdlib.h> + +#include <magenta/syscalls.h> + +#include "internal.h" + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + while (requested > 0) { + size_t output_bytes_this_pass = MX_CPRNG_DRAW_MAX_LEN; + if (requested < output_bytes_this_pass) { + output_bytes_this_pass = requested; + } + size_t bytes_drawn; + mx_status_t status = + mx_cprng_draw(out, output_bytes_this_pass, &bytes_drawn); + if (status != NO_ERROR) { + abort(); + } + requested -= bytes_drawn; + out += bytes_drawn; + } +} + +#endif /* OPENSSL_FUCHSIA && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */ diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/internal.h b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/internal.h new file mode 100644 index 000000000..dcff3aa6e --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/internal.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating + * system. */ +void CRYPTO_sysrand(uint8_t *buf, size_t len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H */ diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/rand.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/rand.c new file mode 100644 index 000000000..51da6ba27 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/rand.c @@ -0,0 +1,244 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <openssl/rand.h> + +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include <openssl/chacha.h> +#include <openssl/cpu.h> +#include <openssl/mem.h> + +#include "internal.h" +#include "../internal.h" + + +/* It's assumed that the operating system always has an unfailing source of + * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system + * entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we + * don't try to handle it.) + * + * In addition, the hardware may provide a low-latency RNG. Intel's rdrand + * instruction is the canonical example of this. When a hardware RNG is + * available we don't need to worry about an RNG failure arising from fork()ing + * the process or moving a VM, so we can keep thread-local RNG state and XOR + * the hardware entropy in. + * + * (We assume that the OS entropy is safe from fork()ing and VM duplication. + * This might be a bit of a leap of faith, esp on Windows, but there's nothing + * that we can do about it.) */ + +/* rand_thread_state contains the per-thread state for the RNG. This is only + * used if the system has support for a hardware RNG. */ +struct rand_thread_state { + uint8_t key[32]; + uint64_t calls_used; + size_t bytes_used; + uint8_t partial_block[64]; + unsigned partial_block_used; +}; + +/* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll + * serve before reading a new key from the operating system. This only applies + * if we have a hardware RNG. */ +static const unsigned kMaxCallsPerRefresh = 1024; + +/* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from + * |RAND_bytes| before reading a new key from the operating system. This only + * applies if we have a hardware RNG. */ +static const uint64_t kMaxBytesPerRefresh = 1024 * 1024; + +/* rand_thread_state_free frees a |rand_thread_state|. This is called when a + * thread exits. */ +static void rand_thread_state_free(void *state) { + if (state == NULL) { + return; + } + + OPENSSL_cleanse(state, sizeof(struct rand_thread_state)); + OPENSSL_free(state); +} + +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \ + !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) + +/* These functions are defined in asm/rdrand-x86_64.pl */ +extern int CRYPTO_rdrand(uint8_t out[8]); +extern int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len); + +static int have_rdrand(void) { + return (OPENSSL_ia32cap_P[1] & (1u << 30)) != 0; +} + +static int hwrand(uint8_t *buf, size_t len) { + if (!have_rdrand()) { + return 0; + } + + const size_t len_multiple8 = len & ~7; + if (!CRYPTO_rdrand_multiple8_buf(buf, len_multiple8)) { + return 0; + } + len -= len_multiple8; + + if (len != 0) { + assert(len < 8); + + uint8_t rand_buf[8]; + if (!CRYPTO_rdrand(rand_buf)) { + return 0; + } + OPENSSL_memcpy(buf + len_multiple8, rand_buf, len); + } + + return 1; +} + +#else + +static int hwrand(uint8_t *buf, size_t len) { + return 0; +} + +#endif + +int RAND_bytes(uint8_t *buf, size_t len) { + if (len == 0) { + return 1; + } + + if (!hwrand(buf, len)) { + /* Without a hardware RNG to save us from address-space duplication, the OS + * entropy is used directly. */ + CRYPTO_sysrand(buf, len); + return 1; + } + + struct rand_thread_state *state = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND); + if (state == NULL) { + state = OPENSSL_malloc(sizeof(struct rand_thread_state)); + if (state == NULL || + !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state, + rand_thread_state_free)) { + CRYPTO_sysrand(buf, len); + return 1; + } + + OPENSSL_memset(state->partial_block, 0, sizeof(state->partial_block)); + state->calls_used = kMaxCallsPerRefresh; + } + + if (state->calls_used >= kMaxCallsPerRefresh || + state->bytes_used >= kMaxBytesPerRefresh) { + CRYPTO_sysrand(state->key, sizeof(state->key)); + state->calls_used = 0; + state->bytes_used = 0; + state->partial_block_used = sizeof(state->partial_block); + } + + if (len >= sizeof(state->partial_block)) { + size_t remaining = len; + while (remaining > 0) { + /* kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this + * is sufficient and easier on 32-bit. */ + static const size_t kMaxBytesPerCall = 0x80000000; + size_t todo = remaining; + if (todo > kMaxBytesPerCall) { + todo = kMaxBytesPerCall; + } + uint8_t nonce[12]; + OPENSSL_memset(nonce, 0, 4); + OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(buf, buf, todo, state->key, nonce, 0); + buf += todo; + remaining -= todo; + state->calls_used++; + } + } else { + if (sizeof(state->partial_block) - state->partial_block_used < len) { + uint8_t nonce[12]; + OPENSSL_memset(nonce, 0, 4); + OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used)); + CRYPTO_chacha_20(state->partial_block, state->partial_block, + sizeof(state->partial_block), state->key, nonce, 0); + state->partial_block_used = 0; + } + + unsigned i; + for (i = 0; i < len; i++) { + buf[i] ^= state->partial_block[state->partial_block_used++]; + } + state->calls_used++; + } + state->bytes_used += len; + + return 1; +} + +int RAND_pseudo_bytes(uint8_t *buf, size_t len) { + return RAND_bytes(buf, len); +} + +void RAND_seed(const void *buf, int num) { + /* OpenSSH calls |RAND_seed| before jailing on the assumption that any needed + * file descriptors etc will be opened. */ + uint8_t unused; + RAND_bytes(&unused, sizeof(unused)); +} + +int RAND_load_file(const char *path, long num) { + if (num < 0) { /* read the "whole file" */ + return 1; + } else if (num <= INT_MAX) { + return (int) num; + } else { + return INT_MAX; + } +} + +const char *RAND_file_name(char *buf, size_t num) { return NULL; } + +void RAND_add(const void *buf, int num, double entropy) {} + +int RAND_egd(const char *path) { + return 255; +} + +int RAND_poll(void) { + return 1; +} + +int RAND_status(void) { + return 1; +} + +static const struct rand_meth_st kSSLeayMethod = { + RAND_seed, + RAND_bytes, + RAND_cleanup, + RAND_add, + RAND_pseudo_bytes, + RAND_status, +}; + +RAND_METHOD *RAND_SSLeay(void) { + return (RAND_METHOD*) &kSSLeayMethod; +} + +void RAND_set_rand_method(const RAND_METHOD *method) {} + +void RAND_cleanup(void) {} diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/urandom.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/urandom.c new file mode 100644 index 000000000..23bdcf487 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/urandom.c @@ -0,0 +1,335 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE /* needed for syscall() on Linux. */ +#endif + +#include <openssl/rand.h> + +#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_FUCHSIA) && \ + !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#if defined(OPENSSL_LINUX) +#include <sys/syscall.h> +#endif + +#include <openssl/thread.h> +#include <openssl/mem.h> + +#include "internal.h" +#include "../internal.h" + + +#if defined(OPENSSL_LINUX) + +#if defined(OPENSSL_X86_64) +#define EXPECTED_SYS_getrandom 318 +#elif defined(OPENSSL_X86) +#define EXPECTED_SYS_getrandom 355 +#elif defined(OPENSSL_AARCH64) +#define EXPECTED_SYS_getrandom 278 +#elif defined(OPENSSL_ARM) +#define EXPECTED_SYS_getrandom 384 +#elif defined(OPENSSL_PPC64LE) +#define EXPECTED_SYS_getrandom 359 +#endif + +#if defined(EXPECTED_SYS_getrandom) +#define USE_SYS_getrandom + +#if defined(SYS_getrandom) + +#if SYS_getrandom != EXPECTED_SYS_getrandom +#error "system call number for getrandom is not the expected value" +#endif + +#else /* SYS_getrandom */ + +#define SYS_getrandom EXPECTED_SYS_getrandom + +#endif /* SYS_getrandom */ + +#endif /* EXPECTED_SYS_getrandom */ + +#if !defined(GRND_NONBLOCK) +#define GRND_NONBLOCK 1 +#endif + +#endif /* OPENSSL_LINUX */ + +/* This file implements a PRNG by reading from /dev/urandom, optionally with a + * buffer, which is unsafe across |fork|. */ + +#define BUF_SIZE 4096 + +/* rand_buffer contains unused, random bytes, some of which may have been + * consumed already. */ +struct rand_buffer { + size_t used; + uint8_t rand[BUF_SIZE]; +}; + +/* requested_lock is used to protect the |*_requested| variables. */ +static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT; + +/* The following constants are magic values of |urandom_fd|. */ +static const int kUnset = -2; +static const int kHaveGetrandom = -3; + +/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by + * |requested_lock|. */ +static int urandom_fd_requested = -2 /* kUnset */; + +/* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */ +static int urandom_fd = -2 /* kUnset */; + +/* urandom_buffering_requested is set by |RAND_enable_fork_unsafe_buffering|. + * It's protected by |requested_lock|. */ +static int urandom_buffering_requested = 0; + +/* urandom_buffering controls whether buffering is enabled (1) or not (0). This + * is protected by |once|. */ +static int urandom_buffering = 0; + +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; + +/* init_once initializes the state of this module to values previously + * requested. This is the only function that modifies |urandom_fd| and + * |urandom_buffering|, whose values may be read safely after calling the + * once. */ +static void init_once(void) { + CRYPTO_STATIC_MUTEX_lock_read(&requested_lock); + urandom_buffering = urandom_buffering_requested; + int fd = urandom_fd_requested; + CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock); + +#if defined(USE_SYS_getrandom) + uint8_t dummy; + long getrandom_ret = + syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK); + + if (getrandom_ret == 1) { + urandom_fd = kHaveGetrandom; + return; + } else if (getrandom_ret == -1 && errno == EAGAIN) { + fprintf(stderr, + "getrandom indicates that the entropy pool has not been " + "initialized. Rather than continue with poor entropy, this process " + "will block until entropy is available.\n"); + do { + getrandom_ret = + syscall(SYS_getrandom, &dummy, sizeof(dummy), 0 /* no flags */); + } while (getrandom_ret == -1 && errno == EINTR); + + if (getrandom_ret == 1) { + urandom_fd = kHaveGetrandom; + return; + } + } +#endif /* USE_SYS_getrandom */ + + if (fd == kUnset) { + do { + fd = open("/dev/urandom", O_RDONLY); + } while (fd == -1 && errno == EINTR); + } + + if (fd < 0) { + abort(); + } + + int flags = fcntl(fd, F_GETFD); + if (flags == -1) { + /* Native Client doesn't implement |fcntl|. */ + if (errno != ENOSYS) { + abort(); + } + } else { + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) { + abort(); + } + } + urandom_fd = fd; +} + +void RAND_set_urandom_fd(int fd) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_fd == kHaveGetrandom) { + close(fd); + } else if (urandom_fd != fd) { + abort(); // Already initialized. + } +} + +void RAND_enable_fork_unsafe_buffering(int fd) { + if (fd >= 0) { + fd = dup(fd); + if (fd < 0) { + abort(); + } + } else { + fd = kUnset; + } + + CRYPTO_STATIC_MUTEX_lock_write(&requested_lock); + urandom_buffering_requested = 1; + urandom_fd_requested = fd; + CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock); + + CRYPTO_once(&once, init_once); + if (urandom_buffering != 1) { + abort(); // Already initialized + } + + if (fd >= 0) { + if (urandom_fd == kHaveGetrandom) { + close(fd); + } else if (urandom_fd != fd) { + abort(); // Already initialized. + } + } +} + +static struct rand_buffer *get_thread_local_buffer(void) { + struct rand_buffer *buf = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF); + if (buf != NULL) { + return buf; + } + + buf = OPENSSL_malloc(sizeof(struct rand_buffer)); + if (buf == NULL) { + return NULL; + } + buf->used = BUF_SIZE; /* To trigger a |fill_with_entropy| on first use. */ + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF, buf, + OPENSSL_free)) { + OPENSSL_free(buf); + return NULL; + } + + return buf; +} + +#if defined(USE_SYS_getrandom) && defined(__has_feature) +#if __has_feature(memory_sanitizer) +void __msan_unpoison(void *, size_t); +#endif +#endif + +/* fill_with_entropy writes |len| bytes of entropy into |out|. It returns one + * on success and zero on error. */ +static char fill_with_entropy(uint8_t *out, size_t len) { + while (len > 0) { + ssize_t r; + + if (urandom_fd == kHaveGetrandom) { +#if defined(USE_SYS_getrandom) + do { + r = syscall(SYS_getrandom, out, len, 0 /* no flags */); + } while (r == -1 && errno == EINTR); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + if (r > 0) { + /* MSAN doesn't recognise |syscall| and thus doesn't notice that we + * have initialised the output buffer. */ + __msan_unpoison(out, r); + } +#endif /* memory_sanitizer */ +#endif /*__has_feature */ + +#else /* USE_SYS_getrandom */ + abort(); +#endif + } else { + do { + r = read(urandom_fd, out, len); + } while (r == -1 && errno == EINTR); + } + + if (r <= 0) { + return 0; + } + out += r; + len -= r; + } + + return 1; +} + +/* read_from_buffer reads |requested| random bytes from the buffer into |out|, + * refilling it if necessary to satisfy the request. */ +static void read_from_buffer(struct rand_buffer *buf, + uint8_t *out, size_t requested) { + size_t remaining = BUF_SIZE - buf->used; + + while (requested > remaining) { + OPENSSL_memcpy(out, &buf->rand[buf->used], remaining); + buf->used += remaining; + out += remaining; + requested -= remaining; + + if (!fill_with_entropy(buf->rand, BUF_SIZE)) { + abort(); + return; + } + buf->used = 0; + remaining = BUF_SIZE; + } + + OPENSSL_memcpy(out, &buf->rand[buf->used], requested); + buf->used += requested; +} + +/* CRYPTO_sysrand puts |requested| random bytes into |out|. */ +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + if (requested == 0) { + return; + } + + CRYPTO_once(&once, init_once); + if (urandom_buffering && requested < BUF_SIZE) { + struct rand_buffer *buf = get_thread_local_buffer(); + if (buf != NULL) { + read_from_buffer(buf, out, requested); + return; + } + } + + if (!fill_with_entropy(out, requested)) { + abort(); + } +} + +#endif /* !OPENSSL_WINDOWS && !defined(OPENSSL_FUCHSIA) && \ + !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */ diff --git a/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/windows.c b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/windows.c new file mode 100644 index 000000000..f47182d90 --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl/crypto/rand/windows.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <openssl/rand.h> + +#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) + +#include <limits.h> +#include <stdlib.h> + +OPENSSL_MSVC_PRAGMA(warning(push, 3)) + +#include <windows.h> + +/* #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the + * "Community Additions" comment on MSDN here: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */ +#define SystemFunction036 NTAPI SystemFunction036 +#include <ntsecapi.h> +#undef SystemFunction036 + +OPENSSL_MSVC_PRAGMA(warning(pop)) + +#include "internal.h" + + +void CRYPTO_sysrand(uint8_t *out, size_t requested) { + while (requested > 0) { + ULONG output_bytes_this_pass = ULONG_MAX; + if (requested < output_bytes_this_pass) { + output_bytes_this_pass = (ULONG)requested; + } + if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) { + abort(); + } + requested -= output_bytes_this_pass; + out += output_bytes_this_pass; + } + return; +} + +#endif /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */ |