Move much of rand/ into the FIPS module.

Support for platforms that we don't support FIPS on doesn't need to be
in the module. Also, functions for dealing with whether fork-unsafe
buffering is enabled are left out because they aren't implementing any
cryptography and they use global r/w state, making their inclusion
painful.

Change-Id: I71a0123db6f5449e9dfc7ec7dea0944428e661aa
Reviewed-on: https://boringssl-review.googlesource.com/15084
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
Adam Langley 2017-04-14 11:16:20 -07:00
parent f3d3cee4fe
commit 7784104dd8
22 changed files with 219 additions and 150 deletions

View File

@ -90,7 +90,7 @@ add_subdirectory(curve25519)
# Level 1, depends only on 0.*
add_subdirectory(digest_extra)
add_subdirectory(cipher)
add_subdirectory(rand)
add_subdirectory(rand_extra)
add_subdirectory(bio)
add_subdirectory(bn)
add_subdirectory(obj)
@ -177,7 +177,7 @@ add_library(
$<TARGET_OBJECTS:buf>
$<TARGET_OBJECTS:bn>
$<TARGET_OBJECTS:bio>
$<TARGET_OBJECTS:rand>
$<TARGET_OBJECTS:rand_extra>
$<TARGET_OBJECTS:obj>
$<TARGET_OBJECTS:asn1>
$<TARGET_OBJECTS:engine>
@ -245,7 +245,7 @@ add_executable(
ec/ec_test.cc
err/err_test.cc
evp/evp_extra_test.cc
rand/ctrdrbg_test.cc
fipsmodule/rand/ctrdrbg_test.cc
rsa/rsa_test.cc
$<TARGET_OBJECTS:gtest_main>

View File

@ -117,7 +117,7 @@
#include <openssl/type_check.h>
#include "../internal.h"
#include "../rand/internal.h"
#include "../fipsmodule/rand/internal.h"
static const uint8_t kZeroAdditionalData[32] = {0};

View File

@ -14,6 +14,7 @@ if (${ARCH} STREQUAL "x86_64")
vpaes-x86_64.${ASM_EXT}
aesni-gcm-x86_64.${ASM_EXT}
ghash-x86_64.${ASM_EXT}
rdrand-x86_64.${ASM_EXT}
)
endif()
@ -85,6 +86,7 @@ perlasm(ghash-x86_64.${ASM_EXT} modes/asm/ghash-x86_64.pl)
perlasm(ghash-x86.${ASM_EXT} modes/asm/ghash-x86.pl)
perlasm(md5-586.${ASM_EXT} md5/asm/md5-586.pl)
perlasm(md5-x86_64.${ASM_EXT} md5/asm/md5-x86_64.pl)
perlasm(rdrand-x86_64.${ASM_EXT} rand/asm/rdrand-x86_64.pl)
perlasm(sha1-586.${ASM_EXT} sha/asm/sha1-586.pl)
perlasm(sha1-armv4-large.${ASM_EXT} sha/asm/sha1-armv4-large.pl)
perlasm(sha1-armv8.${ASM_EXT} sha/asm/sha1-armv8.pl)
@ -198,3 +200,14 @@ add_executable(
target_link_libraries(gcm_test crypto)
add_dependencies(all_tests gcm_test)
add_executable(
ctrdrbg_vector_test
rand/ctrdrbg_vector_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(ctrdrbg_vector_test crypto)
add_dependencies(all_tests ctrdrbg_vector_test)

View File

@ -12,6 +12,10 @@
* 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/aead.h>
#include <openssl/aes.h>
#include <openssl/base.h>
@ -19,13 +23,13 @@
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/des.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/ec_key.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
#include "../internal.h"
#include "../rand/internal.h"
#include "rand/internal.h"
#include "aes/aes.c"
#include "aes/key_wrap.c"
@ -41,6 +45,9 @@
#include "modes/gcm.c"
#include "modes/ofb.c"
#include "modes/polyval.c"
#include "rand/ctrdrbg.c"
#include "rand/rand.c"
#include "rand/urandom.c"
#include "sha/sha1-altivec.c"
#include "sha/sha1.c"
#include "sha/sha256.c"

View File

@ -21,13 +21,24 @@
#if defined(BORINGSSL_FIPS)
#define DEFINE_BSS_GET(type, name) \
#define DEFINE_BSS_GET(type, name) \
static type name __attribute__((used)); \
type *name##_bss_get(void);
/* For FIPS builds we require that CRYPTO_ONCE_INIT be zero. */
#define DEFINE_STATIC_ONCE(name) DEFINE_BSS_GET(CRYPTO_once_t, name)
/* For FIPS builds we require that CRYPTO_STATIC_MUTEX_INIT be zero. */
#define DEFINE_STATIC_MUTEX(name) \
DEFINE_BSS_GET(struct CRYPTO_STATIC_MUTEX, name)
#else
#define DEFINE_BSS_GET(type, name) \
static type name; \
static type name; \
static type *name##_bss_get(void) { return &name; }
#define DEFINE_STATIC_ONCE(name) \
static CRYPTO_once_t name = CRYPTO_ONCE_INIT; \
static CRYPTO_once_t *name##_bss_get(void) { return &name; }
#define DEFINE_STATIC_MUTEX(name) \
static struct CRYPTO_STATIC_MUTEX name = CRYPTO_STATIC_MUTEX_INIT; \
static struct CRYPTO_STATIC_MUTEX *name##_bss_get(void) { return &name; }
#endif
/* DEFINE_METHOD_FUNCTION defines a function named |name| which returns a
@ -53,7 +64,7 @@
* order is undefined. See FIPS.md for more details. */
#define DEFINE_METHOD_FUNCTION(type, name) \
DEFINE_BSS_GET(type, name##_storage) \
DEFINE_BSS_GET(CRYPTO_once_t, name##_once) \
DEFINE_STATIC_ONCE(name##_once) \
static void name##_do_init(type *out); \
static void name##_init(void) { name##_do_init(name##_storage_bss_get()); } \
const type *name(void) { \

View File

@ -19,7 +19,7 @@ $output = shift;
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
( $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";

View File

@ -18,7 +18,7 @@
#include <openssl/mem.h>
#include "internal.h"
#include "../cipher/internal.h"
#include "../../cipher/internal.h"
/* Section references in this file refer to SP 800-90Ar1:

View File

@ -18,7 +18,7 @@
#include <openssl/sha.h>
#include "internal.h"
#include "../test/test_util.h"
#include "../../test/test_util.h"
TEST(CTRDRBGTest, Basic) {

View File

@ -17,8 +17,8 @@
#include <openssl/crypto.h>
#include "internal.h"
#include "../test/test_util.h"
#include "../test/file_test.h"
#include "../../test/test_util.h"
#include "../../test/file_test.h"
static bool TestCTRDRBG(FileTest *t, void *arg) {

View File

@ -17,8 +17,8 @@
#include <openssl/aes.h>
#include "../internal.h"
#include "../fipsmodule/modes/internal.h"
#include "../../internal.h"
#include "../modes/internal.h"
#if defined(__cplusplus)
extern "C" {

View File

@ -23,7 +23,7 @@
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
#include "../../internal.h"
/* It's assumed that the operating system always has an unfailing source of
@ -261,53 +261,3 @@ int RAND_bytes(uint8_t *out, size_t out_len) {
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) {}

View File

@ -12,10 +12,6 @@
* 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) && \
@ -38,7 +34,8 @@
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
#include "../delocate.h"
#include "../../internal.h"
#if defined(OPENSSL_LINUX)
@ -78,30 +75,42 @@
#endif /* OPENSSL_LINUX */
/* requested_lock is used to protect the |*_requested| variables. */
static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT;
/* rand_lock is used to protect the |*_requested| variables. */
DEFINE_STATIC_MUTEX(rand_lock);
/* The following constants are magic values of |urandom_fd|. */
static const int kUnset = -2;
static const int kUnset = 0;
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 */;
* |rand_lock|. */
DEFINE_BSS_GET(int, urandom_fd_requested);
/* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */
static int urandom_fd = -2 /* kUnset */;
DEFINE_BSS_GET(int, urandom_fd);
static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
DEFINE_STATIC_ONCE(rand_once);
#if defined(USE_SYS_getrandom) || defined(BORINGSSL_FIPS)
/* message writes |msg| to stderr. We use this because referencing |stderr|
* with |fprintf| generates relocations, which is a problem inside the FIPS
* module. */
static void message(const char *msg) {
ssize_t r;
do {
r = write(2, msg, strlen(msg));
} while (r == -1 && errno == EINTR);
}
#endif
/* 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);
int fd = urandom_fd_requested;
CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock);
CRYPTO_STATIC_MUTEX_lock_read(rand_lock_bss_get());
int fd = *urandom_fd_requested_bss_get();
CRYPTO_STATIC_MUTEX_unlock_read(rand_lock_bss_get());
#if defined(USE_SYS_getrandom)
uint8_t dummy;
@ -109,20 +118,21 @@ static void init_once(void) {
syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
if (getrandom_ret == 1) {
urandom_fd = kHaveGetrandom;
*urandom_fd_bss_get() = 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");
message(
"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;
*urandom_fd_bss_get() = kHaveGetrandom;
return;
}
}
@ -138,6 +148,19 @@ static void init_once(void) {
abort();
}
assert(kUnset == 0);
if (fd == kUnset) {
/* Because we want to keep |urandom_fd| in the BSS, we have to initialise
* it to zero. But zero is a valid file descriptor too. Thus if open
* returns zero for /dev/urandom, we dup it to get a non-zero number. */
fd = dup(fd);
close(kUnset);
if (fd <= 0) {
abort();
}
}
#if defined(BORINGSSL_FIPS)
/* In FIPS mode we ensure that the kernel has sufficient entropy before
* continuing. This is automatically handled by getrandom, which requires
@ -147,9 +170,9 @@ static void init_once(void) {
for (;;) {
int entropy_bits;
if (ioctl(fd, RNDGETENTCNT, &entropy_bits)) {
fprintf(stderr,
"RNDGETENTCNT on /dev/urandom failed. We cannot continue in this "
"case when in FIPS mode.\n");
message(
"RNDGETENTCNT on /dev/urandom failed. We cannot continue in this "
"case when in FIPS mode.\n");
abort();
}
@ -159,10 +182,10 @@ static void init_once(void) {
}
if (first_iteration) {
fprintf(stderr,
"The kernel entropy pool contains too few bits: have %d, want "
"%d. This process is built in FIPS mode and will block until "
"sufficient entropy is available.\n", entropy_bits, kBitsNeeded);
message(
"The kernel entropy pool contains too few bits. This process is "
"built in FIPS mode and will block until sufficient entropy is "
"available.\n");
}
first_iteration = 0;
@ -182,7 +205,7 @@ static void init_once(void) {
abort();
}
}
urandom_fd = fd;
*urandom_fd_bss_get() = fd;
}
void RAND_set_urandom_fd(int fd) {
@ -191,14 +214,27 @@ void RAND_set_urandom_fd(int fd) {
abort();
}
CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
urandom_fd_requested = fd;
CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
assert(kUnset == 0);
if (fd == kUnset) {
/* Because we want to keep |urandom_fd| in the BSS, we have to initialise
* it to zero. But zero is a valid file descriptor too. Thus if dup
* returned zero we dup it again to get a non-zero number. */
fd = dup(fd);
close(kUnset);
CRYPTO_once(&once, init_once);
if (urandom_fd == kHaveGetrandom) {
if (fd <= 0) {
abort();
}
}
CRYPTO_STATIC_MUTEX_lock_write(rand_lock_bss_get());
*urandom_fd_requested_bss_get() = fd;
CRYPTO_STATIC_MUTEX_unlock_write(rand_lock_bss_get());
CRYPTO_once(rand_once_bss_get(), init_once);
if (*urandom_fd_bss_get() == kHaveGetrandom) {
close(fd);
} else if (urandom_fd != fd) {
} else if (*urandom_fd_bss_get() != fd) {
abort(); // Already initialized.
}
}
@ -215,7 +251,7 @@ static char fill_with_entropy(uint8_t *out, size_t len) {
while (len > 0) {
ssize_t r;
if (urandom_fd == kHaveGetrandom) {
if (*urandom_fd_bss_get() == kHaveGetrandom) {
#if defined(USE_SYS_getrandom)
do {
r = syscall(SYS_getrandom, out, len, 0 /* no flags */);
@ -236,7 +272,7 @@ static char fill_with_entropy(uint8_t *out, size_t len) {
#endif
} else {
do {
r = read(urandom_fd, out, len);
r = read(*urandom_fd_bss_get(), out, len);
} while (r == -1 && errno == EINTR);
}
@ -256,7 +292,7 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
return;
}
CRYPTO_once(&once, init_once);
CRYPTO_once(rand_once_bss_get(), init_once);
if (!fill_with_entropy(out, requested)) {
abort();

View File

@ -1,38 +0,0 @@
include_directories(../../include)
if (${ARCH} STREQUAL "x86_64")
set(
RAND_ARCH_SOURCES
rdrand-x86_64.${ASM_EXT}
)
endif()
add_library(
rand
OBJECT
ctrdrbg.c
deterministic.c
forkunsafe.c
fuchsia.c
rand.c
urandom.c
windows.c
${RAND_ARCH_SOURCES}
)
perlasm(rdrand-x86_64.${ASM_EXT} asm/rdrand-x86_64.pl)
add_executable(
ctrdrbg_vector_test
ctrdrbg_vector_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(ctrdrbg_vector_test crypto)
add_dependencies(all_tests ctrdrbg_vector_test)

View File

@ -0,0 +1,12 @@
include_directories(../../include)
add_library(
rand_extra
OBJECT
forkunsafe.c
fuchsia.c
rand_extra.c
windows.c
)

View File

@ -20,8 +20,8 @@
#include <openssl/chacha.h>
#include "internal.h"
#include "../internal.h"
#include "../fipsmodule/rand/internal.h"
/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occurred.

View File

@ -16,7 +16,7 @@
#include <stdlib.h>
#include "internal.h"
#include "../fipsmodule/rand/internal.h"
/* g_buffering_enabled is true if fork-unsafe buffering has been enabled. */

View File

@ -21,7 +21,7 @@
#include <magenta/syscalls.h>
#include "internal.h"
#include "../fipsmodule/rand/internal.h"
void CRYPTO_sysrand(uint8_t *out, size_t requested) {
while (requested > 0) {

View File

@ -0,0 +1,68 @@
/* 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>
#include <limits.h>
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) {}

View File

@ -32,7 +32,7 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
OPENSSL_MSVC_PRAGMA(warning(pop))
#include "internal.h"
#include "../fipsmodule/rand/internal.h"
void CRYPTO_sysrand(uint8_t *out, size_t requested) {

View File

@ -103,6 +103,9 @@ static void call_once_thread(void) {
static CRYPTO_once_t once_init_value = CRYPTO_ONCE_INIT;
static CRYPTO_once_t once_bss;
static struct CRYPTO_STATIC_MUTEX mutex_init_value = CRYPTO_STATIC_MUTEX_INIT;
static struct CRYPTO_STATIC_MUTEX mutex_bss;
static int test_once(void) {
if (g_once_init_called != 0) {
fprintf(stderr, "g_once_init_called was non-zero at start.\n");
@ -127,13 +130,20 @@ static int test_once(void) {
}
if (FIPS_mode()) {
/* Our FIPS tooling currently requires that |CRYPTO_ONCE_INIT| is all
* zeros, so the |CRYPTO_once_t| is placed in the bss. */
/* Our FIPS tooling currently requires that |CRYPTO_ONCE_INIT| and
* |CRYPTO_STATIC_MUTEX_INIT| are all zeros and so can be placed in the BSS
* section. */
if (OPENSSL_memcmp((void *)&once_init_value, (void *)&once_bss,
sizeof(CRYPTO_once_t)) != 0) {
fprintf(stderr, "CRYPTO_ONCE_INIT did not expand to all zeros.\n");
return 0;
}
if (OPENSSL_memcmp((void *)&mutex_init_value, (void *)&mutex_bss,
sizeof(struct CRYPTO_STATIC_MUTEX)) != 0) {
fprintf(stderr, "CRYPTO_STATIC_MUTEX did not expand to all zeros.\n");
return 0;
}
}
return 1;

View File

@ -54,7 +54,7 @@
["crypto/pkcs8/pkcs8_test"],
["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_tests.txt"],
["crypto/pool/pool_test"],
["crypto/rand/ctrdrbg_vector_test", "crypto/rand/ctrdrbg_vectors.txt"],
["crypto/fipsmodule/ctrdrbg_vector_test", "crypto/fipsmodule/rand/ctrdrbg_vectors.txt"],
["crypto/refcount_test"],
["crypto/thread_test"],
["crypto/x509/x509_test"],