summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-11-15 01:52:03 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-11-15 01:52:03 +0000
commitc6957566e22929a3c13cdd1b0984433ffbf3e8b6 (patch)
tree5e06709d4eb6fb449856a106fb53f3dd1aa83c39
parentb7ce8aa1705e803a3bc48c6f1e15d56b7cd5ef5a (diff)
parentc022f1c5ca2b97fd459252ca26cd6872a63155d6 (diff)
downloadboringssl-android13-qpr1-s8-release.tar.gz
Change-Id: I3b0f39b3b59665399032b79b7a8d3433351ac575
-rw-r--r--Android.bp91
-rw-r--r--BUILD.generated.bzl1
-rw-r--r--TEST_MAPPING7
-rw-r--r--apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S52
-rw-r--r--linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S52
-rw-r--r--src/crypto/fipsmodule/CMakeLists.txt10
-rw-r--r--src/crypto/fipsmodule/ec/asm/p256-armv8-asm.pl50
-rw-r--r--src/crypto/fipsmodule/ec/p256-nistz.h10
-rw-r--r--src/crypto/fipsmodule/rand/ctrdrbg.c17
-rw-r--r--src/crypto/fipsmodule/rand/ctrdrbg_test.cc14
-rw-r--r--src/crypto/fipsmodule/rand/internal.h36
-rw-r--r--src/crypto/fipsmodule/rand/rand.c100
-rw-r--r--src/crypto/fipsmodule/rand/urandom_test.cc469
-rw-r--r--src/crypto/fipsmodule/self_check/self_check.c1
-rw-r--r--src/crypto/fipsmodule/service_indicator/service_indicator_test.cc1
-rw-r--r--src/crypto/internal.h10
-rw-r--r--src/crypto/rand_extra/passive.c136
-rw-r--r--src/include/openssl/base.h1
-rw-r--r--src/include/openssl/ctrdrbg.h76
-rw-r--r--src/rust/wrapper.h1
-rw-r--r--src/util/fipstools/acvp/modulewrapper/modulewrapper.cc1
-rw-r--r--src/util/fipstools/delocate/delocate.go2
-rw-r--r--src/util/fipstools/test_fips.c1
-rw-r--r--win-aarch64/crypto/fipsmodule/p256-armv8-asm.S56
24 files changed, 815 insertions, 380 deletions
diff --git a/Android.bp b/Android.bp
index 84c70c72..40acf086 100644
--- a/Android.bp
+++ b/Android.bp
@@ -566,3 +566,94 @@ cc_binary {
"src/util/fipstools/test_fips.c",
],
}
+
+// Rust bindings
+rust_bindgen {
+ name: "libbssl_sys_raw",
+ source_stem: "bindings",
+ crate_name: "bssl_sys_raw",
+ host_supported: true,
+ wrapper_src: "src/rust/wrapper.h",
+ vendor_available: true,
+ bindgen_flags: [
+ // Adapted from upstream the src/rust/CMakeLists.txt file at:
+ // https://boringssl.googlesource.com/boringssl/+/refs/heads/master/rust/CMakeLists.txt
+ "--no-derive-default",
+ "--enable-function-attribute-detection",
+ "--use-core",
+ "--size_t-is-usize",
+ "--default-macro-constant-type=signed",
+ "--rustified-enum=point_conversion_form_t",
+ // These are not BoringSSL symbols, they are from glibc
+ // and are not relevant to the build besides throwing warnings
+ // about their 'long double' (aka u128) not being FFI safe.
+ // We block those functions so that the build doesn't
+ // spam warnings.
+ //
+ // https://github.com/rust-lang/rust-bindgen/issues/1549 describes the current problem
+ // and other folks' solutions.
+ "--blocklist-function=strtold",
+ "--blocklist-function=qecvt",
+ "--blocklist-function=qecvt_r",
+ "--blocklist-function=qgcvt",
+ "--blocklist-function=qfcvt",
+ "--blocklist-function=qfcvt_r",
+ ],
+ shared_libs: [
+ "libcrypto",
+ "libssl",
+ ],
+}
+
+// Encapsulate the bindgen-generated layout tests as a test target.
+rust_test {
+ name: "libbssl_sys_raw_test",
+ srcs: [
+ ":libbssl_sys_raw",
+ ],
+ crate_name: "bssl_sys_raw_test",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ clippy_lints: "none",
+ lints: "none",
+}
+
+// Rust's bindgen doesn't cope with macros, so this target includes C functions that
+// do the same thing as macros defined in BoringSSL header files.
+cc_library_static {
+ name: "libbssl_rust_support",
+ host_supported: true,
+ defaults: ["boringssl_flags"],
+ srcs: ["src/rust/rust_wrapper.c"],
+ shared_libs: [
+ "libcrypto",
+ "libssl",
+ ],
+}
+
+// Replace the upstream CMake placeholder with a re-export of all of the local bindgen output.
+gensrcs {
+ name: "libbssl_sys_src",
+ srcs: ["src/rust/src/lib.rs"],
+ cmd: "sed 's@^.{INCLUDES}@pub use bssl_sys_raw::*;@' $(in) > $(out)",
+}
+
+rust_library {
+ name: "libbssl_ffi",
+ host_supported: true,
+ crate_name: "bssl_ffi",
+ visibility: [
+ "//external/rust/crates/openssl",
+ "//system/keymint/boringssl",
+ "//system/security/prng_seeder",
+ ],
+ // Use the modified source with placeholder replaced.
+ srcs: [":libbssl_sys_src"],
+ vendor_available: true,
+ // Since libbssl_sys_raw is not publically visible, we can't
+ // accidentally force a double-link by linking statically, so do so.
+ rlibs: ["libbssl_sys_raw"],
+ static_libs: [
+ "libbssl_rust_support",
+ ],
+}
diff --git a/BUILD.generated.bzl b/BUILD.generated.bzl
index a1bef2ea..bac765af 100644
--- a/BUILD.generated.bzl
+++ b/BUILD.generated.bzl
@@ -154,6 +154,7 @@ crypto_headers = [
"src/include/openssl/conf.h",
"src/include/openssl/cpu.h",
"src/include/openssl/crypto.h",
+ "src/include/openssl/ctrdrbg.h",
"src/include/openssl/curve25519.h",
"src/include/openssl/des.h",
"src/include/openssl/dh.h",
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 00000000..ce976386
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libbssl_sys_raw_test"
+ }
+ ]
+}
diff --git a/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S b/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S
index 0b655fc1..7a5202dd 100644
--- a/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S
+++ b/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S
@@ -31,58 +31,6 @@ LordK:
.byte 69,67,80,95,78,73,83,84,90,50,53,54,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
.align 2
-// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl _ecp_nistz256_to_mont
-.private_extern _ecp_nistz256_to_mont
-
-.align 6
-_ecp_nistz256_to_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- ldr x3,LRR // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,Lpoly+8
- ldr x13,Lpoly+24
- adr x2,LRR // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-
-
-// void ecp_nistz256_from_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl _ecp_nistz256_from_mont
-.private_extern _ecp_nistz256_from_mont
-
-.align 4
-_ecp_nistz256_from_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- mov x3,#1 // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,Lpoly+8
- ldr x13,Lpoly+24
- adr x2,Lone // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-
-
// void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4],
// const BN_ULONG x2[4]);
.globl _ecp_nistz256_mul_mont
diff --git a/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S b/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S
index 2106b851..3efcccb6 100644
--- a/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S
+++ b/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S
@@ -32,58 +32,6 @@
.byte 69,67,80,95,78,73,83,84,90,50,53,54,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
.align 2
-// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_to_mont
-.hidden ecp_nistz256_to_mont
-.type ecp_nistz256_to_mont,%function
-.align 6
-ecp_nistz256_to_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- ldr x3,.LRR // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,.Lpoly+8
- ldr x13,.Lpoly+24
- adr x2,.LRR // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont
-
-// void ecp_nistz256_from_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_from_mont
-.hidden ecp_nistz256_from_mont
-.type ecp_nistz256_from_mont,%function
-.align 4
-ecp_nistz256_from_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- mov x3,#1 // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,.Lpoly+8
- ldr x13,.Lpoly+24
- adr x2,.Lone // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
-
// void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4],
// const BN_ULONG x2[4]);
.globl ecp_nistz256_mul_mont
diff --git a/src/crypto/fipsmodule/CMakeLists.txt b/src/crypto/fipsmodule/CMakeLists.txt
index b99ebc71..a04ef6aa 100644
--- a/src/crypto/fipsmodule/CMakeLists.txt
+++ b/src/crypto/fipsmodule/CMakeLists.txt
@@ -202,19 +202,11 @@ if(FIPS_DELOCATE)
set_target_properties(bcm_hashunset PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(bcm_hashunset PROPERTIES LINKER_LANGUAGE C)
- set(MAYBE_INJECT_HASH_SHA256_FLAG "")
- # If building with OPENSSL_NO_ASM then ARCH will be "generic", but we still
- # need to use SHA-256. Since this only matters for FIPS, we only need to
- # worry about the Linux spelling of AArch64.
- if (ARCH STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
- set(MAYBE_INJECT_HASH_SHA256_FLAG "-sha256")
- endif()
-
go_executable(inject_hash
boringssl.googlesource.com/boringssl/util/fipstools/inject_hash)
add_custom_command(
OUTPUT bcm.o
- COMMAND ./inject_hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset> ${MAYBE_INJECT_HASH_SHA256_FLAG}
+ COMMAND ./inject_hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
DEPENDS bcm_hashunset inject_hash
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
diff --git a/src/crypto/fipsmodule/ec/asm/p256-armv8-asm.pl b/src/crypto/fipsmodule/ec/asm/p256-armv8-asm.pl
index f2926b8e..0d628e73 100644
--- a/src/crypto/fipsmodule/ec/asm/p256-armv8-asm.pl
+++ b/src/crypto/fipsmodule/ec/asm/p256-armv8-asm.pl
@@ -72,56 +72,6 @@ $code.=<<___;
.quad 0xccd1c8aaee00bc4f
.asciz "ECP_NISTZ256 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
-// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_to_mont
-.type ecp_nistz256_to_mont,%function
-.align 6
-ecp_nistz256_to_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- ldr $bi,.LRR // bp[0]
- ldp $a0,$a1,[$ap]
- ldp $a2,$a3,[$ap,#16]
- ldr $poly1,.Lpoly+8
- ldr $poly3,.Lpoly+24
- adr $bp,.LRR // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont
-
-// void ecp_nistz256_from_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_from_mont
-.type ecp_nistz256_from_mont,%function
-.align 4
-ecp_nistz256_from_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- mov $bi,#1 // bp[0]
- ldp $a0,$a1,[$ap]
- ldp $a2,$a3,[$ap,#16]
- ldr $poly1,.Lpoly+8
- ldr $poly3,.Lpoly+24
- adr $bp,.Lone // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
-
// void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4],
// const BN_ULONG x2[4]);
.globl ecp_nistz256_mul_mont
diff --git a/src/crypto/fipsmodule/ec/p256-nistz.h b/src/crypto/fipsmodule/ec/p256-nistz.h
index 0d0a6bea..3f5ea021 100644
--- a/src/crypto/fipsmodule/ec/p256-nistz.h
+++ b/src/crypto/fipsmodule/ec/p256-nistz.h
@@ -64,16 +64,6 @@ static inline void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS],
ecp_nistz256_mul_mont(res, in, ONE);
}
-// ecp_nistz256_to_mont sets |res| to |in|, converted to Montgomery domain
-// by multiplying with RR = 2^512 mod P precomputed for NIST P256 curve.
-static inline void ecp_nistz256_to_mont(BN_ULONG res[P256_LIMBS],
- const BN_ULONG in[P256_LIMBS]) {
- static const BN_ULONG RR[P256_LIMBS] = {
- TOBN(0x00000000, 0x00000003), TOBN(0xfffffffb, 0xffffffff),
- TOBN(0xffffffff, 0xfffffffe), TOBN(0x00000004, 0xfffffffd)};
- ecp_nistz256_mul_mont(res, in, RR);
-}
-
// P-256 scalar operations.
//
diff --git a/src/crypto/fipsmodule/rand/ctrdrbg.c b/src/crypto/fipsmodule/rand/ctrdrbg.c
index 83e7f5b6..2b036828 100644
--- a/src/crypto/fipsmodule/rand/ctrdrbg.c
+++ b/src/crypto/fipsmodule/rand/ctrdrbg.c
@@ -12,7 +12,7 @@
* 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 <openssl/ctrdrbg.h>
#include <openssl/type_check.h>
#include <openssl/mem.h>
@@ -28,6 +28,21 @@
// See table 3.
static const uint64_t kMaxReseedCount = UINT64_C(1) << 48;
+CTR_DRBG_STATE *CTR_DRBG_new(const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
+ const uint8_t *personalization,
+ size_t personalization_len) {
+ CTR_DRBG_STATE *drbg = OPENSSL_malloc(sizeof(CTR_DRBG_STATE));
+ if (drbg == NULL ||
+ !CTR_DRBG_init(drbg, entropy, personalization, personalization_len)) {
+ CTR_DRBG_free(drbg);
+ return NULL;
+ }
+
+ return drbg;
+}
+
+void CTR_DRBG_free(CTR_DRBG_STATE *state) { OPENSSL_free(state); }
+
int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
const uint8_t *personalization, size_t personalization_len) {
diff --git a/src/crypto/fipsmodule/rand/ctrdrbg_test.cc b/src/crypto/fipsmodule/rand/ctrdrbg_test.cc
index 0cc48b14..e6ebbca2 100644
--- a/src/crypto/fipsmodule/rand/ctrdrbg_test.cc
+++ b/src/crypto/fipsmodule/rand/ctrdrbg_test.cc
@@ -14,7 +14,7 @@
#include <gtest/gtest.h>
-#include <openssl/rand.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/sha.h>
#include "internal.h"
@@ -60,6 +60,18 @@ TEST(CTRDRBGTest, Basic) {
CTR_DRBG_clear(&drbg);
}
+TEST(CTRDRBGTest, Allocated) {
+ const uint8_t kSeed[CTR_DRBG_ENTROPY_LEN] = {0};
+
+ CTR_DRBG_STATE *allocated = CTR_DRBG_new(kSeed, nullptr, 0);
+ ASSERT_TRUE(allocated);
+ CTR_DRBG_free(allocated);
+
+ allocated = CTR_DRBG_new(kSeed, nullptr, 1<<20);
+ ASSERT_FALSE(allocated);
+ CTR_DRBG_free(allocated);
+}
+
TEST(CTRDRBGTest, Large) {
const uint8_t kSeed[CTR_DRBG_ENTROPY_LEN] = {0};
diff --git a/src/crypto/fipsmodule/rand/internal.h b/src/crypto/fipsmodule/rand/internal.h
index eccf047f..a770ebc9 100644
--- a/src/crypto/fipsmodule/rand/internal.h
+++ b/src/crypto/fipsmodule/rand/internal.h
@@ -16,6 +16,7 @@
#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
#include <openssl/aes.h>
+#include <openssl/ctrdrbg.h>
#include "../../internal.h"
#include "../modes/internal.h"
@@ -49,10 +50,10 @@ void CRYPTO_get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
int *out_used_cpu);
// RAND_load_entropy supplies |entropy_len| bytes of entropy to the module. The
-// |from_cpu| parameter is true iff the entropy was obtained directly from the
-// CPU.
+// |want_additional_input| parameter is true iff the entropy was obtained from
+// a source other than the system, e.g. directly from the CPU.
void RAND_load_entropy(const uint8_t *entropy, size_t entropy_len,
- int from_cpu);
+ int want_additional_input);
// RAND_need_entropy is implemented outside of the FIPS module and is called
// when the module has stopped because it has run out of entropy.
@@ -95,7 +96,7 @@ int rand_fork_unsafe_buffering_enabled(void);
// CTR_DRBG_STATE contains the state of a CTR_DRBG based on AES-256. See SP
// 800-90Ar1.
-typedef struct {
+struct ctr_drbg_state_st {
AES_KEY ks;
block128_f block;
ctr128_f ctr;
@@ -104,11 +105,7 @@ typedef struct {
uint32_t words[4];
} counter;
uint64_t reseed_counter;
-} CTR_DRBG_STATE;
-
-// See SP 800-90Ar1, table 3.
-#define CTR_DRBG_ENTROPY_LEN 48
-#define CTR_DRBG_MAX_GENERATE_LENGTH 65536
+};
// CTR_DRBG_init initialises |*drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of
// entropy in |entropy| and, optionally, a personalization string up to
@@ -119,27 +116,6 @@ OPENSSL_EXPORT int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
const uint8_t *personalization,
size_t personalization_len);
-// CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy
-// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of
-// additional data. It returns one on success or zero on error.
-OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg,
- const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
- const uint8_t *additional_data,
- size_t additional_data_len);
-
-// CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional
-// data (if any) and then writes |out_len| random bytes to |out|, where
-// |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or
-// zero on error.
-OPENSSL_EXPORT int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out,
- size_t out_len,
- const uint8_t *additional_data,
- size_t additional_data_len);
-
-// CTR_DRBG_clear zeroises the state of |drbg|.
-OPENSSL_EXPORT void CTR_DRBG_clear(CTR_DRBG_STATE *drbg);
-
-
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
OPENSSL_INLINE int have_rdrand(void) {
diff --git a/src/crypto/fipsmodule/rand/rand.c b/src/crypto/fipsmodule/rand/rand.c
index 357be391..54397f9b 100644
--- a/src/crypto/fipsmodule/rand/rand.c
+++ b/src/crypto/fipsmodule/rand/rand.c
@@ -23,6 +23,7 @@
#endif
#include <openssl/chacha.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/mem.h>
#include <openssl/type_check.h>
@@ -162,19 +163,13 @@ static int rdrand(uint8_t *buf, size_t len) {
#if defined(BORINGSSL_FIPS)
void CRYPTO_get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
- int *out_used_cpu) {
- *out_used_cpu = 0;
+ int *out_want_additional_input) {
+ *out_want_additional_input = 0;
if (have_rdrand() && rdrand(out_entropy, out_entropy_len)) {
- *out_used_cpu = 1;
+ *out_want_additional_input = 1;
} 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
@@ -183,20 +178,22 @@ void CRYPTO_get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
struct entropy_buffer {
// bytes contains entropy suitable for seeding a DRBG.
- uint8_t bytes[CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
+ uint8_t
+ bytes[CRNGT_BLOCK_SIZE + CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
// bytes_valid indicates the number of bytes of |bytes| that contain valid
// data.
size_t bytes_valid;
- // from_cpu is true if any of the contents of |bytes| were obtained directly
- // from the CPU.
- int from_cpu;
+ // want_additional_input is true if any of the contents of |bytes| were
+ // obtained via a method other than from the kernel. In these cases entropy
+ // from the kernel is also provided via an additional input to the DRBG.
+ int want_additional_input;
};
DEFINE_BSS_GET(struct entropy_buffer, entropy_buffer);
DEFINE_STATIC_MUTEX(entropy_buffer_lock);
void RAND_load_entropy(const uint8_t *entropy, size_t entropy_len,
- int from_cpu) {
+ int want_additional_input) {
struct entropy_buffer *const buffer = entropy_buffer_bss_get();
CRYPTO_STATIC_MUTEX_lock_write(entropy_buffer_lock_bss_get());
@@ -207,14 +204,15 @@ void RAND_load_entropy(const uint8_t *entropy, size_t entropy_len,
OPENSSL_memcpy(&buffer->bytes[buffer->bytes_valid], entropy, entropy_len);
buffer->bytes_valid += entropy_len;
- buffer->from_cpu |= from_cpu && (entropy_len != 0);
+ buffer->want_additional_input |=
+ want_additional_input && (entropy_len != 0);
CRYPTO_STATIC_MUTEX_unlock_write(entropy_buffer_lock_bss_get());
}
// get_seed_entropy fills |out_entropy_len| bytes of |out_entropy| from the
// global |entropy_buffer|.
static void get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
- int *out_used_cpu) {
+ int *out_want_additional_input) {
struct entropy_buffer *const buffer = entropy_buffer_bss_get();
if (out_entropy_len > sizeof(buffer->bytes)) {
abort();
@@ -227,53 +225,64 @@ static void get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
CRYPTO_STATIC_MUTEX_lock_write(entropy_buffer_lock_bss_get());
}
- *out_used_cpu = buffer->from_cpu;
+ *out_want_additional_input = buffer->want_additional_input;
OPENSSL_memcpy(out_entropy, buffer->bytes, out_entropy_len);
OPENSSL_memmove(buffer->bytes, &buffer->bytes[out_entropy_len],
buffer->bytes_valid - out_entropy_len);
buffer->bytes_valid -= out_entropy_len;
if (buffer->bytes_valid == 0) {
- buffer->from_cpu = 0;
+ buffer->want_additional_input = 0;
}
CRYPTO_STATIC_MUTEX_unlock_write(entropy_buffer_lock_bss_get());
}
-// rand_get_seed fills |seed| with entropy and sets |*out_used_cpu| to one if
-// that entropy came directly from the CPU and zero otherwise.
+// rand_get_seed fills |seed| with entropy and sets
+// |*out_want_additional_input| to one if that entropy came directly from the
+// CPU and zero otherwise.
static void rand_get_seed(struct rand_thread_state *state,
uint8_t seed[CTR_DRBG_ENTROPY_LEN],
- int *out_used_cpu) {
- if (!state->last_block_valid) {
- int unused;
- get_seed_entropy(state->last_block, sizeof(state->last_block), &unused);
- state->last_block_valid = 1;
+ int *out_want_additional_input) {
+ uint8_t entropy_bytes[sizeof(state->last_block) +
+ CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
+ uint8_t *entropy = entropy_bytes;
+ size_t entropy_len = sizeof(entropy_bytes);
+
+ if (state->last_block_valid) {
+ // No need to fill |state->last_block| with entropy from the read.
+ entropy += sizeof(state->last_block);
+ entropy_len -= sizeof(state->last_block);
}
- uint8_t entropy[CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
- get_seed_entropy(entropy, sizeof(entropy), out_used_cpu);
+ get_seed_entropy(entropy, entropy_len, out_want_additional_input);
+
+ if (!state->last_block_valid) {
+ OPENSSL_memcpy(state->last_block, entropy, sizeof(state->last_block));
+ entropy += sizeof(state->last_block);
+ entropy_len -= sizeof(state->last_block);
+ }
// See FIPS 140-2, section 4.9.2. This is the “continuous random number
// generator test” which causes the program to randomly abort. Hopefully the
// rate of failure is small enough not to be a problem in practice.
- if (CRYPTO_memcmp(state->last_block, entropy, CRNGT_BLOCK_SIZE) == 0) {
+ if (CRYPTO_memcmp(state->last_block, entropy, sizeof(state->last_block)) ==
+ 0) {
fprintf(stderr, "CRNGT failed.\n");
BORINGSSL_FIPS_abort();
}
- OPENSSL_STATIC_ASSERT(sizeof(entropy) % CRNGT_BLOCK_SIZE == 0, "");
- for (size_t i = CRNGT_BLOCK_SIZE; i < sizeof(entropy);
- i += CRNGT_BLOCK_SIZE) {
+ assert(entropy_len % CRNGT_BLOCK_SIZE == 0);
+ for (size_t i = CRNGT_BLOCK_SIZE; i < entropy_len; i += CRNGT_BLOCK_SIZE) {
if (CRYPTO_memcmp(entropy + i - CRNGT_BLOCK_SIZE, entropy + i,
CRNGT_BLOCK_SIZE) == 0) {
fprintf(stderr, "CRNGT failed.\n");
BORINGSSL_FIPS_abort();
}
}
- OPENSSL_memcpy(state->last_block,
- entropy + sizeof(entropy) - CRNGT_BLOCK_SIZE,
+ OPENSSL_memcpy(state->last_block, entropy + entropy_len - CRNGT_BLOCK_SIZE,
CRNGT_BLOCK_SIZE);
+ assert(entropy_len == BORINGSSL_FIPS_OVERREAD * CTR_DRBG_ENTROPY_LEN);
OPENSSL_memcpy(seed, entropy, CTR_DRBG_ENTROPY_LEN);
for (size_t i = 1; i < BORINGSSL_FIPS_OVERREAD; i++) {
@@ -285,15 +294,16 @@ static void rand_get_seed(struct rand_thread_state *state,
#else
-// rand_get_seed fills |seed| with entropy and sets |*out_used_cpu| to one if
-// that entropy came directly from the CPU and zero otherwise.
+// rand_get_seed fills |seed| with entropy and sets
+// |*out_want_additional_input| to one if that entropy came directly from the
+// CPU and zero otherwise.
static void rand_get_seed(struct rand_thread_state *state,
uint8_t seed[CTR_DRBG_ENTROPY_LEN],
- int *out_used_cpu) {
+ int *out_want_additional_input) {
// If not in FIPS mode, we don't overread from the system entropy source and
// we don't depend only on the hardware RDRAND.
CRYPTO_sysrand_for_seed(seed, CTR_DRBG_ENTROPY_LEN);
- *out_used_cpu = 0;
+ *out_want_additional_input = 0;
}
#endif
@@ -352,16 +362,16 @@ void RAND_bytes_with_additional_data(uint8_t *out, size_t out_len,
state->last_block_valid = 0;
uint8_t seed[CTR_DRBG_ENTROPY_LEN];
- int used_cpu;
- rand_get_seed(state, seed, &used_cpu);
+ int want_additional_input;
+ rand_get_seed(state, seed, &want_additional_input);
uint8_t personalization[CTR_DRBG_ENTROPY_LEN] = {0};
size_t personalization_len = 0;
#if defined(OPENSSL_URANDOM)
- // If we used RDRAND, also opportunistically read from the system. This
- // avoids solely relying on the hardware once the entropy pool has been
- // initialized.
- if (used_cpu &&
+ // If we used something other than system entropy then also
+ // opportunistically read from the system. This avoids solely relying on the
+ // hardware once the entropy pool has been initialized.
+ if (want_additional_input &&
CRYPTO_sysrand_if_available(personalization, sizeof(personalization))) {
personalization_len = sizeof(personalization);
}
@@ -392,8 +402,8 @@ void RAND_bytes_with_additional_data(uint8_t *out, size_t out_len,
if (state->calls >= kReseedInterval ||
state->fork_generation != fork_generation) {
uint8_t seed[CTR_DRBG_ENTROPY_LEN];
- int used_cpu;
- rand_get_seed(state, seed, &used_cpu);
+ int want_additional_input;
+ rand_get_seed(state, seed, &want_additional_input);
#if defined(BORINGSSL_FIPS)
// Take a read lock around accesses to |state->drbg|. This is needed to
// avoid returning bad entropy if we race with
diff --git a/src/crypto/fipsmodule/rand/urandom_test.cc b/src/crypto/fipsmodule/rand/urandom_test.cc
index 0a1d7539..37002f9f 100644
--- a/src/crypto/fipsmodule/rand/urandom_test.cc
+++ b/src/crypto/fipsmodule/rand/urandom_test.cc
@@ -15,17 +15,22 @@
#include <gtest/gtest.h>
#include <stdlib.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/rand.h>
-#include "internal.h"
#include "getrandom_fillin.h"
+#include "internal.h"
-#if defined(OPENSSL_X86_64) && !defined(BORINGSSL_SHARED_LIBRARY) && \
+#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
+ !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"
@@ -34,6 +39,21 @@
#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.
@@ -45,6 +65,10 @@ struct Event {
kOpen,
kUrandomRead,
kUrandomIoctl,
+ kSocket,
+ kConnect,
+ kSocketRead,
+ kSocketClose,
kAbort,
};
@@ -81,6 +105,27 @@ struct Event {
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;
@@ -105,6 +150,19 @@ struct Event {
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()";
}
@@ -145,7 +203,193 @@ static const unsigned URANDOM_NOT_READY = 8;
static const unsigned GETRANDOM_ERROR = 16;
// Reading from /dev/urandom gives |EINVAL|.
static const unsigned URANDOM_ERROR = 32;
-static const unsigned NEXT_FLAG = 64;
+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(&regs, child_pid)) {
+ return false;
+ }
+ regs.regs.rax = ret;
+ return ptrace(PTRACE_SETREGS, child_pid, nullptr, &regs.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(&regs, &orig_regs->regs, sizeof(regs));
+ regs.rdi = -1;
+ return ptrace(PTRACE_SETREGS, child_pid, nullptr, &regs) == 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(&regs, child_pid) && regs_set(child_pid, &regs, 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;
+ }
+}
// 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
@@ -184,6 +428,10 @@ static void GetTrace(std::vector<Event> *out_trace, unsigned flags,
// 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));
@@ -198,76 +446,130 @@ static void GetTrace(std::vector<Event> *out_trace, unsigned flags,
// Otherwise the only valid ptrace event is a system call stop.
ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));
- struct user_regs_struct regs;
- ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, &regs));
- const auto syscall_number = regs.orig_rax;
+ struct regs regs;
+ ASSERT_TRUE(regs_read(&regs, child_pid));
bool is_opening_urandom = false;
+ bool is_socket_call = false;
bool is_urandom_ioctl = false;
uintptr_t ioctl_output_addr = 0;
- // inject_error is zero to indicate that the system call should run
+ bool is_socket_read = false;
+ uint64_t socket_read_bytes = 0;
+ // force_result is unset 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 error should be injected on return.
- int inject_error = 0;
+ // should not run and that the given value should be injected on return.
+ SyscallResult force_result;
- switch (syscall_number) {
+ switch (regs.syscall) {
case __NR_getrandom:
if (flags & NO_GETRANDOM) {
- inject_error = -ENOSYS;
+ force_result = -ENOSYS;
} else if (flags & GETRANDOM_ERROR) {
- inject_error = -EINVAL;
+ force_result = -EINVAL;
} else if (flags & GETRANDOM_NOT_READY) {
- if (regs.rdx & GRND_NONBLOCK) {
- inject_error = -EAGAIN;
+ if (regs.args[2] & GRND_NONBLOCK) {
+ force_result = -EAGAIN;
}
}
out_trace->push_back(
- Event::GetRandom(/*length=*/regs.rsi, /*flags=*/regs.rdx));
+ Event::GetRandom(/*length=*/regs.args[1], /*flags=*/regs.args[2]));
break;
case __NR_openat:
- case __NR_open: {
+#if defined(OPENSSL_X86_64)
+ case __NR_open:
+#endif
+ {
// 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 *>(
- (syscall_number == __NR_openat) ? regs.rsi : regs.rdi);
+ (regs.syscall == __NR_openat) ? regs.args[1] : regs.args[0]);
out_trace->push_back(Event::Open(filename));
is_opening_urandom = strcmp(filename, "/dev/urandom") == 0;
if (is_opening_urandom && (flags & NO_URANDOM)) {
- inject_error = -ENOENT;
+ force_result = -ENOENT;
}
break;
}
case __NR_read: {
- const int read_fd = regs.rdi;
+ const int read_fd = regs.args[0];
if (urandom_fd >= 0 && urandom_fd == read_fd) {
- out_trace->push_back(Event::UrandomRead(/*length=*/regs.rdx));
+ out_trace->push_back(Event::UrandomRead(/*length=*/regs.args[2]));
if (flags & URANDOM_ERROR) {
- inject_error = -EINVAL;
+ force_result = -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.rdi;
+ const int ioctl_fd = regs.args[0];
if (urandom_fd >= 0 && ioctl_fd == urandom_fd &&
- regs.rsi == RNDGETENTCNT) {
+ regs.args[1] == RNDGETENTCNT) {
out_trace->push_back(Event::UrandomIoctl());
is_urandom_ioctl = true;
- ioctl_output_addr = regs.rdx;
+ ioctl_output_addr = regs.args[2];
+ }
+ 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 (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, &regs));
+ if (force_result.has_value()) {
+ ASSERT_TRUE(regs_break_syscall(child_pid, &regs));
}
ASSERT_EQ(0, ptrace(PTRACE_SYSCALL, child_pid, 0, 0));
@@ -284,15 +586,14 @@ static void GetTrace(std::vector<Event> *out_trace, unsigned flags,
// and know that these events happen in pairs.
ASSERT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));
- if (inject_error) {
- if (inject_error != -ENOSYS) {
- ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, &regs));
- regs.rax = inject_error;
- ASSERT_EQ(0, ptrace(PTRACE_SETREGS, child_pid, nullptr, &regs));
- }
+ if (force_result.has_value()) {
+ ASSERT_TRUE(regs_set_ret(child_pid, force_result.value()));
} else if (is_opening_urandom) {
- ASSERT_EQ(0, ptrace(PTRACE_GETREGS, child_pid, nullptr, &regs));
- urandom_fd = regs.rax;
+ ASSERT_TRUE(regs_read(&regs, child_pid));
+ urandom_fd = regs.ret;
+ } else if (is_socket_call) {
+ ASSERT_TRUE(regs_read(&regs, child_pid));
+ sock_fd = regs.ret;
} 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.
@@ -305,21 +606,19 @@ static void GetTrace(std::vector<Event> *out_trace, unsigned flags,
flags &= ~URANDOM_NOT_READY;
}
- // 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)));
+ 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));
}
}
}
@@ -331,24 +630,46 @@ static void TestFunction() {
RAND_bytes(&byte, sizeof(byte));
}
-static bool have_fork_detection() {
- return CRYPTO_get_fork_generation() != 0;
+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;
}
// 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;
@@ -362,7 +683,7 @@ static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
}
wait_for_entropy = [&ret, &urandom_probed, flags] {
- if (!is_fips || urandom_probed) {
+ if (!kIsFIPS || urandom_probed) {
return;
}
@@ -413,14 +734,15 @@ static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
};
}
- const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN * (is_fips ? 10 : 1);
+ const size_t kSeedLength = CTR_DRBG_ENTROPY_LEN * (kIsFIPS ? 10 : 1);
const size_t kAdditionalDataLength = 32;
if (!have_rdrand()) {
if ((!have_fork_detection() && !sysrand(true, kAdditionalDataLength)) ||
// Initialise CRNGT.
- (is_fips && !sysrand(true, 16)) ||
- !sysrand(true, kSeedLength) ||
+ (!used_daemon && !sysrand(true, kSeedLength + (kIsFIPS ? 16 : 0))) ||
+ // Personalisation draw if the daemon was used.
+ (used_daemon && !sysrand(false, CTR_DRBG_ENTROPY_LEN)) ||
// Second entropy draw.
(!have_fork_detection() && !sysrand(true, kAdditionalDataLength))) {
return ret;
@@ -433,7 +755,7 @@ static std::vector<Event> TestFunctionPRNGModel(unsigned flags) {
// 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(!is_fips, CTR_DRBG_ENTROPY_LEN) ||
+ !sysrand(!kIsFIPS, CTR_DRBG_ENTROPY_LEN) ||
// Second entropy draw's additional data.
(!have_fast_rdrand() && !have_fork_detection() &&
!sysrand(false, kAdditionalDataLength))) {
@@ -480,12 +802,23 @@ TEST(URandomTest, Test) {
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);
@@ -516,5 +849,5 @@ int main(int argc, char **argv) {
return 0;
}
-#endif // X86_64 && !SHARED_LIBRARY && !UNSAFE_DETERMINISTIC_MODE &&
- // USE_NR_getrandom
+#endif // (X86_64 || AARCH64) && !SHARED_LIBRARY &&
+ // !UNSAFE_DETERMINISTIC_MODE && USE_NR_getrandom
diff --git a/src/crypto/fipsmodule/self_check/self_check.c b/src/crypto/fipsmodule/self_check/self_check.c
index fe9c9141..19f57434 100644
--- a/src/crypto/fipsmodule/self_check/self_check.c
+++ b/src/crypto/fipsmodule/self_check/self_check.c
@@ -20,6 +20,7 @@
#include <openssl/aead.h>
#include <openssl/aes.h>
#include <openssl/bn.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
diff --git a/src/crypto/fipsmodule/service_indicator/service_indicator_test.cc b/src/crypto/fipsmodule/service_indicator/service_indicator_test.cc
index d0da9c91..4389b981 100644
--- a/src/crypto/fipsmodule/service_indicator/service_indicator_test.cc
+++ b/src/crypto/fipsmodule/service_indicator/service_indicator_test.cc
@@ -20,6 +20,7 @@
#include <openssl/cipher.h>
#include <openssl/cmac.h>
#include <openssl/crypto.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index c9b5e8e4..2e94399c 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -881,6 +881,16 @@ static inline void CRYPTO_store_u32_be(void *out, uint32_t v) {
OPENSSL_memcpy(out, &v, sizeof(v));
}
+static inline uint64_t CRYPTO_load_u64_le(const void *in) {
+ uint64_t v;
+ OPENSSL_memcpy(&v, in, sizeof(v));
+ return v;
+}
+
+static inline void CRYPTO_store_u64_le(void *out, uint64_t v) {
+ OPENSSL_memcpy(out, &v, sizeof(v));
+}
+
static inline uint64_t CRYPTO_load_u64_be(const void *ptr) {
uint64_t ret;
OPENSSL_memcpy(&ret, ptr, sizeof(ret));
diff --git a/src/crypto/rand_extra/passive.c b/src/crypto/rand_extra/passive.c
index a2b388f8..e091bff5 100644
--- a/src/crypto/rand_extra/passive.c
+++ b/src/crypto/rand_extra/passive.c
@@ -12,23 +12,149 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#include <openssl/base.h>
+#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[CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD];
+ uint8_t buf[ENTROPY_READ_LEN];
size_t todo = sizeof(buf);
if (todo > bytes_needed) {
todo = bytes_needed;
}
- int used_cpu;
- CRYPTO_get_seed_entropy(buf, todo, &used_cpu);
- RAND_load_entropy(buf, todo, used_cpu);
+ 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);
+ }
+
+ RAND_load_entropy(buf, todo, want_additional_input);
}
#endif // FIPS
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 4ab9eca7..c2c953bf 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -391,6 +391,7 @@ typedef struct conf_st CONF;
typedef struct conf_value_st CONF_VALUE;
typedef struct crypto_buffer_pool_st CRYPTO_BUFFER_POOL;
typedef struct crypto_buffer_st CRYPTO_BUFFER;
+typedef struct ctr_drbg_state_st CTR_DRBG_STATE;
typedef struct dh_st DH;
typedef struct dsa_st DSA;
typedef struct ec_group_st EC_GROUP;
diff --git a/src/include/openssl/ctrdrbg.h b/src/include/openssl/ctrdrbg.h
new file mode 100644
index 00000000..62afe0c1
--- /dev/null
+++ b/src/include/openssl/ctrdrbg.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2022, 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_CTRDRBG_H
+#define OPENSSL_HEADER_CTRDRBG_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// FIPS pseudo-random number generator.
+
+
+// CTR-DRBG state objects.
+//
+// CTR_DRBG_STATE contains the state of a FIPS AES-CTR-based pseudo-random
+// number generator. If BoringSSL was built in FIPS mode then this is a FIPS
+// Approved algorithm.
+
+// CTR_DRBG_ENTROPY_LEN is the number of bytes of input entropy. See SP
+// 800-90Ar1, table 3.
+#define CTR_DRBG_ENTROPY_LEN 48
+
+// CTR_DRBG_MAX_GENERATE_LENGTH is the maximum number of bytes that can be
+// generated in a single call to |CTR_DRBG_generate|.
+#define CTR_DRBG_MAX_GENERATE_LENGTH 65536
+
+// CTR_DRBG_new returns an initialized |CTR_DRBG_STATE|, or NULL if either
+// allocation failed or if |personalization_len| is invalid.
+OPENSSL_EXPORT CTR_DRBG_STATE *CTR_DRBG_new(
+ const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *personalization,
+ size_t personalization_len);
+
+// CTR_DRBG_free frees |state| if non-NULL, or else does nothing.
+OPENSSL_EXPORT void CTR_DRBG_free(CTR_DRBG_STATE* state);
+
+// CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy
+// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of
+// additional data. It returns one on success or zero on error.
+OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg,
+ const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
+ const uint8_t *additional_data,
+ size_t additional_data_len);
+
+// CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional
+// data (if any) and then writes |out_len| random bytes to |out|, where
+// |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or
+// zero on error.
+OPENSSL_EXPORT int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out,
+ size_t out_len,
+ const uint8_t *additional_data,
+ size_t additional_data_len);
+
+// CTR_DRBG_clear zeroises the state of |drbg|.
+OPENSSL_EXPORT void CTR_DRBG_clear(CTR_DRBG_STATE *drbg);
+
+
+#if defined(__cplusplus)
+} // extern C
+#endif
+
+#endif // OPENSSL_HEADER_CTRDRBG_H
diff --git a/src/rust/wrapper.h b/src/rust/wrapper.h
index aa5aeedb..ff466423 100644
--- a/src/rust/wrapper.h
+++ b/src/rust/wrapper.h
@@ -18,6 +18,7 @@
#include "../include/openssl/conf.h"
#include "../include/openssl/cpu.h"
#include "../include/openssl/crypto.h"
+#include "../include/openssl/ctrdrbg.h"
#include "../include/openssl/curve25519.h"
#include "../include/openssl/des.h"
#include "../include/openssl/dh.h"
diff --git a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
index f3e583d5..f65492c0 100644
--- a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
+++ b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
@@ -29,6 +29,7 @@
#include <openssl/bn.h>
#include <openssl/cipher.h>
#include <openssl/cmac.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
diff --git a/src/util/fipstools/delocate/delocate.go b/src/util/fipstools/delocate/delocate.go
index 55c86715..84508aa8 100644
--- a/src/util/fipstools/delocate/delocate.go
+++ b/src/util/fipstools/delocate/delocate.go
@@ -439,7 +439,7 @@ func (d *delocation) processAarch64Instruction(statement, instruction *node32) (
argNodes := instructionArgs(instruction.next)
switch instructionName {
- case "cset", "csel", "csetm", "cneg", "csinv", "cinc", "csinc", "csneg":
+ case "ccmn", "ccmp", "cinc", "cinv", "cneg", "csel", "cset", "csetm", "csinc", "csinv", "csneg":
// These functions are special because they take a condition-code name as
// an argument and that looks like a symbol reference.
d.writeNode(statement)
diff --git a/src/util/fipstools/test_fips.c b/src/util/fipstools/test_fips.c
index e192b616..42ed96b2 100644
--- a/src/util/fipstools/test_fips.c
+++ b/src/util/fipstools/test_fips.c
@@ -21,6 +21,7 @@
#include <openssl/aes.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
+#include <openssl/ctrdrbg.h>
#include <openssl/des.h>
#include <openssl/dh.h>
#include <openssl/ecdsa.h>
diff --git a/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S b/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S
index 4ebf3abd..cfffc0d8 100644
--- a/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S
+++ b/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S
@@ -32,62 +32,6 @@ LordK:
.byte 69,67,80,95,78,73,83,84,90,50,53,54,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
.align 2
-// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_to_mont
-
-.def ecp_nistz256_to_mont
- .type 32
-.endef
-.align 6
-ecp_nistz256_to_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- ldr x3,LRR // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,Lpoly+8
- ldr x13,Lpoly+24
- adr x2,LRR // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-
-
-// void ecp_nistz256_from_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
-.globl ecp_nistz256_from_mont
-
-.def ecp_nistz256_from_mont
- .type 32
-.endef
-.align 4
-ecp_nistz256_from_mont:
- AARCH64_SIGN_LINK_REGISTER
- stp x29,x30,[sp,#-32]!
- add x29,sp,#0
- stp x19,x20,[sp,#16]
-
- mov x3,#1 // bp[0]
- ldp x4,x5,[x1]
- ldp x6,x7,[x1,#16]
- ldr x12,Lpoly+8
- ldr x13,Lpoly+24
- adr x2,Lone // &bp[0]
-
- bl __ecp_nistz256_mul_mont
-
- ldp x19,x20,[sp,#16]
- ldp x29,x30,[sp],#32
- AARCH64_VALIDATE_LINK_REGISTER
- ret
-
-
// void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4],
// const BN_ULONG x2[4]);
.globl ecp_nistz256_mul_mont