Revert "Fetch entropy from a system daemon in FIPS mode on Android."
This reverts commit 4259ae81982aa312e52e8ba9fd8b9e8ed4b317f2.
Some Android builders perhaps lack getrandom support.
Change-Id: Ic7537c07dacb31a54adb453ddd5f82a789089eaf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/53625
Auto-Submit: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/rand/rand.c b/crypto/fipsmodule/rand/rand.c
index 54397f9..f78e66a 100644
--- a/crypto/fipsmodule/rand/rand.c
+++ b/crypto/fipsmodule/rand/rand.c
@@ -170,6 +170,12 @@
} else {
CRYPTO_sysrand_for_seed(out_entropy, out_entropy_len);
}
+
+ if (boringssl_fips_break_test("CRNG")) {
+ // This breaks the "continuous random number generator test" defined in FIPS
+ // 140-2, section 4.9.2, and implemented in |rand_get_seed|.
+ OPENSSL_memset(out_entropy, 0, out_entropy_len);
+ }
}
// In passive entropy mode, entropy is supplied from outside of the module via
diff --git a/crypto/fipsmodule/rand/urandom_test.cc b/crypto/fipsmodule/rand/urandom_test.cc
index 37002f9..dabaf39 100644
--- a/crypto/fipsmodule/rand/urandom_test.cc
+++ b/crypto/fipsmodule/rand/urandom_test.cc
@@ -18,19 +18,15 @@
#include <openssl/ctrdrbg.h>
#include <openssl/rand.h>
-#include "getrandom_fillin.h"
#include "internal.h"
+#include "getrandom_fillin.h"
-#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
- !defined(BORINGSSL_SHARED_LIBRARY) && \
+#if defined(OPENSSL_X86_64) && !defined(BORINGSSL_SHARED_LIBRARY) && \
!defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) && defined(USE_NR_getrandom)
#include <linux/random.h>
#include <sys/ptrace.h>
-#include <sys/socket.h>
#include <sys/syscall.h>
-#include <sys/uio.h>
-#include <sys/un.h>
#include <sys/user.h>
#include "fork_detect.h"
@@ -39,21 +35,6 @@
#define PTRACE_O_EXITKILL (1 << 20)
#endif
-#if defined(BORINGSSL_FIPS)
-static const bool kIsFIPS = true;
-#if defined(OPENSSL_ANDROID)
-static const bool kUsesDaemon = true;
-#else
-static const bool kUsesDaemon = false;
-#endif
-#else
-static const bool kIsFIPS = false;
-static const bool kUsesDaemon = false;
-#endif
-
-// kDaemonWriteLength is the number of bytes that the entropy daemon writes.
-static const size_t kDaemonWriteLength = 496;
-
// This test can be run with $OPENSSL_ia32cap=~0x4000000000000000 in order to
// simulate the absence of RDRAND of machines that have it.
@@ -65,10 +46,6 @@
kOpen,
kUrandomRead,
kUrandomIoctl,
- kSocket,
- kConnect,
- kSocketRead,
- kSocketClose,
kAbort,
};
@@ -105,27 +82,6 @@
return e;
}
- static Event Socket() {
- Event e(Syscall::kSocket);
- return e;
- }
-
- static Event Connect() {
- Event e(Syscall::kConnect);
- return e;
- }
-
- static Event SocketRead(size_t length) {
- Event e(Syscall::kSocketRead);
- e.length = length;
- return e;
- }
-
- static Event SocketClose() {
- Event e(Syscall::kSocketClose);
- return e;
- }
-
static Event Abort() {
Event e(Syscall::kAbort);
return e;
@@ -150,19 +106,6 @@
case Syscall::kUrandomIoctl:
return "ioctl(urandom_fd, RNDGETENTCNT, _)";
- case Syscall::kSocket:
- return "socket(UNIX, STREAM, _)";
-
- case Syscall::kConnect:
- return "connect(sock, _, _)";
-
- case Syscall::kSocketRead:
- snprintf(buf, sizeof(buf), "read(sock_fd, _, %zu)", length);
- break;
-
- case Syscall::kSocketClose:
- return "close(sock)";
-
case Syscall::kAbort:
return "abort()";
}
@@ -203,193 +146,7 @@
static const unsigned GETRANDOM_ERROR = 16;
// Reading from /dev/urandom gives |EINVAL|.
static const unsigned URANDOM_ERROR = 32;
-static const unsigned SOCKET_ERROR = 64;
-static const unsigned CONNECT_ERROR = 128;
-static const unsigned SOCKET_READ_ERROR = 256;
-static const unsigned SOCKET_READ_SHORT = 512;
-static const unsigned NEXT_FLAG = 1024;
-
-// regs_read fetches the registers of |child_pid| and writes them to |out_regs|.
-// That structure will contain at least the following members:
-// syscall: the syscall number, if registers were read just before entering
-// one.
-// args[0..2]: syscall arguments, if registers were read just before
-// entering one.
-// ret: the syscall return value, if registers were read just after finishing
-// one.
-//
-// This call returns true on success and false otherwise.
-static bool regs_read(struct regs *out_regs, int child_pid);
-
-// regs_set_ret sets the return value of the system call that |child_pid| has
-// just finished, to |ret|. It returns true on success and false otherwise.
-static bool regs_set_ret(int child_pid, int ret);
-
-// regs_break_syscall causes the system call that |child_pid| is about to enter
-// to fail to run.
-static bool regs_break_syscall(int child_pid, const struct regs *orig_regs);
-
-#if defined(OPENSSL_X86_64)
-
-struct regs {
- uintptr_t syscall;
- uintptr_t args[3];
- uintptr_t ret;
- struct user_regs_struct regs;
-};
-
-static bool regs_read(struct regs *out_regs, int child_pid) {
- if (ptrace(PTRACE_GETREGS, child_pid, nullptr, &out_regs->regs) != 0) {
- return false;
- }
-
- out_regs->syscall = out_regs->regs.orig_rax;
- out_regs->ret = out_regs->regs.rax;
- out_regs->args[0] = out_regs->regs.rdi;
- out_regs->args[1] = out_regs->regs.rsi;
- out_regs->args[2] = out_regs->regs.rdx;
- return true;
-}
-
-static bool regs_set_ret(int child_pid, int ret) {
- struct regs regs;
- if (!regs_read(®s, child_pid)) {
- return false;
- }
- regs.regs.rax = ret;
- return ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s.regs) == 0;
-}
-
-static bool regs_break_syscall(int child_pid, const struct regs *orig_regs) {
- // Replacing the syscall number with -1 doesn't work on AArch64 thus we set
- // the first argument to -1, which suffices to break the syscalls that we care
- // about here.
- struct user_regs_struct regs;
- memcpy(®s, &orig_regs->regs, sizeof(regs));
- regs.rdi = -1;
- return ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s) == 0;
-}
-
-#elif defined(OPENSSL_AARCH64)
-
-struct regs {
- uintptr_t syscall;
- uintptr_t args[3];
- uintptr_t ret;
- uint64_t regs[9];
-};
-
-static bool regs_read(struct regs *out_regs, int child_pid) {
- struct iovec io;
- io.iov_base = out_regs->regs;
- io.iov_len = sizeof(out_regs->regs);
- if (ptrace(PTRACE_GETREGSET, child_pid, (void *)/*NT_PRSTATUS*/ 1, &io) !=
- 0) {
- return false;
- }
-
- out_regs->syscall = out_regs->regs[8];
- out_regs->ret = out_regs->regs[0];
- out_regs->args[0] = out_regs->regs[0];
- out_regs->args[1] = out_regs->regs[1];
- out_regs->args[2] = out_regs->regs[2];
-
- return true;
-}
-
-static bool regs_set(int child_pid, const struct regs *orig_regs,
- uint64_t x0_value) {
- uint64_t regs[OPENSSL_ARRAY_SIZE(orig_regs->regs)];
- memcpy(regs, orig_regs->regs, sizeof(regs));
- regs[0] = x0_value;
-
- struct iovec io;
- io.iov_base = regs;
- io.iov_len = sizeof(regs);
- return ptrace(PTRACE_SETREGSET, child_pid, (void *)/*NT_PRSTATUS*/ 1, &io) ==
- 0;
-}
-
-static bool regs_set_ret(int child_pid, int ret) {
- struct regs regs;
- return regs_read(®s, child_pid) && regs_set(child_pid, ®s, ret);
-}
-
-static bool regs_break_syscall(int child_pid, const struct regs *orig_regs) {
- // Replacing the syscall number with -1 doesn't work on AArch64 thus we set
- // the first argument to -1, which suffices to break the syscalls that we care
- // about here.
- return regs_set(child_pid, orig_regs, -1);
-}
-
-#endif
-
-// SyscallResult is like std::optional<int>.
-// TODO: use std::optional when we can use C++17.
-class SyscallResult {
- public:
- SyscallResult &operator=(int value) {
- has_value_ = true;
- value_ = value;
- return *this;
- }
-
- int value() const {
- if (!has_value_) {
- abort();
- }
- return value_;
- }
-
- bool has_value() const { return has_value_; }
-
- private:
- bool has_value_ = false;
- int value_ = 0;
-};
-
-// memcpy_to_remote copies |n| bytes from |in_src| in the local address space,
-// to |dest| in the address space of |child_pid|.
-static void memcpy_to_remote(int child_pid, uint64_t dest, const void *in_src,
- size_t n) {
- const uint8_t *src = reinterpret_cast<const uint8_t *>(in_src);
-
- // ptrace always works with ill-defined "words", which appear to be 64-bit
- // on 64-bit systems.
-#if !defined(OPENSSL_64_BIT)
-#error "This code probably doesn't work"
-#endif
-
- while (n) {
- const uintptr_t aligned_addr = dest & ~7;
- const uintptr_t offset = dest - aligned_addr;
- const size_t space = 8 - offset;
- size_t todo = n;
- if (todo > space) {
- todo = space;
- }
-
- uint64_t word;
- if (offset == 0 && todo == 8) {
- word = CRYPTO_load_u64_le(src);
- } else {
- uint8_t bytes[8];
- CRYPTO_store_u64_le(
- bytes, ptrace(PTRACE_PEEKDATA, child_pid,
- reinterpret_cast<void *>(aligned_addr), nullptr));
- memcpy(&bytes[offset], src, todo);
- word = CRYPTO_load_u64_le(bytes);
- }
-
- ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, child_pid,
- reinterpret_cast<void *>(aligned_addr),
- reinterpret_cast<void *>(word)));
-
- src += todo;
- n -= todo;
- dest += todo;
- }
-}
+static const unsigned NEXT_FLAG = 64;
// GetTrace runs |thunk| in a forked process and observes the resulting system
// calls using ptrace. It simulates a variety of failures based on the contents
@@ -428,10 +185,6 @@
// process, if it opens it.
int urandom_fd = -1;
- // sock_fd tracks the file descriptor number for the socket to the entropy
- // daemon, if one is opened.
- int sock_fd = -1;
-
for (;;) {
// Advance the child to the next system call.
ASSERT_EQ(0, ptrace(PTRACE_SYSCALL, child_pid, 0, 0));
@@ -446,130 +199,76 @@
// Otherwise the only valid ptrace event is a system call stop.
ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));
- struct regs regs;
- ASSERT_TRUE(regs_read(®s, child_pid));
+ struct user_regs_struct regs;
+ ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, ®s));
+ const auto syscall_number = regs.orig_rax;
bool is_opening_urandom = false;
- bool is_socket_call = false;
bool is_urandom_ioctl = false;
uintptr_t ioctl_output_addr = 0;
- bool is_socket_read = false;
- uint64_t socket_read_bytes = 0;
- // force_result is unset to indicate that the system call should run
+ // inject_error is zero to indicate that the system call should run
// normally. Otherwise it's, e.g. -EINVAL, to indicate that the system call
- // should not run and that the given value should be injected on return.
- SyscallResult force_result;
+ // should not run and that error should be injected on return.
+ int inject_error = 0;
- switch (regs.syscall) {
+ switch (syscall_number) {
case __NR_getrandom:
if (flags & NO_GETRANDOM) {
- force_result = -ENOSYS;
+ inject_error = -ENOSYS;
} else if (flags & GETRANDOM_ERROR) {
- force_result = -EINVAL;
+ inject_error = -EINVAL;
} else if (flags & GETRANDOM_NOT_READY) {
- if (regs.args[2] & GRND_NONBLOCK) {
- force_result = -EAGAIN;
+ if (regs.rdx & GRND_NONBLOCK) {
+ inject_error = -EAGAIN;
}
}
out_trace->push_back(
- Event::GetRandom(/*length=*/regs.args[1], /*flags=*/regs.args[2]));
+ Event::GetRandom(/*length=*/regs.rsi, /*flags=*/regs.rdx));
break;
case __NR_openat:
-#if defined(OPENSSL_X86_64)
- case __NR_open:
-#endif
- {
+ case __NR_open: {
// It's assumed that any arguments to open(2) are constants in read-only
// memory and thus the pointer in the child's context will also be a
// valid pointer in our address space.
const char *filename = reinterpret_cast<const char *>(
- (regs.syscall == __NR_openat) ? regs.args[1] : regs.args[0]);
+ (syscall_number == __NR_openat) ? regs.rsi : regs.rdi);
out_trace->push_back(Event::Open(filename));
is_opening_urandom = strcmp(filename, "/dev/urandom") == 0;
if (is_opening_urandom && (flags & NO_URANDOM)) {
- force_result = -ENOENT;
+ inject_error = -ENOENT;
}
break;
}
case __NR_read: {
- const int read_fd = regs.args[0];
+ const int read_fd = regs.rdi;
if (urandom_fd >= 0 && urandom_fd == read_fd) {
- out_trace->push_back(Event::UrandomRead(/*length=*/regs.args[2]));
+ out_trace->push_back(Event::UrandomRead(/*length=*/regs.rdx));
if (flags & URANDOM_ERROR) {
- force_result = -EINVAL;
+ inject_error = -EINVAL;
}
- } else if (sock_fd >= 0 && sock_fd == read_fd) {
- uint64_t length = regs.args[2];
- out_trace->push_back(Event::SocketRead(length));
- if (flags & SOCKET_READ_ERROR) {
- force_result = -EINVAL;
- } else {
- is_socket_read = true;
- socket_read_bytes = length;
-
- if (flags & SOCKET_READ_SHORT) {
- ASSERT_GT(socket_read_bytes, 0u);
- socket_read_bytes--;
- flags &= ~SOCKET_READ_SHORT;
- }
- }
- }
- break;
- }
-
- case __NR_close: {
- if (sock_fd >= 0 && static_cast<int>(regs.args[0]) == sock_fd) {
- out_trace->push_back(Event::SocketClose());
- sock_fd = -1;
}
break;
}
case __NR_ioctl: {
- const int ioctl_fd = regs.args[0];
+ const int ioctl_fd = regs.rdi;
if (urandom_fd >= 0 && ioctl_fd == urandom_fd &&
- regs.args[1] == RNDGETENTCNT) {
+ regs.rsi == RNDGETENTCNT) {
out_trace->push_back(Event::UrandomIoctl());
is_urandom_ioctl = true;
- ioctl_output_addr = regs.args[2];
+ ioctl_output_addr = regs.rdx;
}
- break;
- }
-
- case __NR_socket: {
- const int family = regs.args[0];
- const int type = regs.args[1];
- if (family == AF_UNIX && type == SOCK_STREAM) {
- out_trace->push_back(Event::Socket());
- is_socket_call = true;
- if (flags & SOCKET_ERROR) {
- force_result = -EINVAL;
- }
- }
- break;
- }
-
- case __NR_connect: {
- const int connect_fd = regs.args[0];
- if (sock_fd >= 0 && connect_fd == sock_fd) {
- out_trace->push_back(Event::Connect());
- if (flags & CONNECT_ERROR) {
- force_result = -EINVAL;
- } else {
- // The test system might not have an entropy daemon running so
- // inject a success result.
- force_result = 0;
- }
- }
-
- break;
}
}
- if (force_result.has_value()) {
- ASSERT_TRUE(regs_break_syscall(child_pid, ®s));
+ if (inject_error) {
+ // Replace the system call number with -1 to cause the kernel to ignore
+ // the call. The -ENOSYS will be replaced later with the value of
+ // |inject_error|.
+ regs.orig_rax = -1;
+ ASSERT_EQ(0, ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s));
}
ASSERT_EQ(0, ptrace(PTRACE_SYSCALL, child_pid, 0, 0));
@@ -586,14 +285,15 @@
// and know that these events happen in pairs.
ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));
- if (force_result.has_value()) {
- ASSERT_TRUE(regs_set_ret(child_pid, force_result.value()));
+ if (inject_error) {
+ if (inject_error != -ENOSYS) {
+ ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, ®s));
+ regs.rax = inject_error;
+ ASSERT_EQ(0, ptrace(PTRACE_SETREGS, child_pid, nullptr, ®s));
+ }
} else if (is_opening_urandom) {
- ASSERT_TRUE(regs_read(®s, child_pid));
- urandom_fd = regs.ret;
- } else if (is_socket_call) {
- ASSERT_TRUE(regs_read(®s, child_pid));
- sock_fd = regs.ret;
+ ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, ®s));
+ urandom_fd = regs.rax;
} else if (is_urandom_ioctl) {
// The result is the number of bits of entropy that the kernel currently
// believes that it has. urandom.c waits until 256 bits are ready.
@@ -606,19 +306,21 @@
flags &= ~URANDOM_NOT_READY;
}
- memcpy_to_remote(child_pid, ioctl_output_addr, &result, sizeof(result));
- } else if (is_socket_read) {
- // Simulate a response from the entropy daemon since it might not be
- // running on the current system.
- uint8_t entropy[kDaemonWriteLength];
- ASSERT_LE(socket_read_bytes, sizeof(entropy));
-
- for (size_t i = 0; i < sizeof(entropy); i++) {
- entropy[i] = i & 0xff;
- }
- memcpy_to_remote(child_pid, regs.args[1], entropy, socket_read_bytes);
-
- ASSERT_TRUE(regs_set_ret(child_pid, socket_read_bytes));
+ // ptrace always works with ill-defined "words", which appear to be 64-bit
+ // on x86-64. Since the ioctl result is a 32-bit int, do a
+ // read-modify-write to inject the answer.
+ const uintptr_t aligned_addr = ioctl_output_addr & ~7;
+ const uintptr_t offset = ioctl_output_addr - aligned_addr;
+ union {
+ uint64_t word;
+ uint8_t bytes[8];
+ } u;
+ u.word = ptrace(PTRACE_PEEKDATA, child_pid,
+ reinterpret_cast<void *>(aligned_addr), nullptr);
+ memcpy(&u.bytes[offset], &result, sizeof(result));
+ ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, child_pid,
+ reinterpret_cast<void *>(aligned_addr),
+ reinterpret_cast<void *>(u.word)));
}
}
}
@@ -630,46 +332,24 @@
RAND_bytes(&byte, sizeof(byte));
}
-static bool have_fork_detection() { return CRYPTO_get_fork_generation() != 0; }
-
-static bool AppendDaemonEvents(std::vector<Event> *events, unsigned flags) {
- events->push_back(Event::Socket());
- if (flags & SOCKET_ERROR) {
- return false;
- }
-
- bool ret = false;
- events->push_back(Event::Connect());
- if (flags & CONNECT_ERROR) {
- goto out;
- }
-
- events->push_back(Event::SocketRead(kDaemonWriteLength));
- if (flags & SOCKET_READ_ERROR) {
- goto out;
- }
-
- if (flags & SOCKET_READ_SHORT) {
- events->push_back(Event::SocketRead(1));
- }
-
- ret = true;
-
-out:
- events->push_back(Event::SocketClose());
- return ret;
+static bool have_fork_detection() {
+ return CRYPTO_get_fork_generation() != 0;
}
// TestFunctionPRNGModel is a model of how the urandom.c code will behave when
// |TestFunction| is run. It should return the same trace of events that
// |GetTrace| will observe the real code making.
static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
+#if defined(BORINGSSL_FIPS)
+ static const bool is_fips = true;
+#else
+ static const bool is_fips = false;
+#endif
+
std::vector<Event> ret;
bool urandom_probed = false;
bool getrandom_ready = false;
- const bool used_daemon = kUsesDaemon && AppendDaemonEvents(&ret, flags);
-
// Probe for getrandom support
ret.push_back(Event::GetRandom(1, GRND_NONBLOCK));
std::function<void()> wait_for_entropy;
@@ -683,7 +363,7 @@
}
wait_for_entropy = [&ret, &urandom_probed, flags] {
- if (!kIsFIPS || urandom_probed) {
+ if (!is_fips || urandom_probed) {
return;
}
@@ -734,15 +414,13 @@
};
}
- const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN * (kIsFIPS ? 10 : 1);
+ const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN * (is_fips ? 10 : 1);
const size_t kAdditionalDataLength = 32;
if (!have_rdrand()) {
if ((!have_fork_detection() && !sysrand(true, kAdditionalDataLength)) ||
// Initialise CRNGT.
- (!used_daemon && !sysrand(true, kSeedLength + (kIsFIPS ? 16 : 0))) ||
- // Personalisation draw if the daemon was used.
- (used_daemon && !sysrand(false, CTR_DRBG_ENTROPY_LEN)) ||
+ !sysrand(true, kSeedLength + (is_fips ? 16 : 0)) ||
// Second entropy draw.
(!have_fork_detection() && !sysrand(true, kAdditionalDataLength))) {
return ret;
@@ -755,7 +433,7 @@
// Opportuntistic entropy draw in FIPS mode because RDRAND was used.
// In non-FIPS mode it's just drawn from |CRYPTO_sysrand| in a blocking
// way.
- !sysrand(!kIsFIPS, CTR_DRBG_ENTROPY_LEN) ||
+ !sysrand(!is_fips, CTR_DRBG_ENTROPY_LEN) ||
// Second entropy draw's additional data.
(!have_fast_rdrand() && !have_fork_detection() &&
!sysrand(false, kAdditionalDataLength))) {
@@ -802,23 +480,12 @@
SCOPED_TRACE(buf);
for (unsigned flags = 0; flags < NEXT_FLAG; flags++) {
- if (!kUsesDaemon && (flags & (SOCKET_ERROR | CONNECT_ERROR |
- SOCKET_READ_ERROR | SOCKET_READ_SHORT))) {
- // These cases are meaningless unless the code will try to use the entropy
- // daemon.
- continue;
- }
-
TRACE_FLAG(NO_GETRANDOM);
TRACE_FLAG(NO_URANDOM);
TRACE_FLAG(GETRANDOM_NOT_READY);
TRACE_FLAG(URANDOM_NOT_READY);
TRACE_FLAG(GETRANDOM_ERROR);
TRACE_FLAG(URANDOM_ERROR);
- TRACE_FLAG(SOCKET_ERROR);
- TRACE_FLAG(CONNECT_ERROR);
- TRACE_FLAG(SOCKET_READ_ERROR);
- TRACE_FLAG(SOCKET_READ_SHORT);
const std::vector<Event> expected_trace = TestFunctionPRNGModel(flags);
CheckInvariants(expected_trace);
@@ -849,5 +516,5 @@
return 0;
}
-#endif // (X86_64 || AARCH64) && !SHARED_LIBRARY &&
- // !UNSAFE_DETERMINISTIC_MODE && USE_NR_getrandom
+#endif // X86_64 && !SHARED_LIBRARY && !UNSAFE_DETERMINISTIC_MODE &&
+ // USE_NR_getrandom
diff --git a/crypto/rand_extra/passive.c b/crypto/rand_extra/passive.c
index e091bff..f27803b 100644
--- a/crypto/rand_extra/passive.c
+++ b/crypto/rand_extra/passive.c
@@ -15,145 +15,21 @@
#include <openssl/ctrdrbg.h>
#include "../fipsmodule/rand/internal.h"
-#include "../internal.h"
#if defined(BORINGSSL_FIPS)
-#define ENTROPY_READ_LEN \
- (/* last_block size */ 16 + CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD)
-
-#if defined(OPENSSL_ANDROID)
-
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-static struct CRYPTO_STATIC_MUTEX g_socket_history_lock =
- CRYPTO_STATIC_MUTEX_INIT;
-
-// socket_history_t enumerates whether the entropy daemon should be contacted
-// for a given entropy request. Values other than socket_not_yet_attempted are
-// sticky so if the first attempt to read from the daemon fails it's assumed
-// that the daemon is not present and no more attempts will be made. If the
-// first attempt is successful then attempts will be made forever more.
-enum socket_history_t {
- // initial value, no connections to the entropy daemon have been made yet.
- socket_not_yet_attempted = 0,
- // reading from the entropy daemon was successful
- socket_success,
- // reading from the entropy daemon failed.
- socket_failed,
-};
-
-enum socket_history_t g_socket_history = socket_not_yet_attempted;
-
-// DAEMON_RESPONSE_LEN is the number of bytes that the entropy daemon replies
-// with.
-#define DAEMON_RESPONSE_LEN 496
-
-OPENSSL_STATIC_ASSERT(ENTROPY_READ_LEN == DAEMON_RESPONSE_LEN,
- "entropy daemon response length mismatch");
-
-static int get_seed_from_daemon(uint8_t *out_entropy, size_t out_entropy_len) {
- // |RAND_need_entropy| should never call this function for more than
- // |DAEMON_RESPONSE_LEN| bytes.
- if (out_entropy_len > DAEMON_RESPONSE_LEN) {
- abort();
- }
-
- CRYPTO_STATIC_MUTEX_lock_read(&g_socket_history_lock);
- const enum socket_history_t socket_history = g_socket_history;
- CRYPTO_STATIC_MUTEX_unlock_read(&g_socket_history_lock);
-
- if (socket_history == socket_failed) {
- return 0;
- }
-
- int ret = 0;
- const int sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- goto out;
- }
-
- struct sockaddr_un sun;
- memset(&sun, 0, sizeof(sun));
- sun.sun_family = AF_UNIX;
- static const char kSocketPath[] = "/dev/socket/prng_seeder";
- OPENSSL_memcpy(sun.sun_path, kSocketPath, sizeof(kSocketPath));
-
- if (connect(sock, (struct sockaddr *)&sun, sizeof(sun))) {
- goto out;
- }
-
- uint8_t buffer[DAEMON_RESPONSE_LEN];
- size_t done = 0;
- while (done < sizeof(buffer)) {
- ssize_t n;
- do {
- n = read(sock, buffer + done, sizeof(buffer) - done);
- } while (n == -1 && errno == EINTR);
-
- if (n < 1) {
- goto out;
- }
- done += n;
- }
-
- if (done != DAEMON_RESPONSE_LEN) {
- // The daemon should always write |DAEMON_RESPONSE_LEN| bytes on every
- // connection.
- goto out;
- }
-
- assert(out_entropy_len <= DAEMON_RESPONSE_LEN);
- OPENSSL_memcpy(out_entropy, buffer, out_entropy_len);
- ret = 1;
-
-out:
- if (socket_history == socket_not_yet_attempted) {
- CRYPTO_STATIC_MUTEX_lock_write(&g_socket_history_lock);
- if (g_socket_history == socket_not_yet_attempted) {
- g_socket_history = (ret == 0) ? socket_failed : socket_success;
- }
- CRYPTO_STATIC_MUTEX_unlock_write(&g_socket_history_lock);
- }
-
- close(sock);
- return ret;
-}
-
-#else
-
-static int get_seed_from_daemon(uint8_t *out_entropy, size_t out_entropy_len) {
- return 0;
-}
-
-#endif // OPENSSL_ANDROID
-
// RAND_need_entropy is called by the FIPS module when it has blocked because of
// a lack of entropy. This signal is used as an indication to feed it more.
void RAND_need_entropy(size_t bytes_needed) {
- uint8_t buf[ENTROPY_READ_LEN];
+ uint8_t buf[/* last_block size */ 16 +
+ CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
size_t todo = sizeof(buf);
if (todo > bytes_needed) {
todo = bytes_needed;
}
int want_additional_input;
- if (get_seed_from_daemon(buf, todo)) {
- want_additional_input = 1;
- } else {
- CRYPTO_get_seed_entropy(buf, todo, &want_additional_input);
- }
-
- if (boringssl_fips_break_test("CRNG")) {
- // This breaks the "continuous random number generator test" defined in FIPS
- // 140-2, section 4.9.2, and implemented in |rand_get_seed|.
- OPENSSL_memset(buf, 0, todo);
- }
-
+ CRYPTO_get_seed_entropy(buf, todo, &want_additional_input);
RAND_load_entropy(buf, todo, want_additional_input);
}