Snap for 9143244 from aa6b738d994f6e44a0ec25a3dc16c74c748dc951 to tm-qpr2-release

Change-Id: I6a3c290da284aa89e3e0e4105a5545ee5a0bd38e
diff --git a/Android.bp b/Android.bp
index 84c70c7..40acf08 100644
--- a/Android.bp
+++ b/Android.bp
@@ -566,3 +566,94 @@
         "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 a1bef2e..bac765a 100644
--- a/BUILD.generated.bzl
+++ b/BUILD.generated.bzl
@@ -154,6 +154,7 @@
     "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 0000000..ce97638
--- /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 0b655fc..7a5202d 100644
--- a/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S
+++ b/apple-aarch64/crypto/fipsmodule/p256-armv8-asm.S
@@ -31,58 +31,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
-.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 2106b85..3efcccb 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 b99ebc7..a04ef6a 100644
--- a/src/crypto/fipsmodule/CMakeLists.txt
+++ b/src/crypto/fipsmodule/CMakeLists.txt
@@ -202,19 +202,11 @@
   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 f2926b8..0d628e7 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 @@
 .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 0d0a6be..3f5ea02 100644
--- a/src/crypto/fipsmodule/ec/p256-nistz.h
+++ b/src/crypto/fipsmodule/ec/p256-nistz.h
@@ -64,16 +64,6 @@
   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 83e7f5b..2b03682 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 0cc48b1..e6ebbca 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 @@
   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 eccf047..a770ebc 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 @@
                              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 @@
 
 // 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 @@
     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 @@
                                  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 357be39..54397f9 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 @@
 #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 @@
 
 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 @@
 
   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 @@
     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 @@
 
 #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 @@
 
     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 @@
   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 0a1d753..37002f9 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 @@
     kOpen,
     kUrandomRead,
     kUrandomIoctl,
+    kSocket,
+    kConnect,
+    kSocketRead,
+    kSocketClose,
     kAbort,
   };
 
@@ -81,6 +105,27 @@
     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 @@
       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 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 @@
   // 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 @@
     // 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 @@
     // 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 @@
         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 @@
   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 @@
     }
 
     wait_for_entropy = [&ret, &urandom_probed, flags] {
-      if (!is_fips || urandom_probed) {
+      if (!kIsFIPS || urandom_probed) {
         return;
       }
 
@@ -413,14 +734,15 @@
     };
   }
 
-  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 @@
       // 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 @@
   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 @@
   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 fe9c914..19f5743 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 d0da9c9..4389b98 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 c9b5e8e..2e94399 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -881,6 +881,16 @@
   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 a2b388f..e091bff 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 4ab9eca..c2c953b 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -391,6 +391,7 @@
 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 0000000..62afe0c
--- /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 aa5aeed..ff46642 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 f3e583d..f65492c 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 55c8671..84508aa 100644
--- a/src/util/fipstools/delocate/delocate.go
+++ b/src/util/fipstools/delocate/delocate.go
@@ -439,7 +439,7 @@
 	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 e192b61..42ed96b 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 4ebf3ab..cfffc0d 100644
--- a/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S
+++ b/win-aarch64/crypto/fipsmodule/p256-armv8-asm.S
@@ -32,62 +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
-
-.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