Snap for 10118161 from d513cbc24acec3bfefe3fccb0d963bfcea876a03 to aml-frc-release

Change-Id: Ifb1075d30d2d46c9a209bd1cbfc8fe08bf82fc33
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 26c3e0e..20dbea6 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-d89702704febab30774e8af22450899af297bfb0
+32b51305debe43e38e7bf2c2b13c4ebf3b474e80
diff --git a/BUILD.generated.bzl b/BUILD.generated.bzl
index 8aade95..738e105 100644
--- a/BUILD.generated.bzl
+++ b/BUILD.generated.bzl
@@ -59,6 +59,7 @@
     "src/crypto/fipsmodule/ec/wnaf.c",
     "src/crypto/fipsmodule/ecdh/ecdh.c",
     "src/crypto/fipsmodule/ecdsa/ecdsa.c",
+    "src/crypto/fipsmodule/hkdf/hkdf.c",
     "src/crypto/fipsmodule/hmac/hmac.c",
     "src/crypto/fipsmodule/md4/md4.c",
     "src/crypto/fipsmodule/md5/md5.c",
@@ -259,14 +260,17 @@
     "src/crypto/pkcs8/internal.h",
     "src/crypto/poly1305/internal.h",
     "src/crypto/pool/internal.h",
+    "src/crypto/rsa_extra/internal.h",
     "src/crypto/trust_token/internal.h",
     "src/crypto/x509/internal.h",
     "src/crypto/x509v3/ext_dat.h",
     "src/crypto/x509v3/internal.h",
     "src/third_party/fiat/curve25519_32.h",
     "src/third_party/fiat/curve25519_64.h",
+    "src/third_party/fiat/curve25519_64_msvc.h",
     "src/third_party/fiat/p256_32.h",
     "src/third_party/fiat/p256_64.h",
+    "src/third_party/fiat/p256_64_msvc.h",
 ]
 
 crypto_sources = [
@@ -376,7 +380,6 @@
     "src/crypto/ex_data.c",
     "src/crypto/fipsmodule/bcm.c",
     "src/crypto/fipsmodule/fips_shared_support.c",
-    "src/crypto/hkdf/hkdf.c",
     "src/crypto/hpke/hpke.c",
     "src/crypto/hrss/hrss.c",
     "src/crypto/kyber/keccak.c",
@@ -412,6 +415,7 @@
     "src/crypto/refcount_c11.c",
     "src/crypto/refcount_lock.c",
     "src/crypto/rsa_extra/rsa_asn1.c",
+    "src/crypto/rsa_extra/rsa_crypt.c",
     "src/crypto/rsa_extra/rsa_print.c",
     "src/crypto/siphash/siphash.c",
     "src/crypto/stack/stack.c",
diff --git a/BUILD.generated_tests.bzl b/BUILD.generated_tests.bzl
index 96d1183..92dec1e 100644
--- a/BUILD.generated_tests.bzl
+++ b/BUILD.generated_tests.bzl
@@ -47,6 +47,7 @@
     "src/crypto/pkcs8/internal.h",
     "src/crypto/poly1305/internal.h",
     "src/crypto/pool/internal.h",
+    "src/crypto/rsa_extra/internal.h",
     "src/crypto/test/abi_test.h",
     "src/crypto/test/file_test.cc",
     "src/crypto/test/file_test.h",
@@ -71,8 +72,10 @@
     "src/ssl/test/test_state.h",
     "src/third_party/fiat/curve25519_32.h",
     "src/third_party/fiat/curve25519_64.h",
+    "src/third_party/fiat/curve25519_64_msvc.h",
     "src/third_party/fiat/p256_32.h",
     "src/third_party/fiat/p256_64.h",
+    "src/third_party/fiat/p256_64_msvc.h",
 ]
 
 crypto_test_sources = [
@@ -110,13 +113,13 @@
     "src/crypto/fipsmodule/ec/ec_test.cc",
     "src/crypto/fipsmodule/ec/p256-nistz_test.cc",
     "src/crypto/fipsmodule/ecdsa/ecdsa_test.cc",
+    "src/crypto/fipsmodule/hkdf/hkdf_test.cc",
     "src/crypto/fipsmodule/md5/md5_test.cc",
     "src/crypto/fipsmodule/modes/gcm_test.cc",
     "src/crypto/fipsmodule/rand/ctrdrbg_test.cc",
     "src/crypto/fipsmodule/rand/fork_detect_test.cc",
     "src/crypto/fipsmodule/service_indicator/service_indicator_test.cc",
     "src/crypto/fipsmodule/sha/sha_test.cc",
-    "src/crypto/hkdf/hkdf_test.cc",
     "src/crypto/hmac_extra/hmac_test.cc",
     "src/crypto/hpke/hpke_test.cc",
     "src/crypto/hrss/hrss_test.cc",
diff --git a/android-sources.cmake b/android-sources.cmake
index ae46f6d..b54eb16 100644
--- a/android-sources.cmake
+++ b/android-sources.cmake
@@ -123,7 +123,6 @@
   ${BORINGSSL_ROOT}src/crypto/ex_data.c
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/bcm.c
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/fips_shared_support.c
-  ${BORINGSSL_ROOT}src/crypto/hkdf/hkdf.c
   ${BORINGSSL_ROOT}src/crypto/hpke/hpke.c
   ${BORINGSSL_ROOT}src/crypto/hrss/hrss.c
   ${BORINGSSL_ROOT}src/crypto/kyber/keccak.c
@@ -159,6 +158,7 @@
   ${BORINGSSL_ROOT}src/crypto/refcount_c11.c
   ${BORINGSSL_ROOT}src/crypto/refcount_lock.c
   ${BORINGSSL_ROOT}src/crypto/rsa_extra/rsa_asn1.c
+  ${BORINGSSL_ROOT}src/crypto/rsa_extra/rsa_crypt.c
   ${BORINGSSL_ROOT}src/crypto/rsa_extra/rsa_print.c
   ${BORINGSSL_ROOT}src/crypto/siphash/siphash.c
   ${BORINGSSL_ROOT}src/crypto/stack/stack.c
@@ -340,13 +340,13 @@
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/ec/ec_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/ec/p256-nistz_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/ecdsa/ecdsa_test.cc
+  ${BORINGSSL_ROOT}src/crypto/fipsmodule/hkdf/hkdf_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/md5/md5_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/modes/gcm_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/rand/ctrdrbg_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/rand/fork_detect_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/service_indicator/service_indicator_test.cc
   ${BORINGSSL_ROOT}src/crypto/fipsmodule/sha/sha_test.cc
-  ${BORINGSSL_ROOT}src/crypto/hkdf/hkdf_test.cc
   ${BORINGSSL_ROOT}src/crypto/hmac_extra/hmac_test.cc
   ${BORINGSSL_ROOT}src/crypto/hpke/hpke_test.cc
   ${BORINGSSL_ROOT}src/crypto/hrss/hrss_test.cc
diff --git a/eureka.mk b/eureka.mk
index 1593859..b5991a1 100644
--- a/eureka.mk
+++ b/eureka.mk
@@ -121,7 +121,6 @@
   src/crypto/ex_data.c\
   src/crypto/fipsmodule/bcm.c\
   src/crypto/fipsmodule/fips_shared_support.c\
-  src/crypto/hkdf/hkdf.c\
   src/crypto/hpke/hpke.c\
   src/crypto/hrss/hrss.c\
   src/crypto/kyber/keccak.c\
@@ -157,6 +156,7 @@
   src/crypto/refcount_c11.c\
   src/crypto/refcount_lock.c\
   src/crypto/rsa_extra/rsa_asn1.c\
+  src/crypto/rsa_extra/rsa_crypt.c\
   src/crypto/rsa_extra/rsa_print.c\
   src/crypto/siphash/siphash.c\
   src/crypto/stack/stack.c\
diff --git a/sources.bp b/sources.bp
index a544492..afb5546 100644
--- a/sources.bp
+++ b/sources.bp
@@ -122,7 +122,6 @@
         "src/crypto/evp/sign.c",
         "src/crypto/ex_data.c",
         "src/crypto/fipsmodule/fips_shared_support.c",
-        "src/crypto/hkdf/hkdf.c",
         "src/crypto/hpke/hpke.c",
         "src/crypto/hrss/hrss.c",
         "src/crypto/kyber/keccak.c",
@@ -158,6 +157,7 @@
         "src/crypto/refcount_c11.c",
         "src/crypto/refcount_lock.c",
         "src/crypto/rsa_extra/rsa_asn1.c",
+        "src/crypto/rsa_extra/rsa_crypt.c",
         "src/crypto/rsa_extra/rsa_print.c",
         "src/crypto/siphash/siphash.c",
         "src/crypto/stack/stack.c",
@@ -459,13 +459,13 @@
         "src/crypto/fipsmodule/ec/ec_test.cc",
         "src/crypto/fipsmodule/ec/p256-nistz_test.cc",
         "src/crypto/fipsmodule/ecdsa/ecdsa_test.cc",
+        "src/crypto/fipsmodule/hkdf/hkdf_test.cc",
         "src/crypto/fipsmodule/md5/md5_test.cc",
         "src/crypto/fipsmodule/modes/gcm_test.cc",
         "src/crypto/fipsmodule/rand/ctrdrbg_test.cc",
         "src/crypto/fipsmodule/rand/fork_detect_test.cc",
         "src/crypto/fipsmodule/service_indicator/service_indicator_test.cc",
         "src/crypto/fipsmodule/sha/sha_test.cc",
-        "src/crypto/hkdf/hkdf_test.cc",
         "src/crypto/hmac_extra/hmac_test.cc",
         "src/crypto/hpke/hpke_test.cc",
         "src/crypto/hrss/hrss_test.cc",
diff --git a/sources.mk b/sources.mk
index 1f1ee6e..ab80efb 100644
--- a/sources.mk
+++ b/sources.mk
@@ -121,7 +121,6 @@
   src/crypto/ex_data.c\
   src/crypto/fipsmodule/bcm.c\
   src/crypto/fipsmodule/fips_shared_support.c\
-  src/crypto/hkdf/hkdf.c\
   src/crypto/hpke/hpke.c\
   src/crypto/hrss/hrss.c\
   src/crypto/kyber/keccak.c\
@@ -157,6 +156,7 @@
   src/crypto/refcount_c11.c\
   src/crypto/refcount_lock.c\
   src/crypto/rsa_extra/rsa_asn1.c\
+  src/crypto/rsa_extra/rsa_crypt.c\
   src/crypto/rsa_extra/rsa_print.c\
   src/crypto/siphash/siphash.c\
   src/crypto/stack/stack.c\
diff --git a/src/BUILDING.md b/src/BUILDING.md
index bedba3c..4dcd0f4 100644
--- a/src/BUILDING.md
+++ b/src/BUILDING.md
@@ -48,17 +48,13 @@
 
 Using Ninja (note the 'N' is capitalized in the cmake invocation):
 
-    mkdir build
-    cd build
-    cmake -GNinja ..
-    ninja
+    cmake -GNinja -B build
+    ninja -C build
 
 Using Make (does not work on Windows):
 
-    mkdir build
-    cd build
-    cmake ..
-    make
+    cmake -B build
+    make -C build
 
 You usually don't need to run `cmake` again after changing `CMakeLists.txt`
 files because the build scripts will detect changes to them and rebuild
@@ -69,10 +65,9 @@
 `cmake` to configure a release build.
 
 If you want to cross-compile then there is an example toolchain file for 32-bit
-Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like
-this:
+Intel in `util/`. Wipe out the build directory, run `cmake` like this:
 
-    cmake -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-toolchain.cmake -GNinja ..
+    cmake -B build -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-toolchain.cmake -GNinja
 
 If you want to build as a shared library, pass `-DBUILD_SHARED_LIBS=1`. On
 Windows, where functions need to be tagged with `dllimport` when coming from a
@@ -93,12 +88,12 @@
 or later. This has been tested with version r16b of the NDK.
 
 Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the
-directory. Then make a build directory as above and run CMake like this:
+directory. Then run CMake like this:
 
     cmake -DANDROID_ABI=armeabi-v7a \
           -DANDROID_PLATFORM=android-19 \
           -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-          -GNinja ..
+          -GNinja -B build
 
 Once you've run that, Ninja should produce Android-compatible binaries.  You
 can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or
@@ -140,7 +135,7 @@
 should specify the prefix to add to all symbols, and the
 `BORINGSSL_PREFIX_SYMBOLS` CMake variable should specify the path to a file
 which contains a list of symbols which should be prefixed (one per line;
-comments are supported with `#`). In other words, `cmake ..
+comments are supported with `#`). In other words, `cmake -B build
 -DBORINGSSL_PREFIX=MY_CUSTOM_PREFIX
 -DBORINGSSL_PREFIX_SYMBOLS=/path/to/symbols.txt` will configure the build to add
 the prefix `MY_CUSTOM_PREFIX` to all of the symbols listed in
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a1fb153..aac5f0d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,6 +17,7 @@
 
 include(sources.cmake)
 include(cmake/go.cmake)
+include(cmake/paths.cmake)
 include(cmake/perlasm.cmake)
 
 enable_language(C)
diff --git a/src/FUZZING.md b/src/FUZZING.md
index 5653acc..89cf5e9 100644
--- a/src/FUZZING.md
+++ b/src/FUZZING.md
@@ -7,10 +7,8 @@
 In order to build the fuzz tests you will need at least Clang 6.0. Pass `-DFUZZ=1` on the CMake command line to enable building BoringSSL with coverage and AddressSanitizer, and to build the fuzz test binaries. You'll probably need to set the `CC` and `CXX` environment variables too, like this:
 
 ```
-mkdir build
-cd build
-CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 ..
-ninja
+CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 -B build
+ninja -C build
 ```
 
 
diff --git a/src/cmake/go.cmake b/src/cmake/go.cmake
index 61a01f5..966ad32 100644
--- a/src/cmake/go.cmake
+++ b/src/cmake/go.cmake
@@ -34,10 +34,7 @@
   else()
     # Ninja expects the target in the depfile to match the output. This is a
     # relative path from the build directory.
-    string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length)
-    math(EXPR root_dir_length "${root_dir_length} + 1")
-    string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target)
-    set(target "${target}/${dest}")
+    binary_dir_relative_path(${dest} target)
 
     set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d")
     add_custom_command(OUTPUT ${dest}
diff --git a/src/cmake/paths.cmake b/src/cmake/paths.cmake
new file mode 100644
index 0000000..43ebc40
--- /dev/null
+++ b/src/cmake/paths.cmake
@@ -0,0 +1,11 @@
+# binary_dir_relative_path sets outvar to
+# ${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}, but expressed relative to
+# ${CMAKE_BINARY_DIR}.
+#
+# TODO(davidben): When we require CMake 3.20 or later, this can be replaced with
+# the built-in cmake_path(RELATIVE_PATH) function.
+function(binary_dir_relative_path cur_bin_dir_relative outvar)
+  string(LENGTH "${CMAKE_BINARY_DIR}/" root_dir_length)
+  string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}" ${root_dir_length} -1 result)
+  set(${outvar} ${result} PARENT_SCOPE)
+endfunction()
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index 6cc16a8..cdb5ddc 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -168,7 +168,6 @@
   evp/scrypt.c
   evp/sign.c
   ex_data.c
-  hkdf/hkdf.c
   hpke/hpke.c
   hrss/hrss.c
   kyber/keccak.c
@@ -204,6 +203,7 @@
   refcount_c11.c
   refcount_lock.c
   rsa_extra/rsa_asn1.c
+  rsa_extra/rsa_crypt.c
   rsa_extra/rsa_print.c
   stack/stack.c
   siphash/siphash.c
@@ -389,13 +389,13 @@
   fipsmodule/ec/ec_test.cc
   fipsmodule/ec/p256-nistz_test.cc
   fipsmodule/ecdsa/ecdsa_test.cc
+  fipsmodule/hkdf/hkdf_test.cc
   fipsmodule/md5/md5_test.cc
   fipsmodule/modes/gcm_test.cc
   fipsmodule/rand/ctrdrbg_test.cc
   fipsmodule/rand/fork_detect_test.cc
   fipsmodule/service_indicator/service_indicator_test.cc
   fipsmodule/sha/sha_test.cc
-  hkdf/hkdf_test.cc
   hpke/hpke_test.cc
   hmac_extra/hmac_test.cc
   hrss/hrss_test.cc
diff --git a/src/crypto/asn1/a_mbstr.c b/src/crypto/asn1/a_mbstr.c
index 85a7b98..8fc82ab 100644
--- a/src/crypto/asn1/a_mbstr.c
+++ b/src/crypto/asn1/a_mbstr.c
@@ -73,18 +73,19 @@
 // horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
 // size limits too.
 
-int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
-                       int inform, unsigned long mask) {
-  return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in,
+                       ossl_ssize_t len, int inform, unsigned long mask) {
+  return ASN1_mbstring_ncopy(out, in, len, inform, mask, /*minsize=*/0,
+                             /*maxsize=*/0);
 }
 
 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
 
-int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
-                        int inform, unsigned long mask, long minsize,
-                        long maxsize) {
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in,
+                        ossl_ssize_t len, int inform, unsigned long mask,
+                        ossl_ssize_t minsize, ossl_ssize_t maxsize) {
   if (len == -1) {
     len = strlen((const char *)in);
   }
@@ -164,14 +165,14 @@
     utf8_len += cbb_get_utf8_len(c);
     if (maxsize > 0 && nchar > (size_t)maxsize) {
       OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
-      ERR_add_error_dataf("maxsize=%ld", maxsize);
+      ERR_add_error_dataf("maxsize=%zu", (size_t)maxsize);
       return -1;
     }
   }
 
   if (minsize > 0 && nchar < (size_t)minsize) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
-    ERR_add_error_dataf("minsize=%ld", minsize);
+    ERR_add_error_dataf("minsize=%zu", (size_t)minsize);
     return -1;
   }
 
diff --git a/src/crypto/asn1/a_strnid.c b/src/crypto/asn1/a_strnid.c
index 3be266e..48c223d 100644
--- a/src/crypto/asn1/a_strnid.c
+++ b/src/crypto/asn1/a_strnid.c
@@ -87,7 +87,7 @@
 // a corresponding OID. For example certificates and certificate requests.
 
 ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
-                                    int len, int inform, int nid) {
+                                    ossl_ssize_t len, int inform, int nid) {
   ASN1_STRING *str = NULL;
   int ret;
   if (!out) {
diff --git a/src/crypto/asn1/asn1_test.cc b/src/crypto/asn1/asn1_test.cc
index 5c43793..849cfe9 100644
--- a/src/crypto/asn1/asn1_test.cc
+++ b/src/crypto/asn1/asn1_test.cc
@@ -107,8 +107,12 @@
   TestSerialize(obj.get(), i2d_ASN1_TYPE, kTag128);
 
   // The historical in-memory representation of |kTag128| was for both
-  // |obj->type| and |obj->value.asn1_string->type| to be NULL. This is no
-  // longer used and should be rejected by the encoder.
+  // |obj->type| and |obj->value.asn1_string->type| to be 128. This is no
+  // longer used but is still accepted by the encoder.
+  //
+  // TODO(crbug.com/boringssl/412): The encoder should reject it. However, it is
+  // still needed to support some edge cases in |ASN1_PRINTABLE|. When that is
+  // fixed, test that we reject it.
   obj.reset(ASN1_TYPE_new());
   ASSERT_TRUE(obj);
   obj->type = 128;
@@ -116,7 +120,7 @@
   ASSERT_TRUE(obj->value.asn1_string);
   const uint8_t zero = 0;
   ASSERT_TRUE(ASN1_STRING_set(obj->value.asn1_string, &zero, sizeof(zero)));
-  EXPECT_EQ(-1, i2d_ASN1_TYPE(obj.get(), nullptr));
+  TestSerialize(obj.get(), i2d_ASN1_TYPE, kTag128);
 
   // If a tag is known, but has the wrong constructed bit, it should be
   // rejected, not placed in |V_ASN1_OTHER|.
diff --git a/src/crypto/asn1/internal.h b/src/crypto/asn1/internal.h
index 64e1e6b..5dca728 100644
--- a/src/crypto/asn1/internal.h
+++ b/src/crypto/asn1/internal.h
@@ -56,8 +56,8 @@
  *
  */
 
-#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
-#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
+#ifndef OPENSSL_HEADER_ASN1_INTERNAL_H
+#define OPENSSL_HEADER_ASN1_INTERNAL_H
 
 #include <time.h>
 
@@ -266,4 +266,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_ASN1_ASN1_LOCL_H
+#endif  // OPENSSL_HEADER_ASN1_INTERNAL_H
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index 23c526e..24ab04f 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -85,7 +85,7 @@
 static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
                                    long len, const ASN1_TEMPLATE *tt, char opt,
                                    CRYPTO_BUFFER *buf, int depth);
-static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len,
                        int utype, const ASN1_ITEM *it);
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
                                  long len, const ASN1_ITEM *it, int tag,
@@ -749,7 +749,7 @@
 
 // Translate ASN1 content octets into a structure
 
-static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len,
                        int utype, const ASN1_ITEM *it) {
   ASN1_VALUE **opval = NULL;
   ASN1_STRING *stmp;
@@ -837,7 +837,14 @@
     case V_ASN1_UTF8STRING:
     case V_ASN1_OTHER:
     case V_ASN1_SET:
-    case V_ASN1_SEQUENCE: {
+    case V_ASN1_SEQUENCE:
+    // TODO(crbug.com/boringssl/412): This default case should be removed, now
+    // that we've resolved https://crbug.com/boringssl/561. However, it is still
+    // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
+    // broadly doesn't tolerate unrecognized universal tags, but except for
+    // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
+    // X509Test.NameAttributeValues test.
+    default: {
       CBS cbs;
       CBS_init(&cbs, cont, (size_t)len);
       if (utype == V_ASN1_BMPSTRING) {
@@ -900,9 +907,6 @@
       }
       break;
     }
-    default:
-      OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
-      goto err;
   }
   // If ASN1_ANY and NULL type fix up value
   if (typ && (utype == V_ASN1_NULL)) {
diff --git a/src/crypto/asn1/tasn_enc.c b/src/crypto/asn1/tasn_enc.c
index b0d72ce..e85400b 100644
--- a/src/crypto/asn1/tasn_enc.c
+++ b/src/crypto/asn1/tasn_enc.c
@@ -693,15 +693,18 @@
     case V_ASN1_SET:
     // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|.
     case V_ASN1_OTHER:
+    // TODO(crbug.com/boringssl/412): This default case should be removed, now
+    // that we've resolved https://crbug.com/boringssl/561. However, it is still
+    // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
+    // broadly doesn't tolerate unrecognized universal tags, but except for
+    // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
+    // X509Test.NameAttributeValues test.
+    default:
       // All based on ASN1_STRING and handled the same
       strtmp = (ASN1_STRING *)*pval;
       cont = strtmp->data;
       len = strtmp->length;
       break;
-
-    default:
-      OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
-      return -1;
   }
   if (cout && len) {
     OPENSSL_memcpy(cout, cont, len);
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 610c733..ca5cbff 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -423,7 +423,7 @@
 }
 
 static int print_bio(const char *str, size_t len, void *bio) {
-  return BIO_write((BIO *)bio, str, len);
+  return BIO_write_all((BIO *)bio, str, len);
 }
 
 void ERR_print_errors(BIO *bio) {
@@ -462,9 +462,11 @@
       OPENSSL_free(*out);
       return 0;
     }
-    const size_t todo = len - done;
-    assert(todo < INT_MAX);
-    const int n = BIO_read(bio, *out + done, todo);
+    size_t todo = len - done;
+    if (todo > INT_MAX) {
+      todo = INT_MAX;
+    }
+    const int n = BIO_read(bio, *out + done, (int)todo);
     if (n == 0) {
       *out_len = done;
       return 1;
diff --git a/src/crypto/bio/bio_mem.c b/src/crypto/bio/bio_mem.c
index b483989..1ee148b 100644
--- a/src/crypto/bio/bio_mem.c
+++ b/src/crypto/bio/bio_mem.c
@@ -130,13 +130,15 @@
 }
 
 static int mem_read(BIO *bio, char *out, int outl) {
-  int ret;
-  BUF_MEM *b = (BUF_MEM*) bio->ptr;
-
   BIO_clear_retry_flags(bio);
-  ret = outl;
-  if (b->length < INT_MAX && ret > (int)b->length) {
-    ret = b->length;
+  if (outl <= 0) {
+    return 0;
+  }
+
+  BUF_MEM *b = bio->ptr;
+  int ret = outl;
+  if ((size_t)ret > b->length) {
+    ret = (int)b->length;
   }
 
   if (ret > 0) {
@@ -157,65 +159,49 @@
 }
 
 static int mem_write(BIO *bio, const char *in, int inl) {
-  int ret = -1;
-  int blen;
-  BUF_MEM *b;
-
-  b = (BUF_MEM *)bio->ptr;
+  BIO_clear_retry_flags(bio);
+  if (inl <= 0) {
+    return 0;  // Successfully write zero bytes.
+  }
 
   if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
     OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
-    goto err;
+    return -1;
   }
 
-  BIO_clear_retry_flags(bio);
-  blen = b->length;
-  if (INT_MAX - blen < inl) {
-    goto err;
+  BUF_MEM *b = bio->ptr;
+  if (!BUF_MEM_append(b, in, inl)) {
+    return -1;
   }
-  if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
-    goto err;
-  }
-  OPENSSL_memcpy(&b->data[blen], in, inl);
-  ret = inl;
 
-err:
-  return ret;
+  return inl;
 }
 
 static int mem_gets(BIO *bio, char *buf, int size) {
-  int i, j;
-  char *p;
-  BUF_MEM *b = (BUF_MEM *)bio->ptr;
-
   BIO_clear_retry_flags(bio);
-  j = b->length;
-  if (size - 1 < j) {
-    j = size - 1;
-  }
-  if (j <= 0) {
-    if (size > 0) {
-      *buf = 0;
-    }
+  if (size <= 0) {
     return 0;
   }
 
-  p = b->data;
-  for (i = 0; i < j; i++) {
-    if (p[i] == '\n') {
-      i++;
-      break;
-    }
+  // The buffer size includes space for the trailing NUL, so we can read at most
+  // one fewer byte.
+  BUF_MEM *b = bio->ptr;
+  int ret = size - 1;
+  if ((size_t)ret > b->length) {
+    ret = (int)b->length;
   }
 
-  // i is now the max num of bytes to copy, either j or up to and including the
-  // first newline
-
-  i = mem_read(bio, buf, i);
-  if (i > 0) {
-    buf[i] = '\0';
+  // Stop at the first newline.
+  const char *newline = OPENSSL_memchr(b->data, '\n', ret);
+  if (newline != NULL) {
+    ret = (int)(newline - b->data + 1);
   }
-  return i;
+
+  ret = mem_read(bio, buf, ret);
+  if (ret >= 0) {
+    buf[ret] = '\0';
+  }
+  return ret;
 }
 
 static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 342325c..6610be9 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -219,6 +219,265 @@
   }
 }
 
+TEST(BIOTest, MemReadOnly) {
+  // A memory BIO created from |BIO_new_mem_buf| is a read-only buffer.
+  static const char kData[] = "abcdefghijklmno";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kData, strlen(kData)));
+  ASSERT_TRUE(bio);
+
+  // Writing to read-only buffers should fail.
+  EXPECT_EQ(BIO_write(bio.get(), kData, strlen(kData)), -1);
+
+  const uint8_t *contents;
+  size_t len;
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes(kData));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Read less than the whole buffer.
+  char buf[6];
+  int ret = BIO_read(bio.get(), buf, sizeof(buf));
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("abcdef"));
+
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("ghijklmno"));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  ret = BIO_read(bio.get(), buf, sizeof(buf));
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("ghijkl"));
+
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("mno"));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Read the remainder of the buffer.
+  ret = BIO_read(bio.get(), buf, sizeof(buf));
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("mno"));
+
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes(""));
+  EXPECT_EQ(BIO_eof(bio.get()), 1);
+
+  // By default, reading from a consumed read-only buffer returns EOF.
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), 0);
+  EXPECT_FALSE(BIO_should_read(bio.get()));
+
+  // A memory BIO can be configured to return an error instead of EOF. This is
+  // error is returned as retryable. (This is not especially useful here. It
+  // makes more sense for a writable BIO.)
+  EXPECT_EQ(BIO_set_mem_eof_return(bio.get(), -1), 1);
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), -1);
+  EXPECT_TRUE(BIO_should_read(bio.get()));
+
+  // Read exactly the right number of bytes, to test the boundary condition is
+  // correct.
+  bio.reset(BIO_new_mem_buf("abc", 3));
+  ASSERT_TRUE(bio);
+  ret = BIO_read(bio.get(), buf, 3);
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("abc"));
+  EXPECT_EQ(BIO_eof(bio.get()), 1);
+}
+
+TEST(BIOTest, MemWritable) {
+  // A memory BIO created from |BIO_new| is writable.
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+  ASSERT_TRUE(bio);
+
+  // It is initially empty.
+  const uint8_t *contents;
+  size_t len;
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes(""));
+  EXPECT_EQ(BIO_eof(bio.get()), 1);
+
+  // Reading from it should default to returning a retryable error.
+  char buf[32];
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), -1);
+  EXPECT_TRUE(BIO_should_read(bio.get()));
+
+  // This can be configured to return an EOF.
+  EXPECT_EQ(BIO_set_mem_eof_return(bio.get(), 0), 1);
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), 0);
+  EXPECT_FALSE(BIO_should_read(bio.get()));
+
+  // Restore the default. A writable memory |BIO| is typically used in this mode
+  // so additional data can be written when exhausted.
+  EXPECT_EQ(BIO_set_mem_eof_return(bio.get(), -1), 1);
+
+  // Writes append to the buffer.
+  ASSERT_EQ(BIO_write(bio.get(), "abcdef", 6), 6);
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("abcdef"));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Writes can include embedded NULs.
+  ASSERT_EQ(BIO_write(bio.get(), "\0ghijk", 6), 6);
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("abcdef\0ghijk", 12));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Do a partial read.
+  int ret = BIO_read(bio.get(), buf, 4);
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("abcd"));
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("ef\0ghijk", 8));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Reads and writes may alternate.
+  ASSERT_EQ(BIO_write(bio.get(), "lmnopq", 6), 6);
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("ef\0ghijklmnopq", 14));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // Reads may consume embedded NULs.
+  ret = BIO_read(bio.get(), buf, 4);
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("ef\0g", 4));
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes("hijklmnopq"));
+  EXPECT_EQ(BIO_eof(bio.get()), 0);
+
+  // The read buffer exceeds the |BIO|, so we consume everything.
+  ret = BIO_read(bio.get(), buf, sizeof(buf));
+  ASSERT_GT(ret, 0);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("hijklmnopq"));
+  ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+  EXPECT_EQ(Bytes(contents, len), Bytes(""));
+  EXPECT_EQ(BIO_eof(bio.get()), 1);
+
+  // The |BIO| is now empty.
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), -1);
+  EXPECT_TRUE(BIO_should_read(bio.get()));
+
+  // Repeat the above, reading exactly the right number of bytes, to test the
+  // boundary condition is correct.
+  ASSERT_EQ(BIO_write(bio.get(), "abc", 3), 3);
+  ret = BIO_read(bio.get(), buf, 3);
+  EXPECT_EQ(Bytes(buf, ret), Bytes("abc"));
+  EXPECT_EQ(BIO_read(bio.get(), buf, sizeof(buf)), -1);
+  EXPECT_TRUE(BIO_should_read(bio.get()));
+  EXPECT_EQ(BIO_eof(bio.get()), 1);
+}
+
+TEST(BIOTest, Gets) {
+  const struct {
+    std::string bio;
+    int gets_len;
+    std::string gets_result;
+  } kGetsTests[] = {
+      // BIO_gets should stop at the first newline. If the buffer is too small,
+      // stop there instead. Note the buffer size
+      // includes a trailing NUL.
+      {"123456789\n123456789", 5, "1234"},
+      {"123456789\n123456789", 9, "12345678"},
+      {"123456789\n123456789", 10, "123456789"},
+      {"123456789\n123456789", 11, "123456789\n"},
+      {"123456789\n123456789", 12, "123456789\n"},
+      {"123456789\n123456789", 256, "123456789\n"},
+
+      // If we run out of buffer, read the whole buffer.
+      {"12345", 5, "1234"},
+      {"12345", 6, "12345"},
+      {"12345", 10, "12345"},
+
+      // NUL bytes do not terminate gets.
+      {std::string("abc\0def\nghi", 11), 256, std::string("abc\0def\n", 8)},
+
+      // An output size of one means we cannot read any bytes. Only the trailing
+      // NUL is included.
+      {"12345", 1, ""},
+
+      // Empty line.
+      {"\nabcdef", 256, "\n"},
+      // Empty BIO.
+      {"", 256, ""},
+  };
+  for (const auto& t : kGetsTests) {
+    SCOPED_TRACE(t.bio);
+    SCOPED_TRACE(t.gets_len);
+
+    auto check_bio_gets = [&](BIO *bio) {
+      std::vector<char> buf(t.gets_len, 'a');
+      int ret = BIO_gets(bio, buf.data(), t.gets_len);
+      ASSERT_GE(ret, 0);
+      // |BIO_gets| should write a NUL terminator, not counted in the return
+      // value.
+      EXPECT_EQ(Bytes(buf.data(), ret + 1),
+                Bytes(t.gets_result.data(), t.gets_result.size() + 1));
+
+      // The remaining data should still be in the BIO.
+      buf.resize(t.bio.size() + 1);
+      ret = BIO_read(bio, buf.data(), static_cast<int>(buf.size()));
+      ASSERT_GE(ret, 0);
+      EXPECT_EQ(Bytes(buf.data(), ret),
+                Bytes(t.bio.substr(t.gets_result.size())));
+    };
+
+    {
+      SCOPED_TRACE("memory");
+      bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(t.bio.data(), t.bio.size()));
+      ASSERT_TRUE(bio);
+      check_bio_gets(bio.get());
+    }
+
+    using ScopedFILE = std::unique_ptr<FILE, decltype(&fclose)>;
+    ScopedFILE file(tmpfile(), fclose);
+#if defined(OPENSSL_ANDROID)
+    // On Android, when running from an APK, |tmpfile| does not work. See
+    // b/36991167#comment8.
+    if (!file) {
+      fprintf(stderr, "tmpfile failed: %s (%d). Skipping file-based tests.\n",
+              strerror(errno), errno);
+      continue;
+    }
+#else
+    ASSERT_TRUE(file);
+#endif
+
+    if (!t.bio.empty()) {
+      ASSERT_EQ(1u,
+                fwrite(t.bio.data(), t.bio.size(), /*nitems=*/1, file.get()));
+      ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
+    }
+
+    // TODO(crbug.com/boringssl/585): If the line has an embedded NUL, file
+    // BIOs do not currently report the answer correctly.
+    if (t.bio.find('\0') == std::string::npos) {
+      SCOPED_TRACE("file");
+      bssl::UniquePtr<BIO> bio(BIO_new_fp(file.get(), BIO_NOCLOSE));
+      ASSERT_TRUE(bio);
+      check_bio_gets(bio.get());
+    }
+
+    ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
+
+    {
+      SCOPED_TRACE("fd");
+#if defined(OPENSSL_WINDOWS)
+      int fd = _fileno(file.get());
+#else
+      int fd = fileno(file.get());
+#endif
+      bssl::UniquePtr<BIO> bio(BIO_new_fd(fd, BIO_NOCLOSE));
+      ASSERT_TRUE(bio);
+      check_bio_gets(bio.get());
+    }
+  }
+
+  // Negative and zero lengths should not output anything, even a trailing NUL.
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf("12345", -1));
+  ASSERT_TRUE(bio);
+  char c = 'a';
+  EXPECT_EQ(0, BIO_gets(bio.get(), &c, -1));
+  EXPECT_EQ(0, BIO_gets(bio.get(), &c, 0));
+  EXPECT_EQ(c, 'a');
+}
+
 // Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
 class BIOPairTest : public testing::TestWithParam<bool> {};
 
diff --git a/src/crypto/bio/fd.c b/src/crypto/bio/fd.c
index 2980b7d..7775d7a 100644
--- a/src/crypto/bio/fd.c
+++ b/src/crypto/bio/fd.c
@@ -241,20 +241,24 @@
 }
 
 static int fd_gets(BIO *bp, char *buf, int size) {
-  char *ptr = buf;
-  char *end = buf + size - 1;
-
   if (size <= 0) {
     return 0;
   }
 
-  while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
+  char *ptr = buf;
+  char *end = buf + size - 1;
+  while (ptr < end && fd_read(bp, ptr, 1) > 0) {
+    char c = ptr[0];
     ptr++;
+    if (c == '\n') {
+      break;
+    }
   }
 
   ptr[0] = '\0';
 
-  return ptr - buf;
+  // The output length is bounded by |size|.
+  return (int)(ptr - buf);
 }
 
 static const BIO_METHOD methods_fdp = {
diff --git a/src/crypto/bio/file.c b/src/crypto/bio/file.c
index 0f2fffb..8ba9c54 100644
--- a/src/crypto/bio/file.c
+++ b/src/crypto/bio/file.c
@@ -157,13 +157,11 @@
 }
 
 static int file_write(BIO *b, const char *in, int inl) {
-  int ret = 0;
-
   if (!b->init) {
     return 0;
   }
 
-  ret = fwrite(in, inl, 1, (FILE *)b->ptr);
+  int ret = (int)fwrite(in, inl, 1, (FILE *)b->ptr);
   if (ret > 0) {
     ret = inl;
   }
@@ -253,20 +251,18 @@
 }
 
 static int file_gets(BIO *bp, char *buf, int size) {
-  int ret = 0;
-
   if (size == 0) {
     return 0;
   }
 
   if (!fgets(buf, size, (FILE *)bp->ptr)) {
     buf[0] = 0;
-    goto err;
+    // TODO(davidben): This doesn't distinguish error and EOF. This should check
+    // |ferror| as in |file_read|.
+    return 0;
   }
-  ret = strlen(buf);
 
-err:
-  return ret;
+  return (int)strlen(buf);
 }
 
 static const BIO_METHOD methods_filep = {
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
index c4d09c1..40711cd 100644
--- a/src/crypto/bio/pair.c
+++ b/src/crypto/bio/pair.c
@@ -221,7 +221,8 @@
     rest -= chunk;
   } while (rest);
 
-  return size;
+  // |size| is bounded by the buffer size, which fits in |int|.
+  return (int)size;
 }
 
 static int bio_write(BIO *bio, const char *buf, int num_) {
@@ -293,7 +294,8 @@
     buf += chunk;
   } while (rest);
 
-  return num;
+  // |num| is bounded by the buffer size, which fits in |int|.
+  return (int)num;
 }
 
 static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
diff --git a/src/crypto/cipher_extra/cipher_test.cc b/src/crypto/cipher_extra/cipher_test.cc
index 80146fe..4c8c142 100644
--- a/src/crypto/cipher_extra/cipher_test.cc
+++ b/src/crypto/cipher_extra/cipher_test.cc
@@ -208,8 +208,9 @@
   // pre-computed key schedule and a streaming operation.
   ASSERT_TRUE(MaybeCopyCipherContext(copy, &ctx));
   if (is_aead) {
-    ASSERT_TRUE(
-        EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN, iv.size(), 0));
+    ASSERT_LE(iv.size(), size_t{INT_MAX});
+    ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN,
+                                    static_cast<int>(iv.size()), 0));
   } else {
     ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get()));
   }
diff --git a/src/crypto/cipher_extra/e_tls.c b/src/crypto/cipher_extra/e_tls.c
index cfaf95d..00b4824 100644
--- a/src/crypto/cipher_extra/e_tls.c
+++ b/src/crypto/cipher_extra/e_tls.c
@@ -442,13 +442,6 @@
   return 1;
 }
 
-static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                   size_t key_len, size_t tag_len,
-                                   enum evp_aead_direction_t dir) {
-  return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(),
-                       EVP_sha1(), 1 /* implicit iv */);
-}
-
 static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
     SHA_DIGEST_LENGTH + 16,  // key len (SHA1 + AES128)
     16,                      // nonce len (IV)
@@ -551,23 +544,6 @@
     aead_tls_tag_len,
 };
 
-static const EVP_AEAD aead_null_sha1_tls = {
-    SHA_DIGEST_LENGTH,  // key len
-    0,                  // nonce len
-    SHA_DIGEST_LENGTH,  // overhead (SHA1)
-    SHA_DIGEST_LENGTH,  // max tag length
-    0,                  // seal_scatter_supports_extra_in
-
-    NULL,  // init
-    aead_null_sha1_tls_init,
-    aead_tls_cleanup,
-    aead_tls_open,
-    aead_tls_seal_scatter,
-    NULL,  // open_gather
-    NULL,  // get_iv
-    aead_tls_tag_len,
-};
-
 const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
   return &aead_aes_128_cbc_sha1_tls;
 }
@@ -591,5 +567,3 @@
 const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void) {
   return &aead_des_ede3_cbc_sha1_tls_implicit_iv;
 }
-
-const EVP_AEAD *EVP_aead_null_sha1_tls(void) { return &aead_null_sha1_tls; }
diff --git a/src/crypto/crypto_test.cc b/src/crypto/crypto_test.cc
index caccba5..4543d5c 100644
--- a/src/crypto/crypto_test.cc
+++ b/src/crypto/crypto_test.cc
@@ -158,3 +158,12 @@
   BORINGSSL_integrity_test();
 }
 #endif
+
+OPENSSL_DEPRECATED static void DeprecatedFunction() {}
+
+OPENSSL_BEGIN_ALLOW_DEPRECATED
+TEST(CryptoTest, DeprecatedFunction) {
+  // This is deprecated, but should not trigger any warnings.
+  DeprecatedFunction();
+}
+OPENSSL_END_ALLOW_DEPRECATED
diff --git a/src/crypto/curve25519/curve25519.c b/src/crypto/curve25519/curve25519.c
index 6a0af2d..c0289ff 100644
--- a/src/crypto/curve25519/curve25519.c
+++ b/src/crypto/curve25519/curve25519.c
@@ -35,11 +35,13 @@
 // Various pre-computed constants.
 #include "./curve25519_tables.h"
 
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(BORINGSSL_HAS_UINT128)
 #include "../../third_party/fiat/curve25519_64.h"
+#elif defined(OPENSSL_64_BIT)
+#include "../../third_party/fiat/curve25519_64_msvc.h"
 #else
 #include "../../third_party/fiat/curve25519_32.h"
-#endif  // BORINGSSL_CURVE25519_64BIT
+#endif
 
 
 // Low-level intrinsic operations
@@ -64,7 +66,7 @@
 
 // Field operations.
 
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
 
 typedef uint64_t fe_limb_t;
 #define FE_NUM_LIMBS 5
@@ -144,7 +146,7 @@
     }                                                                    \
   } while (0)
 
-#endif  // BORINGSSL_CURVE25519_64BIT
+#endif  // OPENSSL_64_BIT
 
 static_assert(sizeof(fe) == sizeof(fe_limb_t) * FE_NUM_LIMBS,
               "fe_limb_t[FE_NUM_LIMBS] is inconsistent with fe");
diff --git a/src/crypto/curve25519/curve25519_tables.h b/src/crypto/curve25519/curve25519_tables.h
index 310581c..ad1f036 100644
--- a/src/crypto/curve25519/curve25519_tables.h
+++ b/src/crypto/curve25519/curve25519_tables.h
@@ -17,7 +17,7 @@
 
 
 static const fe d = {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
     929955233495203, 466365720129213, 1662059464998953, 2033849074728123,
     1442794654840575
 #else
@@ -27,7 +27,7 @@
 }};
 
 static const fe sqrtm1 = {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
     1718705420411056, 234908883556509, 2233514472574048, 2117202627021982,
     765476049583133
 #else
@@ -37,7 +37,7 @@
 }};
 
 static const fe d2 = {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
     1859910466990425, 932731440258426, 1072319116312658, 1815898335770999,
     633789495995903
 #else
@@ -146,7 +146,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1288382639258501, 245678601348599, 269427782077623,
                 1462984067271730, 137412439391563
 #else
@@ -155,7 +155,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 62697248952638, 204681361388450, 631292143396476,
                 338455783676468, 1213667448819585
 #else
@@ -164,7 +164,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 301289933810280, 1259582250014073, 1422107436869536,
                 796239922652654, 1953934009299142
 #else
@@ -175,7 +175,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1380971894829527, 790832306631236, 2067202295274102,
                 1995808275510000, 1566530869037010
 #else
@@ -184,7 +184,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 463307831301544, 432984605774163, 1610641361907204,
                 750899048855000, 1894842303421586
 #else
@@ -193,7 +193,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 748439484463711, 1033211726465151, 1396005112841647,
                 1611506220286469, 1972177495910992
 #else
@@ -204,7 +204,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1601611775252272, 1720807796594148, 1132070835939856,
                 1260455018889551, 2147779492816911
 #else
@@ -213,7 +213,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 316559037616741, 2177824224946892, 1459442586438991,
                 1461528397712656, 751590696113597
 #else
@@ -222,7 +222,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1850748884277385, 1200145853858453, 1068094770532492,
                 672251375690438, 1586055907191707
 #else
@@ -233,7 +233,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 934282339813791, 1846903124198670, 1172395437954843,
                 1007037127761661, 1830588347719256
 #else
@@ -242,7 +242,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1694390458783935, 1735906047636159, 705069562067493,
                 648033061693059, 696214010414170
 #else
@@ -251,7 +251,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1121406372216585, 192876649532226, 190294192191717,
                 1994165897297032, 2245000007398739
 #else
@@ -262,7 +262,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 769950342298419, 132954430919746, 844085933195555,
                 974092374476333, 726076285546016
 #else
@@ -271,7 +271,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 425251763115706, 608463272472562, 442562545713235,
                 837766094556764, 374555092627893
 #else
@@ -280,7 +280,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1086255230780037, 274979815921559, 1960002765731872,
                 929474102396301, 1190409889297339
 #else
@@ -291,7 +291,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1388594989461809, 316767091099457, 394298842192982,
                 1230079486801005, 1440737038838979
 #else
@@ -300,7 +300,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 7380825640100, 146210432690483, 304903576448906,
                 1198869323871120, 997689833219095
 #else
@@ -309,7 +309,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1181317918772081, 114573476638901, 262805072233344,
                 265712217171332, 294181933805782
 #else
@@ -320,7 +320,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 665000864555967, 2065379846933859, 370231110385876,
                 350988370788628, 1233371373142985
 #else
@@ -329,7 +329,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2019367628972465, 676711900706637, 110710997811333,
                 1108646842542025, 517791959672113
 #else
@@ -338,7 +338,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 965130719900578, 247011430587952, 526356006571389,
                 91986625355052, 2157223321444601
 #else
@@ -349,7 +349,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2068619540119183, 1966274918058806, 957728544705549,
                 729906502578991, 159834893065166
 #else
@@ -358,7 +358,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2073601412052185, 31021124762708, 264500969797082,
                 248034690651703, 1030252227928288
 #else
@@ -367,7 +367,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 551790716293402, 1989538725166328, 801169423371717,
                 2052451893578887, 678432056995012
 #else
@@ -380,7 +380,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1368953770187805, 790347636712921, 437508475667162,
                 2142576377050580, 1932081720066286
 #else
@@ -389,7 +389,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 953638594433374, 1092333936795051, 1419774766716690,
                 805677984380077, 859228993502513
 #else
@@ -398,7 +398,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1200766035879111, 20142053207432, 1465634435977050,
                 1645256912097844, 295121984874596
 #else
@@ -409,7 +409,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1735718747031557, 1248237894295956, 1204753118328107,
                 976066523550493, 65943769534592
 #else
@@ -418,7 +418,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1060098822528990, 1586825862073490, 212301317240126,
                 1975302711403555, 666724059764335
 #else
@@ -427,7 +427,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1091990273418756, 1572899409348578, 80968014455247,
                 306009358661350, 1520450739132526
 #else
@@ -438,7 +438,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1480517209436112, 1511153322193952, 1244343858991172,
                 304788150493241, 369136856496443
 #else
@@ -447,7 +447,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2151330273626164, 762045184746182, 1688074332551515,
                 823046109005759, 907602769079491
 #else
@@ -456,7 +456,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2047386910586836, 168470092900250, 1552838872594810,
                 340951180073789, 360819374702533
 #else
@@ -467,7 +467,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1982622644432056, 2014393600336956, 128909208804214,
                 1617792623929191, 105294281913815
 #else
@@ -476,7 +476,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 980234343912898, 1712256739246056, 588935272190264,
                 204298813091998, 841798321043288
 #else
@@ -485,7 +485,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 197561292938973, 454817274782871, 1963754960082318,
                 2113372252160468, 971377527342673
 #else
@@ -496,7 +496,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 164699448829328, 3127451757672, 1199504971548753,
                 1766155447043652, 1899238924683527
 #else
@@ -505,7 +505,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 732262946680281, 1674412764227063, 2182456405662809,
                 1350894754474250, 558458873295247
 #else
@@ -514,7 +514,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2103305098582922, 1960809151316468, 715134605001343,
                 1454892949167181, 40827143824949
 #else
@@ -525,7 +525,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1239289043050212, 1744654158124578, 758702410031698,
                 1796762995074688, 1603056663766
 #else
@@ -534,7 +534,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2232056027107988, 987343914584615, 2115594492994461,
                 1819598072792159, 1119305654014850
 #else
@@ -543,7 +543,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 320153677847348, 939613871605645, 641883205761567,
                 1930009789398224, 329165806634126
 #else
@@ -554,7 +554,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 980930490474130, 1242488692177893, 1251446316964684,
                 1086618677993530, 1961430968465772
 #else
@@ -563,7 +563,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 276821765317453, 1536835591188030, 1305212741412361,
                 61473904210175, 2051377036983058
 #else
@@ -572,7 +572,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 833449923882501, 1750270368490475, 1123347002068295,
                 185477424765687, 278090826653186
 #else
@@ -583,7 +583,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 794524995833413, 1849907304548286, 53348672473145,
                 1272368559505217, 1147304168324779
 #else
@@ -592,7 +592,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1504846112759364, 1203096289004681, 562139421471418,
                 274333017451844, 1284344053775441
 #else
@@ -601,7 +601,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 483048732424432, 2116063063343382, 30120189902313,
                 292451576741007, 1156379271702225
 #else
@@ -614,7 +614,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 928372153029038, 2147692869914564, 1455665844462196,
                 1986737809425946, 185207050258089
 #else
@@ -623,7 +623,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 137732961814206, 706670923917341, 1387038086865771,
                 1965643813686352, 1384777115696347
 #else
@@ -632,7 +632,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 481144981981577, 2053319313589856, 2065402289827512,
                 617954271490316, 1106602634668125
 #else
@@ -643,7 +643,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 696298019648792, 893299659040895, 1148636718636009,
                 26734077349617, 2203955659340681
 #else
@@ -652,7 +652,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 657390353372855, 998499966885562, 991893336905797,
                 810470207106761, 343139804608786
 #else
@@ -661,7 +661,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 791736669492960, 934767652997115, 824656780392914,
                 1759463253018643, 361530362383518
 #else
@@ -672,7 +672,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2022541353055597, 2094700262587466, 1551008075025686,
                 242785517418164, 695985404963562
 #else
@@ -681,7 +681,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1287487199965223, 2215311941380308, 1552928390931986,
                 1664859529680196, 1125004975265243
 #else
@@ -690,7 +690,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 677434665154918, 989582503122485, 1817429540898386,
                 1052904935475344, 1143826298169798
 #else
@@ -701,7 +701,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 367266328308408, 318431188922404, 695629353755355,
                 634085657580832, 24581612564426
 #else
@@ -710,7 +710,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 773360688841258, 1815381330538070, 363773437667376,
                 539629987070205, 783280434248437
 #else
@@ -719,7 +719,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 180820816194166, 168937968377394, 748416242794470,
                 1227281252254508, 1567587861004268
 #else
@@ -730,7 +730,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 478775558583645, 2062896624554807, 699391259285399,
                 358099408427873, 1277310261461761
 #else
@@ -739,7 +739,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1984740906540026, 1079164179400229, 1056021349262661,
                 1659958556483663, 1088529069025527
 #else
@@ -748,7 +748,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 580736401511151, 1842931091388998, 1177201471228238,
                 2075460256527244, 1301133425678027
 #else
@@ -759,7 +759,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1515728832059182, 1575261009617579, 1510246567196186,
                 191078022609704, 116661716289141
 #else
@@ -768,7 +768,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1295295738269652, 1714742313707026, 545583042462581,
                 2034411676262552, 1513248090013606
 #else
@@ -777,7 +777,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 230710545179830, 30821514358353, 760704303452229,
                 390668103790604, 573437871383156
 #else
@@ -788,7 +788,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1169380107545646, 263167233745614, 2022901299054448,
                 819900753251120, 2023898464874585
 #else
@@ -797,7 +797,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2102254323485823, 1570832666216754, 34696906544624,
                 1993213739807337, 70638552271463
 #else
@@ -806,7 +806,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 894132856735058, 548675863558441, 845349339503395,
                 1942269668326667, 1615682209874691
 #else
@@ -817,7 +817,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1287670217537834, 1222355136884920, 1846481788678694,
                 1150426571265110, 1613523400722047
 #else
@@ -826,7 +826,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 793388516527298, 1315457083650035, 1972286999342417,
                 1901825953052455, 338269477222410
 #else
@@ -835,7 +835,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 550201530671806, 778605267108140, 2063911101902983,
                 115500557286349, 2041641272971022
 #else
@@ -848,7 +848,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 717255318455100, 519313764361315, 2080406977303708,
                 541981206705521, 774328150311600
 #else
@@ -857,7 +857,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 261715221532238, 1795354330069993, 1496878026850283,
                 499739720521052, 389031152673770
 #else
@@ -866,7 +866,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1997217696294013, 1717306351628065, 1684313917746180,
                 1644426076011410, 1857378133465451
 #else
@@ -877,7 +877,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1475434724792648, 76931896285979, 1116729029771667,
                 2002544139318042, 725547833803938
 #else
@@ -886,7 +886,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2022306639183567, 726296063571875, 315345054448644,
                 1058733329149221, 1448201136060677
 #else
@@ -895,7 +895,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1710065158525665, 1895094923036397, 123988286168546,
                 1145519900776355, 1607510767693874
 #else
@@ -906,7 +906,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 561605375422540, 1071733543815037, 131496498800990,
                 1946868434569999, 828138133964203
 #else
@@ -915,7 +915,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1548495173745801, 442310529226540, 998072547000384,
                 553054358385281, 644824326376171
 #else
@@ -924,7 +924,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1445526537029440, 2225519789662536, 914628859347385,
                 1064754194555068, 1660295614401091
 #else
@@ -935,7 +935,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1199690223111956, 24028135822341, 66638289244341,
                 57626156285975, 565093967979607
 #else
@@ -944,7 +944,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 876926774220824, 554618976488214, 1012056309841565,
                 839961821554611, 1414499340307677
 #else
@@ -953,7 +953,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 703047626104145, 1266841406201770, 165556500219173,
                 486991595001879, 1011325891650656
 #else
@@ -964,7 +964,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1622861044480487, 1156394801573634, 1869132565415504,
                 327103985777730, 2095342781472284
 #else
@@ -973,7 +973,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 334886927423922, 489511099221528, 129160865966726,
                 1720809113143481, 619700195649254
 #else
@@ -982,7 +982,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1646545795166119, 1758370782583567, 714746174550637,
                 1472693650165135, 898994790308209
 #else
@@ -993,7 +993,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 333403773039279, 295772542452938, 1693106465353610,
                 912330357530760, 471235657950362
 #else
@@ -1002,7 +1002,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1811196219982022, 1068969825533602, 289602974833439,
                 1988956043611592, 863562343398367
 #else
@@ -1011,7 +1011,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 906282429780072, 2108672665779781, 432396390473936,
                 150625823801893, 1708930497638539
 #else
@@ -1022,7 +1022,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 925664675702328, 21416848568684, 1831436641861340,
                 601157008940113, 371818055044496
 #else
@@ -1031,7 +1031,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1479786007267725, 1738881859066675, 68646196476567,
                 2146507056100328, 1247662817535471
 #else
@@ -1040,7 +1040,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 52035296774456, 939969390708103, 312023458773250,
                 59873523517659, 1231345905848899
 #else
@@ -1051,7 +1051,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 643355106415761, 290186807495774, 2013561737429023,
                 319648069511546, 393736678496162
 #else
@@ -1060,7 +1060,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 129358342392716, 1932811617704777, 1176749390799681,
                 398040349861790, 1170779668090425
 #else
@@ -1069,7 +1069,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2051980782668029, 121859921510665, 2048329875753063,
                 1235229850149665, 519062146124755
 #else
@@ -1082,7 +1082,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1608170971973096, 415809060360428, 1350468408164766,
                 2038620059057678, 1026904485989112
 #else
@@ -1091,7 +1091,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1837656083115103, 1510134048812070, 906263674192061,
                 1821064197805734, 565375124676301
 #else
@@ -1100,7 +1100,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 578027192365650, 2034800251375322, 2128954087207123,
                 478816193810521, 2196171989962750
 #else
@@ -1111,7 +1111,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1633188840273139, 852787172373708, 1548762607215796,
                 1266275218902681, 1107218203325133
 #else
@@ -1120,7 +1120,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 462189358480054, 1784816734159228, 1611334301651368,
                 1303938263943540, 707589560319424
 #else
@@ -1129,7 +1129,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1038829280972848, 38176604650029, 753193246598573,
                 1136076426528122, 595709990562434
 #else
@@ -1140,7 +1140,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1408451820859834, 2194984964010833, 2198361797561729,
                 1061962440055713, 1645147963442934
 #else
@@ -1149,7 +1149,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 4701053362120, 1647641066302348, 1047553002242085,
                 1923635013395977, 206970314902065
 #else
@@ -1158,7 +1158,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1750479161778571, 1362553355169293, 1891721260220598,
                 966109370862782, 1024913988299801
 #else
@@ -1169,7 +1169,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 212699049131723, 1117950018299775, 1873945661751056,
                 1403802921984058, 130896082652698
 #else
@@ -1178,7 +1178,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 636808533673210, 1262201711667560, 390951380330599,
                 1663420692697294, 561951321757406
 #else
@@ -1187,7 +1187,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 520731594438141, 1446301499955692, 273753264629267,
                 1565101517999256, 1019411827004672
 #else
@@ -1198,7 +1198,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 926527492029409, 1191853477411379, 734233225181171,
                 184038887541270, 1790426146325343
 #else
@@ -1207,7 +1207,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1464651961852572, 1483737295721717, 1519450561335517,
                 1161429831763785, 405914998179977
 #else
@@ -1216,7 +1216,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 996126634382301, 796204125879525, 127517800546509,
                 344155944689303, 615279846169038
 #else
@@ -1227,7 +1227,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 738724080975276, 2188666632415296, 1961313708559162,
                 1506545807547587, 1151301638969740
 #else
@@ -1236,7 +1236,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 622917337413835, 1218989177089035, 1284857712846592,
                 970502061709359, 351025208117090
 #else
@@ -1245,7 +1245,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2067814584765580, 1677855129927492, 2086109782475197,
                 235286517313238, 1416314046739645
 #else
@@ -1256,7 +1256,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 586844262630358, 307444381952195, 458399356043426,
                 602068024507062, 1028548203415243
 #else
@@ -1265,7 +1265,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 678489922928203, 2016657584724032, 90977383049628,
                 1026831907234582, 615271492942522
 #else
@@ -1274,7 +1274,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 301225714012278, 1094837270268560, 1202288391010439,
                 644352775178361, 1647055902137983
 #else
@@ -1285,7 +1285,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1210746697896478, 1416608304244708, 686487477217856,
                 1245131191434135, 1051238336855737
 #else
@@ -1294,7 +1294,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1135604073198207, 1683322080485474, 769147804376683,
                 2086688130589414, 900445683120379
 #else
@@ -1303,7 +1303,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1971518477615628, 401909519527336, 448627091057375,
                 1409486868273821, 1214789035034363
 #else
@@ -1316,7 +1316,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1364039144731711, 1897497433586190, 2203097701135459,
                 145461396811251, 1349844460790699
 #else
@@ -1325,7 +1325,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1045230323257973, 818206601145807, 630513189076103,
                 1672046528998132, 807204017562437
 #else
@@ -1334,7 +1334,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 439961968385997, 386362664488986, 1382706320807688,
                 309894000125359, 2207801346498567
 #else
@@ -1345,7 +1345,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1229004686397588, 920643968530863, 123975893911178,
                 681423993215777, 1400559197080973
 #else
@@ -1354,7 +1354,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2003766096898049, 170074059235165, 1141124258967971,
                 1485419893480973, 1573762821028725
 #else
@@ -1363,7 +1363,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 729905708611432, 1270323270673202, 123353058984288,
                 426460209632942, 2195574535456672
 #else
@@ -1374,7 +1374,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1271140255321235, 2044363183174497, 52125387634689,
                 1445120246694705, 942541986339084
 #else
@@ -1383,7 +1383,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1761608437466135, 583360847526804, 1586706389685493,
                 2157056599579261, 1170692369685772
 #else
@@ -1392,7 +1392,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 871476219910823, 1878769545097794, 2241832391238412,
                 548957640601001, 690047440233174
 #else
@@ -1403,7 +1403,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 297194732135507, 1366347803776820, 1301185512245601,
                 561849853336294, 1533554921345731
 #else
@@ -1412,7 +1412,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 999628998628371, 1132836708493400, 2084741674517453,
                 469343353015612, 678782988708035
 #else
@@ -1421,7 +1421,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2189427607417022, 699801937082607, 412764402319267,
                 1478091893643349, 2244675696854460
 #else
@@ -1432,7 +1432,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1712292055966563, 204413590624874, 1405738637332841,
                 408981300829763, 861082219276721
 #else
@@ -1441,7 +1441,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 508561155940631, 966928475686665, 2236717801150132,
                 424543858577297, 2089272956986143
 #else
@@ -1450,7 +1450,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 221245220129925, 1156020201681217, 491145634799213,
                 542422431960839, 828100817819207
 #else
@@ -1461,7 +1461,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 153756971240384, 1299874139923977, 393099165260502,
                 1058234455773022, 996989038681183
 #else
@@ -1470,7 +1470,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 559086812798481, 573177704212711, 1629737083816402,
                 1399819713462595, 1646954378266038
 #else
@@ -1479,7 +1479,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1887963056288059, 228507035730124, 1468368348640282,
                 930557653420194, 613513962454686
 #else
@@ -1490,7 +1490,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1224529808187553, 1577022856702685, 2206946542980843,
                 625883007765001, 279930793512158
 #else
@@ -1499,7 +1499,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1076287717051609, 1114455570543035, 187297059715481,
                 250446884292121, 1885187512550540
 #else
@@ -1508,7 +1508,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 902497362940219, 76749815795675, 1657927525633846,
                 1420238379745202, 1340321636548352
 #else
@@ -1519,7 +1519,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1129576631190784, 1281994010027327, 996844254743018,
                 257876363489249, 1150850742055018
 #else
@@ -1528,7 +1528,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 628740660038789, 1943038498527841, 467786347793886,
                 1093341428303375, 235413859513003
 #else
@@ -1537,7 +1537,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 237425418909360, 469614029179605, 1512389769174935,
                 1241726368345357, 441602891065214
 #else
@@ -1550,7 +1550,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1736417953058555, 726531315520508, 1833335034432527,
                 1629442561574747, 624418919286085
 #else
@@ -1559,7 +1559,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1960754663920689, 497040957888962, 1909832851283095,
                 1271432136996826, 2219780368020940
 #else
@@ -1568,7 +1568,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1537037379417136, 1358865369268262, 2130838645654099,
                 828733687040705, 1999987652890901
 #else
@@ -1579,7 +1579,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 629042105241814, 1098854999137608, 887281544569320,
                 1423102019874777, 7911258951561
 #else
@@ -1588,7 +1588,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1811562332665373, 1501882019007673, 2213763501088999,
                 359573079719636, 36370565049116
 #else
@@ -1597,7 +1597,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 218907117361280, 1209298913016966, 1944312619096112,
                 1130690631451061, 1342327389191701
 #else
@@ -1608,7 +1608,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1369976867854704, 1396479602419169, 1765656654398856,
                 2203659200586299, 998327836117241
 #else
@@ -1617,7 +1617,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2230701885562825, 1348173180338974, 2172856128624598,
                 1426538746123771, 444193481326151
 #else
@@ -1626,7 +1626,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 784210426627951, 918204562375674, 1284546780452985,
                 1324534636134684, 1872449409642708
 #else
@@ -1637,7 +1637,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 319638829540294, 596282656808406, 2037902696412608,
                 1557219121643918, 341938082688094
 #else
@@ -1646,7 +1646,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1901860206695915, 2004489122065736, 1625847061568236,
                 973529743399879, 2075287685312905
 #else
@@ -1655,7 +1655,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1371853944110545, 1042332820512553, 1949855697918254,
                 1791195775521505, 37487364849293
 #else
@@ -1666,7 +1666,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 687200189577855, 1082536651125675, 644224940871546,
                 340923196057951, 343581346747396
 #else
@@ -1675,7 +1675,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2082717129583892, 27829425539422, 145655066671970,
                 1690527209845512, 1865260509673478
 #else
@@ -1684,7 +1684,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1059729620568824, 2163709103470266, 1440302280256872,
                 1769143160546397, 869830310425069
 #else
@@ -1695,7 +1695,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1609516219779025, 777277757338817, 2101121130363987,
                 550762194946473, 1905542338659364
 #else
@@ -1704,7 +1704,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2024821921041576, 426948675450149, 595133284085473,
                 471860860885970, 600321679413000
 #else
@@ -1713,7 +1713,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 598474602406721, 1468128276358244, 1191923149557635,
                 1501376424093216, 1281662691293476
 #else
@@ -1724,7 +1724,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1721138489890707, 1264336102277790, 433064545421287,
                 1359988423149466, 1561871293409447
 #else
@@ -1733,7 +1733,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 719520245587143, 393380711632345, 132350400863381,
                 1543271270810729, 1819543295798660
 #else
@@ -1742,7 +1742,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 396397949784152, 1811354474471839, 1362679985304303,
                 2117033964846756, 498041172552279
 #else
@@ -1753,7 +1753,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1812471844975748, 1856491995543149, 126579494584102,
                 1036244859282620, 1975108050082550
 #else
@@ -1762,7 +1762,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 650623932407995, 1137551288410575, 2125223403615539,
                 1725658013221271, 2134892965117796
 #else
@@ -1771,7 +1771,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 522584000310195, 1241762481390450, 1743702789495384,
                 2227404127826575, 1686746002148897
 #else
@@ -1784,7 +1784,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 427904865186312, 1703211129693455, 1585368107547509,
                 1436984488744336, 761188534613978
 #else
@@ -1793,7 +1793,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 318101947455002, 248138407995851, 1481904195303927,
                 309278454311197, 1258516760217879
 #else
@@ -1802,7 +1802,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1275068538599310, 513726919533379, 349926553492294,
                 688428871968420, 1702400196000666
 #else
@@ -1813,7 +1813,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1061864036265233, 961611260325381, 321859632700838,
                 1045600629959517, 1985130202504038
 #else
@@ -1822,7 +1822,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1558816436882417, 1962896332636523, 1337709822062152,
                 1501413830776938, 294436165831932
 #else
@@ -1831,7 +1831,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 818359826554971, 1862173000996177, 626821592884859,
                 573655738872376, 1749691246745455
 #else
@@ -1842,7 +1842,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1988022651432119, 1082111498586040, 1834020786104821,
                 1454826876423687, 692929915223122
 #else
@@ -1851,7 +1851,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2146513703733331, 584788900394667, 464965657279958,
                 2183973639356127, 238371159456790
 #else
@@ -1860,7 +1860,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1129007025494441, 2197883144413266, 265142755578169,
                 971864464758890, 1983715884903702
 #else
@@ -1871,7 +1871,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1291366624493075, 381456718189114, 1711482489312444,
                 1815233647702022, 892279782992467
 #else
@@ -1880,7 +1880,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 444548969917454, 1452286453853356, 2113731441506810,
                 645188273895859, 810317625309512
 #else
@@ -1889,7 +1889,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2242724082797924, 1373354730327868, 1006520110883049,
                 2147330369940688, 1151816104883620
 #else
@@ -1900,7 +1900,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1745720200383796, 1911723143175317, 2056329390702074,
                 355227174309849, 879232794371100
 #else
@@ -1909,7 +1909,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 163723479936298, 115424889803150, 1156016391581227,
                 1894942220753364, 1970549419986329
 #else
@@ -1918,7 +1918,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 681981452362484, 267208874112496, 1374683991933094,
                 638600984916117, 646178654558546
 #else
@@ -1929,7 +1929,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 13378654854251, 106237307029567, 1944412051589651,
                 1841976767925457, 230702819835573
 #else
@@ -1938,7 +1938,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 260683893467075, 854060306077237, 913639551980112,
                 4704576840123, 280254810808712
 #else
@@ -1947,7 +1947,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 715374893080287, 1173334812210491, 1806524662079626,
                 1894596008000979, 398905715033393
 #else
@@ -1958,7 +1958,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 500026409727661, 1596431288195371, 1420380351989370,
                 985211561521489, 392444930785633
 #else
@@ -1967,7 +1967,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2096421546958141, 1922523000950363, 789831022876840,
                 427295144688779, 320923973161730
 #else
@@ -1976,7 +1976,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1927770723575450, 1485792977512719, 1850996108474547,
                 551696031508956, 2126047405475647
 #else
@@ -1987,7 +1987,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2112099158080148, 742570803909715, 6484558077432,
                 1951119898618916, 93090382703416
 #else
@@ -1996,7 +1996,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 383905201636970, 859946997631870, 855623867637644,
                 1017125780577795, 794250831877809
 #else
@@ -2005,7 +2005,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 77571826285752, 999304298101753, 487841111777762,
                 1038031143212339, 339066367948762
 #else
@@ -2018,7 +2018,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 674994775520533, 266035846330789, 826951213393478,
                 1405007746162285, 1781791018620876
 #else
@@ -2027,7 +2027,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1001412661522686, 348196197067298, 1666614366723946,
                 888424995032760, 580747687801357
 #else
@@ -2036,7 +2036,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1939560076207777, 1409892634407635, 552574736069277,
                 383854338280405, 190706709864139
 #else
@@ -2047,7 +2047,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2177087163428741, 1439255351721944, 1208070840382793,
                 2230616362004769, 1396886392021913
 #else
@@ -2056,7 +2056,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 676962063230039, 1880275537148808, 2046721011602706,
                 888463247083003, 1318301552024067
 #else
@@ -2065,7 +2065,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1466980508178206, 617045217998949, 652303580573628,
                 757303753529064, 207583137376902
 #else
@@ -2076,7 +2076,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1511056752906902, 105403126891277, 493434892772846,
                 1091943425335976, 1802717338077427
 #else
@@ -2085,7 +2085,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1853982405405128, 1878664056251147, 1528011020803992,
                 1019626468153565, 1128438412189035
 #else
@@ -2094,7 +2094,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1963939888391106, 293456433791664, 697897559513649,
                 985882796904380, 796244541237972
 #else
@@ -2105,7 +2105,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 416770998629779, 389655552427054, 1314476859406756,
                 1749382513022778, 1161905598739491
 #else
@@ -2114,7 +2114,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1428358296490651, 1027115282420478, 304840698058337,
                 441410174026628, 1819358356278573
 #else
@@ -2123,7 +2123,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 204943430200135, 1554861433819175, 216426658514651,
                 264149070665950, 2047097371738319
 #else
@@ -2134,7 +2134,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1934415182909034, 1393285083565062, 516409331772960,
                 1157690734993892, 121039666594268
 #else
@@ -2143,7 +2143,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 662035583584445, 286736105093098, 1131773000510616,
                 818494214211439, 472943792054479
 #else
@@ -2152,7 +2152,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 665784778135882, 1893179629898606, 808313193813106,
                 276797254706413, 1563426179676396
 #else
@@ -2163,7 +2163,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 945205108984232, 526277562959295, 1324180513733566,
                 1666970227868664, 153547609289173
 #else
@@ -2172,7 +2172,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2031433403516252, 203996615228162, 170487168837083,
                 981513604791390, 843573964916831
 #else
@@ -2181,7 +2181,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1476570093962618, 838514669399805, 1857930577281364,
                 2017007352225784, 317085545220047
 #else
@@ -2192,7 +2192,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1461557121912842, 1600674043318359, 2157134900399597,
                 1670641601940616, 127765583803283
 #else
@@ -2201,7 +2201,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1293543509393474, 2143624609202546, 1058361566797508,
                 214097127393994, 946888515472729
 #else
@@ -2210,7 +2210,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 357067959932916, 1290876214345711, 521245575443703,
                 1494975468601005, 800942377643885
 #else
@@ -2221,7 +2221,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 566116659100033, 820247422481740, 994464017954148,
                 327157611686365, 92591318111744
 #else
@@ -2230,7 +2230,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 617256647603209, 1652107761099439, 1857213046645471,
                 1085597175214970, 817432759830522
 #else
@@ -2239,7 +2239,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 771808161440705, 1323510426395069, 680497615846440,
                 851580615547985, 1320806384849017
 #else
@@ -2252,7 +2252,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1219260086131915, 647169006596815, 79601124759706,
                 2161724213426748, 404861897060198
 #else
@@ -2261,7 +2261,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1327968293887866, 1335500852943256, 1401587164534264,
                 558137311952440, 1551360549268902
 #else
@@ -2270,7 +2270,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 417621685193956, 1429953819744454, 396157358457099,
                 1940470778873255, 214000046234152
 #else
@@ -2281,7 +2281,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1268047918491973, 2172375426948536, 1533916099229249,
                 1761293575457130, 1590622667026765
 #else
@@ -2290,7 +2290,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1627072914981959, 2211603081280073, 1912369601616504,
                 1191770436221309, 2187309757525860
 #else
@@ -2299,7 +2299,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1149147819689533, 378692712667677, 828475842424202,
                 2218619146419342, 70688125792186
 #else
@@ -2310,7 +2310,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1299739417079761, 1438616663452759, 1536729078504412,
                 2053896748919838, 1008421032591246
 #else
@@ -2319,7 +2319,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2040723824657366, 399555637875075, 632543375452995,
                 872649937008051, 1235394727030233
 #else
@@ -2328,7 +2328,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2211311599327900, 2139787259888175, 938706616835350,
                 12609661139114, 2081897930719789
 #else
@@ -2339,7 +2339,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1324994503390450, 336982330582631, 1183998925654177,
                 1091654665913274, 48727673971319
 #else
@@ -2348,7 +2348,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1845522914617879, 1222198248335542, 150841072760134,
                 1927029069940982, 1189913404498011
 #else
@@ -2357,7 +2357,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1079559557592645, 2215338383666441, 1903569501302605,
                 49033973033940, 305703433934152
 #else
@@ -2368,7 +2368,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 94653405416909, 1386121349852999, 1062130477891762,
                 36553947479274, 833669648948846
 #else
@@ -2377,7 +2377,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1432015813136298, 440364795295369, 1395647062821501,
                 1976874522764578, 934452372723352
 #else
@@ -2386,7 +2386,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1296625309219774, 2068273464883862, 1858621048097805,
                 1492281814208508, 2235868981918946
 #else
@@ -2397,7 +2397,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1490330266465570, 1858795661361448, 1436241134969763,
                 294573218899647, 1208140011028933
 #else
@@ -2406,7 +2406,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1282462923712748, 741885683986255, 2027754642827561,
                 518989529541027, 1826610009555945
 #else
@@ -2415,7 +2415,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1525827120027511, 723686461809551, 1597702369236987,
                 244802101764964, 1502833890372311
 #else
@@ -2426,7 +2426,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 113622036244513, 1233740067745854, 674109952278496,
                 2114345180342965, 166764512856263
 #else
@@ -2435,7 +2435,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2041668749310338, 2184405322203901, 1633400637611036,
                 2110682505536899, 2048144390084644
 #else
@@ -2444,7 +2444,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 503058759232932, 760293024620937, 2027152777219493,
                 666858468148475, 1539184379870952
 #else
@@ -2455,7 +2455,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1916168475367211, 915626432541343, 883217071712575,
                 363427871374304, 1976029821251593
 #else
@@ -2464,7 +2464,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 678039535434506, 570587290189340, 1605302676614120,
                 2147762562875701, 1706063797091704
 #else
@@ -2473,7 +2473,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1439489648586438, 2194580753290951, 832380563557396,
                 561521973970522, 584497280718389
 #else
@@ -2486,7 +2486,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 187989455492609, 681223515948275, 1933493571072456,
                 1872921007304880, 488162364135671
 #else
@@ -2495,7 +2495,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1413466089534451, 410844090765630, 1397263346404072,
                 408227143123410, 1594561803147811
 #else
@@ -2504,7 +2504,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2102170800973153, 719462588665004, 1479649438510153,
                 1097529543970028, 1302363283777685
 #else
@@ -2515,7 +2515,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 942065717847195, 1069313679352961, 2007341951411051,
                 70973416446291, 1419433790163706
 #else
@@ -2524,7 +2524,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1146565545556377, 1661971299445212, 406681704748893,
                 564452436406089, 1109109865829139
 #else
@@ -2533,7 +2533,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2214421081775077, 1165671861210569, 1890453018796184,
                 3556249878661, 442116172656317
 #else
@@ -2544,7 +2544,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 753830546620811, 1666955059895019, 1530775289309243,
                 1119987029104146, 2164156153857580
 #else
@@ -2553,7 +2553,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 615171919212796, 1523849404854568, 854560460547503,
                 2067097370290715, 1765325848586042
 #else
@@ -2562,7 +2562,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1094538949313667, 1796592198908825, 870221004284388,
                 2025558921863561, 1699010892802384
 #else
@@ -2573,7 +2573,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1951351290725195, 1916457206844795, 198025184438026,
                 1909076887557595, 1938542290318919
 #else
@@ -2582,7 +2582,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1014323197538413, 869150639940606, 1756009942696599,
                 1334952557375672, 1544945379082874
 #else
@@ -2591,7 +2591,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 764055910920305, 1603590757375439, 146805246592357,
                 1843313433854297, 954279890114939
 #else
@@ -2602,7 +2602,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 80113526615750, 764536758732259, 1055139345100233,
                 469252651759390, 617897512431515
 #else
@@ -2611,7 +2611,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 74497112547268, 740094153192149, 1745254631717581,
                 727713886503130, 1283034364416928
 #else
@@ -2620,7 +2620,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 525892105991110, 1723776830270342, 1476444848991936,
                 573789489857760, 133864092632978
 #else
@@ -2631,7 +2631,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 542611720192581, 1986812262899321, 1162535242465837,
                 481498966143464, 544600533583622
 #else
@@ -2640,7 +2640,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 64123227344372, 1239927720647794, 1360722983445904,
                 222610813654661, 62429487187991
 #else
@@ -2649,7 +2649,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1793193323953132, 91096687857833, 70945970938921,
                 2158587638946380, 1537042406482111
 #else
@@ -2660,7 +2660,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1895854577604609, 1394895708949416, 1728548428495944,
                 1140864900240149, 563645333603061
 #else
@@ -2669,7 +2669,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 141358280486863, 91435889572504, 1087208572552643,
                 1829599652522921, 1193307020643647
 #else
@@ -2678,7 +2678,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1611230858525381, 950720175540785, 499589887488610,
                 2001656988495019, 88977313255908
 #else
@@ -2689,7 +2689,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1189080501479658, 2184348804772597, 1040818725742319,
                 2018318290311834, 1712060030915354
 #else
@@ -2698,7 +2698,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 873966876953756, 1090638350350440, 1708559325189137,
                 672344594801910, 1320437969700239
 #else
@@ -2707,7 +2707,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1508590048271766, 1131769479776094, 101550868699323,
                 428297785557897, 561791648661744
 #else
@@ -2720,7 +2720,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 756417570499462, 237882279232602, 2136263418594016,
                 1701968045454886, 703713185137472
 #else
@@ -2729,7 +2729,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1781187809325462, 1697624151492346, 1381393690939988,
                 175194132284669, 1483054666415238
 #else
@@ -2738,7 +2738,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2175517777364616, 708781536456029, 955668231122942,
                 1967557500069555, 2021208005604118
 #else
@@ -2749,7 +2749,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1115135966606887, 224217372950782, 915967306279222,
                 593866251291540, 561747094208006
 #else
@@ -2758,7 +2758,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1443163092879439, 391875531646162, 2180847134654632,
                 464538543018753, 1594098196837178
 #else
@@ -2767,7 +2767,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 850858855888869, 319436476624586, 327807784938441,
                 740785849558761, 17128415486016
 #else
@@ -2778,7 +2778,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2132756334090067, 536247820155645, 48907151276867,
                 608473197600695, 1261689545022784
 #else
@@ -2787,7 +2787,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1525176236978354, 974205476721062, 293436255662638,
                 148269621098039, 137961998433963
 #else
@@ -2796,7 +2796,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1121075518299410, 2071745529082111, 1265567917414828,
                 1648196578317805, 496232102750820
 #else
@@ -2807,7 +2807,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 122321229299801, 1022922077493685, 2001275453369484,
                 2017441881607947, 993205880778002
 #else
@@ -2816,7 +2816,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 654925550560074, 1168810995576858, 575655959430926,
                 905758704861388, 496774564663534
 #else
@@ -2825,7 +2825,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1954109525779738, 2117022646152485, 338102630417180,
                 1194140505732026, 107881734943492
 #else
@@ -2836,7 +2836,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1714785840001267, 2036500018681589, 1876380234251966,
                 2056717182974196, 1645855254384642
 #else
@@ -2845,7 +2845,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 106431476499341, 62482972120563, 1513446655109411,
                 807258751769522, 538491469114
 #else
@@ -2854,7 +2854,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2002850762893643, 1243624520538135, 1486040410574605,
                 2184752338181213, 378495998083531
 #else
@@ -2865,7 +2865,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 922510868424903, 1089502620807680, 402544072617374,
                 1131446598479839, 1290278588136533
 #else
@@ -2874,7 +2874,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1867998812076769, 715425053580701, 39968586461416,
                 2173068014586163, 653822651801304
 #else
@@ -2883,7 +2883,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 162892278589453, 182585796682149, 75093073137630,
                 497037941226502, 133871727117371
 #else
@@ -2894,7 +2894,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1914596576579670, 1608999621851578, 1987629837704609,
                 1519655314857977, 1819193753409464
 #else
@@ -2903,7 +2903,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1949315551096831, 1069003344994464, 1939165033499916,
                 1548227205730856, 1933767655861407
 #else
@@ -2912,7 +2912,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1730519386931635, 1393284965610134, 1597143735726030,
                 416032382447158, 1429665248828629
 #else
@@ -2923,7 +2923,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 360275475604565, 547835731063078, 215360904187529,
                 596646739879007, 332709650425085
 #else
@@ -2932,7 +2932,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 47602113726801, 1522314509708010, 437706261372925,
                 814035330438027, 335930650933545
 #else
@@ -2941,7 +2941,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1291597595523886, 1058020588994081, 402837842324045,
                 1363323695882781, 2105763393033193
 #else
@@ -2954,7 +2954,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 109521982566564, 1715257748585139, 1112231216891516,
                 2046641005101484, 134249157157013
 #else
@@ -2963,7 +2963,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2156991030936798, 2227544497153325, 1869050094431622,
                 754875860479115, 1754242344267058
 #else
@@ -2972,7 +2972,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1846089562873800, 98894784984326, 1412430299204844,
                 171351226625762, 1100604760929008
 #else
@@ -2983,7 +2983,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 84172382130492, 499710970700046, 425749630620778,
                 1762872794206857, 612842602127960
 #else
@@ -2992,7 +2992,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 868309334532756, 1703010512741873, 1952690008738057,
                 4325269926064, 2071083554962116
 #else
@@ -3001,7 +3001,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 523094549451158, 401938899487815, 1407690589076010,
                 2022387426254453, 158660516411257
 #else
@@ -3012,7 +3012,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 612867287630009, 448212612103814, 571629077419196,
                 1466796750919376, 1728478129663858
 #else
@@ -3021,7 +3021,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1723848973783452, 2208822520534681, 1718748322776940,
                 1974268454121942, 1194212502258141
 #else
@@ -3030,7 +3030,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1254114807944608, 977770684047110, 2010756238954993,
                 1783628927194099, 1525962994408256
 #else
@@ -3041,7 +3041,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 232464058235826, 1948628555342434, 1835348780427694,
                 1031609499437291, 64472106918373
 #else
@@ -3050,7 +3050,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 767338676040683, 754089548318405, 1523192045639075,
                 435746025122062, 512692508440385
 #else
@@ -3059,7 +3059,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1255955808701983, 1700487367990941, 1166401238800299,
                 1175121994891534, 1190934801395380
 #else
@@ -3070,7 +3070,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 349144008168292, 1337012557669162, 1475912332999108,
                 1321618454900458, 47611291904320
 #else
@@ -3079,7 +3079,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 877519947135419, 2172838026132651, 272304391224129,
                 1655143327559984, 886229406429814
 #else
@@ -3088,7 +3088,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 375806028254706, 214463229793940, 572906353144089,
                 572168269875638, 697556386112979
 #else
@@ -3099,7 +3099,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1168827102357844, 823864273033637, 2071538752104697,
                 788062026895924, 599578340743362
 #else
@@ -3108,7 +3108,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1948116082078088, 2054898304487796, 2204939184983900,
                 210526805152138, 786593586607626
 #else
@@ -3117,7 +3117,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1915320147894736, 156481169009469, 655050471180417,
                 592917090415421, 2165897438660879
 #else
@@ -3128,7 +3128,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1726336468579724, 1119932070398949, 1929199510967666,
                 33918788322959, 1836837863503150
 #else
@@ -3137,7 +3137,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 829996854845988, 217061778005138, 1686565909803640,
                 1346948817219846, 1723823550730181
 #else
@@ -3146,7 +3146,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 384301494966394, 687038900403062, 2211195391021739,
                 254684538421383, 1245698430589680
 #else
@@ -3157,7 +3157,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1247567493562688, 1978182094455847, 183871474792955,
                 806570235643435, 288461518067916
 #else
@@ -3166,7 +3166,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1449077384734201, 38285445457996, 2136537659177832,
                 2146493000841573, 725161151123125
 #else
@@ -3175,7 +3175,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1201928866368855, 800415690605445, 1703146756828343,
                 997278587541744, 1858284414104014
 #else
@@ -3188,7 +3188,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 356468809648877, 782373916933152, 1718002439402870,
                 1392222252219254, 663171266061951
 #else
@@ -3197,7 +3197,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 759628738230460, 1012693474275852, 353780233086498,
                 246080061387552, 2030378857679162
 #else
@@ -3206,7 +3206,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2040672435071076, 888593182036908, 1298443657189359,
                 1804780278521327, 354070726137060
 #else
@@ -3217,7 +3217,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1894938527423184, 1463213041477277, 474410505497651,
                 247294963033299, 877975941029128
 #else
@@ -3226,7 +3226,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 207937160991127, 12966911039119, 820997788283092,
                 1010440472205286, 1701372890140810
 #else
@@ -3235,7 +3235,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 218882774543183, 533427444716285, 1233243976733245,
                 435054256891319, 1509568989549904
 #else
@@ -3246,7 +3246,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1888838535711826, 1052177758340622, 1213553803324135,
                 169182009127332, 463374268115872
 #else
@@ -3255,7 +3255,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 299137589460312, 1594371588983567, 868058494039073,
                 257771590636681, 1805012993142921
 #else
@@ -3264,7 +3264,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1806842755664364, 2098896946025095, 1356630998422878,
                 1458279806348064, 347755825962072
 #else
@@ -3275,7 +3275,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1402334161391744, 1560083671046299, 1008585416617747,
                 1147797150908892, 1420416683642459
 #else
@@ -3284,7 +3284,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 665506704253369, 273770475169863, 799236974202630,
                 848328990077558, 1811448782807931
 #else
@@ -3293,7 +3293,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1468412523962641, 771866649897997, 1931766110147832,
                 799561180078482, 524837559150077
 #else
@@ -3304,7 +3304,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2223212657821850, 630416247363666, 2144451165500328,
                 816911130947791, 1024351058410032
 #else
@@ -3313,7 +3313,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1266603897524861, 156378408858100, 1275649024228779,
                 447738405888420, 253186462063095
 #else
@@ -3322,7 +3322,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2022215964509735, 136144366993649, 1800716593296582,
                 1193970603800203, 871675847064218
 #else
@@ -3333,7 +3333,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1862751661970328, 851596246739884, 1519315554814041,
                 1542798466547449, 1417975335901520
 #else
@@ -3342,7 +3342,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1228168094547481, 334133883362894, 587567568420081,
                 433612590281181, 603390400373205
 #else
@@ -3351,7 +3351,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 121893973206505, 1843345804916664, 1703118377384911,
                 497810164760654, 101150811654673
 #else
@@ -3362,7 +3362,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 458346255946468, 290909935619344, 1452768413850679,
                 550922875254215, 1537286854336538
 #else
@@ -3371,7 +3371,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 584322311184395, 380661238802118, 114839394528060,
                 655082270500073, 2111856026034852
 #else
@@ -3380,7 +3380,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 996965581008991, 2148998626477022, 1012273164934654,
                 1073876063914522, 1688031788934939
 #else
@@ -3391,7 +3391,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 923487018849600, 2085106799623355, 528082801620136,
                 1606206360876188, 735907091712524
 #else
@@ -3400,7 +3400,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1697697887804317, 1335343703828273, 831288615207040,
                 949416685250051, 288760277392022
 #else
@@ -3409,7 +3409,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1419122478109648, 1325574567803701, 602393874111094,
                 2107893372601700, 1314159682671307
 #else
@@ -3422,7 +3422,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2201150872731804, 2180241023425241, 97663456423163,
                 1633405770247824, 848945042443986
 #else
@@ -3431,7 +3431,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1173339555550611, 818605084277583, 47521504364289,
                 924108720564965, 735423405754506
 #else
@@ -3440,7 +3440,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 830104860549448, 1886653193241086, 1600929509383773,
                 1475051275443631, 286679780900937
 #else
@@ -3451,7 +3451,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1577111294832995, 1030899169768747, 144900916293530,
                 1964672592979567, 568390100955250
 #else
@@ -3460,7 +3460,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 278388655910247, 487143369099838, 927762205508727,
                 181017540174210, 1616886700741287
 #else
@@ -3469,7 +3469,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1191033906638969, 940823957346562, 1606870843663445,
                 861684761499847, 658674867251089
 #else
@@ -3480,7 +3480,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1875032594195546, 1427106132796197, 724736390962158,
                 901860512044740, 635268497268760
 #else
@@ -3489,7 +3489,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 622869792298357, 1903919278950367, 1922588621661629,
                 1520574711600434, 1087100760174640
 #else
@@ -3498,7 +3498,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 25465949416618, 1693639527318811, 1526153382657203,
                 125943137857169, 145276964043999
 #else
@@ -3509,7 +3509,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 214739857969358, 920212862967915, 1939901550972269,
                 1211862791775221, 85097515720120
 #else
@@ -3518,7 +3518,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2006245852772938, 734762734836159, 254642929763427,
                 1406213292755966, 239303749517686
 #else
@@ -3527,7 +3527,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1619678837192149, 1919424032779215, 1357391272956794,
                 1525634040073113, 1310226789796241
 #else
@@ -3538,7 +3538,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1040763709762123, 1704449869235352, 605263070456329,
                 1998838089036355, 1312142911487502
 #else
@@ -3547,7 +3547,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1996723311435669, 1844342766567060, 985455700466044,
                 1165924681400960, 311508689870129
 #else
@@ -3556,7 +3556,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 43173156290518, 2202883069785309, 1137787467085917,
                 1733636061944606, 1394992037553852
 #else
@@ -3567,7 +3567,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 670078326344559, 555655025059356, 471959386282438,
                 2141455487356409, 849015953823125
 #else
@@ -3576,7 +3576,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2197214573372804, 794254097241315, 1030190060513737,
                 267632515541902, 2040478049202624
 #else
@@ -3585,7 +3585,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1812516004670529, 1609256702920783, 1706897079364493,
                 258549904773295, 996051247540686
 #else
@@ -3596,7 +3596,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1540374301420584, 1764656898914615, 1810104162020396,
                 923808779163088, 664390074196579
 #else
@@ -3605,7 +3605,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1323460699404750, 1262690757880991, 871777133477900,
                 1060078894988977, 1712236889662886
 #else
@@ -3614,7 +3614,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1696163952057966, 1391710137550823, 608793846867416,
                 1034391509472039, 1780770894075012
 #else
@@ -3625,7 +3625,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1367603834210841, 2131988646583224, 890353773628144,
                 1908908219165595, 270836895252891
 #else
@@ -3634,7 +3634,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 597536315471731, 40375058742586, 1942256403956049,
                 1185484645495932, 312666282024145
 #else
@@ -3643,7 +3643,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1919411405316294, 1234508526402192, 1066863051997083,
                 1008444703737597, 1348810787701552
 #else
@@ -3656,7 +3656,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2102881477513865, 1570274565945361, 1573617900503708,
                 18662635732583, 2232324307922098
 #else
@@ -3665,7 +3665,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1853931367696942, 8107973870707, 350214504129299,
                 775206934582587, 1752317649166792
 #else
@@ -3674,7 +3674,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1417148368003523, 721357181628282, 505725498207811,
                 373232277872983, 261634707184480
 #else
@@ -3685,7 +3685,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2186733281493267, 2250694917008620, 1014829812957440,
                 479998161452389, 83566193876474
 #else
@@ -3694,7 +3694,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1268116367301224, 560157088142809, 802626839600444,
                 2210189936605713, 1129993785579988
 #else
@@ -3703,7 +3703,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 615183387352312, 917611676109240, 878893615973325,
                 978940963313282, 938686890583575
 #else
@@ -3714,7 +3714,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 522024729211672, 1045059315315808, 1892245413707790,
                 1907891107684253, 2059998109500714
 #else
@@ -3723,7 +3723,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1799679152208884, 912132775900387, 25967768040979,
                 432130448590461, 274568990261996
 #else
@@ -3732,7 +3732,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 98698809797682, 2144627600856209, 1907959298569602,
                 811491302610148, 1262481774981493
 #else
@@ -3743,7 +3743,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1791451399743152, 1713538728337276, 118349997257490,
                 1882306388849954, 158235232210248
 #else
@@ -3752,7 +3752,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1217809823321928, 2173947284933160, 1986927836272325,
                 1388114931125539, 12686131160169
 #else
@@ -3761,7 +3761,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1650875518872272, 1136263858253897, 1732115601395988,
                 734312880662190, 1252904681142109
 #else
@@ -3772,7 +3772,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 372986456113865, 525430915458171, 2116279931702135,
                 501422713587815, 1907002872974925
 #else
@@ -3781,7 +3781,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 803147181835288, 868941437997146, 316299302989663,
                 943495589630550, 571224287904572
 #else
@@ -3790,7 +3790,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 227742695588364, 1776969298667369, 628602552821802,
                 457210915378118, 2041906378111140
 #else
@@ -3801,7 +3801,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 815000523470260, 913085688728307, 1052060118271173,
                 1345536665214223, 541623413135555
 #else
@@ -3810,7 +3810,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1580216071604333, 1877997504342444, 857147161260913,
                 703522726778478, 2182763974211603
 #else
@@ -3819,7 +3819,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1870080310923419, 71988220958492, 1783225432016732,
                 615915287105016, 1035570475990230
 #else
@@ -3830,7 +3830,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 730987750830150, 857613889540280, 1083813157271766,
                 1002817255970169, 1719228484436074
 #else
@@ -3839,7 +3839,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 377616581647602, 1581980403078513, 804044118130621,
                 2034382823044191, 643844048472185
 #else
@@ -3848,7 +3848,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 176957326463017, 1573744060478586, 528642225008045,
                 1816109618372371, 1515140189765006
 #else
@@ -3859,7 +3859,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1888911448245718, 1387110895611080, 1924503794066429,
                 1731539523700949, 2230378382645454
 #else
@@ -3868,7 +3868,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 443392177002051, 233793396845137, 2199506622312416,
                 1011858706515937, 974676837063129
 #else
@@ -3877,7 +3877,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1846351103143623, 1949984838808427, 671247021915253,
                 1946756846184401, 1929296930380217
 #else
@@ -3890,7 +3890,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 849646212452002, 1410198775302919, 73767886183695,
                 1641663456615812, 762256272452411
 #else
@@ -3899,7 +3899,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 692017667358279, 723305578826727, 1638042139863265,
                 748219305990306, 334589200523901
 #else
@@ -3908,7 +3908,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 22893968530686, 2235758574399251, 1661465835630252,
                 925707319443452, 1203475116966621
 #else
@@ -3919,7 +3919,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 801299035785166, 1733292596726131, 1664508947088596,
                 467749120991922, 1647498584535623
 #else
@@ -3928,7 +3928,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 903105258014366, 427141894933047, 561187017169777,
                 1884330244401954, 1914145708422219
 #else
@@ -3937,7 +3937,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1344191060517578, 1960935031767890, 1518838929955259,
                 1781502350597190, 1564784025565682
 #else
@@ -3948,7 +3948,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 673723351748086, 1979969272514923, 1175287312495508,
                 1187589090978666, 1881897672213940
 #else
@@ -3957,7 +3957,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1917185587363432, 1098342571752737, 5935801044414,
                 2000527662351839, 1538640296181569
 #else
@@ -3966,7 +3966,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2495540013192, 678856913479236, 224998292422872,
                 219635787698590, 1972465269000940
 #else
@@ -3977,7 +3977,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 271413961212179, 1353052061471651, 344711291283483,
                 2014925838520662, 2006221033113941
 #else
@@ -3986,7 +3986,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 194583029968109, 514316781467765, 829677956235672,
                 1676415686873082, 810104584395840
 #else
@@ -3995,7 +3995,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1980510813313589, 1948645276483975, 152063780665900,
                 129968026417582, 256984195613935
 #else
@@ -4006,7 +4006,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1860190562533102, 1936576191345085, 461100292705964,
                 1811043097042830, 957486749306835
 #else
@@ -4015,7 +4015,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 796664815624365, 1543160838872951, 1500897791837765,
                 1667315977988401, 599303877030711
 #else
@@ -4024,7 +4024,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1151480509533204, 2136010406720455, 738796060240027,
                 319298003765044, 1150614464349587
 #else
@@ -4035,7 +4035,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1731069268103150, 735642447616087, 1364750481334268,
                 417232839982871, 927108269127661
 #else
@@ -4044,7 +4044,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1017222050227968, 1987716148359, 2234319589635701,
                 621282683093392, 2132553131763026
 #else
@@ -4053,7 +4053,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1567828528453324, 1017807205202360, 565295260895298,
                 829541698429100, 307243822276582
 #else
@@ -4064,7 +4064,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 249079270936248, 1501514259790706, 947909724204848,
                 944551802437487, 552658763982480
 #else
@@ -4073,7 +4073,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2089966982947227, 1854140343916181, 2151980759220007,
                 2139781292261749, 158070445864917
 #else
@@ -4082,7 +4082,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1338766321464554, 1906702607371284, 1519569445519894,
                 115384726262267, 1393058953390992
 #else
@@ -4093,7 +4093,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1364621558265400, 1512388234908357, 1926731583198686,
                 2041482526432505, 920401122333774
 #else
@@ -4102,7 +4102,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1884844597333588, 601480070269079, 620203503079537,
                 1079527400117915, 1202076693132015
 #else
@@ -4111,7 +4111,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 840922919763324, 727955812569642, 1303406629750194,
                 522898432152867, 294161410441865
 #else
@@ -4124,7 +4124,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 353760790835310, 1598361541848743, 1122905698202299,
                 1922533590158905, 419107700666580
 #else
@@ -4133,7 +4133,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 359856369838236, 180914355488683, 861726472646627,
                 218807937262986, 575626773232501
 #else
@@ -4142,7 +4142,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 755467689082474, 909202735047934, 730078068932500,
                 936309075711518, 2007798262842972
 #else
@@ -4153,7 +4153,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1609384177904073, 362745185608627, 1335318541768201,
                 800965770436248, 547877979267412
 #else
@@ -4162,7 +4162,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 984339177776787, 815727786505884, 1645154585713747,
                 1659074964378553, 1686601651984156
 #else
@@ -4171,7 +4171,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1697863093781930, 599794399429786, 1104556219769607,
                 830560774794755, 12812858601017
 #else
@@ -4182,7 +4182,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1168737550514982, 897832437380552, 463140296333799,
                 302564600022547, 2008360505135501
 #else
@@ -4191,7 +4191,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1856930662813910, 678090852002597, 1920179140755167,
                 1259527833759868, 55540971895511
 #else
@@ -4200,7 +4200,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1158643631044921, 476554103621892, 178447851439725,
                 1305025542653569, 103433927680625
 #else
@@ -4211,7 +4211,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2176793111709008, 1576725716350391, 2009350167273523,
                 2012390194631546, 2125297410909580
 #else
@@ -4220,7 +4220,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 825403285195098, 2144208587560784, 1925552004644643,
                 1915177840006985, 1015952128947864
 #else
@@ -4229,7 +4229,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1807108316634472, 1534392066433717, 347342975407218,
                 1153820745616376, 7375003497471
 #else
@@ -4240,7 +4240,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 983061001799725, 431211889901241, 2201903782961093,
                 817393911064341, 2214616493042167
 #else
@@ -4249,7 +4249,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 228567918409756, 865093958780220, 358083886450556,
                 159617889659320, 1360637926292598
 #else
@@ -4258,7 +4258,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 234147501399755, 2229469128637390, 2175289352258889,
                 1397401514549353, 1885288963089922
 #else
@@ -4269,7 +4269,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1111762412951562, 252849572507389, 1048714233823341,
                 146111095601446, 1237505378776770
 #else
@@ -4278,7 +4278,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1113790697840279, 1051167139966244, 1045930658550944,
                 2011366241542643, 1686166824620755
 #else
@@ -4287,7 +4287,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1054097349305049, 1872495070333352, 182121071220717,
                 1064378906787311, 100273572924182
 #else
@@ -4298,7 +4298,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1306410853171605, 1627717417672447, 50983221088417,
                 1109249951172250, 870201789081392
 #else
@@ -4307,7 +4307,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 104233794644221, 1548919791188248, 2224541913267306,
                 2054909377116478, 1043803389015153
 #else
@@ -4316,7 +4316,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 216762189468802, 707284285441622, 190678557969733,
                 973969342604308, 1403009538434867
 #else
@@ -4327,7 +4327,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1279024291038477, 344776835218310, 273722096017199,
                 1834200436811442, 634517197663804
 #else
@@ -4336,7 +4336,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 343805853118335, 1302216857414201, 566872543223541,
                 2051138939539004, 321428858384280
 #else
@@ -4345,7 +4345,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 470067171324852, 1618629234173951, 2000092177515639,
                 7307679772789, 1117521120249968
 #else
@@ -4358,7 +4358,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 278151578291475, 1810282338562947, 1771599529530998,
                 1383659409671631, 685373414471841
 #else
@@ -4367,7 +4367,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 577009397403102, 1791440261786291, 2177643735971638,
                 174546149911960, 1412505077782326
 #else
@@ -4376,7 +4376,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 893719721537457, 1201282458018197, 1522349501711173,
                 58011597740583, 1130406465887139
 #else
@@ -4387,7 +4387,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 412607348255453, 1280455764199780, 2233277987330768,
                 14180080401665, 331584698417165
 #else
@@ -4396,7 +4396,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 262483770854550, 990511055108216, 526885552771698,
                 571664396646158, 354086190278723
 #else
@@ -4405,7 +4405,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1820352417585487, 24495617171480, 1547899057533253,
                 10041836186225, 480457105094042
 #else
@@ -4416,7 +4416,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2023310314989233, 637905337525881, 2106474638900687,
                 557820711084072, 1687858215057826
 #else
@@ -4425,7 +4425,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1144168702609745, 604444390410187, 1544541121756138,
                 1925315550126027, 626401428894002
 #else
@@ -4434,7 +4434,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1922168257351784, 2018674099908659, 1776454117494445,
                 956539191509034, 36031129147635
 #else
@@ -4445,7 +4445,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 544644538748041, 1039872944430374, 876750409130610,
                 710657711326551, 1216952687484972
 #else
@@ -4454,7 +4454,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 58242421545916, 2035812695641843, 2118491866122923,
                 1191684463816273, 46921517454099
 #else
@@ -4463,7 +4463,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 272268252444639, 1374166457774292, 2230115177009552,
                 1053149803909880, 1354288411641016
 #else
@@ -4474,7 +4474,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1857910905368338, 1754729879288912, 885945464109877,
                 1516096106802166, 1602902393369811
 #else
@@ -4483,7 +4483,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1193437069800958, 901107149704790, 999672920611411,
                 477584824802207, 364239578697845
 #else
@@ -4492,7 +4492,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 886299989548838, 1538292895758047, 1590564179491896,
                 1944527126709657, 837344427345298
 #else
@@ -4503,7 +4503,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 754558365378305, 1712186480903618, 1703656826337531,
                 750310918489786, 518996040250900
 #else
@@ -4512,7 +4512,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1309847803895382, 1462151862813074, 211370866671570,
                 1544595152703681, 1027691798954090
 #else
@@ -4521,7 +4521,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 803217563745370, 1884799722343599, 1357706345069218,
                 2244955901722095, 730869460037413
 #else
@@ -4532,7 +4532,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 689299471295966, 1831210565161071, 1375187341585438,
                 1106284977546171, 1893781834054269
 #else
@@ -4541,7 +4541,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 696351368613042, 1494385251239250, 738037133616932,
                 636385507851544, 927483222611406
 #else
@@ -4550,7 +4550,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1949114198209333, 1104419699537997, 783495707664463,
                 1747473107602770, 2002634765788641
 #else
@@ -4561,7 +4561,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1607325776830197, 530883941415333, 1451089452727895,
                 1581691157083423, 496100432831154
 #else
@@ -4570,7 +4570,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1068900648804224, 2006891997072550, 1134049269345549,
                 1638760646180091, 2055396084625778
 #else
@@ -4579,7 +4579,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2222475519314561, 1870703901472013, 1884051508440561,
                 1344072275216753, 1318025677799069
 #else
@@ -4592,7 +4592,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 155711679280656, 681100400509288, 389811735211209,
                 2135723811340709, 408733211204125
 #else
@@ -4601,7 +4601,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 7813206966729, 194444201427550, 2071405409526507,
                 1065605076176312, 1645486789731291
 #else
@@ -4610,7 +4610,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 16625790644959, 1647648827778410, 1579910185572704,
                 436452271048548, 121070048451050
 #else
@@ -4621,7 +4621,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1037263028552531, 568385780377829, 297953104144430,
                 1558584511931211, 2238221839292471
 #else
@@ -4630,7 +4630,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 190565267697443, 672855706028058, 338796554369226,
                 337687268493904, 853246848691734
 #else
@@ -4639,7 +4639,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1763863028400139, 766498079432444, 1321118624818005,
                 69494294452268, 858786744165651
 #else
@@ -4650,7 +4650,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1292056768563024, 1456632109855638, 1100631247050184,
                 1386133165675321, 1232898350193752
 #else
@@ -4659,7 +4659,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 366253102478259, 525676242508811, 1449610995265438,
                 1183300845322183, 185960306491545
 #else
@@ -4668,7 +4668,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 28315355815982, 460422265558930, 1799675876678724,
                 1969256312504498, 1051823843138725
 #else
@@ -4679,7 +4679,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 156914999361983, 1606148405719949, 1665208410108430,
                 317643278692271, 1383783705665320
 #else
@@ -4688,7 +4688,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 54684536365732, 2210010038536222, 1194984798155308,
                 535239027773705, 1516355079301361
 #else
@@ -4697,7 +4697,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1484387703771650, 198537510937949, 2186282186359116,
                 617687444857508, 647477376402122
 #else
@@ -4708,7 +4708,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2147715541830533, 500032538445817, 646380016884826,
                 352227855331122, 1488268620408052
 #else
@@ -4717,7 +4717,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 159386186465542, 1877626593362941, 618737197060512,
                 1026674284330807, 1158121760792685
 #else
@@ -4726,7 +4726,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1744544377739822, 1964054180355661, 1685781755873170,
                 2169740670377448, 1286112621104591
 #else
@@ -4737,7 +4737,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 81977249784993, 1667943117713086, 1668983819634866,
                 1605016835177615, 1353960708075544
 #else
@@ -4746,7 +4746,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1602253788689063, 439542044889886, 2220348297664483,
                 657877410752869, 157451572512238
 #else
@@ -4755,7 +4755,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1029287186166717, 65860128430192, 525298368814832,
                 1491902500801986, 1461064796385400
 #else
@@ -4766,7 +4766,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 408216988729246, 2121095722306989, 913562102267595,
                 1879708920318308, 241061448436731
 #else
@@ -4775,7 +4775,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1185483484383269, 1356339572588553, 584932367316448,
                 102132779946470, 1792922621116791
 #else
@@ -4784,7 +4784,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1966196870701923, 2230044620318636, 1425982460745905,
                 261167817826569, 46517743394330
 #else
@@ -4795,7 +4795,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 107077591595359, 884959942172345, 27306869797400,
                 2224911448949390, 964352058245223
 #else
@@ -4804,7 +4804,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1730194207717538, 431790042319772, 1831515233279467,
                 1372080552768581, 1074513929381760
 #else
@@ -4813,7 +4813,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1450880638731607, 1019861580989005, 1229729455116861,
                 1174945729836143, 826083146840706
 #else
@@ -4826,7 +4826,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1899935429242705, 1602068751520477, 940583196550370,
                 82431069053859, 1540863155745696
 #else
@@ -4835,7 +4835,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2136688454840028, 2099509000964294, 1690800495246475,
                 1217643678575476, 828720645084218
 #else
@@ -4844,7 +4844,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 765548025667841, 462473984016099, 998061409979798,
                 546353034089527, 2212508972466858
 #else
@@ -4855,7 +4855,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 46575283771160, 892570971573071, 1281983193144090,
                 1491520128287375, 75847005908304
 #else
@@ -4864,7 +4864,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1801436127943107, 1734436817907890, 1268728090345068,
                 167003097070711, 2233597765834956
 #else
@@ -4873,7 +4873,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1997562060465113, 1048700225534011, 7615603985628,
                 1855310849546841, 2242557647635213
 #else
@@ -4884,7 +4884,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1161017320376250, 492624580169043, 2169815802355237,
                 976496781732542, 1770879511019629
 #else
@@ -4893,7 +4893,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1357044908364776, 729130645262438, 1762469072918979,
                 1365633616878458, 181282906404941
 #else
@@ -4902,7 +4902,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1080413443139865, 1155205815510486, 1848782073549786,
                 622566975152580, 124965574467971
 #else
@@ -4913,7 +4913,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1184526762066993, 247622751762817, 692129017206356,
                 820018689412496, 2188697339828085
 #else
@@ -4922,7 +4922,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2020536369003019, 202261491735136, 1053169669150884,
                 2056531979272544, 778165514694311
 #else
@@ -4931,7 +4931,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 237404399610207, 1308324858405118, 1229680749538400,
                 720131409105291, 1958958863624906
 #else
@@ -4942,7 +4942,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 515583508038846, 17656978857189, 1717918437373989,
                 1568052070792483, 46975803123923
 #else
@@ -4951,7 +4951,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 281527309158085, 36970532401524, 866906920877543,
                 2222282602952734, 1289598729589882
 #else
@@ -4960,7 +4960,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1278207464902042, 494742455008756, 1262082121427081,
                 1577236621659884, 1888786707293291
 #else
@@ -4971,7 +4971,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 353042527954210, 1830056151907359, 1111731275799225,
                 174960955838824, 404312815582675
 #else
@@ -4980,7 +4980,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2064251142068628, 1666421603389706, 1419271365315441,
                 468767774902855, 191535130366583
 #else
@@ -4989,7 +4989,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1716987058588002, 1859366439773457, 1767194234188234,
                 64476199777924, 1117233614485261
 #else
@@ -5000,7 +5000,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 984292135520292, 135138246951259, 2220652137473167,
                 1722843421165029, 190482558012909
 #else
@@ -5009,7 +5009,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 298845952651262, 1166086588952562, 1179896526238434,
                 1347812759398693, 1412945390096208
 #else
@@ -5018,7 +5018,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1143239552672925, 906436640714209, 2177000572812152,
                 2075299936108548, 325186347798433
 #else
@@ -5029,7 +5029,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 721024854374772, 684487861263316, 1373438744094159,
                 2193186935276995, 1387043709851261
 #else
@@ -5038,7 +5038,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 418098668140962, 715065997721283, 1471916138376055,
                 2168570337288357, 937812682637044
 #else
@@ -5047,7 +5047,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1043584187226485, 2143395746619356, 2209558562919611,
                 482427979307092, 847556718384018
 #else
@@ -5060,7 +5060,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1248731221520759, 1465200936117687, 540803492710140,
                 52978634680892, 261434490176109
 #else
@@ -5069,7 +5069,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1057329623869501, 620334067429122, 461700859268034,
                 2012481616501857, 297268569108938
 #else
@@ -5078,7 +5078,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1055352180870759, 1553151421852298, 1510903185371259,
                 1470458349428097, 1226259419062731
 #else
@@ -5089,7 +5089,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1492988790301668, 790326625573331, 1190107028409745,
                 1389394752159193, 1620408196604194
 #else
@@ -5098,7 +5098,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 47000654413729, 1004754424173864, 1868044813557703,
                 173236934059409, 588771199737015
 #else
@@ -5107,7 +5107,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 30498470091663, 1082245510489825, 576771653181956,
                 806509986132686, 1317634017056939
 #else
@@ -5118,7 +5118,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 420308055751555, 1493354863316002, 165206721528088,
                 1884845694919786, 2065456951573059
 #else
@@ -5127,7 +5127,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1115636332012334, 1854340990964155, 83792697369514,
                 1972177451994021, 457455116057587
 #else
@@ -5136,7 +5136,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1698968457310898, 1435137169051090, 1083661677032510,
                 938363267483709, 340103887207182
 #else
@@ -5147,7 +5147,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1995325341336574, 911500251774648, 164010755403692,
                 855378419194762, 1573601397528842
 #else
@@ -5156,7 +5156,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 241719380661528, 310028521317150, 1215881323380194,
                 1408214976493624, 2141142156467363
 #else
@@ -5165,7 +5165,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1315157046163473, 727368447885818, 1363466668108618,
                 1668921439990361, 1398483384337907
 #else
@@ -5176,7 +5176,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 75029678299646, 1015388206460473, 1849729037055212,
                 1939814616452984, 444404230394954
 #else
@@ -5185,7 +5185,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2053597130993710, 2024431685856332, 2233550957004860,
                 2012407275509545, 872546993104440
 #else
@@ -5194,7 +5194,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1217269667678610, 599909351968693, 1390077048548598,
                 1471879360694802, 739586172317596
 #else
@@ -5205,7 +5205,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1718318639380794, 1560510726633958, 904462881159922,
                 1418028351780052, 94404349451937
 #else
@@ -5214,7 +5214,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2132502667405250, 214379346175414, 1502748313768060,
                 1960071701057800, 1353971822643138
 #else
@@ -5223,7 +5223,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 319394212043702, 2127459436033571, 717646691535162,
                 663366796076914, 318459064945314
 #else
@@ -5234,7 +5234,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 405989424923593, 1960452633787083, 667349034401665,
                 1492674260767112, 1451061489880787
 #else
@@ -5243,7 +5243,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 947085906234007, 323284730494107, 1485778563977200,
                 728576821512394, 901584347702286
 #else
@@ -5252,7 +5252,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1575783124125742, 2126210792434375, 1569430791264065,
                 1402582372904727, 1891780248341114
 #else
@@ -5263,7 +5263,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 838432205560695, 1997703511451664, 1018791879907867,
                 1662001808174331, 78328132957753
 #else
@@ -5272,7 +5272,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 739152638255629, 2074935399403557, 505483666745895,
                 1611883356514088, 628654635394878
 #else
@@ -5281,7 +5281,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1822054032121349, 643057948186973, 7306757352712,
                 577249257962099, 284735863382083
 #else
@@ -5294,7 +5294,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1366558556363930, 1448606567552086, 1478881020944768,
                 165803179355898, 1115718458123498
 #else
@@ -5303,7 +5303,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 204146226972102, 1630511199034723, 2215235214174763,
                 174665910283542, 956127674017216
 #else
@@ -5312,7 +5312,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1562934578796716, 1070893489712745, 11324610642270,
                 958989751581897, 2172552325473805
 #else
@@ -5323,7 +5323,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1770564423056027, 735523631664565, 1326060113795289,
                 1509650369341127, 65892421582684
 #else
@@ -5332,7 +5332,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 623682558650637, 1337866509471512, 990313350206649,
                 1314236615762469, 1164772974270275
 #else
@@ -5341,7 +5341,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 223256821462517, 723690150104139, 1000261663630601,
                 933280913953265, 254872671543046
 #else
@@ -5352,7 +5352,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1969087237026041, 624795725447124, 1335555107635969,
                 2069986355593023, 1712100149341902
 #else
@@ -5361,7 +5361,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1236103475266979, 1837885883267218, 1026072585230455,
                 1025865513954973, 1801964901432134
 #else
@@ -5370,7 +5370,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1115241013365517, 1712251818829143, 2148864332502771,
                 2096001471438138, 2235017246626125
 #else
@@ -5381,7 +5381,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1299268198601632, 2047148477845621, 2165648650132450,
                 1612539282026145, 514197911628890
 #else
@@ -5390,7 +5390,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 118352772338543, 1067608711804704, 1434796676193498,
                 1683240170548391, 230866769907437
 #else
@@ -5399,7 +5399,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1850689576796636, 1601590730430274, 1139674615958142,
                 1954384401440257, 76039205311
 #else
@@ -5410,7 +5410,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1723387471374172, 997301467038410, 533927635123657,
                 20928644693965, 1756575222802513
 #else
@@ -5419,7 +5419,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2146711623855116, 503278928021499, 625853062251406,
                 1109121378393107, 1033853809911861
 #else
@@ -5428,7 +5428,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 571005965509422, 2005213373292546, 1016697270349626,
                 56607856974274, 914438579435146
 #else
@@ -5439,7 +5439,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1346698876211176, 2076651707527589, 1084761571110205,
                 265334478828406, 1068954492309671
 #else
@@ -5448,7 +5448,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1769967932677654, 1695893319756416, 1151863389675920,
                 1781042784397689, 400287774418285
 #else
@@ -5457,7 +5457,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1851867764003121, 403841933237558, 820549523771987,
                 761292590207581, 1743735048551143
 #else
@@ -5468,7 +5468,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 410915148140008, 2107072311871739, 1004367461876503,
                 99684895396761, 1180818713503224
 #else
@@ -5477,7 +5477,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 285945406881439, 648174397347453, 1098403762631981,
                 1366547441102991, 1505876883139217
 #else
@@ -5486,7 +5486,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 672095903120153, 1675918957959872, 636236529315028,
                 1569297300327696, 2164144194785875
 #else
@@ -5497,7 +5497,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1902708175321798, 1035343530915438, 1178560808893263,
                 301095684058146, 1280977479761118
 #else
@@ -5506,7 +5506,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1615357281742403, 404257611616381, 2160201349780978,
                 1160947379188955, 1578038619549541
 #else
@@ -5515,7 +5515,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2013087639791217, 822734930507457, 1785668418619014,
                 1668650702946164, 389450875221715
 #else
@@ -5528,7 +5528,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 453918449698368, 106406819929001, 2072540975937135,
                 308588860670238, 1304394580755385
 #else
@@ -5537,7 +5537,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1295082798350326, 2091844511495996, 1851348972587817,
                 3375039684596, 789440738712837
 #else
@@ -5546,7 +5546,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2083069137186154, 848523102004566, 993982213589257,
                 1405313299916317, 1532824818698468
 #else
@@ -5557,7 +5557,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1495961298852430, 1397203457344779, 1774950217066942,
                 139302743555696, 66603584342787
 #else
@@ -5566,7 +5566,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1782411379088302, 1096724939964781, 27593390721418,
                 542241850291353, 1540337798439873
 #else
@@ -5575,7 +5575,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 693543956581437, 171507720360750, 1557908942697227,
                 1074697073443438, 1104093109037196
 #else
@@ -5586,7 +5586,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 345288228393419, 1099643569747172, 134881908403743,
                 1740551994106740, 248212179299770
 #else
@@ -5595,7 +5595,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 231429562203065, 1526290236421172, 2021375064026423,
                 1520954495658041, 806337791525116
 #else
@@ -5604,7 +5604,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1079623667189886, 872403650198613, 766894200588288,
                 2163700860774109, 2023464507911816
 #else
@@ -5615,7 +5615,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 854645372543796, 1936406001954827, 151460662541253,
                 825325739271555, 1554306377287556
 #else
@@ -5624,7 +5624,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1497138821904622, 1044820250515590, 1742593886423484,
                 1237204112746837, 849047450816987
 #else
@@ -5633,7 +5633,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 667962773375330, 1897271816877105, 1399712621683474,
                 1143302161683099, 2081798441209593
 #else
@@ -5644,7 +5644,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 127147851567005, 1936114012888110, 1704424366552046,
                 856674880716312, 716603621335359
 #else
@@ -5653,7 +5653,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1072409664800960, 2146937497077528, 1508780108920651,
                 935767602384853, 1112800433544068
 #else
@@ -5662,7 +5662,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 333549023751292, 280219272863308, 2104176666454852,
                 1036466864875785, 536135186520207
 #else
@@ -5673,7 +5673,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 373666279883137, 146457241530109, 304116267127857,
                 416088749147715, 1258577131183391
 #else
@@ -5682,7 +5682,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1186115062588401, 2251609796968486, 1098944457878953,
                 1153112761201374, 1791625503417267
 #else
@@ -5691,7 +5691,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1870078460219737, 2129630962183380, 852283639691142,
                 292865602592851, 401904317342226
 #else
@@ -5702,7 +5702,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1361070124828035, 815664541425524, 1026798897364671,
                 1951790935390647, 555874891834790
 #else
@@ -5711,7 +5711,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1546301003424277, 459094500062839, 1097668518375311,
                 1780297770129643, 720763293687608
 #else
@@ -5720,7 +5720,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1212405311403990, 1536693382542438, 61028431067459,
                 1863929423417129, 1223219538638038
 #else
@@ -5731,7 +5731,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1294303766540260, 1183557465955093, 882271357233093,
                 63854569425375, 2213283684565087
 #else
@@ -5740,7 +5740,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 339050984211414, 601386726509773, 413735232134068,
                 966191255137228, 1839475899458159
 #else
@@ -5749,7 +5749,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 235605972169408, 2174055643032978, 1538335001838863,
                 1281866796917192, 1815940222628465
 #else
@@ -5762,7 +5762,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1632352921721536, 1833328609514701, 2092779091951987,
                 1923956201873226, 2210068022482919
 #else
@@ -5771,7 +5771,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 35271216625062, 1712350667021807, 983664255668860,
                 98571260373038, 1232645608559836
 #else
@@ -5780,7 +5780,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1998172393429622, 1798947921427073, 784387737563581,
                 1589352214827263, 1589861734168180
 #else
@@ -5791,7 +5791,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1733739258725305, 31715717059538, 201969945218860,
                 992093044556990, 1194308773174556
 #else
@@ -5800,7 +5800,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 846415389605137, 746163495539180, 829658752826080,
                 592067705956946, 957242537821393
 #else
@@ -5809,7 +5809,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1758148849754419, 619249044817679, 168089007997045,
                 1371497636330523, 1867101418880350
 #else
@@ -5820,7 +5820,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 326633984209635, 261759506071016, 1700682323676193,
                 1577907266349064, 1217647663383016
 #else
@@ -5829,7 +5829,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1714182387328607, 1477856482074168, 574895689942184,
                 2159118410227270, 1555532449716575
 #else
@@ -5838,7 +5838,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 853828206885131, 998498946036955, 1835887550391235,
                 207627336608048, 258363815956050
 #else
@@ -5849,7 +5849,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 141141474651677, 1236728744905256, 643101419899887,
                 1646615130509173, 1208239602291765
 #else
@@ -5858,7 +5858,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1501663228068911, 1354879465566912, 1444432675498247,
                 897812463852601, 855062598754348
 #else
@@ -5867,7 +5867,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 714380763546606, 1032824444965790, 1774073483745338,
                 1063840874947367, 1738680636537158
 #else
@@ -5878,7 +5878,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1640635546696252, 633168953192112, 2212651044092396,
                 30590958583852, 368515260889378
 #else
@@ -5887,7 +5887,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1171650314802029, 1567085444565577, 1453660792008405,
                 757914533009261, 1619511342778196
 #else
@@ -5896,7 +5896,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 420958967093237, 971103481109486, 2169549185607107,
                 1301191633558497, 1661514101014240
 #else
@@ -5907,7 +5907,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 907123651818302, 1332556122804146, 1824055253424487,
                 1367614217442959, 1982558335973172
 #else
@@ -5916,7 +5916,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1121533090144639, 1021251337022187, 110469995947421,
                 1511059774758394, 2110035908131662
 #else
@@ -5925,7 +5925,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 303213233384524, 2061932261128138, 352862124777736,
                 40828818670255, 249879468482660
 #else
@@ -5936,7 +5936,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 856559257852200, 508517664949010, 1378193767894916,
                 1723459126947129, 1962275756614521
 #else
@@ -5945,7 +5945,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1445691340537320, 40614383122127, 402104303144865,
                 485134269878232, 1659439323587426
 #else
@@ -5954,7 +5954,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 20057458979482, 1183363722525800, 2140003847237215,
                 2053873950687614, 2112017736174909
 #else
@@ -5965,7 +5965,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2228654250927986, 1483591363415267, 1368661293910956,
                 1076511285177291, 526650682059608
 #else
@@ -5974,7 +5974,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 709481497028540, 531682216165724, 316963769431931,
                 1814315888453765, 258560242424104
 #else
@@ -5983,7 +5983,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1053447823660455, 1955135194248683, 1010900954918985,
                 1182614026976701, 1240051576966610
 #else
@@ -5996,7 +5996,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1957943897155497, 1788667368028035, 137692910029106,
                 1039519607062, 826404763313028
 #else
@@ -6005,7 +6005,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1848942433095597, 1582009882530495, 1849292741020143,
                 1068498323302788, 2001402229799484
 #else
@@ -6014,7 +6014,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1528282417624269, 2142492439828191, 2179662545816034,
                 362568973150328, 1591374675250271
 #else
@@ -6025,7 +6025,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 160026679434388, 232341189218716, 2149181472355545,
                 598041771119831, 183859001910173
 #else
@@ -6034,7 +6034,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2013278155187349, 662660471354454, 793981225706267,
                 411706605985744, 804490933124791
 #else
@@ -6043,7 +6043,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2051892037280204, 488391251096321, 2230187337030708,
                 930221970662692, 679002758255210
 #else
@@ -6054,7 +6054,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1530723630438670, 875873929577927, 341560134269988,
                 449903119530753, 1055551308214179
 #else
@@ -6063,7 +6063,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1461835919309432, 1955256480136428, 180866187813063,
                 1551979252664528, 557743861963950
 #else
@@ -6072,7 +6072,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 359179641731115, 1324915145732949, 902828372691474,
                 294254275669987, 1887036027752957
 #else
@@ -6083,7 +6083,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2043271609454323, 2038225437857464, 1317528426475850,
                 1398989128982787, 2027639881006861
 #else
@@ -6092,7 +6092,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2072902725256516, 312132452743412, 309930885642209,
                 996244312618453, 1590501300352303
 #else
@@ -6101,7 +6101,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1397254305160710, 695734355138021, 2233992044438756,
                 1776180593969996, 1085588199351115
 #else
@@ -6112,7 +6112,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 440567051331029, 254894786356681, 493869224930222,
                 1556322069683366, 1567456540319218
 #else
@@ -6121,7 +6121,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1950722461391320, 1907845598854797, 1822757481635527,
                 2121567704750244, 73811931471221
 #else
@@ -6130,7 +6130,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 387139307395758, 2058036430315676, 1220915649965325,
                 1794832055328951, 1230009312169328
 #else
@@ -6141,7 +6141,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1765973779329517, 659344059446977, 19821901606666,
                 1301928341311214, 1116266004075885
 #else
@@ -6150,7 +6150,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1127572801181483, 1224743760571696, 1276219889847274,
                 1529738721702581, 1589819666871853
 #else
@@ -6159,7 +6159,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2181229378964934, 2190885205260020, 1511536077659137,
                 1246504208580490, 668883326494241
 #else
@@ -6170,7 +6170,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 437866655573314, 669026411194768, 81896997980338,
                 523874406393178, 245052060935236
 #else
@@ -6179,7 +6179,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1975438052228868, 1071801519999806, 594652299224319,
                 1877697652668809, 1489635366987285
 #else
@@ -6188,7 +6188,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 958592545673770, 233048016518599, 851568750216589,
                 567703851596087, 1740300006094761
 #else
@@ -6199,7 +6199,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2014540178270324, 192672779514432, 213877182641530,
                 2194819933853411, 1716422829364835
 #else
@@ -6208,7 +6208,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1540769606609725, 2148289943846077, 1597804156127445,
                 1230603716683868, 815423458809453
 #else
@@ -6217,7 +6217,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1738560251245018, 1779576754536888, 1783765347671392,
                 1880170990446751, 1088225159617541
 #else
@@ -6230,7 +6230,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 659303913929492, 1956447718227573, 1830568515922666,
                 841069049744408, 1669607124206368
 #else
@@ -6239,7 +6239,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1143465490433355, 1532194726196059, 1093276745494697,
                 481041706116088, 2121405433561163
 #else
@@ -6248,7 +6248,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1686424298744462, 1451806974487153, 266296068846582,
                 1834686947542675, 1720762336132256
 #else
@@ -6259,7 +6259,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 889217026388959, 1043290623284660, 856125087551909,
                 1669272323124636, 1603340330827879
 #else
@@ -6268,7 +6268,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1206396181488998, 333158148435054, 1402633492821422,
                 1120091191722026, 1945474114550509
 #else
@@ -6277,7 +6277,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 766720088232571, 1512222781191002, 1189719893490790,
                 2091302129467914, 2141418006894941
 #else
@@ -6288,7 +6288,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 419663647306612, 1998875112167987, 1426599870253707,
                 1154928355379510, 486538532138187
 #else
@@ -6297,7 +6297,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 938160078005954, 1421776319053174, 1941643234741774,
                 180002183320818, 1414380336750546
 #else
@@ -6306,7 +6306,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 398001940109652, 1577721237663248, 1012748649830402,
                 1540516006905144, 1011684812884559
 #else
@@ -6317,7 +6317,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1653276489969630, 6081825167624, 1921777941170836,
                 1604139841794531, 861211053640641
 #else
@@ -6326,7 +6326,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 996661541407379, 1455877387952927, 744312806857277,
                 139213896196746, 1000282908547789
 #else
@@ -6335,7 +6335,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1450817495603008, 1476865707053229, 1030490562252053,
                 620966950353376, 1744760161539058
 #else
@@ -6346,7 +6346,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 559728410002599, 37056661641185, 2038622963352006,
                 1637244893271723, 1026565352238948
 #else
@@ -6355,7 +6355,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 962165956135846, 1116599660248791, 182090178006815,
                 1455605467021751, 196053588803284
 #else
@@ -6364,7 +6364,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 796863823080135, 1897365583584155, 420466939481601,
                 2165972651724672, 932177357788289
 #else
@@ -6375,7 +6375,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 877047233620632, 1375632631944375, 643773611882121,
                 660022738847877, 19353932331831
 #else
@@ -6384,7 +6384,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2216943882299338, 394841323190322, 2222656898319671,
                 558186553950529, 1077236877025190
 #else
@@ -6393,7 +6393,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 801118384953213, 1914330175515892, 574541023311511,
                 1471123787903705, 1526158900256288
 #else
@@ -6404,7 +6404,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 949617889087234, 2207116611267331, 912920039141287,
                 501158539198789, 62362560771472
 #else
@@ -6413,7 +6413,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1474518386765335, 1760793622169197, 1157399790472736,
                 1622864308058898, 165428294422792
 #else
@@ -6422,7 +6422,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1961673048027128, 102619413083113, 1051982726768458,
                 1603657989805485, 1941613251499678
 #else
@@ -6433,7 +6433,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1401939116319266, 335306339903072, 72046196085786,
                 862423201496006, 850518754531384
 #else
@@ -6442,7 +6442,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1234706593321979, 1083343891215917, 898273974314935,
                 1640859118399498, 157578398571149
 #else
@@ -6451,7 +6451,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1143483057726416, 1992614991758919, 674268662140796,
                 1773370048077526, 674318359920189
 #else
@@ -6464,7 +6464,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1835401379538542, 173900035308392, 818247630716732,
                 1762100412152786, 1021506399448291
 #else
@@ -6473,7 +6473,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1506632088156630, 2127481795522179, 513812919490255,
                 140643715928370, 442476620300318
 #else
@@ -6482,7 +6482,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2056683376856736, 219094741662735, 2193541883188309,
                 1841182310235800, 556477468664293
 #else
@@ -6493,7 +6493,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1315019427910827, 1049075855992603, 2066573052986543,
                 266904467185534, 2040482348591520
 #else
@@ -6502,7 +6502,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 94096246544434, 922482381166992, 24517828745563,
                 2139430508542503, 2097139044231004
 #else
@@ -6511,7 +6511,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 537697207950515, 1399352016347350, 1563663552106345,
                 2148749520888918, 549922092988516
 #else
@@ -6522,7 +6522,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1747985413252434, 680511052635695, 1809559829982725,
                 594274250930054, 201673170745982
 #else
@@ -6531,7 +6531,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 323583936109569, 1973572998577657, 1192219029966558,
                 79354804385273, 1374043025560347
 #else
@@ -6540,7 +6540,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 213277331329947, 416202017849623, 1950535221091783,
                 1313441578103244, 2171386783823658
 #else
@@ -6551,7 +6551,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 189088804229831, 993969372859110, 895870121536987,
                 1547301535298256, 1477373024911350
 #else
@@ -6560,7 +6560,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1620578418245010, 541035331188469, 2235785724453865,
                 2154865809088198, 1974627268751826
 #else
@@ -6569,7 +6569,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1346805451740245, 1350981335690626, 942744349501813,
                 2155094562545502, 1012483751693409
 #else
@@ -6580,7 +6580,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2107080134091762, 1132567062788208, 1824935377687210,
                 769194804343737, 1857941799971888
 #else
@@ -6589,7 +6589,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1074666112436467, 249279386739593, 1174337926625354,
                 1559013532006480, 1472287775519121
 #else
@@ -6598,7 +6598,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1872620123779532, 1892932666768992, 1921559078394978,
                 1270573311796160, 1438913646755037
 #else
@@ -6609,7 +6609,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 837390187648199, 1012253300223599, 989780015893987,
                 1351393287739814, 328627746545550
 #else
@@ -6618,7 +6618,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1028328827183114, 1711043289969857, 1350832470374933,
                 1923164689604327, 1495656368846911
 #else
@@ -6627,7 +6627,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1900828492104143, 430212361082163, 687437570852799,
                 832514536673512, 1685641495940794
 #else
@@ -6638,7 +6638,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 842632847936398, 605670026766216, 290836444839585,
                 163210774892356, 2213815011799645
 #else
@@ -6647,7 +6647,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1176336383453996, 1725477294339771, 12700622672454,
                 678015708818208, 162724078519879
 #else
@@ -6656,7 +6656,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1448049969043497, 1789411762943521, 385587766217753,
                 90201620913498, 832999441066823
 #else
@@ -6667,7 +6667,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 516086333293313, 2240508292484616, 1351669528166508,
                 1223255565316488, 750235824427138
 #else
@@ -6676,7 +6676,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1263624896582495, 1102602401673328, 526302183714372,
                 2152015839128799, 1483839308490010
 #else
@@ -6685,7 +6685,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 442991718646863, 1599275157036458, 1925389027579192,
                 899514691371390, 350263251085160
 #else
@@ -6698,7 +6698,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1689713572022143, 593854559254373, 978095044791970,
                 1985127338729499, 1676069120347625
 #else
@@ -6707,7 +6707,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1557207018622683, 340631692799603, 1477725909476187,
                 614735951619419, 2033237123746766
 #else
@@ -6716,7 +6716,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 968764929340557, 1225534776710944, 662967304013036,
                 1155521416178595, 791142883466590
 #else
@@ -6727,7 +6727,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1487081286167458, 993039441814934, 1792378982844640,
                 698652444999874, 2153908693179754
 #else
@@ -6736,7 +6736,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1123181311102823, 685575944875442, 507605465509927,
                 1412590462117473, 568017325228626
 #else
@@ -6745,7 +6745,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 560258797465417, 2193971151466401, 1824086900849026,
                 579056363542056, 1690063960036441
 #else
@@ -6756,7 +6756,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1918407319222416, 353767553059963, 1930426334528099,
                 1564816146005724, 1861342381708096
 #else
@@ -6765,7 +6765,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2131325168777276, 1176636658428908, 1756922641512981,
                 1390243617176012, 1966325177038383
 #else
@@ -6774,7 +6774,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2063958120364491, 2140267332393533, 699896251574968,
                 273268351312140, 375580724713232
 #else
@@ -6785,7 +6785,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2024297515263178, 416959329722687, 1079014235017302,
                 171612225573183, 1031677520051053
 #else
@@ -6794,7 +6794,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2033900009388450, 1744902869870788, 2190580087917640,
                 1949474984254121, 231049754293748
 #else
@@ -6803,7 +6803,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 343868674606581, 550155864008088, 1450580864229630,
                 481603765195050, 896972360018042
 #else
@@ -6814,7 +6814,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2151139328380127, 314745882084928, 59756825775204,
                 1676664391494651, 2048348075599360
 #else
@@ -6823,7 +6823,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1528930066340597, 1605003907059576, 1055061081337675,
                 1458319101947665, 1234195845213142
 #else
@@ -6832,7 +6832,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 830430507734812, 1780282976102377, 1425386760709037,
                 362399353095425, 2168861579799910
 #else
@@ -6843,7 +6843,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1155762232730333, 980662895504006, 2053766700883521,
                 490966214077606, 510405877041357
 #else
@@ -6852,7 +6852,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1683750316716132, 652278688286128, 1221798761193539,
                 1897360681476669, 319658166027343
 #else
@@ -6861,7 +6861,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 618808732869972, 72755186759744, 2060379135624181,
                 1730731526741822, 48862757828238
 #else
@@ -6872,7 +6872,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1463171970593505, 1143040711767452, 614590986558883,
                 1409210575145591, 1882816996436803
 #else
@@ -6881,7 +6881,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2230133264691131, 563950955091024, 2042915975426398,
                 827314356293472, 672028980152815
 #else
@@ -6890,7 +6890,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 264204366029760, 1654686424479449, 2185050199932931,
                 2207056159091748, 506015669043634
 #else
@@ -6901,7 +6901,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1784446333136569, 1973746527984364, 334856327359575,
                 1156769775884610, 1023950124675478
 #else
@@ -6910,7 +6910,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2065270940578383, 31477096270353, 306421879113491,
                 181958643936686, 1907105536686083
 #else
@@ -6919,7 +6919,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1496516440779464, 1748485652986458, 872778352227340,
                 818358834654919, 97932669284220
 #else
@@ -6932,7 +6932,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 471636015770351, 672455402793577, 1804995246884103,
                 1842309243470804, 1501862504981682
 #else
@@ -6941,7 +6941,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1013216974933691, 538921919682598, 1915776722521558,
                 1742822441583877, 1886550687916656
 #else
@@ -6950,7 +6950,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2094270000643336, 303971879192276, 40801275554748,
                 649448917027930, 1818544418535447
 #else
@@ -6961,7 +6961,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2241737709499165, 549397817447461, 838180519319392,
                 1725686958520781, 1705639080897747
 #else
@@ -6970,7 +6970,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1216074541925116, 50120933933509, 1565829004133810,
                 721728156134580, 349206064666188
 #else
@@ -6979,7 +6979,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 948617110470858, 346222547451945, 1126511960599975,
                 1759386906004538, 493053284802266
 #else
@@ -6990,7 +6990,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1454933046815146, 874696014266362, 1467170975468588,
                 1432316382418897, 2111710746366763
 #else
@@ -6999,7 +6999,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2105387117364450, 1996463405126433, 1303008614294500,
                 851908115948209, 1353742049788635
 #else
@@ -7008,7 +7008,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 750300956351719, 1487736556065813, 15158817002104,
                 1511998221598392, 971739901354129
 #else
@@ -7019,7 +7019,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1874648163531693, 2124487685930551, 1810030029384882,
                 918400043048335, 586348627300650
 #else
@@ -7028,7 +7028,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1235084464747900, 1166111146432082, 1745394857881591,
                 1405516473883040, 4463504151617
 #else
@@ -7037,7 +7037,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1663810156463827, 327797390285791, 1341846161759410,
                 1964121122800605, 1747470312055380
 #else
@@ -7048,7 +7048,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 660005247548233, 2071860029952887, 1358748199950107,
                 911703252219107, 1014379923023831
 #else
@@ -7057,7 +7057,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2206641276178231, 1690587809721504, 1600173622825126,
                 2156096097634421, 1106822408548216
 #else
@@ -7066,7 +7066,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1344788193552206, 1949552134239140, 1735915881729557,
                 675891104100469, 1834220014427292
 #else
@@ -7077,7 +7077,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1920949492387964, 158885288387530, 70308263664033,
                 626038464897817, 1468081726101009
 #else
@@ -7086,7 +7086,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 622221042073383, 1210146474039168, 1742246422343683,
                 1403839361379025, 417189490895736
 #else
@@ -7095,7 +7095,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 22727256592983, 168471543384997, 1324340989803650,
                 1839310709638189, 504999476432775
 #else
@@ -7106,7 +7106,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1313240518756327, 1721896294296942, 52263574587266,
                 2065069734239232, 804910473424630
 #else
@@ -7115,7 +7115,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1337466662091884, 1287645354669772, 2018019646776184,
                 652181229374245, 898011753211715
 #else
@@ -7124,7 +7124,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1969792547910734, 779969968247557, 2011350094423418,
                 1823964252907487, 1058949448296945
 #else
@@ -7135,7 +7135,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 207343737062002, 1118176942430253, 758894594548164,
                 806764629546266, 1157700123092949
 #else
@@ -7144,7 +7144,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1273565321399022, 1638509681964574, 759235866488935,
                 666015124346707, 897983460943405
 #else
@@ -7153,7 +7153,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1717263794012298, 1059601762860786, 1837819172257618,
                 1054130665797229, 680893204263559
 #else
@@ -7166,7 +7166,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2237039662793603, 2249022333361206, 2058613546633703,
                 149454094845279, 2215176649164582
 #else
@@ -7175,7 +7175,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 79472182719605, 1851130257050174, 1825744808933107,
                 821667333481068, 781795293511946
 #else
@@ -7184,7 +7184,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 755822026485370, 152464789723500, 1178207602290608,
                 410307889503239, 156581253571278
 #else
@@ -7195,7 +7195,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1418185496130297, 484520167728613, 1646737281442950,
                 1401487684670265, 1349185550126961
 #else
@@ -7204,7 +7204,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1495380034400429, 325049476417173, 46346894893933,
                 1553408840354856, 828980101835683
 #else
@@ -7213,7 +7213,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1280337889310282, 2070832742866672, 1640940617225222,
                 2098284908289951, 450929509534434
 #else
@@ -7224,7 +7224,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 407703353998781, 126572141483652, 286039827513621,
                 1999255076709338, 2030511179441770
 #else
@@ -7233,7 +7233,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1254958221100483, 1153235960999843, 942907704968834,
                 637105404087392, 1149293270147267
 #else
@@ -7242,7 +7242,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 894249020470196, 400291701616810, 406878712230981,
                 1599128793487393, 1145868722604026
 #else
@@ -7253,7 +7253,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1497955250203334, 110116344653260, 1128535642171976,
                 1900106496009660, 129792717460909
 #else
@@ -7262,7 +7262,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 452487513298665, 1352120549024569, 1173495883910956,
                 1999111705922009, 367328130454226
 #else
@@ -7271,7 +7271,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1717539401269642, 1475188995688487, 891921989653942,
                 836824441505699, 1885988485608364
 #else
@@ -7282,7 +7282,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1241784121422547, 187337051947583, 1118481812236193,
                 428747751936362, 30358898927325
 #else
@@ -7291,7 +7291,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2022432361201842, 1088816090685051, 1977843398539868,
                 1854834215890724, 564238862029357
 #else
@@ -7300,7 +7300,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 938868489100585, 1100285072929025, 1017806255688848,
                 1957262154788833, 152787950560442
 #else
@@ -7311,7 +7311,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 867319417678923, 620471962942542, 226032203305716,
                 342001443957629, 1761675818237336
 #else
@@ -7320,7 +7320,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1295072362439987, 931227904689414, 1355731432641687,
                 922235735834035, 892227229410209
 #else
@@ -7329,7 +7329,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1680989767906154, 535362787031440, 2136691276706570,
                 1942228485381244, 1267350086882274
 #else
@@ -7340,7 +7340,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 366018233770527, 432660629755596, 126409707644535,
                 1973842949591662, 645627343442376
 #else
@@ -7349,7 +7349,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 535509430575217, 546885533737322, 1524675609547799,
                 2138095752851703, 1260738089896827
 #else
@@ -7358,7 +7358,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1159906385590467, 2198530004321610, 714559485023225,
                 81880727882151, 1484020820037082
 #else
@@ -7369,7 +7369,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1377485731340769, 2046328105512000, 1802058637158797,
                 62146136768173, 1356993908853901
 #else
@@ -7378,7 +7378,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2013612215646735, 1830770575920375, 536135310219832,
                 609272325580394, 270684344495013
 #else
@@ -7387,7 +7387,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1237542585982777, 2228682050256790, 1385281931622824,
                 593183794882890, 493654978552689
 #else
@@ -7400,7 +7400,7 @@
     {
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 47341488007760, 1891414891220257, 983894663308928,
                 176161768286818, 1126261115179708
 #else
@@ -7409,7 +7409,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1694030170963455, 502038567066200, 1691160065225467,
                 949628319562187, 275110186693066
 #else
@@ -7418,7 +7418,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1124515748676336, 1661673816593408, 1499640319059718,
                 1584929449166988, 558148594103306
 #else
@@ -7429,7 +7429,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1784525599998356, 1619698033617383, 2097300287550715,
                 258265458103756, 1905684794832758
 #else
@@ -7438,7 +7438,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1288941072872766, 931787902039402, 190731008859042,
                 2006859954667190, 1005931482221702
 #else
@@ -7447,7 +7447,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1465551264822703, 152905080555927, 680334307368453,
                 173227184634745, 666407097159852
 #else
@@ -7458,7 +7458,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2111017076203943, 1378760485794347, 1248583954016456,
                 1352289194864422, 1895180776543896
 #else
@@ -7467,7 +7467,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 171348223915638, 662766099800389, 462338943760497,
                 466917763340314, 656911292869115
 #else
@@ -7476,7 +7476,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 488623681976577, 866497561541722, 1708105560937768,
                 1673781214218839, 1506146329818807
 #else
@@ -7487,7 +7487,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 160425464456957, 950394373239689, 430497123340934,
                 711676555398832, 320964687779005
 #else
@@ -7496,7 +7496,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 988979367990485, 1359729327576302, 1301834257246029,
                 294141160829308, 29348272277475
 #else
@@ -7505,7 +7505,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1434382743317910, 100082049942065, 221102347892623,
                 186982837860588, 1305765053501834
 #else
@@ -7516,7 +7516,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 2205916462268190, 499863829790820, 961960554686616,
                 158062762756985, 1841471168298305
 #else
@@ -7525,7 +7525,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1191737341426592, 1847042034978363, 1382213545049056,
                 1039952395710448, 788812858896859
 #else
@@ -7534,7 +7534,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1346965964571152, 1291881610839830, 2142916164336056,
                 786821641205979, 1571709146321039
 #else
@@ -7545,7 +7545,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 787164375951248, 202869205373189, 1356590421032140,
                 1431233331032510, 786341368775957
 #else
@@ -7554,7 +7554,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 492448143532951, 304105152670757, 1761767168301056,
                 233782684697790, 1981295323106089
 #else
@@ -7563,7 +7563,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 665807507761866, 1343384868355425, 895831046139653,
                 439338948736892, 1986828765695105
 #else
@@ -7574,7 +7574,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 756096210874553, 1721699973539149, 258765301727885,
                 1390588532210645, 1212530909934781
 #else
@@ -7583,7 +7583,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 852891097972275, 1816988871354562, 1543772755726524,
                 1174710635522444, 202129090724628
 #else
@@ -7592,7 +7592,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1205281565824323, 22430498399418, 992947814485516,
                 1392458699738672, 688441466734558
 #else
@@ -7603,7 +7603,7 @@
         },
         {
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1050627428414972, 1955849529137135, 2171162376368357,
                 91745868298214, 447733118757826
 #else
@@ -7612,7 +7612,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1287181461435438, 622722465530711, 880952150571872,
                 741035693459198, 311565274989772
 #else
@@ -7621,7 +7621,7 @@
 #endif
             }},
             {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
                 1003649078149734, 545233927396469, 1849786171789880,
                 1318943684880434, 280345687170552
 #else
@@ -7639,7 +7639,7 @@
 static const ge_precomp Bi[8] = {
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1288382639258501, 245678601348599, 269427782077623,
             1462984067271730, 137412439391563
 #else
@@ -7648,7 +7648,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             62697248952638, 204681361388450, 631292143396476, 338455783676468,
             1213667448819585
 #else
@@ -7657,7 +7657,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             301289933810280, 1259582250014073, 1422107436869536,
             796239922652654, 1953934009299142
 #else
@@ -7668,7 +7668,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1601611775252272, 1720807796594148, 1132070835939856,
             1260455018889551, 2147779492816911
 #else
@@ -7677,7 +7677,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             316559037616741, 2177824224946892, 1459442586438991,
             1461528397712656, 751590696113597
 #else
@@ -7686,7 +7686,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1850748884277385, 1200145853858453, 1068094770532492,
             672251375690438, 1586055907191707
 #else
@@ -7697,7 +7697,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             769950342298419, 132954430919746, 844085933195555, 974092374476333,
             726076285546016
 #else
@@ -7706,7 +7706,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             425251763115706, 608463272472562, 442562545713235, 837766094556764,
             374555092627893
 #else
@@ -7715,7 +7715,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1086255230780037, 274979815921559, 1960002765731872,
             929474102396301, 1190409889297339
 #else
@@ -7726,7 +7726,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             665000864555967, 2065379846933859, 370231110385876, 350988370788628,
             1233371373142985
 #else
@@ -7735,7 +7735,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             2019367628972465, 676711900706637, 110710997811333,
             1108646842542025, 517791959672113
 #else
@@ -7744,7 +7744,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             965130719900578, 247011430587952, 526356006571389, 91986625355052,
             2157223321444601
 #else
@@ -7755,7 +7755,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1802695059465007, 1664899123557221, 593559490740857,
             2160434469266659, 927570450755031
 #else
@@ -7764,7 +7764,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1725674970513508, 1933645953859181, 1542344539275782,
             1767788773573747, 1297447965928905
 #else
@@ -7773,7 +7773,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1381809363726107, 1430341051343062, 2061843536018959,
             1551778050872521, 2036394857967624
 #else
@@ -7784,7 +7784,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1970894096313054, 528066325833207, 1619374932191227,
             2207306624415883, 1169170329061080
 #else
@@ -7793,7 +7793,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             2070390218572616, 1458919061857835, 624171843017421,
             1055332792707765, 433987520732508
 #else
@@ -7802,7 +7802,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             893653801273833, 1168026499324677, 1242553501121234,
             1306366254304474, 1086752658510815
 #else
@@ -7813,7 +7813,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             213454002618221, 939771523987438, 1159882208056014, 317388369627517,
             621213314200687
 #else
@@ -7822,7 +7822,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1971678598905747, 338026507889165, 762398079972271, 655096486107477,
             42299032696322
 #else
@@ -7831,7 +7831,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             177130678690680, 1754759263300204, 1864311296286618,
             1180675631479880, 1292726903152791
 #else
@@ -7842,7 +7842,7 @@
     },
     {
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1913163449625248, 460779200291993, 2193883288642314,
             1008900146920800, 1721983679009502
 #else
@@ -7851,7 +7851,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             1070401523076875, 1272492007800961, 1910153608563310,
             2075579521696771, 1191169788841221
 #else
@@ -7860,7 +7860,7 @@
 #endif
         }},
         {{
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
             692896803108118, 500174642072499, 2068223309439677,
             1162190621851337, 1426986007309901
 #else
diff --git a/src/crypto/curve25519/internal.h b/src/crypto/curve25519/internal.h
index 76ff78f..1420601 100644
--- a/src/crypto/curve25519/internal.h
+++ b/src/crypto/curve25519/internal.h
@@ -32,11 +32,7 @@
                  const uint8_t point[32]);
 #endif
 
-#if defined(BORINGSSL_HAS_UINT128)
-#define BORINGSSL_CURVE25519_64BIT
-#endif
-
-#if defined(BORINGSSL_CURVE25519_64BIT)
+#if defined(OPENSSL_64_BIT)
 // fe means field element. Here the field is \Z/(2^255-19). An element t,
 // entries t[0]...t[4], represents the integer t[0]+2^51 t[1]+2^102 t[2]+2^153
 // t[3]+2^204 t[4].
diff --git a/src/crypto/curve25519/make_curve25519_tables.py b/src/crypto/curve25519/make_curve25519_tables.py
index 50dee2a..c3cf12a 100755
--- a/src/crypto/curve25519/make_curve25519_tables.py
+++ b/src/crypto/curve25519/make_curve25519_tables.py
@@ -110,7 +110,7 @@
     return ret
 
 def to_literal(x):
-    ret = "{{\n#if defined(BORINGSSL_CURVE25519_64BIT)\n"
+    ret = "{{\n#if defined(OPENSSL_64_BIT)\n"
     ret += ", ".join(map(str, to_base_51(x)))
     ret += "\n#else\n"
     ret += ", ".join(map(str, to_base_25_5(x)))
diff --git a/src/crypto/ec_extra/hash_to_curve.c b/src/crypto/ec_extra/hash_to_curve.c
index fecd535..6c9abf9 100644
--- a/src/crypto/ec_extra/hash_to_curve.c
+++ b/src/crypto/ec_extra/hash_to_curve.c
@@ -466,6 +466,18 @@
                                                msg, msg_len);
 }
 
+int ec_hash_to_scalar_p384_xmd_sha384(
+    const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
+    const uint8_t *msg, size_t msg_len) {
+  if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
+    OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
+    return 0;
+  }
+
+  return hash_to_scalar(group, EVP_sha384(), out, dst, dst_len, /*k=*/192, msg,
+                        msg_len);
+}
+
 int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
     const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
     size_t dst_len, const uint8_t *msg, size_t msg_len) {
diff --git a/src/crypto/ec_extra/internal.h b/src/crypto/ec_extra/internal.h
index c7f517d..cf6ff2f 100644
--- a/src/crypto/ec_extra/internal.h
+++ b/src/crypto/ec_extra/internal.h
@@ -44,6 +44,14 @@
     const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
     size_t dst_len, const uint8_t *msg, size_t msg_len);
 
+// ec_hash_to_scalar_p384_xmd_sha384 hashes |msg| to a scalar on |group|
+// and writes the result to |out|, using the hash_to_field operation from the
+// P384_XMD:SHA-384_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-16, but
+// generating a value modulo the group order rather than a field element.
+OPENSSL_EXPORT int ec_hash_to_scalar_p384_xmd_sha384(
+    const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
+    const uint8_t *msg, size_t msg_len);
+
 // ec_hash_to_curve_p384_xmd_sha512_sswu_draft07 hashes |msg| to a point on
 // |group| and writes the result to |out|, implementing the
 // P384_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-07. It
diff --git a/src/crypto/err/err_data_generate.go b/src/crypto/err/err_data_generate.go
index 332b4e1..d4a7c28 100644
--- a/src/crypto/err/err_data_generate.go
+++ b/src/crypto/err/err_data_generate.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
@@ -115,23 +117,8 @@
 	return nil
 }
 
-// keySlice is a type that implements sorting of entries values.
-type keySlice []uint32
-
-func (ks keySlice) Len() int {
-	return len(ks)
-}
-
-func (ks keySlice) Less(i, j int) bool {
-	return (ks[i] >> 15) < (ks[j] >> 15)
-}
-
-func (ks keySlice) Swap(i, j int) {
-	ks[i], ks[j] = ks[j], ks[i]
-}
-
 func (st *stringList) buildList() []uint32 {
-	sort.Sort(keySlice(st.entries))
+	sort.Slice(st.entries, func(i, j int) bool { return (st.entries[i] >> 15) < (st.entries[j] >> 15) })
 	return st.entries
 }
 
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index dc22450..15eb1ef 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -67,7 +67,7 @@
 #include <openssl/rsa.h>
 
 #include "../internal.h"
-#include "../fipsmodule/rsa/internal.h"
+#include "../rsa_extra/internal.h"
 #include "internal.h"
 
 
diff --git a/src/crypto/fipsmodule/bcm.c b/src/crypto/fipsmodule/bcm.c
index e2e4d90..8231eee 100644
--- a/src/crypto/fipsmodule/bcm.c
+++ b/src/crypto/fipsmodule/bcm.c
@@ -80,6 +80,7 @@
 #include "ec/simple_mul.c"
 #include "ec/util.c"
 #include "ec/wnaf.c"
+#include "hkdf/hkdf.c"
 #include "hmac/hmac.c"
 #include "md4/md4.c"
 #include "md5/md5.c"
diff --git a/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go b/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go
index 1e48df3..2915db5 100644
--- a/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go
+++ b/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/crypto/fipsmodule/bn/check_bn_tests.go b/src/crypto/fipsmodule/bn/check_bn_tests.go
index dd1def8..032b9e3 100644
--- a/src/crypto/fipsmodule/bn/check_bn_tests.go
+++ b/src/crypto/fipsmodule/bn/check_bn_tests.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/crypto/fipsmodule/ec/internal.h b/src/crypto/fipsmodule/ec/internal.h
index 846431f..3b6fa4a 100644
--- a/src/crypto/fipsmodule/ec/internal.h
+++ b/src/crypto/fipsmodule/ec/internal.h
@@ -91,6 +91,8 @@
 // be the largest fields anyone plausibly uses.
 #define EC_MAX_BYTES 66
 #define EC_MAX_WORDS ((EC_MAX_BYTES + BN_BYTES - 1) / BN_BYTES)
+#define EC_MAX_COMPRESSED (EC_MAX_BYTES + 1)
+#define EC_MAX_UNCOMPRESSED (2 * EC_MAX_BYTES + 1)
 
 static_assert(EC_MAX_WORDS <= BN_SMALL_MAX_WORDS,
               "bn_*_small functions not usable");
@@ -119,8 +121,8 @@
 // ec_scalar_from_bytes deserializes |in| and stores the resulting scalar over
 // group |group| to |out|. It returns one on success and zero if |in| is
 // invalid.
-int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out,
-                         const uint8_t *in, size_t len);
+OPENSSL_EXPORT int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out,
+                                        const uint8_t *in, size_t len);
 
 // ec_scalar_reduce sets |out| to |words|, reduced modulo the group order.
 // |words| must be less than order^2. |num| must be at most twice the width of
@@ -279,8 +281,8 @@
 //
 // If only extracting the x-coordinate, use |ec_get_x_coordinate_*| which is
 // slightly faster.
-int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
-                          const EC_RAW_POINT *p);
+OPENSSL_EXPORT int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
+                                         const EC_RAW_POINT *p);
 
 // ec_jacobian_to_affine_batch converts |num| points in |in| from Jacobian
 // coordinates to affine coordinates and writes the results to |out|. It returns
diff --git a/src/crypto/fipsmodule/ec/make_ec_scalar_base_mult_tests.go b/src/crypto/fipsmodule/ec/make_ec_scalar_base_mult_tests.go
index 169d226..1d3896a 100644
--- a/src/crypto/fipsmodule/ec/make_ec_scalar_base_mult_tests.go
+++ b/src/crypto/fipsmodule/ec/make_ec_scalar_base_mult_tests.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/crypto/fipsmodule/ec/make_p256-nistz-tests.go b/src/crypto/fipsmodule/ec/make_p256-nistz-tests.go
index 04a1a1c..e10990b 100644
--- a/src/crypto/fipsmodule/ec/make_p256-nistz-tests.go
+++ b/src/crypto/fipsmodule/ec/make_p256-nistz-tests.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/crypto/fipsmodule/ec/make_tables.go b/src/crypto/fipsmodule/ec/make_tables.go
index 7fb9041..120c40b 100644
--- a/src/crypto/fipsmodule/ec/make_tables.go
+++ b/src/crypto/fipsmodule/ec/make_tables.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
@@ -151,7 +153,7 @@
 // Tables for other points have table[i] = iG for i in 0 .. 16.
 
 // fiat_p256_g_pre_comp is the table of precomputed base points
-#if defined(BORINGSSL_NISTP256_64BIT)
+#if defined(OPENSSL_64_BIT)
 static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = `
 	if _, err := f.WriteString(fileHeader); err != nil {
 		return err
diff --git a/src/crypto/fipsmodule/ec/oct.c b/src/crypto/fipsmodule/ec/oct.c
index 3f0c0d6..eb77643 100644
--- a/src/crypto/fipsmodule/ec/oct.c
+++ b/src/crypto/fipsmodule/ec/oct.c
@@ -320,8 +320,7 @@
   }
 
   if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
-    unsigned long err = ERR_peek_last_error();
-
+    uint32_t err = ERR_peek_last_error();
     if (ERR_GET_LIB(err) == ERR_LIB_BN &&
         ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
       ERR_clear_error();
diff --git a/src/crypto/fipsmodule/ec/p256-nistz_test.cc b/src/crypto/fipsmodule/ec/p256-nistz_test.cc
index 6aa51e8..a53d94e 100644
--- a/src/crypto/fipsmodule/ec/p256-nistz_test.cc
+++ b/src/crypto/fipsmodule/ec/p256-nistz_test.cc
@@ -43,9 +43,11 @@
   // Fill a table with some garbage input.
   alignas(64) P256_POINT table[16];
   for (size_t i = 0; i < 16; i++) {
-    OPENSSL_memset(table[i].X, 3 * i, sizeof(table[i].X));
-    OPENSSL_memset(table[i].Y, 3 * i + 1, sizeof(table[i].Y));
-    OPENSSL_memset(table[i].Z, 3 * i + 2, sizeof(table[i].Z));
+    OPENSSL_memset(table[i].X, static_cast<uint8_t>(3 * i), sizeof(table[i].X));
+    OPENSSL_memset(table[i].Y, static_cast<uint8_t>(3 * i + 1),
+                   sizeof(table[i].Y));
+    OPENSSL_memset(table[i].Z, static_cast<uint8_t>(3 * i + 2),
+                   sizeof(table[i].Z));
   }
 
   for (int i = 0; i <= 16; i++) {
@@ -73,8 +75,9 @@
   // Fill a table with some garbage input.
   alignas(64) P256_POINT_AFFINE table[64];
   for (size_t i = 0; i < 64; i++) {
-    OPENSSL_memset(table[i].X, 2 * i, sizeof(table[i].X));
-    OPENSSL_memset(table[i].Y, 2 * i + 1, sizeof(table[i].Y));
+    OPENSSL_memset(table[i].X, static_cast<uint8_t>(2 * i), sizeof(table[i].X));
+    OPENSSL_memset(table[i].Y, static_cast<uint8_t>(2 * i + 1),
+                   sizeof(table[i].Y));
   }
 
   for (int i = 0; i <= 64; i++) {
diff --git a/src/crypto/fipsmodule/ec/p256.c b/src/crypto/fipsmodule/ec/p256.c
index d67f6c0..cd2b6fc 100644
--- a/src/crypto/fipsmodule/ec/p256.c
+++ b/src/crypto/fipsmodule/ec/p256.c
@@ -31,8 +31,9 @@
 #include "./internal.h"
 
 #if defined(BORINGSSL_HAS_UINT128)
-#define BORINGSSL_NISTP256_64BIT 1
 #include "../../../third_party/fiat/p256_64.h"
+#elif defined(OPENSSL_64_BIT)
+#include "../../../third_party/fiat/p256_64_msvc.h"
 #else
 #include "../../../third_party/fiat/p256_32.h"
 #endif
@@ -40,7 +41,7 @@
 
 // utility functions, handwritten
 
-#if defined(BORINGSSL_NISTP256_64BIT)
+#if defined(OPENSSL_64_BIT)
 #define FIAT_P256_NLIMBS 4
 typedef uint64_t fiat_p256_limb_t;
 typedef uint64_t fiat_p256_felem[FIAT_P256_NLIMBS];
@@ -748,5 +749,3 @@
       ec_simple_scalar_to_montgomery_inv_vartime;
   out->cmp_x_coordinate = ec_GFp_nistp256_cmp_x_coordinate;
 }
-
-#undef BORINGSSL_NISTP256_64BIT
diff --git a/src/crypto/fipsmodule/ec/p256_table.h b/src/crypto/fipsmodule/ec/p256_table.h
index 14129a3..d823d37 100644
--- a/src/crypto/fipsmodule/ec/p256_table.h
+++ b/src/crypto/fipsmodule/ec/p256_table.h
@@ -50,7 +50,7 @@
 // Tables for other points have table[i] = iG for i in 0 .. 16.
 
 // fiat_p256_g_pre_comp is the table of precomputed base points
-#if defined(BORINGSSL_NISTP256_64BIT)
+#if defined(OPENSSL_64_BIT)
 static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = {
     {{{0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510,
        0x18905f76a53755c6},
diff --git a/src/crypto/hkdf/hkdf.c b/src/crypto/fipsmodule/hkdf/hkdf.c
similarity index 98%
rename from src/crypto/hkdf/hkdf.c
rename to src/crypto/fipsmodule/hkdf/hkdf.c
index 23b60af..fa1cc72 100644
--- a/src/crypto/hkdf/hkdf.c
+++ b/src/crypto/fipsmodule/hkdf/hkdf.c
@@ -20,7 +20,7 @@
 #include <openssl/err.h>
 #include <openssl/hmac.h>
 
-#include "../internal.h"
+#include "../../internal.h"
 
 
 int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
diff --git a/src/crypto/hkdf/hkdf_test.cc b/src/crypto/fipsmodule/hkdf/hkdf_test.cc
similarity index 98%
rename from src/crypto/hkdf/hkdf_test.cc
rename to src/crypto/fipsmodule/hkdf/hkdf_test.cc
index 8aad6c8..dd7dd58 100644
--- a/src/crypto/hkdf/hkdf_test.cc
+++ b/src/crypto/fipsmodule/hkdf/hkdf_test.cc
@@ -20,9 +20,9 @@
 
 #include <gtest/gtest.h>
 
-#include "../test/file_test.h"
-#include "../test/test_util.h"
-#include "../test/wycheproof_util.h"
+#include "../../test/file_test.h"
+#include "../../test/test_util.h"
+#include "../../test/wycheproof_util.h"
 
 
 struct HKDFTestVector {
diff --git a/src/crypto/fipsmodule/rsa/internal.h b/src/crypto/fipsmodule/rsa/internal.h
index d0b5a4a..12394a4 100644
--- a/src/crypto/fipsmodule/rsa/internal.h
+++ b/src/crypto/fipsmodule/rsa/internal.h
@@ -67,6 +67,8 @@
 #endif
 
 
+#define RSA_PKCS1_PADDING_SIZE 11
+
 // Default implementations of RSA operations.
 
 const RSA_METHOD *RSA_default_method(void);
@@ -75,8 +77,6 @@
 int rsa_default_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out,
                          size_t max_out, const uint8_t *in, size_t in_len,
                          int padding);
-int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
-                        const uint8_t *in, size_t in_len, int padding);
 int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
                                   size_t len);
 
@@ -90,21 +90,13 @@
                        BN_CTX *ctx);
 
 
+int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed, size_t seed_len,
+               const EVP_MD *md);
 int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
                                  const uint8_t *from, size_t from_len);
 int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
                                    size_t max_out, const uint8_t *from,
                                    size_t from_len);
-int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
-                                 const uint8_t *from, size_t from_len);
-int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
-                                   size_t max_out, const uint8_t *from,
-                                   size_t from_len);
-int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
-                                      size_t max_out, const uint8_t *from,
-                                      size_t from_len, const uint8_t *param,
-                                      size_t param_len, const EVP_MD *md,
-                                      const EVP_MD *mgf1md);
 int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
                          size_t from_len);
 
@@ -112,10 +104,16 @@
 // within DoS bounds.
 int rsa_check_public_key(const RSA *rsa);
 
-// RSA_private_transform calls either the method-specific |private_transform|
-// function (if given) or the generic one. See the comment for
-// |private_transform| in |rsa_meth_st|.
-int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
+// rsa_private_transform_no_self_test calls either the method-specific
+// |private_transform| function (if given) or the generic one. See the comment
+// for |private_transform| in |rsa_meth_st|.
+int rsa_private_transform_no_self_test(RSA *rsa, uint8_t *out,
+                                       const uint8_t *in, size_t len);
+
+// rsa_private_transform acts the same as |rsa_private_transform_no_self_test|
+// but, in FIPS mode, performs an RSA self test before calling the default RSA
+// implementation.
+int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
                           size_t len);
 
 
diff --git a/src/crypto/fipsmodule/rsa/padding.c b/src/crypto/fipsmodule/rsa/padding.c
index 85f7835..998e459 100644
--- a/src/crypto/fipsmodule/rsa/padding.c
+++ b/src/crypto/fipsmodule/rsa/padding.c
@@ -71,8 +71,6 @@
 #include "../../internal.h"
 
 
-#define RSA_PKCS1_PADDING_SIZE 11
-
 int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
                                  const uint8_t *from, size_t from_len) {
   // See RFC 8017, section 9.2.
@@ -146,109 +144,6 @@
   return 1;
 }
 
-static void rand_nonzero(uint8_t *out, size_t len) {
-  FIPS_service_indicator_lock_state();
-  RAND_bytes(out, len);
-
-  for (size_t i = 0; i < len; i++) {
-    while (out[i] == 0) {
-      RAND_bytes(out + i, 1);
-    }
-  }
-
-  FIPS_service_indicator_unlock_state();
-}
-
-int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
-                                 const uint8_t *from, size_t from_len) {
-  // See RFC 8017, section 7.2.1.
-  if (to_len < RSA_PKCS1_PADDING_SIZE) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
-    return 0;
-  }
-
-  if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
-    return 0;
-  }
-
-  to[0] = 0;
-  to[1] = 2;
-
-  size_t padding_len = to_len - 3 - from_len;
-  rand_nonzero(to + 2, padding_len);
-  to[2 + padding_len] = 0;
-  OPENSSL_memcpy(to + to_len - from_len, from, from_len);
-  return 1;
-}
-
-int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
-                                   size_t max_out, const uint8_t *from,
-                                   size_t from_len) {
-  if (from_len == 0) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
-    return 0;
-  }
-
-  // PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
-  // Standard", section 7.2.2.
-  if (from_len < RSA_PKCS1_PADDING_SIZE) {
-    // |from| is zero-padded to the size of the RSA modulus, a public value, so
-    // this can be rejected in non-constant time.
-    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
-    return 0;
-  }
-
-  crypto_word_t first_byte_is_zero = constant_time_eq_w(from[0], 0);
-  crypto_word_t second_byte_is_two = constant_time_eq_w(from[1], 2);
-
-  crypto_word_t zero_index = 0, looking_for_index = CONSTTIME_TRUE_W;
-  for (size_t i = 2; i < from_len; i++) {
-    crypto_word_t equals0 = constant_time_is_zero_w(from[i]);
-    zero_index =
-        constant_time_select_w(looking_for_index & equals0, i, zero_index);
-    looking_for_index = constant_time_select_w(equals0, 0, looking_for_index);
-  }
-
-  // The input must begin with 00 02.
-  crypto_word_t valid_index = first_byte_is_zero;
-  valid_index &= second_byte_is_two;
-
-  // We must have found the end of PS.
-  valid_index &= ~looking_for_index;
-
-  // PS must be at least 8 bytes long, and it starts two bytes into |from|.
-  valid_index &= constant_time_ge_w(zero_index, 2 + 8);
-
-  // Skip the zero byte.
-  zero_index++;
-
-  // NOTE: Although this logic attempts to be constant time, the API contracts
-  // of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
-  // impossible to completely avoid Bleichenbacher's attack. Consumers should
-  // use |RSA_PADDING_NONE| and perform the padding check in constant-time
-  // combined with a swap to a random session key or other mitigation.
-  CONSTTIME_DECLASSIFY(&valid_index, sizeof(valid_index));
-  CONSTTIME_DECLASSIFY(&zero_index, sizeof(zero_index));
-
-  if (!valid_index) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
-    return 0;
-  }
-
-  const size_t msg_len = from_len - zero_index;
-  if (msg_len > max_out) {
-    // This shouldn't happen because this function is always called with
-    // |max_out| as the key size and |from_len| is bounded by the key size.
-    OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
-    return 0;
-  }
-
-  OPENSSL_memcpy(out, &from[zero_index], msg_len);
-  *out_len = msg_len;
-  return 1;
-}
-
 int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
                          size_t from_len) {
   if (from_len > to_len) {
@@ -265,8 +160,8 @@
   return 1;
 }
 
-static int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed,
-                      size_t seed_len, const EVP_MD *md) {
+int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed, size_t seed_len,
+               const EVP_MD *md) {
   int ret = 0;
   EVP_MD_CTX ctx;
   EVP_MD_CTX_init(&ctx);
@@ -310,184 +205,6 @@
   return ret;
 }
 
-int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len,
-                                    const uint8_t *from, size_t from_len,
-                                    const uint8_t *param, size_t param_len,
-                                    const EVP_MD *md, const EVP_MD *mgf1md) {
-  if (md == NULL) {
-    md = EVP_sha1();
-  }
-  if (mgf1md == NULL) {
-    mgf1md = md;
-  }
-
-  size_t mdlen = EVP_MD_size(md);
-
-  if (to_len < 2 * mdlen + 2) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
-    return 0;
-  }
-
-  size_t emlen = to_len - 1;
-  if (from_len > emlen - 2 * mdlen - 1) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
-    return 0;
-  }
-
-  if (emlen < 2 * mdlen + 1) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
-    return 0;
-  }
-
-  to[0] = 0;
-  uint8_t *seed = to + 1;
-  uint8_t *db = to + mdlen + 1;
-
-  uint8_t *dbmask = NULL;
-  int ret = 0;
-  FIPS_service_indicator_lock_state();
-  if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
-    goto out;
-  }
-  OPENSSL_memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
-  db[emlen - from_len - mdlen - 1] = 0x01;
-  OPENSSL_memcpy(db + emlen - from_len - mdlen, from, from_len);
-  if (!RAND_bytes(seed, mdlen)) {
-    goto out;
-  }
-
-  dbmask = OPENSSL_malloc(emlen - mdlen);
-  if (dbmask == NULL) {
-    goto out;
-  }
-
-  if (!PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md)) {
-    goto out;
-  }
-  for (size_t i = 0; i < emlen - mdlen; i++) {
-    db[i] ^= dbmask[i];
-  }
-
-  uint8_t seedmask[EVP_MAX_MD_SIZE];
-  if (!PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md)) {
-    goto out;
-  }
-  for (size_t i = 0; i < mdlen; i++) {
-    seed[i] ^= seedmask[i];
-  }
-  ret = 1;
-
-out:
-  OPENSSL_free(dbmask);
-  FIPS_service_indicator_unlock_state();
-  return ret;
-}
-
-int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
-                                      size_t max_out, const uint8_t *from,
-                                      size_t from_len, const uint8_t *param,
-                                      size_t param_len, const EVP_MD *md,
-                                      const EVP_MD *mgf1md) {
-  uint8_t *db = NULL;
-
-  if (md == NULL) {
-    md = EVP_sha1();
-  }
-  if (mgf1md == NULL) {
-    mgf1md = md;
-  }
-
-  size_t mdlen = EVP_MD_size(md);
-
-  // The encoded message is one byte smaller than the modulus to ensure that it
-  // doesn't end up greater than the modulus. Thus there's an extra "+1" here
-  // compared to https://tools.ietf.org/html/rfc2437#section-9.1.1.2.
-  if (from_len < 1 + 2*mdlen + 1) {
-    // 'from_len' is the length of the modulus, i.e. does not depend on the
-    // particular ciphertext.
-    goto decoding_err;
-  }
-
-  size_t dblen = from_len - mdlen - 1;
-  FIPS_service_indicator_lock_state();
-  db = OPENSSL_malloc(dblen);
-  if (db == NULL) {
-    goto err;
-  }
-
-  const uint8_t *maskedseed = from + 1;
-  const uint8_t *maskeddb = from + 1 + mdlen;
-
-  uint8_t seed[EVP_MAX_MD_SIZE];
-  if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
-    goto err;
-  }
-  for (size_t i = 0; i < mdlen; i++) {
-    seed[i] ^= maskedseed[i];
-  }
-
-  if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
-    goto err;
-  }
-  for (size_t i = 0; i < dblen; i++) {
-    db[i] ^= maskeddb[i];
-  }
-
-  uint8_t phash[EVP_MAX_MD_SIZE];
-  if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
-    goto err;
-  }
-
-  crypto_word_t bad = ~constant_time_is_zero_w(CRYPTO_memcmp(db, phash, mdlen));
-  bad |= ~constant_time_is_zero_w(from[0]);
-
-  crypto_word_t looking_for_one_byte = CONSTTIME_TRUE_W;
-  size_t one_index = 0;
-  for (size_t i = mdlen; i < dblen; i++) {
-    crypto_word_t equals1 = constant_time_eq_w(db[i], 1);
-    crypto_word_t equals0 = constant_time_eq_w(db[i], 0);
-    one_index =
-        constant_time_select_w(looking_for_one_byte & equals1, i, one_index);
-    looking_for_one_byte =
-        constant_time_select_w(equals1, 0, looking_for_one_byte);
-    bad |= looking_for_one_byte & ~equals0;
-  }
-
-  bad |= looking_for_one_byte;
-
-  // Whether the overall padding was valid or not in OAEP is public.
-  if (constant_time_declassify_w(bad)) {
-    goto decoding_err;
-  }
-
-  // Once the padding is known to be valid, the output length is also public.
-  static_assert(sizeof(size_t) <= sizeof(crypto_word_t),
-                "size_t does not fit in crypto_word_t");
-  one_index = constant_time_declassify_w(one_index);
-
-  one_index++;
-  size_t mlen = dblen - one_index;
-  if (max_out < mlen) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
-    goto err;
-  }
-
-  OPENSSL_memcpy(out, db + one_index, mlen);
-  *out_len = mlen;
-  OPENSSL_free(db);
-  FIPS_service_indicator_unlock_state();
-  return 1;
-
-decoding_err:
-  // To avoid chosen ciphertext attacks, the error message should not reveal
-  // which kind of decoding error happened.
-  OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR);
- err:
-  OPENSSL_free(db);
-  FIPS_service_indicator_unlock_state();
-  return 0;
-}
-
 static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
 
 int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash,
@@ -504,9 +221,9 @@
   FIPS_service_indicator_lock_state();
 
   // Negative sLen has special meanings:
-  //	-1	sLen == hLen
-  //	-2	salt length is autorecovered from signature
-  //	-N	reserved
+  //   -1      sLen == hLen
+  //   -2      salt length is autorecovered from signature
+  //   -N      reserved
   size_t hLen = EVP_MD_size(Hash);
   if (sLen == -1) {
     sLen = (int)hLen;
diff --git a/src/crypto/fipsmodule/rsa/rsa.c b/src/crypto/fipsmodule/rsa/rsa.c
index 2139275..dffc8aa 100644
--- a/src/crypto/fipsmodule/rsa/rsa.c
+++ b/src/crypto/fipsmodule/rsa/rsa.c
@@ -288,21 +288,6 @@
   return 1;
 }
 
-int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
-                       int padding) {
-  size_t out_len;
-
-  if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
-    return -1;
-  }
-
-  if (out_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    return -1;
-  }
-  return (int)out_len;
-}
-
 static int rsa_sign_raw_no_self_test(RSA *rsa, size_t *out_len, uint8_t *out,
                                      size_t max_out, const uint8_t *in,
                                      size_t in_len, int padding) {
@@ -320,58 +305,6 @@
                                    padding);
 }
 
-int RSA_private_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
-                        int padding) {
-  size_t out_len;
-
-  if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
-    return -1;
-  }
-
-  if (out_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    return -1;
-  }
-  return (int)out_len;
-}
-
-int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
-                const uint8_t *in, size_t in_len, int padding) {
-  if (rsa->meth->decrypt) {
-    return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding);
-  }
-
-  return rsa_default_decrypt(rsa, out_len, out, max_out, in, in_len, padding);
-}
-
-int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
-                        int padding) {
-  size_t out_len;
-  if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
-    return -1;
-  }
-
-  if (out_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    return -1;
-  }
-  return (int)out_len;
-}
-
-int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
-                       int padding) {
-  size_t out_len;
-  if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
-    return -1;
-  }
-
-  if (out_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    return -1;
-  }
-  return (int)out_len;
-}
-
 unsigned RSA_size(const RSA *rsa) {
   size_t ret = rsa->meth->size ? rsa->meth->size(rsa) : rsa_default_size(rsa);
   // RSA modulus sizes are bounded by |BIGNUM|, which must fit in |unsigned|.
@@ -962,8 +895,8 @@
   return ret;
 }
 
-int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
-                          size_t len) {
+int rsa_private_transform_no_self_test(RSA *rsa, uint8_t *out,
+                                       const uint8_t *in, size_t len) {
   if (rsa->meth->private_transform) {
     return rsa->meth->private_transform(rsa, out, in, len);
   }
@@ -971,6 +904,12 @@
   return rsa_default_private_transform(rsa, out, in, len);
 }
 
+int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
+                          size_t len) {
+  boringssl_ensure_rsa_self_test();
+  return rsa_private_transform_no_self_test(rsa, out, in, len);
+}
+
 int RSA_flags(const RSA *rsa) { return rsa->flags; }
 
 int RSA_test_flags(const RSA *rsa, int flags) { return rsa->flags & flags; }
diff --git a/src/crypto/fipsmodule/rsa/rsa_impl.c b/src/crypto/fipsmodule/rsa/rsa_impl.c
index 4500b1a..dabcd2f 100644
--- a/src/crypto/fipsmodule/rsa/rsa_impl.c
+++ b/src/crypto/fipsmodule/rsa/rsa_impl.c
@@ -266,94 +266,6 @@
   return BN_num_bytes(rsa->n);
 }
 
-int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
-                const uint8_t *in, size_t in_len, int padding) {
-  boringssl_ensure_rsa_self_test();
-
-  if (!rsa_check_public_key(rsa)) {
-    return 0;
-  }
-
-  const unsigned rsa_size = RSA_size(rsa);
-  BIGNUM *f, *result;
-  uint8_t *buf = NULL;
-  BN_CTX *ctx = NULL;
-  int i, ret = 0;
-
-  if (max_out < rsa_size) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
-  }
-
-  BN_CTX_start(ctx);
-  f = BN_CTX_get(ctx);
-  result = BN_CTX_get(ctx);
-  buf = OPENSSL_malloc(rsa_size);
-  if (!f || !result || !buf) {
-    goto err;
-  }
-
-  switch (padding) {
-    case RSA_PKCS1_PADDING:
-      i = RSA_padding_add_PKCS1_type_2(buf, rsa_size, in, in_len);
-      break;
-    case RSA_PKCS1_OAEP_PADDING:
-      // Use the default parameters: SHA-1 for both hashes and no label.
-      i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len,
-                                          NULL, 0, NULL, NULL);
-      break;
-    case RSA_NO_PADDING:
-      i = RSA_padding_add_none(buf, rsa_size, in, in_len);
-      break;
-    default:
-      OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
-      goto err;
-  }
-
-  if (i <= 0) {
-    goto err;
-  }
-
-  if (BN_bin2bn(buf, rsa_size, f) == NULL) {
-    goto err;
-  }
-
-  if (BN_ucmp(f, rsa->n) >= 0) {
-    // usually the padding functions would catch this
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
-    goto err;
-  }
-
-  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
-      !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx, rsa->mont_n)) {
-    goto err;
-  }
-
-  // put in leading 0 bytes if the number is less than the length of the
-  // modulus
-  if (!BN_bn2bin_padded(out, rsa_size, result)) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
-    goto err;
-  }
-
-  *out_len = rsa_size;
-  ret = 1;
-
-err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  OPENSSL_free(buf);
-
-  return ret;
-}
-
 // MAX_BLINDINGS_PER_RSA defines the maximum number of cached BN_BLINDINGs per
 // RSA*. Then this limit is exceeded, BN_BLINDING objects will be created and
 // destroyed as needed.
@@ -516,7 +428,7 @@
     goto err;
   }
 
-  if (!RSA_private_transform(rsa, out, buf, rsa_size)) {
+  if (!rsa_private_transform_no_self_test(rsa, out, buf, rsa_size)) {
     goto err;
   }
 
@@ -530,71 +442,6 @@
   return ret;
 }
 
-int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
-                        const uint8_t *in, size_t in_len, int padding) {
-  boringssl_ensure_rsa_self_test();
-
-  const unsigned rsa_size = RSA_size(rsa);
-  uint8_t *buf = NULL;
-  int ret = 0;
-
-  if (max_out < rsa_size) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (padding == RSA_NO_PADDING) {
-    buf = out;
-  } else {
-    // Allocate a temporary buffer to hold the padded plaintext.
-    buf = OPENSSL_malloc(rsa_size);
-    if (buf == NULL) {
-      goto err;
-    }
-  }
-
-  if (in_len != rsa_size) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
-    goto err;
-  }
-
-  if (!RSA_private_transform(rsa, buf, in, rsa_size)) {
-    goto err;
-  }
-
-  switch (padding) {
-    case RSA_PKCS1_PADDING:
-      ret =
-          RSA_padding_check_PKCS1_type_2(out, out_len, rsa_size, buf, rsa_size);
-      break;
-    case RSA_PKCS1_OAEP_PADDING:
-      // Use the default parameters: SHA-1 for both hashes and no label.
-      ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, out_len, rsa_size, buf,
-                                              rsa_size, NULL, 0, NULL, NULL);
-      break;
-    case RSA_NO_PADDING:
-      *out_len = rsa_size;
-      ret = 1;
-      break;
-    default:
-      OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
-      goto err;
-  }
-
-  CONSTTIME_DECLASSIFY(&ret, sizeof(ret));
-  if (!ret) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
-  } else {
-    CONSTTIME_DECLASSIFY(out, *out_len);
-  }
-
-err:
-  if (padding != RSA_NO_PADDING) {
-    OPENSSL_free(buf);
-  }
-
-  return ret;
-}
 
 static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
 
diff --git a/src/crypto/fipsmodule/self_check/fips.c b/src/crypto/fipsmodule/self_check/fips.c
index ce03957..31e11ef 100644
--- a/src/crypto/fipsmodule/self_check/fips.c
+++ b/src/crypto/fipsmodule/self_check/fips.c
@@ -31,7 +31,7 @@
 const char *FIPS_module_name(void) { return "BoringCrypto"; }
 
 uint32_t FIPS_version(void) {
-  return 0;
+  return 2023042800;
 }
 
 int FIPS_query_algorithm_status(const char *algorithm) {
diff --git a/src/crypto/fipsmodule/self_check/self_check.c b/src/crypto/fipsmodule/self_check/self_check.c
index 08500e5..525cd16 100644
--- a/src/crypto/fipsmodule/self_check/self_check.c
+++ b/src/crypto/fipsmodule/self_check/self_check.c
@@ -26,6 +26,7 @@
 #include <openssl/ec.h>
 #include <openssl/ecdsa.h>
 #include <openssl/ec_key.h>
+#include <openssl/hkdf.h>
 #include <openssl/hmac.h>
 #include <openssl/nid.h>
 #include <openssl/rsa.h>
@@ -946,6 +947,76 @@
     goto err;
   }
 
+  // TLS v1.3: derives a dummy client-early-traffic secret.
+  static const uint8_t kTLS13Secret[32] = {
+      0x02, 0x4a, 0x0d, 0x80, 0xf3, 0x57, 0xf2, 0x49, 0x9a, 0x12, 0x44,
+      0xda, 0xc2, 0x6d, 0xab, 0x66, 0xfc, 0x13, 0xed, 0x85, 0xfc, 0xa7,
+      0x1d, 0xac, 0xe1, 0x46, 0x21, 0x11, 0x19, 0x52, 0x58, 0x74,
+  };
+  static const uint8_t kTLS13Salt[16] = {
+      0x54, 0x61, 0x11, 0x36, 0x75, 0x91, 0xf0, 0xf8,
+      0x92, 0xec, 0x70, 0xbd, 0x78, 0x2a, 0xef, 0x61,
+  };
+  static const uint8_t kTLS13Label[] = "c e traffic";
+  static const uint8_t kTLS13ClientHelloHash[32] = {
+      0x1d, 0xe8, 0x67, 0xed, 0x93, 0x6a, 0x73, 0x65, 0x9b, 0x05, 0xcf,
+      0x8a, 0x22, 0x77, 0xb7, 0x37, 0x29, 0xf2, 0x44, 0x94, 0x81, 0x6a,
+      0x83, 0x33, 0x7f, 0x09, 0xbb, 0x6c, 0xc2, 0x6f, 0x48, 0x9c,
+  };
+  static const uint8_t kTLS13ExpandLabelOutput[32] = {
+      0x62, 0x91, 0x52, 0x90, 0x2e, 0xc9, 0xcf, 0x9c, 0x5f, 0x1e, 0x0a,
+      0xb7, 0x00, 0x33, 0x42, 0x24, 0xc4, 0xe3, 0xba, 0x01, 0x40, 0x32,
+      0x06, 0xab, 0x09, 0x23, 0x8a, 0xdd, 0x01, 0xa4, 0x05, 0xcd,
+  };
+  uint8_t tls13_extract_output[32];
+  size_t tls13_extract_output_len;
+  uint8_t tls13_expand_label_output[32];
+  if (!HKDF_extract(tls13_extract_output, &tls13_extract_output_len,
+                    EVP_sha256(), kTLS13Secret, sizeof(kTLS13Secret),
+                    kTLS13Salt, sizeof(kTLS13Salt)) ||
+      tls13_extract_output_len != sizeof(tls13_extract_output) ||
+      !CRYPTO_tls13_hkdf_expand_label(
+          tls13_expand_label_output, sizeof(tls13_expand_label_output),
+          EVP_sha256(), tls13_extract_output, sizeof(tls13_extract_output),
+          kTLS13Label, sizeof(kTLS13Label) - 1, kTLS13ClientHelloHash,
+          sizeof(kTLS13ClientHelloHash)) ||
+      !check_test(kTLS13ExpandLabelOutput, tls13_expand_label_output,
+                  sizeof(kTLS13ExpandLabelOutput),
+                  "CRYPTO_tls13_hkdf_expand_label")) {
+    fprintf(stderr, "TLSv1.3 KDF failed.\n");
+    goto err;
+  }
+
+  // HKDF
+  static const uint8_t kHKDFSecret[32] = {
+      0x68, 0x67, 0x85, 0x04, 0xb9, 0xb3, 0xad, 0xd1, 0x7d, 0x59, 0x67,
+      0xa1, 0xa7, 0xbd, 0x37, 0x99, 0x3f, 0xd8, 0xa3, 0x3c, 0xe7, 0x30,
+      0x30, 0x71, 0xf3, 0x9c, 0x09, 0x6d, 0x16, 0x35, 0xb3, 0xc9,
+  };
+  static const uint8_t kHKDFSalt[32] = {
+      0x8a, 0xab, 0x18, 0xb4, 0x9b, 0x0a, 0x17, 0xf9, 0xe8, 0xe6, 0x97,
+      0x1a, 0x3d, 0xff, 0xda, 0x9b, 0x26, 0x8b, 0x3d, 0x17, 0x78, 0x0a,
+      0xb3, 0xea, 0x65, 0xdb, 0x2a, 0xc0, 0x29, 0x9c, 0xfa, 0x72,
+  };
+  static const uint8_t kHKDFInfo[32] = {
+      0xe5, 0x6f, 0xf9, 0xe1, 0x18, 0x5e, 0x64, 0x8c, 0x6c, 0x8f, 0xee,
+      0xc6, 0x93, 0x5a, 0xc5, 0x14, 0x8c, 0xf3, 0xd9, 0x78, 0xd2, 0x3a,
+      0x86, 0xdd, 0x01, 0xdf, 0xb9, 0xe9, 0x5e, 0xe5, 0x1a, 0x56,
+  };
+  static const uint8_t kHKDFOutput[32] = {
+      0xa6, 0x29, 0xb4, 0xd7, 0xf4, 0xc1, 0x16, 0x64, 0x71, 0x5e, 0xa4,
+      0xa8, 0xe6, 0x60, 0x8c, 0xf3, 0xc1, 0xa5, 0x03, 0xe2, 0x22, 0xf9,
+      0x89, 0xe2, 0x12, 0x18, 0xbe, 0xef, 0x16, 0x86, 0xe0, 0xec,
+  };
+  uint8_t hkdf_output[sizeof(kHKDFOutput)];
+  if (!HKDF(hkdf_output, sizeof(hkdf_output), EVP_sha256(), kHKDFSecret,
+            sizeof(kHKDFSecret), kHKDFSalt, sizeof(kHKDFSalt), kHKDFInfo,
+            sizeof(kHKDFInfo)) ||
+      !check_test(kHKDFOutput, hkdf_output, sizeof(kHKDFOutput), "HKDF")) {
+    fprintf(stderr, "HKDF failed.\n");
+    goto err;
+  }
+
   ret = 1;
 
 err:
diff --git a/src/crypto/fipsmodule/tls/internal.h b/src/crypto/fipsmodule/tls/internal.h
index ef642a6..535b7eb 100644
--- a/src/crypto/fipsmodule/tls/internal.h
+++ b/src/crypto/fipsmodule/tls/internal.h
@@ -31,6 +31,14 @@
                                    const uint8_t *seed1, size_t seed1_len,
                                    const uint8_t *seed2, size_t seed2_len);
 
+// CRYPTO_tls13_hkdf_expand_label computes the TLS 1.3 KDF function of the same
+// name. See https://www.rfc-editor.org/rfc/rfc8446#section-7.1.
+OPENSSL_EXPORT int CRYPTO_tls13_hkdf_expand_label(
+    uint8_t *out, size_t out_len, const EVP_MD *digest,  //
+    const uint8_t *secret, size_t secret_len,            //
+    const uint8_t *label, size_t label_len,              //
+    const uint8_t *hash, size_t hash_len);
+
 
 #if defined(__cplusplus)
 }
diff --git a/src/crypto/fipsmodule/tls/kdf.c b/src/crypto/fipsmodule/tls/kdf.c
index 046cb52..c4f4976 100644
--- a/src/crypto/fipsmodule/tls/kdf.c
+++ b/src/crypto/fipsmodule/tls/kdf.c
@@ -52,7 +52,9 @@
 
 #include <assert.h>
 
+#include <openssl/bytestring.h>
 #include <openssl/digest.h>
+#include <openssl/hkdf.h>
 #include <openssl/hmac.h>
 #include <openssl/mem.h>
 
@@ -176,3 +178,34 @@
   }
   return ret;
 }
+
+int CRYPTO_tls13_hkdf_expand_label(uint8_t *out, size_t out_len,
+                                   const EVP_MD *digest,  //
+                                   const uint8_t *secret, size_t secret_len,
+                                   const uint8_t *label, size_t label_len,
+                                   const uint8_t *hash, size_t hash_len) {
+  static const uint8_t kProtocolLabel[] = "tls13 ";
+  CBB cbb, child;
+  uint8_t *hkdf_label = NULL;
+  size_t hkdf_label_len;
+
+  CBB_zero(&cbb);
+  if (!CBB_init(&cbb, 2 + 1 + sizeof(kProtocolLabel) - 1 + label_len + 1 +
+                          hash_len) ||
+      !CBB_add_u16(&cbb, out_len) ||
+      !CBB_add_u8_length_prefixed(&cbb, &child) ||
+      !CBB_add_bytes(&child, kProtocolLabel, sizeof(kProtocolLabel) - 1) ||
+      !CBB_add_bytes(&child, label, label_len) ||
+      !CBB_add_u8_length_prefixed(&cbb, &child) ||
+      !CBB_add_bytes(&child, hash, hash_len) ||
+      !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) {
+    CBB_cleanup(&cbb);
+    return 0;
+  }
+
+  const int ret = HKDF_expand(out, out_len, digest, secret, secret_len,
+                              hkdf_label, hkdf_label_len);
+  OPENSSL_free(hkdf_label);
+  return ret;
+}
+
diff --git a/src/crypto/kyber/kyber.c b/src/crypto/kyber/kyber.c
index f2ac30b..010d9d4 100644
--- a/src/crypto/kyber/kyber.c
+++ b/src/crypto/kyber/kyber.c
@@ -283,16 +283,23 @@
 // operates on public inputs.
 static void scalar_from_keccak_vartime(scalar *out,
                                        struct BORINGSSL_keccak_st *keccak_ctx) {
-  uint8_t bytes[3];
-  for (int i = 0; i < DEGREE;) {
-    BORINGSSL_keccak_squeeze(keccak_ctx, bytes, sizeof(bytes));
-    uint16_t d1 = bytes[0] + 256 * (bytes[1] % 16);
-    uint16_t d2 = bytes[1] / 16 + 16 * bytes[2];
-    if (d1 < kPrime) {
-      out->c[i++] = d1;
-    }
-    if (d2 < kPrime && i < DEGREE) {
-      out->c[i++] = d2;
+  assert(keccak_ctx->offset == 0);
+  assert(keccak_ctx->rate_bytes == 168);
+  static_assert(168 % 3 == 0, "block and coefficient boundaries do not align");
+
+  int done = 0;
+  while (done < DEGREE) {
+    uint8_t block[168];
+    BORINGSSL_keccak_squeeze(keccak_ctx, block, sizeof(block));
+    for (size_t i = 0; i < sizeof(block) && done < DEGREE; i += 3) {
+      uint16_t d1 = block[i] + 256 * (block[i + 1] % 16);
+      uint16_t d2 = block[i + 1] / 16 + 16 * block[i + 2];
+      if (d1 < kPrime) {
+        out->c[done++] = d1;
+      }
+      if (d2 < kPrime && done < DEGREE) {
+        out->c[done++] = d2;
+      }
     }
   }
 }
diff --git a/src/crypto/obj/obj_dat.h b/src/crypto/obj/obj_dat.h
index d879233..7cd1153 100644
--- a/src/crypto/obj/obj_dat.h
+++ b/src/crypto/obj/obj_dat.h
@@ -8777,7 +8777,7 @@
     {"AuthPSK", "auth-psk", NID_auth_psk, 0, NULL, 0},
     {"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
     {"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
-    {"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
     {"ED448", "ED448", NID_ED448, 3, &kObjectData[6181], 0},
     {"X448", "X448", NID_X448, 3, &kObjectData[6184], 0},
     {"SHA512-256", "sha512-256", NID_sha512_256, 9, &kObjectData[6187], 0},
@@ -8846,7 +8846,6 @@
     110 /* CAST5-CFB */,
     109 /* CAST5-ECB */,
     111 /* CAST5-OFB */,
-    959 /* CECPQ2 */,
     894 /* CMAC */,
     13 /* CN */,
     141 /* CRLReason */,
@@ -9758,7 +9757,6 @@
     285 /* Biometric Info */,
     179 /* CA Issuers */,
     785 /* CA Repository */,
-    959 /* CECPQ2 */,
     131 /* Code Signing */,
     783 /* Diffie-Hellman based MAC */,
     382 /* Directory */,
diff --git a/src/crypto/obj/obj_mac.num b/src/crypto/obj/obj_mac.num
index c0473bc..583f6e3 100644
--- a/src/crypto/obj/obj_mac.num
+++ b/src/crypto/obj/obj_mac.num
@@ -947,7 +947,6 @@
 auth_psk		956
 kx_any		957
 auth_any		958
-CECPQ2		959
 ED448		960
 X448		961
 sha512_256		962
diff --git a/src/crypto/obj/objects.go b/src/crypto/obj/objects.go
index 1b9ded3..077a6e1 100644
--- a/src/crypto/obj/objects.go
+++ b/src/crypto/obj/objects.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
@@ -520,21 +522,8 @@
 	return os.WriteFile(path, []byte(formatted), 0666)
 }
 
-// TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently
-// common.
-type nidSorter struct {
-	nids []int
-	objs *objects
-	cmp  func(a, b object) bool
-}
-
-func (a nidSorter) obj(i int) object   { return a.objs.byNID[a.nids[i]] }
-func (a nidSorter) Len() int           { return len(a.nids) }
-func (a nidSorter) Swap(i, j int)      { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] }
-func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) }
-
 func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) {
-	sort.Sort(&nidSorter{nids, objs, cmp})
+	sort.Slice(nids, func(i, j int) bool { return cmp(objs.byNID[nids[i]], objs.byNID[nids[j]]) })
 }
 
 func writeData(path string, objs *objects) error {
diff --git a/src/crypto/obj/objects.txt b/src/crypto/obj/objects.txt
index 11151f9..cad6a3b 100644
--- a/src/crypto/obj/objects.txt
+++ b/src/crypto/obj/objects.txt
@@ -1333,7 +1333,6 @@
                  : dh-cofactor-kdf
 
 # NIDs for post quantum key agreements (no corresponding OIDs).
- : CECPQ2
  : X25519Kyber768
  : P256Kyber768
  : P384Kyber768
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index 28ed438..30ba387 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -78,7 +78,8 @@
 static int load_iv(char **fromp, unsigned char *to, size_t num);
 static int check_pem(const char *nm, const char *name);
 
-void PEM_proc_type(char *buf, int type) {
+// PEM_proc_type appends a Proc-Type header to |buf|, determined by |type|.
+static void PEM_proc_type(char buf[PEM_BUFSIZE], int type) {
   const char *str;
 
   if (type == PEM_TYPE_ENCRYPTED) {
@@ -96,24 +97,27 @@
   OPENSSL_strlcat(buf, "\n", PEM_BUFSIZE);
 }
 
-void PEM_dek_info(char *buf, const char *type, int len, char *str) {
+// PEM_dek_info appends a DEK-Info header to |buf|, with an algorithm of |type|
+// and a single parameter, specified by hex-encoding |len| bytes from |str|.
+static void PEM_dek_info(char buf[PEM_BUFSIZE], const char *type, size_t len,
+                         char *str) {
   static const unsigned char map[17] = "0123456789ABCDEF";
-  long i;
-  int j;
 
   OPENSSL_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE);
   OPENSSL_strlcat(buf, type, PEM_BUFSIZE);
   OPENSSL_strlcat(buf, ",", PEM_BUFSIZE);
-  j = strlen(buf);
-  if (j + (len * 2) + 1 > PEM_BUFSIZE) {
+  size_t buf_len = strlen(buf);
+  // We must write an additional |2 * len + 2| bytes after |buf_len|, including
+  // the trailing newline and NUL.
+  if (len > (PEM_BUFSIZE - buf_len - 2) / 2) {
     return;
   }
-  for (i = 0; i < len; i++) {
-    buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
-    buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
+  for (size_t i = 0; i < len; i++) {
+    buf[buf_len + i * 2] = map[(str[i] >> 4) & 0x0f];
+    buf[buf_len + i * 2 + 1] = map[(str[i]) & 0x0f];
   }
-  buf[j + i * 2] = '\n';
-  buf[j + i * 2 + 1] = '\0';
+  buf[buf_len + len * 2] = '\n';
+  buf[buf_len + len * 2 + 1] = '\0';
 }
 
 void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
@@ -318,7 +322,7 @@
       }
       kstr = (unsigned char *)buf;
     }
-    assert(iv_len <= (int)sizeof(iv));
+    assert(iv_len <= sizeof(iv));
     if (!RAND_bytes(iv, iv_len)) {  // Generate a salt
       goto err;
     }
@@ -332,7 +336,7 @@
       OPENSSL_cleanse(buf, PEM_BUFSIZE);
     }
 
-    assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
+    assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof(buf));
 
     buf[0] = '\0';
     PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
@@ -781,5 +785,5 @@
     return 0;
   }
   OPENSSL_strlcpy(buf, userdata, (size_t)size);
-  return len;
+  return (int)len;
 }
diff --git a/src/crypto/rsa_extra/internal.h b/src/crypto/rsa_extra/internal.h
new file mode 100644
index 0000000..6317cfc
--- /dev/null
+++ b/src/crypto/rsa_extra/internal.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+
+#ifndef OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
+#define OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
+                                      size_t max_out, const uint8_t *from,
+                                      size_t from_len, const uint8_t *param,
+                                      size_t param_len, const EVP_MD *md,
+                                      const EVP_MD *mgf1md);
+
+
+#if defined(__cplusplus)
+}  // extern C
+#endif
+
+#endif  // OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
diff --git a/src/crypto/rsa_extra/rsa_crypt.c b/src/crypto/rsa_extra/rsa_crypt.c
new file mode 100644
index 0000000..97afa3d
--- /dev/null
+++ b/src/crypto/rsa_extra/rsa_crypt.c
@@ -0,0 +1,563 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/base.h>
+
+#include <limits.h>
+
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#include <openssl/mem.h>
+#include <openssl/evp.h>
+
+#include "../fipsmodule/bn/internal.h"
+#include "../fipsmodule/rsa/internal.h"
+#include "../internal.h"
+#include "internal.h"
+
+
+static void rand_nonzero(uint8_t *out, size_t len) {
+  RAND_bytes(out, len);
+
+  for (size_t i = 0; i < len; i++) {
+    while (out[i] == 0) {
+      RAND_bytes(out + i, 1);
+    }
+  }
+}
+
+int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len,
+                                    const uint8_t *from, size_t from_len,
+                                    const uint8_t *param, size_t param_len,
+                                    const EVP_MD *md, const EVP_MD *mgf1md) {
+  if (md == NULL) {
+    md = EVP_sha1();
+  }
+  if (mgf1md == NULL) {
+    mgf1md = md;
+  }
+
+  size_t mdlen = EVP_MD_size(md);
+
+  if (to_len < 2 * mdlen + 2) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+    return 0;
+  }
+
+  size_t emlen = to_len - 1;
+  if (from_len > emlen - 2 * mdlen - 1) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+    return 0;
+  }
+
+  if (emlen < 2 * mdlen + 1) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+    return 0;
+  }
+
+  to[0] = 0;
+  uint8_t *seed = to + 1;
+  uint8_t *db = to + mdlen + 1;
+
+  uint8_t *dbmask = NULL;
+  int ret = 0;
+  if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
+    goto out;
+  }
+  OPENSSL_memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
+  db[emlen - from_len - mdlen - 1] = 0x01;
+  OPENSSL_memcpy(db + emlen - from_len - mdlen, from, from_len);
+  if (!RAND_bytes(seed, mdlen)) {
+    goto out;
+  }
+
+  dbmask = OPENSSL_malloc(emlen - mdlen);
+  if (dbmask == NULL) {
+    goto out;
+  }
+
+  if (!PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md)) {
+    goto out;
+  }
+  for (size_t i = 0; i < emlen - mdlen; i++) {
+    db[i] ^= dbmask[i];
+  }
+
+  uint8_t seedmask[EVP_MAX_MD_SIZE];
+  if (!PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md)) {
+    goto out;
+  }
+  for (size_t i = 0; i < mdlen; i++) {
+    seed[i] ^= seedmask[i];
+  }
+  ret = 1;
+
+out:
+  OPENSSL_free(dbmask);
+  return ret;
+}
+
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
+                                      size_t max_out, const uint8_t *from,
+                                      size_t from_len, const uint8_t *param,
+                                      size_t param_len, const EVP_MD *md,
+                                      const EVP_MD *mgf1md) {
+  uint8_t *db = NULL;
+
+  if (md == NULL) {
+    md = EVP_sha1();
+  }
+  if (mgf1md == NULL) {
+    mgf1md = md;
+  }
+
+  size_t mdlen = EVP_MD_size(md);
+
+  // The encoded message is one byte smaller than the modulus to ensure that it
+  // doesn't end up greater than the modulus. Thus there's an extra "+1" here
+  // compared to https://tools.ietf.org/html/rfc2437#section-9.1.1.2.
+  if (from_len < 1 + 2 * mdlen + 1) {
+    // 'from_len' is the length of the modulus, i.e. does not depend on the
+    // particular ciphertext.
+    goto decoding_err;
+  }
+
+  size_t dblen = from_len - mdlen - 1;
+  db = OPENSSL_malloc(dblen);
+  if (db == NULL) {
+    goto err;
+  }
+
+  const uint8_t *maskedseed = from + 1;
+  const uint8_t *maskeddb = from + 1 + mdlen;
+
+  uint8_t seed[EVP_MAX_MD_SIZE];
+  if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
+    goto err;
+  }
+  for (size_t i = 0; i < mdlen; i++) {
+    seed[i] ^= maskedseed[i];
+  }
+
+  if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
+    goto err;
+  }
+  for (size_t i = 0; i < dblen; i++) {
+    db[i] ^= maskeddb[i];
+  }
+
+  uint8_t phash[EVP_MAX_MD_SIZE];
+  if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
+    goto err;
+  }
+
+  crypto_word_t bad = ~constant_time_is_zero_w(CRYPTO_memcmp(db, phash, mdlen));
+  bad |= ~constant_time_is_zero_w(from[0]);
+
+  crypto_word_t looking_for_one_byte = CONSTTIME_TRUE_W;
+  size_t one_index = 0;
+  for (size_t i = mdlen; i < dblen; i++) {
+    crypto_word_t equals1 = constant_time_eq_w(db[i], 1);
+    crypto_word_t equals0 = constant_time_eq_w(db[i], 0);
+    one_index =
+        constant_time_select_w(looking_for_one_byte & equals1, i, one_index);
+    looking_for_one_byte =
+        constant_time_select_w(equals1, 0, looking_for_one_byte);
+    bad |= looking_for_one_byte & ~equals0;
+  }
+
+  bad |= looking_for_one_byte;
+
+  // Whether the overall padding was valid or not in OAEP is public.
+  if (constant_time_declassify_w(bad)) {
+    goto decoding_err;
+  }
+
+  // Once the padding is known to be valid, the output length is also public.
+  static_assert(sizeof(size_t) <= sizeof(crypto_word_t),
+                "size_t does not fit in crypto_word_t");
+  one_index = constant_time_declassify_w(one_index);
+
+  one_index++;
+  size_t mlen = dblen - one_index;
+  if (max_out < mlen) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
+    goto err;
+  }
+
+  OPENSSL_memcpy(out, db + one_index, mlen);
+  *out_len = mlen;
+  OPENSSL_free(db);
+  return 1;
+
+decoding_err:
+  // To avoid chosen ciphertext attacks, the error message should not reveal
+  // which kind of decoding error happened.
+  OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR);
+err:
+  OPENSSL_free(db);
+  return 0;
+}
+
+static int rsa_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
+                                        const uint8_t *from, size_t from_len) {
+  // See RFC 8017, section 7.2.1.
+  if (to_len < RSA_PKCS1_PADDING_SIZE) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+    return 0;
+  }
+
+  if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+    return 0;
+  }
+
+  to[0] = 0;
+  to[1] = 2;
+
+  size_t padding_len = to_len - 3 - from_len;
+  rand_nonzero(to + 2, padding_len);
+  to[2 + padding_len] = 0;
+  OPENSSL_memcpy(to + to_len - from_len, from, from_len);
+  return 1;
+}
+
+static int rsa_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
+                                          size_t max_out, const uint8_t *from,
+                                          size_t from_len) {
+  if (from_len == 0) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
+    return 0;
+  }
+
+  // PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
+  // Standard", section 7.2.2.
+  if (from_len < RSA_PKCS1_PADDING_SIZE) {
+    // |from| is zero-padded to the size of the RSA modulus, a public value, so
+    // this can be rejected in non-constant time.
+    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+    return 0;
+  }
+
+  crypto_word_t first_byte_is_zero = constant_time_eq_w(from[0], 0);
+  crypto_word_t second_byte_is_two = constant_time_eq_w(from[1], 2);
+
+  crypto_word_t zero_index = 0, looking_for_index = CONSTTIME_TRUE_W;
+  for (size_t i = 2; i < from_len; i++) {
+    crypto_word_t equals0 = constant_time_is_zero_w(from[i]);
+    zero_index =
+        constant_time_select_w(looking_for_index & equals0, i, zero_index);
+    looking_for_index = constant_time_select_w(equals0, 0, looking_for_index);
+  }
+
+  // The input must begin with 00 02.
+  crypto_word_t valid_index = first_byte_is_zero;
+  valid_index &= second_byte_is_two;
+
+  // We must have found the end of PS.
+  valid_index &= ~looking_for_index;
+
+  // PS must be at least 8 bytes long, and it starts two bytes into |from|.
+  valid_index &= constant_time_ge_w(zero_index, 2 + 8);
+
+  // Skip the zero byte.
+  zero_index++;
+
+  // NOTE: Although this logic attempts to be constant time, the API contracts
+  // of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
+  // impossible to completely avoid Bleichenbacher's attack. Consumers should
+  // use |RSA_PADDING_NONE| and perform the padding check in constant-time
+  // combined with a swap to a random session key or other mitigation.
+  CONSTTIME_DECLASSIFY(&valid_index, sizeof(valid_index));
+  CONSTTIME_DECLASSIFY(&zero_index, sizeof(zero_index));
+
+  if (!valid_index) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
+    return 0;
+  }
+
+  const size_t msg_len = from_len - zero_index;
+  if (msg_len > max_out) {
+    // This shouldn't happen because this function is always called with
+    // |max_out| as the key size and |from_len| is bounded by the key size.
+    OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
+    return 0;
+  }
+
+  OPENSSL_memcpy(out, &from[zero_index], msg_len);
+  *out_len = msg_len;
+  return 1;
+}
+
+int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+                       int padding) {
+  size_t out_len;
+
+  if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+    return -1;
+  }
+
+  if (out_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
+    return -1;
+  }
+  return (int)out_len;
+}
+
+int RSA_private_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+                        int padding) {
+  size_t out_len;
+
+  if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+    return -1;
+  }
+
+  if (out_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
+    return -1;
+  }
+  return (int)out_len;
+}
+
+int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+                const uint8_t *in, size_t in_len, int padding) {
+  if (!rsa_check_public_key(rsa)) {
+    return 0;
+  }
+
+  const unsigned rsa_size = RSA_size(rsa);
+  BIGNUM *f, *result;
+  uint8_t *buf = NULL;
+  BN_CTX *ctx = NULL;
+  int i, ret = 0;
+
+  if (max_out < rsa_size) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  ctx = BN_CTX_new();
+  if (ctx == NULL) {
+    goto err;
+  }
+
+  BN_CTX_start(ctx);
+  f = BN_CTX_get(ctx);
+  result = BN_CTX_get(ctx);
+  buf = OPENSSL_malloc(rsa_size);
+  if (!f || !result || !buf) {
+    goto err;
+  }
+
+  switch (padding) {
+    case RSA_PKCS1_PADDING:
+      i = rsa_padding_add_PKCS1_type_2(buf, rsa_size, in, in_len);
+      break;
+    case RSA_PKCS1_OAEP_PADDING:
+      // Use the default parameters: SHA-1 for both hashes and no label.
+      i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len, NULL, 0,
+                                          NULL, NULL);
+      break;
+    case RSA_NO_PADDING:
+      i = RSA_padding_add_none(buf, rsa_size, in, in_len);
+      break;
+    default:
+      OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
+      goto err;
+  }
+
+  if (i <= 0) {
+    goto err;
+  }
+
+  if (BN_bin2bn(buf, rsa_size, f) == NULL) {
+    goto err;
+  }
+
+  if (BN_ucmp(f, rsa->n) >= 0) {
+    // usually the padding functions would catch this
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+    goto err;
+  }
+
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+      !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx, rsa->mont_n)) {
+    goto err;
+  }
+
+  // put in leading 0 bytes if the number is less than the length of the
+  // modulus
+  if (!BN_bn2bin_padded(out, rsa_size, result)) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  *out_len = rsa_size;
+  ret = 1;
+
+err:
+  if (ctx != NULL) {
+    BN_CTX_end(ctx);
+    BN_CTX_free(ctx);
+  }
+  OPENSSL_free(buf);
+
+  return ret;
+}
+
+static int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out,
+                               size_t max_out, const uint8_t *in, size_t in_len,
+                               int padding) {
+  const unsigned rsa_size = RSA_size(rsa);
+  uint8_t *buf = NULL;
+  int ret = 0;
+
+  if (max_out < rsa_size) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  if (padding == RSA_NO_PADDING) {
+    buf = out;
+  } else {
+    // Allocate a temporary buffer to hold the padded plaintext.
+    buf = OPENSSL_malloc(rsa_size);
+    if (buf == NULL) {
+      goto err;
+    }
+  }
+
+  if (in_len != rsa_size) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+    goto err;
+  }
+
+  if (!rsa_private_transform(rsa, buf, in, rsa_size)) {
+    goto err;
+  }
+
+  switch (padding) {
+    case RSA_PKCS1_PADDING:
+      ret =
+          rsa_padding_check_PKCS1_type_2(out, out_len, rsa_size, buf, rsa_size);
+      break;
+    case RSA_PKCS1_OAEP_PADDING:
+      // Use the default parameters: SHA-1 for both hashes and no label.
+      ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, out_len, rsa_size, buf,
+                                              rsa_size, NULL, 0, NULL, NULL);
+      break;
+    case RSA_NO_PADDING:
+      *out_len = rsa_size;
+      ret = 1;
+      break;
+    default:
+      OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
+      goto err;
+  }
+
+  CONSTTIME_DECLASSIFY(&ret, sizeof(ret));
+  if (!ret) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
+  } else {
+    CONSTTIME_DECLASSIFY(out, *out_len);
+  }
+
+err:
+  if (padding != RSA_NO_PADDING) {
+    OPENSSL_free(buf);
+  }
+
+  return ret;
+}
+
+int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+                const uint8_t *in, size_t in_len, int padding) {
+  if (rsa->meth->decrypt) {
+    return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding);
+  }
+
+  return rsa_default_decrypt(rsa, out_len, out, max_out, in, in_len, padding);
+}
+
+int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+                        int padding) {
+  size_t out_len;
+  if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+    return -1;
+  }
+
+  if (out_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
+    return -1;
+  }
+  return (int)out_len;
+}
+
+int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+                       int padding) {
+  size_t out_len;
+  if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+    return -1;
+  }
+
+  if (out_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
+    return -1;
+  }
+  return (int)out_len;
+}
diff --git a/src/crypto/trust_token/internal.h b/src/crypto/trust_token/internal.h
index 093b4ac..8fc5d6e 100644
--- a/src/crypto/trust_token/internal.h
+++ b/src/crypto/trust_token/internal.h
@@ -154,6 +154,38 @@
 // function is used to confirm H was computed as expected.
 OPENSSL_EXPORT int pmbtoken_exp2_get_h_for_testing(uint8_t out[97]);
 
+// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
+// functions for |TRUST_TOKENS_pst_v1|'s PMBTokens construction which uses
+// P-384.
+int pmbtoken_pst1_generate_key(CBB *out_private, CBB *out_public);
+int pmbtoken_pst1_derive_key_from_secret(CBB *out_private, CBB *out_public,
+                                         const uint8_t *secret,
+                                         size_t secret_len);
+int pmbtoken_pst1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key,
+                                        const uint8_t *in, size_t len);
+int pmbtoken_pst1_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key,
+                                        const uint8_t *in, size_t len);
+STACK_OF(TRUST_TOKEN_PRETOKEN) *pmbtoken_pst1_blind(CBB *cbb, size_t count,
+                                                    int include_message,
+                                                    const uint8_t *msg,
+                                                    size_t msg_len);
+int pmbtoken_pst1_sign(const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                       size_t num_requested, size_t num_to_issue,
+                       uint8_t private_metadata);
+STACK_OF(TRUST_TOKEN) *pmbtoken_pst1_unblind(
+    const TRUST_TOKEN_CLIENT_KEY *key,
+    const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
+    uint32_t key_id);
+int pmbtoken_pst1_read(const TRUST_TOKEN_ISSUER_KEY *key,
+                       uint8_t out_nonce[TRUST_TOKEN_NONCE_SIZE],
+                       uint8_t *out_private_metadata, const uint8_t *token,
+                       size_t token_len, int include_message,
+                       const uint8_t *msg, size_t msg_len);
+
+// pmbtoken_pst1_get_h_for_testing returns H in uncompressed coordinates. This
+// function is used to confirm H was computed as expected.
+OPENSSL_EXPORT int pmbtoken_pst1_get_h_for_testing(uint8_t out[97]);
+
 
 // VOPRF.
 //
@@ -191,6 +223,36 @@
                     size_t token_len, int include_message, const uint8_t *msg,
                     size_t msg_len);
 
+// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
+// functions for |TRUST_TOKENS_pst_v1|'s VOPRF construction which uses P-384.
+int voprf_pst1_generate_key(CBB *out_private, CBB *out_public);
+int voprf_pst1_derive_key_from_secret(CBB *out_private, CBB *out_public,
+                                      const uint8_t *secret, size_t secret_len);
+int voprf_pst1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key,
+                                     const uint8_t *in, size_t len);
+int voprf_pst1_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key,
+                                     const uint8_t *in, size_t len);
+STACK_OF(TRUST_TOKEN_PRETOKEN) *voprf_pst1_blind(CBB *cbb, size_t count,
+                                                 int include_message,
+                                                 const uint8_t *msg,
+                                                 size_t msg_len);
+int voprf_pst1_sign(const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                    size_t num_requested, size_t num_to_issue,
+                    uint8_t private_metadata);
+OPENSSL_EXPORT int voprf_pst1_sign_with_proof_scalar_for_testing(
+    const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs, size_t num_requested,
+    size_t num_to_issue, uint8_t private_metadata,
+    const uint8_t *proof_scalar_buf, size_t proof_scalar_len);
+STACK_OF(TRUST_TOKEN) *voprf_pst1_unblind(
+    const TRUST_TOKEN_CLIENT_KEY *key,
+    const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
+    uint32_t key_id);
+int voprf_pst1_read(const TRUST_TOKEN_ISSUER_KEY *key,
+                    uint8_t out_nonce[TRUST_TOKEN_NONCE_SIZE],
+                    uint8_t *out_private_metadata, const uint8_t *token,
+                    size_t token_len, int include_message, const uint8_t *msg,
+                    size_t msg_len);
+
 
 // Trust Tokens internals.
 
diff --git a/src/crypto/trust_token/pmbtoken.c b/src/crypto/trust_token/pmbtoken.c
index 2e25cf5..dcb9466 100644
--- a/src/crypto/trust_token/pmbtoken.c
+++ b/src/crypto/trust_token/pmbtoken.c
@@ -944,17 +944,14 @@
     return NULL;
   }
 
-  int ok = 0;
-  STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
-  if (ret == NULL) {
-    return NULL;
-  }
-
   if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
       count > ((size_t)-1) / sizeof(EC_SCALAR)) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
-    return 0;
+    return NULL;
   }
+
+  int ok = 0;
+  STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
   EC_RAW_POINT *Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
   EC_RAW_POINT *Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
   EC_RAW_POINT *Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
@@ -962,11 +959,12 @@
   EC_SCALAR *es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
   CBB batch_cbb;
   CBB_zero(&batch_cbb);
-  if (!Tps ||
-      !Sps ||
-      !Wps ||
-      !Wsps ||
-      !es ||
+  if (ret == NULL ||
+      Tps == NULL ||
+      Sps == NULL ||
+      Wps == NULL ||
+      Wsps == NULL ||
+      es == NULL ||
       !CBB_init(&batch_cbb, 0) ||
       !point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
       !point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
@@ -1510,3 +1508,177 @@
          ec_point_to_bytes(pmbtoken_exp2_method.group, &h,
                            POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97;
 }
+
+// PMBTokens PST v1.
+
+static int pmbtoken_pst1_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
+                                const uint8_t t[TRUST_TOKEN_NONCE_SIZE]) {
+  const uint8_t kHashTLabel[] = "PMBTokens PST V1 HashT";
+  return ec_hash_to_curve_p384_xmd_sha384_sswu(
+      group, out, kHashTLabel, sizeof(kHashTLabel), t, TRUST_TOKEN_NONCE_SIZE);
+}
+
+static int pmbtoken_pst1_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
+                                const EC_AFFINE *t,
+                                const uint8_t s[TRUST_TOKEN_NONCE_SIZE]) {
+  const uint8_t kHashSLabel[] = "PMBTokens PST V1 HashS";
+  int ret = 0;
+  CBB cbb;
+  uint8_t *buf = NULL;
+  size_t len;
+  if (!CBB_init(&cbb, 0) ||
+      !point_to_cbb(&cbb, group, t) ||
+      !CBB_add_bytes(&cbb, s, TRUST_TOKEN_NONCE_SIZE) ||
+      !CBB_finish(&cbb, &buf, &len) ||
+      !ec_hash_to_curve_p384_xmd_sha384_sswu(
+          group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  OPENSSL_free(buf);
+  CBB_cleanup(&cbb);
+  return ret;
+}
+
+static int pmbtoken_pst1_hash_c(const EC_GROUP *group, EC_SCALAR *out,
+                                uint8_t *buf, size_t len) {
+  const uint8_t kHashCLabel[] = "PMBTokens PST V1 HashC";
+  return ec_hash_to_scalar_p384_xmd_sha384(
+      group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
+}
+
+static int pmbtoken_pst1_hash_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
+                                        uint8_t *buf, size_t len) {
+  const uint8_t kHashLabel[] = "PMBTokens PST V1 HashToScalar";
+  return ec_hash_to_scalar_p384_xmd_sha384(
+      group, out, kHashLabel, sizeof(kHashLabel), buf, len);
+}
+
+static int pmbtoken_pst1_ok = 0;
+static PMBTOKEN_METHOD pmbtoken_pst1_method;
+static CRYPTO_once_t pmbtoken_pst1_method_once = CRYPTO_ONCE_INIT;
+
+static void pmbtoken_pst1_init_method_impl(void) {
+  // This is the output of |ec_hash_to_scalar_p384_xmd_sha384| with DST
+  // "PMBTokens PST V1 HashH" and message "generator".
+  static const uint8_t kH[] = {
+      0x04, 0x4c, 0xfa, 0xd4, 0x33, 0x6d, 0x8c, 0x4e, 0x18, 0xce, 0x1a,
+      0x82, 0x7b, 0x53, 0x8c, 0xf8, 0x63, 0x18, 0xe5, 0xa3, 0x96, 0x0d,
+      0x05, 0xde, 0xf4, 0x83, 0xa7, 0xd8, 0xde, 0x9c, 0x50, 0x81, 0x38,
+      0xc9, 0x38, 0x25, 0xa3, 0x70, 0x97, 0xc1, 0x1c, 0x33, 0x2e, 0x83,
+      0x68, 0x64, 0x9c, 0x53, 0x73, 0xc3, 0x03, 0xc1, 0xa9, 0xd8, 0x92,
+      0xa2, 0x32, 0xf4, 0x22, 0x40, 0x07, 0x2d, 0x9b, 0x6f, 0xab, 0xff,
+      0x2a, 0x92, 0x03, 0xb1, 0x73, 0x09, 0x1a, 0x6a, 0x4a, 0xc2, 0x4c,
+      0xac, 0x13, 0x59, 0xf4, 0x28, 0x0e, 0x78, 0x69, 0xa5, 0xdf, 0x0d,
+      0x74, 0xeb, 0x14, 0xca, 0x8a, 0x32, 0xbb, 0xd3, 0x91
+  };
+
+  pmbtoken_pst1_ok = pmbtoken_init_method(
+      &pmbtoken_pst1_method, NID_secp384r1, kH, sizeof(kH),
+      pmbtoken_pst1_hash_t, pmbtoken_pst1_hash_s, pmbtoken_pst1_hash_c,
+      pmbtoken_pst1_hash_to_scalar, 0);
+}
+
+static int pmbtoken_pst1_init_method(void) {
+  CRYPTO_once(&pmbtoken_pst1_method_once, pmbtoken_pst1_init_method_impl);
+  if (!pmbtoken_pst1_ok) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  return 1;
+}
+
+int pmbtoken_pst1_generate_key(CBB *out_private, CBB *out_public) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+
+  return pmbtoken_generate_key(&pmbtoken_pst1_method, out_private, out_public);
+}
+
+
+int pmbtoken_pst1_derive_key_from_secret(CBB *out_private, CBB *out_public,
+                                         const uint8_t *secret,
+                                         size_t secret_len) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+
+  return pmbtoken_derive_key_from_secret(&pmbtoken_pst1_method, out_private,
+                                         out_public, secret, secret_len);
+}
+
+int pmbtoken_pst1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key,
+                                        const uint8_t *in, size_t len) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+  return pmbtoken_client_key_from_bytes(&pmbtoken_pst1_method, key, in, len);
+}
+
+int pmbtoken_pst1_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key,
+                                        const uint8_t *in, size_t len) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+  return pmbtoken_issuer_key_from_bytes(&pmbtoken_pst1_method, key, in, len);
+}
+
+STACK_OF(TRUST_TOKEN_PRETOKEN) *pmbtoken_pst1_blind(CBB *cbb, size_t count,
+                                                    int include_message,
+                                                    const uint8_t *msg,
+                                                    size_t msg_len) {
+  if (!pmbtoken_pst1_init_method()) {
+    return NULL;
+  }
+  return pmbtoken_blind(&pmbtoken_pst1_method, cbb, count, include_message, msg,
+                        msg_len);
+}
+
+int pmbtoken_pst1_sign(const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                       size_t num_requested, size_t num_to_issue,
+                       uint8_t private_metadata) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+  return pmbtoken_sign(&pmbtoken_pst1_method, key, cbb, cbs, num_requested,
+                       num_to_issue, private_metadata);
+}
+
+STACK_OF(TRUST_TOKEN) *pmbtoken_pst1_unblind(
+    const TRUST_TOKEN_CLIENT_KEY *key,
+    const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
+    uint32_t key_id) {
+  if (!pmbtoken_pst1_init_method()) {
+    return NULL;
+  }
+  return pmbtoken_unblind(&pmbtoken_pst1_method, key, pretokens, cbs, count,
+                          key_id);
+}
+
+int pmbtoken_pst1_read(const TRUST_TOKEN_ISSUER_KEY *key,
+                       uint8_t out_nonce[TRUST_TOKEN_NONCE_SIZE],
+                       uint8_t *out_private_metadata, const uint8_t *token,
+                       size_t token_len, int include_message,
+                       const uint8_t *msg, size_t msg_len) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+  return pmbtoken_read(&pmbtoken_pst1_method, key, out_nonce,
+                       out_private_metadata, token, token_len, include_message,
+                       msg, msg_len);
+}
+
+int pmbtoken_pst1_get_h_for_testing(uint8_t out[97]) {
+  if (!pmbtoken_pst1_init_method()) {
+    return 0;
+  }
+  EC_AFFINE h;
+  return ec_jacobian_to_affine(pmbtoken_pst1_method.group, &h,
+                               &pmbtoken_pst1_method.h) &&
+         ec_point_to_bytes(pmbtoken_pst1_method.group, &h,
+                           POINT_CONVERSION_UNCOMPRESSED, out, 97) == 97;
+}
diff --git a/src/crypto/trust_token/trust_token.c b/src/crypto/trust_token/trust_token.c
index 7cccf1a..93172c3 100644
--- a/src/crypto/trust_token/trust_token.c
+++ b/src/crypto/trust_token/trust_token.c
@@ -78,6 +78,41 @@
   return &kMethod;
 }
 
+const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_voprf(void) {
+  static const TRUST_TOKEN_METHOD kMethod = {
+      voprf_pst1_generate_key,
+      voprf_pst1_derive_key_from_secret,
+      voprf_pst1_client_key_from_bytes,
+      voprf_pst1_issuer_key_from_bytes,
+      voprf_pst1_blind,
+      voprf_pst1_sign,
+      voprf_pst1_unblind,
+      voprf_pst1_read,
+      0, /* has_private_metadata */
+      6, /* max_keys */
+      0, /* has_srr */
+  };
+  return &kMethod;
+}
+
+const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_pmb(void) {
+  static const TRUST_TOKEN_METHOD kMethod = {
+      pmbtoken_pst1_generate_key,
+      pmbtoken_pst1_derive_key_from_secret,
+      pmbtoken_pst1_client_key_from_bytes,
+      pmbtoken_pst1_issuer_key_from_bytes,
+      pmbtoken_pst1_blind,
+      pmbtoken_pst1_sign,
+      pmbtoken_pst1_unblind,
+      pmbtoken_pst1_read,
+      1, /* has_private_metadata */
+      3, /* max_keys */
+      0, /* has_srr */
+  };
+  return &kMethod;
+}
+
+
 void TRUST_TOKEN_PRETOKEN_free(TRUST_TOKEN_PRETOKEN *pretoken) {
   OPENSSL_free(pretoken);
 }
diff --git a/src/crypto/trust_token/trust_token_test.cc b/src/crypto/trust_token/trust_token_test.cc
index ae4eb5c..df679b6 100644
--- a/src/crypto/trust_token/trust_token_test.cc
+++ b/src/crypto/trust_token/trust_token_test.cc
@@ -292,11 +292,324 @@
   EXPECT_EQ(Bytes(h), Bytes(expected_bytes, expected_len));
 }
 
+// Test that H in |TRUST_TOKEN_pst_v1_pmb| was computed correctly.
+TEST(TrustTokenTest, HPST1) {
+  const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
+  ASSERT_TRUE(group);
+
+  const uint8_t kHGen[] = "generator";
+  const uint8_t kHLabel[] = "PMBTokens PST V1 HashH";
+
+  bssl::UniquePtr<EC_POINT> expected_h(EC_POINT_new(group));
+  ASSERT_TRUE(expected_h);
+  ASSERT_TRUE(ec_hash_to_curve_p384_xmd_sha384_sswu(
+      group, &expected_h->raw, kHLabel, sizeof(kHLabel), kHGen, sizeof(kHGen)));
+  uint8_t expected_bytes[1 + 2 * EC_MAX_BYTES];
+  size_t expected_len =
+      EC_POINT_point2oct(group, expected_h.get(), POINT_CONVERSION_UNCOMPRESSED,
+                         expected_bytes, sizeof(expected_bytes), nullptr);
+
+  uint8_t h[97];
+  ASSERT_TRUE(pmbtoken_pst1_get_h_for_testing(h));
+  EXPECT_EQ(Bytes(h), Bytes(expected_bytes, expected_len));
+}
+
+static int ec_point_uncompressed_from_compressed(
+    const EC_GROUP *group, uint8_t out[EC_MAX_UNCOMPRESSED], size_t *out_len,
+    const uint8_t *in, size_t len) {
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group));
+  if (!point ||
+      !EC_POINT_oct2point(group, point.get(), in, len, nullptr)) {
+    return 0;
+  }
+
+  *out_len =
+      EC_POINT_point2oct(group, point.get(), POINT_CONVERSION_UNCOMPRESSED, out,
+                         EC_MAX_UNCOMPRESSED, nullptr);
+  return 1;
+}
+
+static bool setup_voprf_test_key(const EC_GROUP *group,
+                                 TRUST_TOKEN_ISSUER_KEY *out) {
+  static const uint8_t kPrivateKey[] = {
+      0x05, 0x16, 0x46, 0xb9, 0xe6, 0xe7, 0xa7, 0x1a, 0xe2, 0x7c, 0x1e, 0x1d,
+      0x0b, 0x87, 0xb4, 0x38, 0x1d, 0xb6, 0xd3, 0x59, 0x5e, 0xee, 0xb1, 0xad,
+      0xb4, 0x15, 0x79, 0xad, 0xbf, 0x99, 0x2f, 0x42, 0x78, 0xf9, 0x01, 0x6e,
+      0xaf, 0xc9, 0x44, 0xed, 0xaa, 0x2b, 0x43, 0x18, 0x35, 0x81, 0x77, 0x9d
+  };
+
+  static const uint8_t kPublicKey[] = {
+      0x03, 0x1d, 0x68, 0x96, 0x86, 0xc6, 0x11, 0x99, 0x1b, 0x55,
+      0xf1, 0xa1, 0xd8, 0xf4, 0x30, 0x5c, 0xcd, 0x6c, 0xb7, 0x19,
+      0x44, 0x6f, 0x66, 0x0a, 0x30, 0xdb, 0x61, 0xb7, 0xaa, 0x87,
+      0xb4, 0x6a, 0xcf, 0x59, 0xb7, 0xc0, 0xd4, 0xa9, 0x07, 0x7b,
+      0x3d, 0xa2, 0x1c, 0x25, 0xdd, 0x48, 0x22, 0x29, 0xa0
+  };
+
+  if (!ec_scalar_from_bytes(group, &out->xs, kPrivateKey,
+                            sizeof(kPrivateKey))) {
+    return false;
+  }
+
+  bssl::UniquePtr<EC_POINT> pub(EC_POINT_new(group));
+  return pub &&
+         EC_POINT_oct2point(group, pub.get(), kPublicKey, sizeof(kPublicKey),
+                            nullptr) &&
+         ec_jacobian_to_affine(group, &out->pubs, &pub->raw);
+}
+
+TEST(TrustTokenTest, PSTV1VOPRFTestVector1) {
+  const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
+  TRUST_TOKEN_ISSUER_KEY key;
+  ASSERT_TRUE(setup_voprf_test_key(group, &key));
+
+  static const uint8_t kBlindedElement[] = {
+      0x02, 0xd3, 0x38, 0xc0, 0x5c, 0xbe, 0xcb, 0x82, 0xde, 0x13,
+      0xd6, 0x70, 0x0f, 0x09, 0xcb, 0x61, 0x19, 0x05, 0x43, 0xa7,
+      0xb7, 0xe2, 0xc6, 0xcd, 0x4f, 0xca, 0x56, 0x88, 0x7e, 0x56,
+      0x4e, 0xa8, 0x26, 0x53, 0xb2, 0x7f, 0xda, 0xd3, 0x83, 0x99,
+      0x5e, 0xa6, 0xd0, 0x2c, 0xf2, 0x6d, 0x0e, 0x24, 0xd9
+  };
+
+  static const uint8_t kEvaluatedElement[] = {
+      0x02, 0xa7, 0xbb, 0xa5, 0x89, 0xb3, 0xe8, 0x67, 0x2a, 0xa1,
+      0x9e, 0x8f, 0xd2, 0x58, 0xde, 0x2e, 0x6a, 0xae, 0x20, 0x10,
+      0x1c, 0x8d, 0x76, 0x12, 0x46, 0xde, 0x97, 0xa6, 0xb5, 0xee,
+      0x9c, 0xf1, 0x05, 0xfe, 0xbc, 0xe4, 0x32, 0x7a, 0x32, 0x62,
+      0x55, 0xa3, 0xc6, 0x04, 0xf6, 0x3f, 0x60, 0x0e, 0xf6
+  };
+
+  static const uint8_t kProof[] = {
+      0xbf, 0xc6, 0xcf, 0x38, 0x59, 0x12, 0x7f, 0x5f, 0xe2, 0x55, 0x48, 0x85,
+      0x98, 0x56, 0xd6, 0xb7, 0xfa, 0x1c, 0x74, 0x59, 0xf0, 0xba, 0x57, 0x12,
+      0xa8, 0x06, 0xfc, 0x09, 0x1a, 0x30, 0x00, 0xc4, 0x2d, 0x8b, 0xa3, 0x4f,
+      0xf4, 0x5f, 0x32, 0xa5, 0x2e, 0x40, 0x53, 0x3e, 0xfd, 0x2a, 0x03, 0xbc,
+      0x87, 0xf3, 0xbf, 0x4f, 0x9f, 0x58, 0x02, 0x82, 0x97, 0xcc, 0xb9, 0xcc,
+      0xb1, 0x8a, 0xe7, 0x18, 0x2b, 0xcd, 0x1e, 0xf2, 0x39, 0xdf, 0x77, 0xe3,
+      0xbe, 0x65, 0xef, 0x14, 0x7f, 0x3a, 0xcf, 0x8b, 0xc9, 0xcb, 0xfc, 0x55,
+      0x24, 0xb7, 0x02, 0x26, 0x34, 0x14, 0xf0, 0x43, 0xe3, 0xb7, 0xca, 0x2e
+  };
+
+  static const uint8_t kProofScalar[] = {
+      0x80, 0x3d, 0x95, 0x5f, 0x0e, 0x07, 0x3a, 0x04, 0xaa, 0x5d, 0x92, 0xb3,
+      0xfb, 0x73, 0x9f, 0x56, 0xf9, 0xdb, 0x00, 0x12, 0x66, 0x67, 0x7f, 0x62,
+      0xc0, 0x95, 0x02, 0x1d, 0xb0, 0x18, 0xcd, 0x8c, 0xbb, 0x55, 0x94, 0x1d,
+      0x40, 0x73, 0x69, 0x8c, 0xe4, 0x5c, 0x40, 0x5d, 0x13, 0x48, 0xb7, 0xb1
+  };
+
+  uint8_t blinded_buf[EC_MAX_UNCOMPRESSED];
+  size_t blinded_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, blinded_buf, &blinded_len, kBlindedElement,
+      sizeof(kBlindedElement)));
+
+  CBS sign_input;
+  CBS_init(&sign_input, blinded_buf, blinded_len);
+  bssl::ScopedCBB response;
+  ASSERT_TRUE(CBB_init(response.get(), 0));
+  ASSERT_TRUE(voprf_pst1_sign_with_proof_scalar_for_testing(
+      &key, response.get(), &sign_input, /*num_requested=*/1,
+      /*num_to_issue=*/1,
+      /*private_metadata=*/0, kProofScalar, sizeof(kProofScalar)));
+
+  uint8_t evaluated_buf[EC_MAX_UNCOMPRESSED];
+  size_t evaluated_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, evaluated_buf, &evaluated_len, kEvaluatedElement,
+      sizeof(kEvaluatedElement)));
+
+  bssl::ScopedCBB expected_response;
+  ASSERT_TRUE(CBB_init(expected_response.get(), 0));
+  ASSERT_TRUE(
+      CBB_add_bytes(expected_response.get(), evaluated_buf, evaluated_len));
+  ASSERT_TRUE(CBB_add_u16(expected_response.get(), sizeof(kProof)));
+  ASSERT_TRUE(CBB_add_bytes(expected_response.get(), kProof, sizeof(kProof)));
+  ASSERT_TRUE(CBB_flush(expected_response.get()));
+
+  ASSERT_EQ(Bytes(CBB_data(expected_response.get()),
+                  CBB_len(expected_response.get())),
+            Bytes(CBB_data(response.get()), CBB_len(response.get())));
+}
+
+TEST(TrustTokenTest, PSTV1VOPRFTestVector2) {
+  const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
+  TRUST_TOKEN_ISSUER_KEY key;
+  ASSERT_TRUE(setup_voprf_test_key(group, &key));
+
+  static const uint8_t kBlindedElement[] = {
+      0x02, 0xf2, 0x74, 0x69, 0xe0, 0x59, 0x88, 0x6f, 0x22, 0x1b,
+      0xe5, 0xf2, 0xcc, 0xa0, 0x3d, 0x2b, 0xdc, 0x61, 0xe5, 0x52,
+      0x21, 0x72, 0x1c, 0x3b, 0x3e, 0x56, 0xfc, 0x01, 0x2e, 0x36,
+      0xd3, 0x1a, 0xe5, 0xf8, 0xdc, 0x05, 0x81, 0x09, 0x59, 0x15,
+      0x56, 0xa6, 0xdb, 0xd3, 0xa8, 0xc6, 0x9c, 0x43, 0x3b
+  };
+
+  static const uint8_t kEvaluatedElement[] = {
+      0x03, 0xf1, 0x6f, 0x90, 0x39, 0x47, 0x03, 0x54, 0x00, 0xe9,
+      0x6b, 0x7f, 0x53, 0x1a, 0x38, 0xd4, 0xa0, 0x7a, 0xc8, 0x9a,
+      0x80, 0xf8, 0x9d, 0x86, 0xa1, 0xbf, 0x08, 0x9c, 0x52, 0x5a,
+      0x92, 0xc7, 0xf4, 0x73, 0x37, 0x29, 0xca, 0x30, 0xc5, 0x6c,
+      0xe7, 0x8b, 0x1a, 0xb4, 0xf7, 0xd9, 0x2d, 0xb8, 0xb4
+  };
+
+  static const uint8_t kProof[] = {
+      0xd0, 0x05, 0xd6, 0xda, 0xaa, 0xd7, 0x57, 0x14, 0x14, 0xc1, 0xe0,
+      0xc7, 0x5f, 0x7e, 0x57, 0xf2, 0x11, 0x3c, 0xa9, 0xf4, 0x60, 0x4e,
+      0x84, 0xbc, 0x90, 0xf9, 0xbe, 0x52, 0xda, 0x89, 0x6f, 0xff, 0x3b,
+      0xee, 0x49, 0x6d, 0xcd, 0xe2, 0xa5, 0x78, 0xae, 0x9d, 0xf3, 0x15,
+      0x03, 0x25, 0x85, 0xf8, 0x01, 0xfb, 0x21, 0xc6, 0x08, 0x0a, 0xc0,
+      0x56, 0x72, 0xb2, 0x91, 0xe5, 0x75, 0xa4, 0x02, 0x95, 0xb3, 0x06,
+      0xd9, 0x67, 0x71, 0x7b, 0x28, 0xe0, 0x8f, 0xcc, 0x8a, 0xd1, 0xca,
+      0xb4, 0x78, 0x45, 0xd1, 0x6a, 0xf7, 0x3b, 0x3e, 0x64, 0x3d, 0xdc,
+      0xc1, 0x91, 0x20, 0x8e, 0x71, 0xc6, 0x46, 0x30
+  };
+
+  static const uint8_t kProofScalar[] = {
+      0x80, 0x3d, 0x95, 0x5f, 0x0e, 0x07, 0x3a, 0x04, 0xaa, 0x5d, 0x92, 0xb3,
+      0xfb, 0x73, 0x9f, 0x56, 0xf9, 0xdb, 0x00, 0x12, 0x66, 0x67, 0x7f, 0x62,
+      0xc0, 0x95, 0x02, 0x1d, 0xb0, 0x18, 0xcd, 0x8c, 0xbb, 0x55, 0x94, 0x1d,
+      0x40, 0x73, 0x69, 0x8c, 0xe4, 0x5c, 0x40, 0x5d, 0x13, 0x48, 0xb7, 0xb1
+  };
+
+  uint8_t blinded_buf[EC_MAX_UNCOMPRESSED];
+  size_t blinded_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, blinded_buf, &blinded_len, kBlindedElement,
+      sizeof(kBlindedElement)));
+
+  CBS sign_input;
+  CBS_init(&sign_input, blinded_buf, blinded_len);
+  bssl::ScopedCBB response;
+  ASSERT_TRUE(CBB_init(response.get(), 0));
+  ASSERT_TRUE(voprf_pst1_sign_with_proof_scalar_for_testing(
+      &key, response.get(), &sign_input, /*num_requested=*/1,
+      /*num_to_issue=*/1,
+      /*private_metadata=*/0, kProofScalar, sizeof(kProofScalar)));
+
+  uint8_t evaluated_buf[EC_MAX_UNCOMPRESSED];
+  size_t evaluated_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, evaluated_buf, &evaluated_len, kEvaluatedElement,
+      sizeof(kEvaluatedElement)));
+
+  bssl::ScopedCBB expected_response;
+  ASSERT_TRUE(CBB_init(expected_response.get(), 0));
+  ASSERT_TRUE(
+      CBB_add_bytes(expected_response.get(), evaluated_buf, evaluated_len));
+  ASSERT_TRUE(CBB_add_u16(expected_response.get(), sizeof(kProof)));
+  ASSERT_TRUE(CBB_add_bytes(expected_response.get(), kProof, sizeof(kProof)));
+  ASSERT_TRUE(CBB_flush(expected_response.get()));
+
+  ASSERT_EQ(Bytes(CBB_data(expected_response.get()),
+                  CBB_len(expected_response.get())),
+            Bytes(CBB_data(response.get()), CBB_len(response.get())));
+}
+
+TEST(TrustTokenTest, PSTV1VOPRFTestVector3) {
+  const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1);
+  TRUST_TOKEN_ISSUER_KEY key;
+  ASSERT_TRUE(setup_voprf_test_key(group, &key));
+
+  static const uint8_t kBlindedElement1[] = {
+      0x02, 0xd3, 0x38, 0xc0, 0x5c, 0xbe, 0xcb, 0x82, 0xde, 0x13,
+      0xd6, 0x70, 0x0f, 0x09, 0xcb, 0x61, 0x19, 0x05, 0x43, 0xa7,
+      0xb7, 0xe2, 0xc6, 0xcd, 0x4f, 0xca, 0x56, 0x88, 0x7e, 0x56,
+      0x4e, 0xa8, 0x26, 0x53, 0xb2, 0x7f, 0xda, 0xd3, 0x83, 0x99,
+      0x5e, 0xa6, 0xd0, 0x2c, 0xf2, 0x6d, 0x0e, 0x24, 0xd9
+  };
+  static const uint8_t kBlindedElement2[] = {
+      0x02, 0xfa, 0x02, 0x47, 0x0d, 0x7f, 0x15, 0x10, 0x18, 0xb4,
+      0x1e, 0x82, 0x22, 0x3c, 0x32, 0xfa, 0xd8, 0x24, 0xde, 0x6a,
+      0xd4, 0xb5, 0xce, 0x9f, 0x8e, 0x9f, 0x98, 0x08, 0x3c, 0x9a,
+      0x72, 0x6d, 0xe9, 0xa1, 0xfc, 0x39, 0xd7, 0xa0, 0xcb, 0x6f,
+      0x4f, 0x18, 0x8d, 0xd9, 0xce, 0xa0, 0x14, 0x74, 0xcd
+  };
+
+  static const uint8_t kEvaluatedElement1[] = {
+      0x02, 0xa7, 0xbb, 0xa5, 0x89, 0xb3, 0xe8, 0x67, 0x2a, 0xa1,
+      0x9e, 0x8f, 0xd2, 0x58, 0xde, 0x2e, 0x6a, 0xae, 0x20, 0x10,
+      0x1c, 0x8d, 0x76, 0x12, 0x46, 0xde, 0x97, 0xa6, 0xb5, 0xee,
+      0x9c, 0xf1, 0x05, 0xfe, 0xbc, 0xe4, 0x32, 0x7a, 0x32, 0x62,
+      0x55, 0xa3, 0xc6, 0x04, 0xf6, 0x3f, 0x60, 0x0e, 0xf6
+  };
+
+  static const uint8_t kEvaluatedElement2[] = {
+      0x02, 0x8e, 0x9e, 0x11, 0x56, 0x25, 0xff, 0x4c, 0x2f, 0x07,
+      0xbf, 0x87, 0xce, 0x3f, 0xd7, 0x3f, 0xc7, 0x79, 0x94, 0xa7,
+      0xa0, 0xc1, 0xdf, 0x03, 0xd2, 0xa6, 0x30, 0xa3, 0xd8, 0x45,
+      0x93, 0x0e, 0x2e, 0x63, 0xa1, 0x65, 0xb1, 0x14, 0xd9, 0x8f,
+      0xe3, 0x4e, 0x61, 0xb6, 0x8d, 0x23, 0xc0, 0xb5, 0x0a
+  };
+
+  static const uint8_t kProof[] = {
+      0x6d, 0x8d, 0xcb, 0xd2, 0xfc, 0x95, 0x55, 0x0a, 0x02, 0x21, 0x1f,
+      0xb7, 0x8a, 0xfd, 0x01, 0x39, 0x33, 0xf3, 0x07, 0xd2, 0x1e, 0x7d,
+      0x85, 0x5b, 0x0b, 0x1e, 0xd0, 0xaf, 0x78, 0x07, 0x6d, 0x81, 0x37,
+      0xad, 0x8b, 0x0a, 0x1b, 0xfa, 0x05, 0x67, 0x6d, 0x32, 0x52, 0x49,
+      0xc1, 0xdb, 0xb9, 0xa5, 0x2b, 0xd8, 0x1b, 0x1c, 0x2b, 0x7b, 0x0e,
+      0xfc, 0x77, 0xcf, 0x7b, 0x27, 0x8e, 0x1c, 0x94, 0x7f, 0x62, 0x83,
+      0xf1, 0xd4, 0xc5, 0x13, 0x05, 0x3f, 0xc0, 0xad, 0x19, 0xe0, 0x26,
+      0xfb, 0x0c, 0x30, 0x65, 0x4b, 0x53, 0xd9, 0xce, 0xa4, 0xb8, 0x7b,
+      0x03, 0x72, 0x71, 0xb5, 0xd2, 0xe2, 0xd0, 0xea
+  };
+
+  static const uint8_t kProofScalar[] = {
+      0xa0, 0x97, 0xe7, 0x22, 0xed, 0x24, 0x27, 0xde, 0x86, 0x96,
+      0x69, 0x10, 0xac, 0xba, 0x9f, 0x5c, 0x35, 0x0e, 0x80, 0x40,
+      0xf8, 0x28, 0xbf, 0x6c, 0xec, 0xa2, 0x74, 0x05, 0x42, 0x0c,
+      0xdf, 0x3d, 0x63, 0xcb, 0x3a, 0xef, 0x00, 0x5f, 0x40, 0xba,
+      0x51, 0x94, 0x3c, 0x80, 0x26, 0x87, 0x79, 0x63
+  };
+
+  uint8_t blinded_buf[2*EC_MAX_UNCOMPRESSED];
+  size_t blinded_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, blinded_buf, &blinded_len, kBlindedElement1,
+      sizeof(kBlindedElement1)));
+  size_t offset = blinded_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, blinded_buf + offset, &blinded_len, kBlindedElement2,
+      sizeof(kBlindedElement2)));
+
+  CBS sign_input;
+  CBS_init(&sign_input, blinded_buf, offset + blinded_len);
+  bssl::ScopedCBB response;
+  ASSERT_TRUE(CBB_init(response.get(), 0));
+  ASSERT_TRUE(voprf_pst1_sign_with_proof_scalar_for_testing(
+      &key, response.get(), &sign_input, /*num_requested=*/2,
+      /*num_to_issue=*/2,
+      /*private_metadata=*/0, kProofScalar, sizeof(kProofScalar)));
+
+  uint8_t evaluated_buf[2 * EC_MAX_UNCOMPRESSED];
+  size_t evaluated_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, evaluated_buf, &evaluated_len, kEvaluatedElement1,
+      sizeof(kEvaluatedElement1)));
+  offset = evaluated_len;
+  ASSERT_TRUE(ec_point_uncompressed_from_compressed(
+      group, evaluated_buf + offset, &evaluated_len, kEvaluatedElement2,
+      sizeof(kEvaluatedElement2)));
+
+  bssl::ScopedCBB expected_response;
+  ASSERT_TRUE(CBB_init(expected_response.get(), 0));
+  ASSERT_TRUE(CBB_add_bytes(expected_response.get(), evaluated_buf,
+                            offset + evaluated_len));
+  ASSERT_TRUE(CBB_add_u16(expected_response.get(), sizeof(kProof)));
+  ASSERT_TRUE(CBB_add_bytes(expected_response.get(), kProof, sizeof(kProof)));
+  ASSERT_TRUE(CBB_flush(expected_response.get()));
+
+  ASSERT_EQ(Bytes(CBB_data(expected_response.get()),
+                  CBB_len(expected_response.get())),
+            Bytes(CBB_data(response.get()), CBB_len(response.get())));
+}
+
 static std::vector<const TRUST_TOKEN_METHOD *> AllMethods() {
   return {
     TRUST_TOKEN_experiment_v1(),
     TRUST_TOKEN_experiment_v2_voprf(),
-    TRUST_TOKEN_experiment_v2_pmb()
+    TRUST_TOKEN_experiment_v2_pmb(),
+    TRUST_TOKEN_pst_v1_voprf(),
+    TRUST_TOKEN_pst_v1_pmb()
   };
 }
 
@@ -773,7 +1086,8 @@
   if (method() == TRUST_TOKEN_experiment_v1()) {
     token_length += 4;
   }
-  if (method() == TRUST_TOKEN_experiment_v2_voprf()) {
+  if (method() == TRUST_TOKEN_experiment_v2_voprf() ||
+      method() == TRUST_TOKEN_pst_v1_voprf()) {
     token_length = 1 + 2 * BN_num_bytes(&group->field);
   }
   for (size_t i = 0; i < count; i++) {
@@ -841,7 +1155,8 @@
   if (method() == TRUST_TOKEN_experiment_v1()) {
     token_length += 4;
   }
-  if (method() == TRUST_TOKEN_experiment_v2_voprf()) {
+  if (method() == TRUST_TOKEN_experiment_v2_voprf() ||
+      method() == TRUST_TOKEN_pst_v1_voprf()) {
     token_length = 1 + 2 * BN_num_bytes(&group->field);
   }
   for (size_t i = 0; i < count; i++) {
diff --git a/src/crypto/trust_token/voprf.c b/src/crypto/trust_token/voprf.c
index adf02a7..aa7df8e 100644
--- a/src/crypto/trust_token/voprf.c
+++ b/src/crypto/trust_token/voprf.c
@@ -63,18 +63,24 @@
 
 static int cbb_add_point(CBB *out, const EC_GROUP *group,
                          const EC_AFFINE *point) {
-  size_t len = ec_point_byte_len(group,  POINT_CONVERSION_UNCOMPRESSED);
-  if (len == 0) {
-    return 0;
-  }
-
   uint8_t *p;
+  size_t len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED);
   return CBB_add_space(out, &p, len) &&
          ec_point_to_bytes(group, point, POINT_CONVERSION_UNCOMPRESSED, p,
                            len) == len &&
          CBB_flush(out);
 }
 
+static int cbb_serialize_point(CBB *out, const EC_GROUP *group,
+                               const EC_AFFINE *point) {
+  uint8_t *p;
+  size_t len = ec_point_byte_len(group, POINT_CONVERSION_COMPRESSED);
+  return CBB_add_u16(out, len) && CBB_add_space(out, &p, len) &&
+         ec_point_to_bytes(group, point, POINT_CONVERSION_COMPRESSED, p, len) ==
+             len &&
+         CBB_flush(out);
+}
+
 static int cbs_get_point(CBS *cbs, const EC_GROUP *group, EC_AFFINE *out) {
   CBS child;
   size_t plen = 1 + 2 * BN_num_bytes(&group->field);
@@ -299,6 +305,30 @@
   return ok;
 }
 
+static int hash_to_scalar_challenge(const VOPRF_METHOD *method, EC_SCALAR *out,
+                                    const EC_AFFINE *Bm, const EC_AFFINE *a0,
+                                    const EC_AFFINE *a1, const EC_AFFINE *a2,
+                                    const EC_AFFINE *a3) {
+  static const uint8_t kChallengeLabel[] = "Challenge";
+
+  CBB cbb;
+  uint8_t transcript[5 * EC_MAX_COMPRESSED + 2 + sizeof(kChallengeLabel) - 1];
+  size_t len;
+  if (!CBB_init_fixed(&cbb, transcript, sizeof(transcript)) ||
+      !cbb_serialize_point(&cbb, method->group, Bm) ||
+      !cbb_serialize_point(&cbb, method->group, a0) ||
+      !cbb_serialize_point(&cbb, method->group, a1) ||
+      !cbb_serialize_point(&cbb, method->group, a2) ||
+      !cbb_serialize_point(&cbb, method->group, a3) ||
+      !CBB_add_bytes(&cbb, kChallengeLabel, sizeof(kChallengeLabel) - 1) ||
+      !CBB_finish(&cbb, NULL, &len) ||
+      !method->hash_to_scalar(method->group, out, transcript, len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
 static int hash_to_scalar_batch(const VOPRF_METHOD *method, EC_SCALAR *out,
                                 const CBB *points, size_t index) {
   static const uint8_t kDLEQBatchLabel[] = "DLEQ BATCH";
@@ -455,9 +485,9 @@
   return 1;
 }
 
-static int voprf_sign(const VOPRF_METHOD *method,
-                      const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
-                      size_t num_requested, size_t num_to_issue) {
+static int voprf_sign_tt(const VOPRF_METHOD *method,
+                         const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                         size_t num_requested, size_t num_to_issue) {
   const EC_GROUP *group = method->group;
   if (num_requested < num_to_issue) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
@@ -553,7 +583,7 @@
   return ret;
 }
 
-static STACK_OF(TRUST_TOKEN) *voprf_unblind(
+static STACK_OF(TRUST_TOKEN) *voprf_unblind_tt(
     const VOPRF_METHOD *method, const TRUST_TOKEN_CLIENT_KEY *key,
     const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
     uint32_t key_id) {
@@ -563,25 +593,23 @@
     return NULL;
   }
 
-  int ok = 0;
-  STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
-  if (ret == NULL) {
-    return NULL;
-  }
-
   if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
       count > ((size_t)-1) / sizeof(EC_SCALAR)) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
-    return 0;
+    return NULL;
   }
+
+  int ok = 0;
+  STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
   EC_RAW_POINT *BTs = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
   EC_RAW_POINT *Zs = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
   EC_SCALAR *es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
   CBB batch_cbb;
   CBB_zero(&batch_cbb);
-  if (!BTs ||
-      !Zs ||
-      !es ||
+  if (ret == NULL ||
+      BTs == NULL ||
+      Zs == NULL ||
+      es == NULL ||
       !CBB_init(&batch_cbb, 0) ||
       !cbb_add_point(&batch_cbb, method->group, &key->pubs)) {
     goto err;
@@ -675,6 +703,397 @@
   return ret;
 }
 
+static void sha384_update_u16(SHA512_CTX *ctx, uint16_t v) {
+  uint8_t buf[2] = {v >> 8, v & 0xff};
+  SHA384_Update(ctx, buf, 2);
+}
+
+static void sha384_update_point_with_length(
+     SHA512_CTX *ctx, const EC_GROUP *group, const EC_AFFINE *point) {
+  uint8_t buf[EC_MAX_COMPRESSED];
+  size_t len = ec_point_to_bytes(group, point, POINT_CONVERSION_COMPRESSED,
+                                 buf, sizeof(buf));
+  assert(len > 0);
+  sha384_update_u16(ctx, (uint16_t)len);
+  SHA384_Update(ctx, buf, len);
+}
+
+static int compute_composite_seed(const VOPRF_METHOD *method,
+                                  uint8_t out[SHA384_DIGEST_LENGTH],
+                                  const EC_AFFINE *pub) {
+  const EC_GROUP *group = method->group;
+  static const uint8_t kSeedDST[] = "Seed-OPRFV1-\x01-P384-SHA384";
+
+  SHA512_CTX hash_ctx;
+  SHA384_Init(&hash_ctx);
+  sha384_update_point_with_length(&hash_ctx, group, pub);
+  sha384_update_u16(&hash_ctx, sizeof(kSeedDST) - 1);
+  SHA384_Update(&hash_ctx, kSeedDST, sizeof(kSeedDST) - 1);
+  SHA384_Final(out, &hash_ctx);
+
+  return 1;
+}
+
+static int compute_composite_element(const VOPRF_METHOD *method,
+                                     uint8_t seed[SHA384_DIGEST_LENGTH],
+                                     EC_SCALAR *di, size_t index,
+                                     const EC_AFFINE *C, const EC_AFFINE *D) {
+  static const uint8_t kCompositeLabel[] = "Composite";
+  const EC_GROUP *group = method->group;
+
+  if (index > UINT16_MAX) {
+    return 0;
+  }
+
+  CBB cbb;
+  uint8_t transcript[2 + SHA384_DIGEST_LENGTH + 2 + 2 * EC_MAX_COMPRESSED +
+                     sizeof(kCompositeLabel) - 1];
+  size_t len;
+  if (!CBB_init_fixed(&cbb, transcript, sizeof(transcript)) ||
+      !CBB_add_u16(&cbb, SHA384_DIGEST_LENGTH) ||
+      !CBB_add_bytes(&cbb, seed, SHA384_DIGEST_LENGTH) ||
+      !CBB_add_u16(&cbb, index) ||
+      !cbb_serialize_point(&cbb, group, C) ||
+      !cbb_serialize_point(&cbb, group, D) ||
+      !CBB_add_bytes(&cbb, kCompositeLabel,
+                     sizeof(kCompositeLabel) - 1) ||
+      !CBB_finish(&cbb, NULL, &len) ||
+      !method->hash_to_scalar(method->group, di, transcript, len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int generate_proof(const VOPRF_METHOD *method, CBB *cbb,
+                          const TRUST_TOKEN_ISSUER_KEY *priv,
+                          const EC_SCALAR *r, const EC_RAW_POINT *M,
+                          const EC_RAW_POINT *Z) {
+  const EC_GROUP *group = method->group;
+
+  enum {
+    idx_M,
+    idx_Z,
+    idx_t2,
+    idx_t3,
+    num_idx,
+  };
+  EC_RAW_POINT jacobians[num_idx];
+
+  if (!ec_point_mul_scalar_base(group, &jacobians[idx_t2], r) ||
+      !ec_point_mul_scalar(group, &jacobians[idx_t3], M, r)) {
+    return 0;
+  }
+
+
+  EC_AFFINE affines[num_idx];
+  jacobians[idx_M] = *M;
+  jacobians[idx_Z] = *Z;
+  if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
+    return 0;
+  }
+
+  EC_SCALAR c;
+  if (!hash_to_scalar_challenge(method, &c, &priv->pubs, &affines[idx_M],
+                                &affines[idx_Z], &affines[idx_t2],
+                                &affines[idx_t3])) {
+    return 0;
+  }
+
+  EC_SCALAR c_mont;
+  ec_scalar_to_montgomery(group, &c_mont, &c);
+
+  // s = r - c*xs
+  EC_SCALAR s;
+  ec_scalar_mul_montgomery(group, &s, &priv->xs, &c_mont);
+  ec_scalar_sub(group, &s, r, &s);
+
+  // Store DLEQ proof in transcript.
+  if (!scalar_to_cbb(cbb, group, &c) ||
+      !scalar_to_cbb(cbb, group, &s)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int verify_proof(const VOPRF_METHOD *method, CBS *cbs,
+                        const TRUST_TOKEN_CLIENT_KEY *pub,
+                        const EC_RAW_POINT *M, const EC_RAW_POINT *Z) {
+  const EC_GROUP *group = method->group;
+
+  enum {
+    idx_M,
+    idx_Z,
+    idx_t2,
+    idx_t3,
+    num_idx,
+  };
+  EC_RAW_POINT jacobians[num_idx];
+
+  EC_SCALAR c, s;
+  if (!scalar_from_cbs(cbs, group, &c) ||
+      !scalar_from_cbs(cbs, group, &s)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
+    return 0;
+  }
+
+  EC_RAW_POINT pubs;
+  ec_affine_to_jacobian(group, &pubs, &pub->pubs);
+  if (!ec_point_mul_scalar_public(group, &jacobians[idx_t2], &s, &pubs,
+                                  &c) ||
+      !mul_public_2(group, &jacobians[idx_t3], M, &s, Z, &c)) {
+    return 0;
+  }
+
+  EC_AFFINE affines[num_idx];
+  jacobians[idx_M] = *M;
+  jacobians[idx_Z] = *Z;
+  if (!ec_jacobian_to_affine_batch(group, affines, jacobians, num_idx)) {
+    return 0;
+  }
+
+  EC_SCALAR expected_c;
+  if (!hash_to_scalar_challenge(method, &expected_c, &pub->pubs,
+                                &affines[idx_M], &affines[idx_Z],
+                                &affines[idx_t2], &affines[idx_t3])) {
+    return 0;
+  }
+
+  // c == expected_c
+  if (!ec_scalar_equal_vartime(group, &c, &expected_c)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_INVALID_PROOF);
+    return 0;
+  }
+
+  return 1;
+}
+
+static int voprf_sign_impl(const VOPRF_METHOD *method,
+                           const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb,
+                           CBS *cbs, size_t num_requested, size_t num_to_issue,
+                           const EC_SCALAR *proof_scalar) {
+  const EC_GROUP *group = method->group;
+  if (num_requested < num_to_issue) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
+      num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  int ret = 0;
+  EC_RAW_POINT *BTs = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Zs = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
+  EC_SCALAR *dis = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
+  if (!BTs || !Zs || !dis) {
+    goto err;
+  }
+
+  uint8_t seed[SHA384_DIGEST_LENGTH];
+  if (!compute_composite_seed(method, seed, &key->pubs)) {
+    goto err;
+  }
+
+  // This implements the BlindEvaluateBatch as defined in section 4 of
+  // draft-robert-privacypass-batched-tokens-01, based on the constructions
+  // in draft-irtf-cfrg-voprf-21. To optimize the computation of the proof,
+  // the computation of di is done during the token signing and passed into
+  // the proof generation.
+  for (size_t i = 0; i < num_to_issue; i++) {
+    EC_AFFINE BT_affine, Z_affine;
+    EC_RAW_POINT BT, Z;
+    if (!cbs_get_point(cbs, group, &BT_affine)) {
+      OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
+      goto err;
+    }
+    ec_affine_to_jacobian(group, &BT, &BT_affine);
+    if (!ec_point_mul_scalar(group, &Z, &BT, &key->xs) ||
+        !ec_jacobian_to_affine(group, &Z_affine, &Z) ||
+        !cbb_add_point(cbb, group, &Z_affine)) {
+      goto err;
+    }
+    BTs[i] = BT;
+    Zs[i] = Z;
+    if (!compute_composite_element(method, seed, &dis[i], i, &BT_affine,
+                                   &Z_affine)) {
+      goto err;
+    }
+
+    if (!CBB_flush(cbb)) {
+      goto err;
+    }
+  }
+
+  EC_RAW_POINT M, Z;
+  if (!ec_point_mul_scalar_public_batch(group, &M,
+                                        /*g_scalar=*/NULL, BTs, dis,
+                                        num_to_issue) ||
+      !ec_point_mul_scalar(group, &Z, &M, &key->xs)) {
+    goto err;
+  }
+
+  CBB proof;
+  if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
+      !generate_proof(method, &proof, key, proof_scalar, &M, &Z) ||
+      !CBB_flush(cbb)) {
+    goto err;
+  }
+
+  // Skip over any unused requests.
+  size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
+  if (!CBS_skip(cbs, point_len * (num_requested - num_to_issue))) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  OPENSSL_free(BTs);
+  OPENSSL_free(Zs);
+  OPENSSL_free(dis);
+  return ret;
+}
+
+static int voprf_sign(const VOPRF_METHOD *method,
+                      const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                      size_t num_requested, size_t num_to_issue) {
+  EC_SCALAR proof_scalar;
+  if (!ec_random_nonzero_scalar(method->group, &proof_scalar,
+                                kDefaultAdditionalData)) {
+    return 0;
+  }
+
+  return voprf_sign_impl(method, key, cbb, cbs, num_requested, num_to_issue,
+                         &proof_scalar);
+}
+
+static int voprf_sign_with_proof_scalar_for_testing(
+    const VOPRF_METHOD *method, const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb,
+    CBS *cbs, size_t num_requested, size_t num_to_issue,
+    const uint8_t *proof_scalar_buf, size_t proof_scalar_len) {
+  EC_SCALAR proof_scalar;
+  if (!ec_scalar_from_bytes(method->group, &proof_scalar, proof_scalar_buf,
+                            proof_scalar_len)) {
+    return 0;
+  }
+  return voprf_sign_impl(method, key, cbb, cbs, num_requested, num_to_issue,
+                         &proof_scalar);
+}
+
+static STACK_OF(TRUST_TOKEN) *voprf_unblind(
+    const VOPRF_METHOD *method, const TRUST_TOKEN_CLIENT_KEY *key,
+    const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
+    uint32_t key_id) {
+  const EC_GROUP *group = method->group;
+  if (count > sk_TRUST_TOKEN_PRETOKEN_num(pretokens)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
+    return NULL;
+  }
+
+  if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
+      count > ((size_t)-1) / sizeof(EC_SCALAR)) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
+    return NULL;
+  }
+
+  int ok = 0;
+  STACK_OF(TRUST_TOKEN) *ret = sk_TRUST_TOKEN_new_null();
+  EC_RAW_POINT *BTs = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_RAW_POINT *Zs = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
+  EC_SCALAR *dis = OPENSSL_malloc(count * sizeof(EC_SCALAR));
+  if (ret == NULL || !BTs || !Zs || !dis) {
+    goto err;
+  }
+
+  uint8_t seed[SHA384_DIGEST_LENGTH];
+  if (!compute_composite_seed(method, seed, &key->pubs)) {
+    goto err;
+  }
+
+  for (size_t i = 0; i < count; i++) {
+    const TRUST_TOKEN_PRETOKEN *pretoken =
+        sk_TRUST_TOKEN_PRETOKEN_value(pretokens, i);
+
+    EC_AFFINE Z_affine;
+    if (!cbs_get_point(cbs, group, &Z_affine)) {
+      OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
+      goto err;
+    }
+
+    ec_affine_to_jacobian(group, &BTs[i], &pretoken->Tp);
+    ec_affine_to_jacobian(group, &Zs[i], &Z_affine);
+    if (!compute_composite_element(method, seed, &dis[i], i, &pretoken->Tp,
+                                   &Z_affine)) {
+      goto err;
+    }
+
+    // Unblind the token.
+    // pretoken->r is rinv.
+    EC_RAW_POINT N;
+    EC_AFFINE N_affine;
+    if (!ec_point_mul_scalar(group, &N, &Zs[i], &pretoken->r) ||
+        !ec_jacobian_to_affine(group, &N_affine, &N)) {
+      goto err;
+    }
+
+    // Serialize the token. Include |key_id| to avoid an extra copy in the layer
+    // above.
+    CBB token_cbb;
+    size_t point_len = 1 + 2 * BN_num_bytes(&group->field);
+    if (!CBB_init(&token_cbb, 4 + TRUST_TOKEN_NONCE_SIZE + (2 + point_len)) ||
+        !CBB_add_u32(&token_cbb, key_id) ||
+        !CBB_add_bytes(&token_cbb, pretoken->salt, TRUST_TOKEN_NONCE_SIZE) ||
+        !cbb_add_point(&token_cbb, group, &N_affine) ||
+        !CBB_flush(&token_cbb)) {
+      CBB_cleanup(&token_cbb);
+      goto err;
+    }
+
+    TRUST_TOKEN *token =
+        TRUST_TOKEN_new(CBB_data(&token_cbb), CBB_len(&token_cbb));
+    CBB_cleanup(&token_cbb);
+    if (token == NULL ||
+        !sk_TRUST_TOKEN_push(ret, token)) {
+      TRUST_TOKEN_free(token);
+      goto err;
+    }
+  }
+
+  EC_RAW_POINT M, Z;
+  if (!ec_point_mul_scalar_public_batch(group, &M,
+                                        /*g_scalar=*/NULL, BTs, dis,
+                                        count) ||
+      !ec_point_mul_scalar_public_batch(group, &Z,
+                                        /*g_scalar=*/NULL, Zs, dis,
+                                        count)) {
+    goto err;
+  }
+
+  CBS proof;
+  if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
+      !verify_proof(method, &proof, key, &M, &Z) ||
+      CBS_len(&proof) != 0) {
+    goto err;
+  }
+
+  ok = 1;
+
+err:
+  OPENSSL_free(BTs);
+  OPENSSL_free(Zs);
+  OPENSSL_free(dis);
+  if (!ok) {
+    sk_TRUST_TOKEN_pop_free(ret, TRUST_TOKEN_free);
+    ret = NULL;
+  }
+  return ret;
+}
+
 static int voprf_read(const VOPRF_METHOD *method,
                       const TRUST_TOKEN_ISSUER_KEY *key,
                       uint8_t out_nonce[TRUST_TOKEN_NONCE_SIZE],
@@ -806,8 +1225,8 @@
   if (!voprf_exp2_init_method() || private_metadata != 0) {
     return 0;
   }
-  return voprf_sign(&voprf_exp2_method, key, cbb, cbs, num_requested,
-                    num_to_issue);
+  return voprf_sign_tt(&voprf_exp2_method, key, cbb, cbs, num_requested,
+                       num_to_issue);
 }
 
 STACK_OF(TRUST_TOKEN) *voprf_exp2_unblind(
@@ -817,7 +1236,8 @@
   if (!voprf_exp2_init_method()) {
     return NULL;
   }
-  return voprf_unblind(&voprf_exp2_method, key, pretokens, cbs, count, key_id);
+  return voprf_unblind_tt(&voprf_exp2_method, key, pretokens, cbs, count,
+                          key_id);
 }
 
 int voprf_exp2_read(const TRUST_TOKEN_ISSUER_KEY *key,
@@ -831,3 +1251,130 @@
   return voprf_read(&voprf_exp2_method, key, out_nonce, token, token_len,
                     include_message, msg, msg_len);
 }
+
+// VOPRF PST v1.
+
+static int voprf_pst1_hash_to_group(const EC_GROUP *group, EC_RAW_POINT *out,
+                                    const uint8_t t[TRUST_TOKEN_NONCE_SIZE]) {
+  const uint8_t kHashTLabel[] = "HashToGroup-OPRFV1-\x01-P384-SHA384";
+  return ec_hash_to_curve_p384_xmd_sha384_sswu(group, out, kHashTLabel,
+                                               sizeof(kHashTLabel) - 1, t,
+                                               TRUST_TOKEN_NONCE_SIZE);
+}
+
+static int voprf_pst1_hash_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
+                             uint8_t *buf, size_t len) {
+  const uint8_t kHashCLabel[] = "HashToScalar-OPRFV1-\x01-P384-SHA384";
+  return ec_hash_to_scalar_p384_xmd_sha384(group, out, kHashCLabel,
+                                           sizeof(kHashCLabel) - 1, buf, len);
+}
+
+static int voprf_pst1_ok = 0;
+static VOPRF_METHOD voprf_pst1_method;
+static CRYPTO_once_t voprf_pst1_method_once = CRYPTO_ONCE_INIT;
+
+static void voprf_pst1_init_method_impl(void) {
+  voprf_pst1_ok =
+      voprf_init_method(&voprf_pst1_method, NID_secp384r1,
+                        voprf_pst1_hash_to_group, voprf_pst1_hash_to_scalar);
+}
+
+static int voprf_pst1_init_method(void) {
+  CRYPTO_once(&voprf_pst1_method_once, voprf_pst1_init_method_impl);
+  if (!voprf_pst1_ok) {
+    OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  return 1;
+}
+
+int voprf_pst1_generate_key(CBB *out_private, CBB *out_public) {
+  if (!voprf_pst1_init_method()) {
+    return 0;
+  }
+
+  return voprf_generate_key(&voprf_pst1_method, out_private, out_public);
+}
+
+int voprf_pst1_derive_key_from_secret(CBB *out_private, CBB *out_public,
+                                      const uint8_t *secret,
+                                      size_t secret_len) {
+  if (!voprf_pst1_init_method()) {
+    return 0;
+  }
+
+  return voprf_derive_key_from_secret(&voprf_pst1_method, out_private,
+                                      out_public, secret, secret_len);
+}
+
+int voprf_pst1_client_key_from_bytes(TRUST_TOKEN_CLIENT_KEY *key,
+                                     const uint8_t *in, size_t len) {
+  if (!voprf_pst1_init_method()) {
+    return 0;
+  }
+  return voprf_client_key_from_bytes(&voprf_pst1_method, key, in, len);
+}
+
+int voprf_pst1_issuer_key_from_bytes(TRUST_TOKEN_ISSUER_KEY *key,
+                                     const uint8_t *in, size_t len) {
+  if (!voprf_pst1_init_method()) {
+    return 0;
+  }
+  return voprf_issuer_key_from_bytes(&voprf_pst1_method, key, in, len);
+}
+
+STACK_OF(TRUST_TOKEN_PRETOKEN) *voprf_pst1_blind(CBB *cbb, size_t count,
+                                                 int include_message,
+                                                 const uint8_t *msg,
+                                                 size_t msg_len) {
+  if (!voprf_pst1_init_method()) {
+    return NULL;
+  }
+  return voprf_blind(&voprf_pst1_method, cbb, count, include_message, msg,
+                     msg_len);
+}
+
+int voprf_pst1_sign(const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
+                    size_t num_requested, size_t num_to_issue,
+                    uint8_t private_metadata) {
+  if (!voprf_pst1_init_method() || private_metadata != 0) {
+    return 0;
+  }
+  return voprf_sign(&voprf_pst1_method, key, cbb, cbs, num_requested,
+                    num_to_issue);
+}
+
+
+int voprf_pst1_sign_with_proof_scalar_for_testing(
+    const TRUST_TOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs, size_t num_requested,
+    size_t num_to_issue, uint8_t private_metadata,
+    const uint8_t *proof_scalar_buf, size_t proof_scalar_len) {
+  if (!voprf_pst1_init_method() || private_metadata != 0) {
+    return 0;
+  }
+  return voprf_sign_with_proof_scalar_for_testing(
+      &voprf_pst1_method, key, cbb, cbs, num_requested, num_to_issue,
+      proof_scalar_buf, proof_scalar_len);
+}
+
+STACK_OF(TRUST_TOKEN) *voprf_pst1_unblind(
+    const TRUST_TOKEN_CLIENT_KEY *key,
+    const STACK_OF(TRUST_TOKEN_PRETOKEN) *pretokens, CBS *cbs, size_t count,
+    uint32_t key_id) {
+  if (!voprf_pst1_init_method()) {
+    return NULL;
+  }
+  return voprf_unblind(&voprf_pst1_method, key, pretokens, cbs, count, key_id);
+}
+
+int voprf_pst1_read(const TRUST_TOKEN_ISSUER_KEY *key,
+                    uint8_t out_nonce[TRUST_TOKEN_NONCE_SIZE],
+                    uint8_t *out_private_metadata, const uint8_t *token,
+                    size_t token_len, int include_message, const uint8_t *msg,
+                    size_t msg_len) {
+  if (!voprf_pst1_init_method()) {
+    return 0;
+  }
+  return voprf_read(&voprf_pst1_method, key, out_nonce, token, token_len,
+                    include_message, msg, msg_len);
+}
diff --git a/src/crypto/x509/a_sign.c b/src/crypto/x509/a_sign.c
index de89fab..7f80e5b 100644
--- a/src/crypto/x509/a_sign.c
+++ b/src/crypto/x509/a_sign.c
@@ -62,6 +62,8 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
+#include <limits.h>
+
 #include "internal.h"
 
 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
@@ -83,17 +85,13 @@
 int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
                        X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
                        void *asn, EVP_MD_CTX *ctx) {
-  EVP_PKEY *pkey;
-  unsigned char *buf_in = NULL, *buf_out = NULL;
-  size_t inl = 0, outl = 0;
-
+  int ret = 0;
+  uint8_t *in = NULL, *out = NULL;
   if (signature->type != V_ASN1_BIT_STRING) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
     goto err;
   }
 
-  pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
-
   // Write out the requested copies of the AlgorithmIdentifier.
   if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) {
     goto err;
@@ -102,26 +100,37 @@
     goto err;
   }
 
-  inl = ASN1_item_i2d(asn, &buf_in, it);
-  outl = EVP_PKEY_size(pkey);
-  buf_out = OPENSSL_malloc((unsigned int)outl);
-  if ((buf_in == NULL) || (buf_out == NULL)) {
-    outl = 0;
+  int in_len = ASN1_item_i2d(asn, &in, it);
+  if (in_len < 0) {
     goto err;
   }
 
-  if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
-    outl = 0;
+  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+  size_t out_len = EVP_PKEY_size(pkey);
+  if (out_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
+    goto err;
+  }
+
+  out = OPENSSL_malloc(out_len);
+  if (out == NULL) {
+    goto err;
+  }
+
+  if (!EVP_DigestSign(ctx, out, &out_len, in, in_len)) {
     OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
     goto err;
   }
-  ASN1_STRING_set0(signature, buf_out, outl);
-  buf_out = NULL;
+
+  ASN1_STRING_set0(signature, out, (int)out_len);
+  out = NULL;
   signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
   signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+  ret = (int)out_len;
+
 err:
   EVP_MD_CTX_cleanup(ctx);
-  OPENSSL_free(buf_in);
-  OPENSSL_free(buf_out);
-  return outl;
+  OPENSSL_free(in);
+  OPENSSL_free(out);
+  return ret;
 }
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
index 937069e..321f63b 100644
--- a/src/crypto/x509/asn1_gen.c
+++ b/src/crypto/x509/asn1_gen.c
@@ -509,7 +509,7 @@
                CBB_flush(cbb);
       }
       if (format == ASN1_GEN_FORMAT_HEX) {
-        long len;
+        size_t len;
         uint8_t *data = x509v3_hex_to_bytes(value, &len);
         if (data == NULL) {
           OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
diff --git a/src/crypto/x509/name_print.c b/src/crypto/x509/name_print.c
index 29207cc..5dc34da 100644
--- a/src/crypto/x509/name_print.c
+++ b/src/crypto/x509/name_print.c
@@ -56,6 +56,7 @@
 
 #include <openssl/x509.h>
 
+#include <assert.h>
 #include <inttypes.h>
 #include <string.h>
 
@@ -84,8 +85,7 @@
 
 static int do_name_ex(BIO *out, const X509_NAME *n, int indent,
                       unsigned long flags) {
-  int i, prev = -1, orflags, cnt;
-  int fn_opt, fn_nid;
+  int prev = -1, orflags;
   char objtmp[80];
   const char *objbuf;
   int outlen, len;
@@ -142,10 +142,8 @@
     sep_eq_len = 1;
   }
 
-  fn_opt = flags & XN_FLAG_FN_MASK;
-
-  cnt = X509_NAME_entry_count(n);
-  for (i = 0; i < cnt; i++) {
+  int cnt = X509_NAME_entry_count(n);
+  for (int i = 0; i < cnt; i++) {
     const X509_NAME_ENTRY *ent;
     if (flags & XN_FLAG_DN_REV) {
       ent = X509_NAME_get_entry(n, cnt - i - 1);
@@ -172,40 +170,20 @@
     prev = X509_NAME_ENTRY_set(ent);
     const ASN1_OBJECT *fn = X509_NAME_ENTRY_get_object(ent);
     const ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent);
-    fn_nid = OBJ_obj2nid(fn);
-    if (fn_opt != XN_FLAG_FN_NONE) {
-      int objlen, fld_len;
-      if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
-        OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
-        fld_len = 0;  // XXX: what should this be?
-        objbuf = objtmp;
-      } else {
-        if (fn_opt == XN_FLAG_FN_SN) {
-          fld_len = FN_WIDTH_SN;
-          objbuf = OBJ_nid2sn(fn_nid);
-        } else if (fn_opt == XN_FLAG_FN_LN) {
-          fld_len = FN_WIDTH_LN;
-          objbuf = OBJ_nid2ln(fn_nid);
-        } else {
-          fld_len = 0;  // XXX: what should this be?
-          objbuf = "";
-        }
-      }
-      objlen = strlen(objbuf);
-      if (!maybe_write(out, objbuf, objlen)) {
-        return -1;
-      }
-      if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
-        if (!do_indent(out, fld_len - objlen)) {
-          return -1;
-        }
-        outlen += fld_len - objlen;
-      }
-      if (!maybe_write(out, sep_eq, sep_eq_len)) {
-        return -1;
-      }
-      outlen += objlen + sep_eq_len;
+    assert((flags & XN_FLAG_FN_MASK) == XN_FLAG_FN_SN);
+    int fn_nid = OBJ_obj2nid(fn);
+    if (fn_nid == NID_undef) {
+      OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
+      objbuf = objtmp;
+    } else {
+      objbuf = OBJ_nid2sn(fn_nid);
     }
+    int objlen = strlen(objbuf);
+    if (!maybe_write(out, objbuf, objlen) ||
+        !maybe_write(out, sep_eq, sep_eq_len)) {
+      return -1;
+    }
+    outlen += objlen + sep_eq_len;
     // If the field name is unknown then fix up the DER dump flag. We
     // might want to limit this further so it will DER dump on anything
     // other than a few 'standard' fields.
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index 6694e3d..1d71576 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -91,14 +91,8 @@
 
 int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
                   unsigned long cflag) {
-  long l;
-  int ret = 0, i;
-  char *m = NULL, mlch = ' ';
+  char mlch = ' ';
   int nmindent = 0;
-  X509_CINF *ci;
-  EVP_PKEY *pkey = NULL;
-  const char *neg;
-
   if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
     mlch = '\n';
     nmindent = 12;
@@ -108,26 +102,26 @@
     nmindent = 16;
   }
 
-  ci = x->cert_info;
+  const X509_CINF *ci = x->cert_info;
   if (!(cflag & X509_FLAG_NO_HEADER)) {
     if (BIO_write(bp, "Certificate:\n", 13) <= 0) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "    Data:\n", 10) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_VERSION)) {
-    l = X509_get_version(x);
+    long l = X509_get_version(x);
     assert(X509_VERSION_1 <= l && l <= X509_VERSION_3);
     if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1,
                    (unsigned long)l) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_SERIAL)) {
     if (BIO_write(bp, "        Serial Number:", 22) <= 0) {
-      goto err;
+      return 0;
     }
 
     const ASN1_INTEGER *serial = X509_get0_serialNumber(x);
@@ -136,19 +130,20 @@
       assert(serial->type != V_ASN1_NEG_INTEGER);
       if (BIO_printf(bp, " %" PRIu64 " (0x%" PRIx64 ")\n", serial_u64,
                      serial_u64) <= 0) {
-        goto err;
+        return 0;
       }
     } else {
       ERR_clear_error();  // Clear |ASN1_INTEGER_get_uint64|'s error.
-      neg = (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
+      const char *neg =
+          (serial->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
       if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) {
-        goto err;
+        return 0;
       }
 
-      for (i = 0; i < serial->length; i++) {
+      for (int i = 0; i < serial->length; i++) {
         if (BIO_printf(bp, "%02x%c", serial->data[i],
                        ((i + 1 == serial->length) ? '\n' : ':')) <= 0) {
-          goto err;
+          return 0;
         }
       }
     }
@@ -156,69 +151,69 @@
 
   if (!(cflag & X509_FLAG_NO_SIGNAME)) {
     if (X509_signature_print(bp, ci->signature, NULL) <= 0) {
-      goto err;
+      return 0;
     }
   }
 
   if (!(cflag & X509_FLAG_NO_ISSUER)) {
     if (BIO_printf(bp, "        Issuer:%c", mlch) <= 0) {
-      goto err;
+      return 0;
     }
     if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) <
         0) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "\n", 1) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_VALIDITY)) {
     if (BIO_write(bp, "        Validity\n", 17) <= 0) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "            Not Before: ", 24) <= 0) {
-      goto err;
+      return 0;
     }
     if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "\n            Not After : ", 25) <= 0) {
-      goto err;
+      return 0;
     }
     if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "\n", 1) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_SUBJECT)) {
     if (BIO_printf(bp, "        Subject:%c", mlch) <= 0) {
-      goto err;
+      return 0;
     }
     if (X509_NAME_print_ex(bp, X509_get_subject_name(x), nmindent, nmflags) <
         0) {
-      goto err;
+      return 0;
     }
     if (BIO_write(bp, "\n", 1) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_PUBKEY)) {
     if (BIO_write(bp, "        Subject Public Key Info:\n", 33) <= 0) {
-      goto err;
+      return 0;
     }
     if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) {
-      goto err;
+      return 0;
     }
     if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) {
-      goto err;
+      return 0;
     }
     if (BIO_puts(bp, "\n") <= 0) {
-      goto err;
+      return 0;
     }
 
-    pkey = X509_get_pubkey(x);
+    EVP_PKEY *pkey = X509_get_pubkey(x);
     if (pkey == NULL) {
       BIO_printf(bp, "%12sUnable to load Public Key\n", "");
       ERR_print_errors(bp);
@@ -231,18 +226,18 @@
   if (!(cflag & X509_FLAG_NO_IDS)) {
     if (ci->issuerUID) {
       if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) {
-        goto err;
+        return 0;
       }
       if (!X509_signature_dump(bp, ci->issuerUID, 12)) {
-        goto err;
+        return 0;
       }
     }
     if (ci->subjectUID) {
       if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) {
-        goto err;
+        return 0;
       }
       if (!X509_signature_dump(bp, ci->subjectUID, 12)) {
-        goto err;
+        return 0;
       }
     }
   }
@@ -253,20 +248,16 @@
 
   if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
     if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) {
-      goto err;
+      return 0;
     }
   }
   if (!(cflag & X509_FLAG_NO_AUX)) {
     if (!X509_CERT_AUX_print(bp, x->aux, 0)) {
-      goto err;
+      return 0;
     }
   }
-  ret = 1;
-err:
-  if (m != NULL) {
-    OPENSSL_free(m);
-  }
-  return ret;
+
+  return 1;
 }
 
 int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
diff --git a/src/crypto/x509/test/make_basic_constraints.go b/src/crypto/x509/test/make_basic_constraints.go
index 67f4b91..ea502b4 100644
--- a/src/crypto/x509/test/make_basic_constraints.go
+++ b/src/crypto/x509/test/make_basic_constraints.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // make_basic_constraints.go generates self-signed certificates with the basic
 // constraints extension.
 package main
diff --git a/src/crypto/x509/test/make_invalid_extensions.go b/src/crypto/x509/test/make_invalid_extensions.go
index 884d933..8287bf8 100644
--- a/src/crypto/x509/test/make_invalid_extensions.go
+++ b/src/crypto/x509/test/make_invalid_extensions.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // make_invalid_extensions.go generates a number of certificate chains with
 // invalid extension encodings.
 package main
diff --git a/src/crypto/x509/test/make_many_constraints.go b/src/crypto/x509/test/make_many_constraints.go
index 07f2edc..24a5c40 100644
--- a/src/crypto/x509/test/make_many_constraints.go
+++ b/src/crypto/x509/test/make_many_constraints.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // make_many_constraints.go generates test certificates many_constraints.pem,
 // many_names*.pem, and some_names*.pem for x509_test.cc
 package main
diff --git a/src/crypto/x509/test/make_policy_certs.go b/src/crypto/x509/test/make_policy_certs.go
index b1c5a60..739d8ce 100644
--- a/src/crypto/x509/test/make_policy_certs.go
+++ b/src/crypto/x509/test/make_policy_certs.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // make_policy_certs.go generates certificates for testing policy handling.
 package main
 
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
index 0dda757..23e92f2 100644
--- a/src/crypto/x509/x509_att.c
+++ b/src/crypto/x509/x509_att.c
@@ -56,153 +56,13 @@
 
 #include <openssl/asn1.h>
 #include <openssl/err.h>
-#include <openssl/evp.h>
 #include <openssl/obj.h>
-#include <openssl/stack.h>
 #include <openssl/x509.h>
 
 #include "../asn1/internal.h"
 #include "internal.h"
 
 
-int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) {
-  return sk_X509_ATTRIBUTE_num(x);
-}
-
-int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
-                           int lastpos) {
-  const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
-  if (obj == NULL) {
-    return -1;
-  }
-  return X509at_get_attr_by_OBJ(x, obj, lastpos);
-}
-
-int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
-                           const ASN1_OBJECT *obj, int lastpos) {
-  int n;
-  X509_ATTRIBUTE *ex;
-
-  if (sk == NULL) {
-    return -1;
-  }
-  lastpos++;
-  if (lastpos < 0) {
-    lastpos = 0;
-  }
-  n = sk_X509_ATTRIBUTE_num(sk);
-  for (; lastpos < n; lastpos++) {
-    ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
-    if (OBJ_cmp(ex->object, obj) == 0) {
-      return lastpos;
-    }
-  }
-  return -1;
-}
-
-X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) {
-  if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) {
-    return NULL;
-  } else {
-    return sk_X509_ATTRIBUTE_value(x, loc);
-  }
-}
-
-X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) {
-  X509_ATTRIBUTE *ret;
-
-  if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc) {
-    return NULL;
-  }
-  ret = sk_X509_ATTRIBUTE_delete(x, loc);
-  return ret;
-}
-
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
-                                           X509_ATTRIBUTE *attr) {
-  X509_ATTRIBUTE *new_attr = NULL;
-  STACK_OF(X509_ATTRIBUTE) *sk = NULL;
-
-  if (x == NULL) {
-    OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
-    goto err;
-  }
-
-  if (*x == NULL) {
-    if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) {
-      goto err;
-    }
-  } else {
-    sk = *x;
-  }
-
-  if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) {
-    goto err;
-  }
-  if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) {
-    goto err;
-  }
-  if (*x == NULL) {
-    *x = sk;
-  }
-  return sk;
-err:
-  if (new_attr != NULL) {
-    X509_ATTRIBUTE_free(new_attr);
-  }
-  if (sk != NULL) {
-    sk_X509_ATTRIBUTE_free(sk);
-  }
-  return NULL;
-}
-
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
-                                                  const ASN1_OBJECT *obj,
-                                                  int type,
-                                                  const unsigned char *bytes,
-                                                  int len) {
-  X509_ATTRIBUTE *attr;
-  STACK_OF(X509_ATTRIBUTE) *ret;
-  attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
-  if (!attr) {
-    return 0;
-  }
-  ret = X509at_add1_attr(x, attr);
-  X509_ATTRIBUTE_free(attr);
-  return ret;
-}
-
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
-                                                  int nid, int type,
-                                                  const unsigned char *bytes,
-                                                  int len) {
-  X509_ATTRIBUTE *attr;
-  STACK_OF(X509_ATTRIBUTE) *ret;
-  attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
-  if (!attr) {
-    return 0;
-  }
-  ret = X509at_add1_attr(x, attr);
-  X509_ATTRIBUTE_free(attr);
-  return ret;
-}
-
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
-                                                  const char *attrname,
-                                                  int type,
-                                                  const unsigned char *bytes,
-                                                  int len) {
-  X509_ATTRIBUTE *attr;
-  STACK_OF(X509_ATTRIBUTE) *ret;
-  attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
-  if (!attr) {
-    return 0;
-  }
-  ret = X509at_add1_attr(x, attr);
-  X509_ATTRIBUTE_free(attr);
-  return ret;
-}
-
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
                                              int attrtype, const void *data,
                                              int len) {
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
index 8734897..69eb63c 100644
--- a/src/crypto/x509/x509_req.c
+++ b/src/crypto/x509/x509_req.c
@@ -160,62 +160,111 @@
   return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
 }
 
-// Request attribute functions
-
 int X509_REQ_get_attr_count(const X509_REQ *req) {
-  return X509at_get_attr_count(req->req_info->attributes);
+  return sk_X509_ATTRIBUTE_num(req->req_info->attributes);
 }
 
 int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) {
-  return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
+  const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+  if (obj == NULL) {
+    return -1;
+  }
+  return X509_REQ_get_attr_by_OBJ(req, obj, lastpos);
 }
 
 int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
                              int lastpos) {
-  return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
+  if (req->req_info->attributes == NULL) {
+    return -1;
+  }
+  lastpos++;
+  if (lastpos < 0) {
+    lastpos = 0;
+  }
+  int n = sk_X509_ATTRIBUTE_num(req->req_info->attributes);
+  for (; lastpos < n; lastpos++) {
+    const X509_ATTRIBUTE *attr =
+        sk_X509_ATTRIBUTE_value(req->req_info->attributes, lastpos);
+    if (OBJ_cmp(attr->object, obj) == 0) {
+      return lastpos;
+    }
+  }
+  return -1;
 }
 
 X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) {
-  return X509at_get_attr(req->req_info->attributes, loc);
+  if (req->req_info->attributes == NULL || loc < 0 ||
+      sk_X509_ATTRIBUTE_num(req->req_info->attributes) <= (size_t)loc) {
+    return NULL;
+  }
+  return sk_X509_ATTRIBUTE_value(req->req_info->attributes, loc);
 }
 
 X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) {
-  return X509at_delete_attr(req->req_info->attributes, loc);
+  if (req->req_info->attributes == NULL || loc < 0 ||
+      sk_X509_ATTRIBUTE_num(req->req_info->attributes) <= (size_t)loc) {
+    return NULL;
+  }
+  return sk_X509_ATTRIBUTE_delete(req->req_info->attributes, loc);
 }
 
-int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) {
-  if (X509at_add1_attr(&req->req_info->attributes, attr)) {
-    return 1;
+static int X509_REQ_add0_attr(X509_REQ *req, X509_ATTRIBUTE *attr) {
+  if (req->req_info->attributes == NULL) {
+    req->req_info->attributes = sk_X509_ATTRIBUTE_new_null();
   }
-  return 0;
+  if (req->req_info->attributes == NULL ||
+      !sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int X509_REQ_add1_attr(X509_REQ *req, const X509_ATTRIBUTE *attr) {
+  X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_dup(attr);
+  if (new_attr == NULL || !X509_REQ_add0_attr(req, new_attr)) {
+    X509_ATTRIBUTE_free(new_attr);
+    return 0;
+  }
+
+  return 1;
 }
 
 int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj,
                               int attrtype, const unsigned char *data,
                               int len) {
-  if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, attrtype, data,
-                              len)) {
-    return 1;
+  X509_ATTRIBUTE *attr =
+      X509_ATTRIBUTE_create_by_OBJ(NULL, obj, attrtype, data, len);
+  if (attr == NULL || !X509_REQ_add0_attr(req, attr)) {
+    X509_ATTRIBUTE_free(attr);
+    return 0;
   }
-  return 0;
+
+  return 1;
 }
 
 int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int attrtype,
                               const unsigned char *data, int len) {
-  if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, attrtype, data,
-                              len)) {
-    return 1;
+  X509_ATTRIBUTE *attr =
+      X509_ATTRIBUTE_create_by_NID(NULL, nid, attrtype, data, len);
+  if (attr == NULL || !X509_REQ_add0_attr(req, attr)) {
+    X509_ATTRIBUTE_free(attr);
+    return 0;
   }
-  return 0;
+
+  return 1;
 }
 
 int X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int attrtype,
                               const unsigned char *data, int len) {
-  if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, attrtype,
-                              data, len)) {
-    return 1;
+  X509_ATTRIBUTE *attr =
+      X509_ATTRIBUTE_create_by_txt(NULL, attrname, attrtype, data, len);
+  if (attr == NULL || !X509_REQ_add0_attr(req, attr)) {
+    X509_ATTRIBUTE_free(attr);
+    return 0;
   }
-  return 0;
+
+  return 1;
 }
 
 void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 056d56a..404ce5b 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -2048,7 +2048,12 @@
         ASSERT_TRUE(
             X509_set1_signature_value(cert.get(), sig.data(), sig.size()));
       } else {
-        ASSERT_TRUE(X509_sign(cert.get(), pkey.get(), EVP_sha384()));
+        int ret = X509_sign(cert.get(), pkey.get(), EVP_sha384());
+        ASSERT_GT(ret, 0);
+        // |X509_sign| returns the length of the signature on success.
+        const ASN1_BIT_STRING *sig;
+        X509_get0_signature(&sig, /*out_alg=*/nullptr, cert.get());
+        EXPECT_EQ(ret, ASN1_STRING_length(sig));
       }
 
       // Check the signature.
@@ -4702,50 +4707,35 @@
        "CN = \"Common "
        "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\", "
        "CN = \" spaces \""},
-      // |XN_FLAG_MULTILINE| is an OpenSSL-specific multi-line format that tries
-      // to vertically align the equal sizes. The vertical alignment doesn't
-      // quite handle multi-valued RDNs right and uses a non-RFC-2253 escaping.
+      // Callers can also customize the output, with both |XN_FLAG_*| and
+      // |ASN1_STRFLGS_*|. |XN_FLAG_SEP_SPLUS_SPC| uses semicolon separators.
       {/*indent=*/0,
-       /*flags=*/XN_FLAG_MULTILINE,
-       "countryName               = US\n"
-       "stateOrProvinceName       = Some State + "
-       "stateOrProvinceName       = Some Other State \\U2603 + "
-       "stateOrProvinceName       = Another State \\U2603 + "
-       "1.2.840.113554.4.1.72585.2 = \\U2603\n"
-       "1.2.840.113554.4.1.72585.3 = 0\\06\\02\\01\\01\\02\\01\\02\n"
-       "organizationName          = Org Name\n"
-       "commonName                = Common "
-       "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\n"
-       "commonName                =  spaces "},
-      // The multiline format indents every line.
-      {/*indent=*/2,
-       /*flags=*/XN_FLAG_MULTILINE,
-       "  countryName               = US\n"
-       "  stateOrProvinceName       = Some State + "
-       "stateOrProvinceName       = Some Other State \\U2603 + "
-       "stateOrProvinceName       = Another State \\U2603 + "
-       "1.2.840.113554.4.1.72585.2 = \\U2603\n"
-       "  1.2.840.113554.4.1.72585.3 = 0\\06\\02\\01\\01\\02\\01\\02\n"
-       "  organizationName          = Org Name\n"
-       "  commonName                = Common "
-       "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\n"
-       "  commonName                =  spaces "},
-      // Callers can also customize the output, wuith both |XN_FLAG_*| and
-      // |ASN1_STRFLGS_*|. |XN_FLAG_SEP_SPLUS_SPC| uses semicolon separators and
-      // |XN_FLAG_FN_OID| forces OIDs.
-      {/*indent=*/0,
-       /*flags=*/XN_FLAG_SEP_SPLUS_SPC | XN_FLAG_FN_OID | ASN1_STRFLGS_RFC2253 |
+       /*flags=*/XN_FLAG_SEP_SPLUS_SPC | ASN1_STRFLGS_RFC2253 |
            ASN1_STRFLGS_ESC_QUOTE,
-       "2.5.4.6=US; "
-       "2.5.4.8=Some State + "
-       "2.5.4.8=Some Other State \\E2\\98\\83 + "
-       "2.5.4.8=Another State \\E2\\98\\83 + "
+       "C=US; "
+       "ST=Some State + "
+       "ST=Some Other State \\E2\\98\\83 + "
+       "ST=Another State \\E2\\98\\83 + "
        "1.2.840.113554.4.1.72585.2=\\E2\\98\\83; "
        "1.2.840.113554.4.1.72585.3=#3006020101020102; "
-       "2.5.4.10=Org Name; "
-       "2.5.4.3=\"Common "
+       "O=Org Name; "
+       "CN=\"Common "
        "Name/CN=A/CN=B,CN=A,CN=B+CN=A+CN=B;CN=A;CN=B\\0ACN=A\\0A\"; "
-       "2.5.4.3=\" spaces \""},
+       "CN=\" spaces \""},
+      // Node uses these parameters.
+      {/*indent=*/0,
+       /*flags=*/ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_CTRL |
+           ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SEP_MULTILINE | XN_FLAG_FN_SN,
+       "C=US\n"
+       "ST=Some State + "
+       "ST=Some Other State \xE2\x98\x83 + "
+       "ST=Another State \xE2\x98\x83 + "
+       "1.2.840.113554.4.1.72585.2=\xE2\x98\x83\n"
+       "1.2.840.113554.4.1.72585.3=0\\06\\02\\01\\01\\02\\01\\02\n"
+       "O=Org Name\n"
+       "CN=Common "
+       "Name/CN=A/CN=B\\,CN=A\\,CN=B\\+CN=A\\+CN=B\\;CN=A\\;CN=B\\0ACN=A\\0A\n"
+       "CN=\\ spaces\\ "},
       // |XN_FLAG_COMPAT| matches |X509_NAME_print|, rather than
       // |X509_NAME_print_ex|.
       //
@@ -6549,3 +6539,103 @@
       0x02, 0x41, 0x42};
   EXPECT_EQ(Bytes(kExpected), Bytes(der, der_len));
 }
+
+TEST(X509Test, NameAttributeValues) {
+  // 1.2.840.113554.4.1.72585.0. We use an unrecognized OID because using an
+  // arbitrary ASN.1 type as the value for commonName is invalid. Our parser
+  // does not check this, but best to avoid unrelated errors in tests, in case
+  // we decide to later.
+  static const uint8_t kOID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
+                                 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00};
+
+  const struct {
+    CBS_ASN1_TAG der_tag;
+    std::string der_contents;
+    int str_type;
+    std::string str_contents;
+  } kTests[] = {
+      // String types are parsed as string types.
+      {CBS_ASN1_BITSTRING, std::string("\0", 1), V_ASN1_BIT_STRING, ""},
+      {CBS_ASN1_UTF8STRING, "abc", V_ASN1_UTF8STRING, "abc"},
+      {CBS_ASN1_NUMERICSTRING, "123", V_ASN1_NUMERICSTRING, "123"},
+      {CBS_ASN1_PRINTABLESTRING, "abc", V_ASN1_PRINTABLESTRING, "abc"},
+      {CBS_ASN1_T61STRING, "abc", V_ASN1_T61STRING, "abc"},
+      {CBS_ASN1_IA5STRING, "abc", V_ASN1_IA5STRING, "abc"},
+      {CBS_ASN1_UNIVERSALSTRING, std::string("\0\0\0a", 4),
+       V_ASN1_UNIVERSALSTRING, std::string("\0\0\0a", 4)},
+      {CBS_ASN1_BMPSTRING, std::string("\0a", 2), V_ASN1_BMPSTRING,
+       std::string("\0a", 2)},
+
+      // ENUMERATED is supported but, currently, INTEGER is not.
+      {CBS_ASN1_ENUMERATED, "\x01", V_ASN1_ENUMERATED, "\x01"},
+
+      // SEQUENCE is supported but, currently, SET is not. Note the
+      // |ASN1_STRING| representation will include the tag and length.
+      {CBS_ASN1_SEQUENCE, "", V_ASN1_SEQUENCE, std::string("\x30\x00", 2)},
+
+      // These types are not actually supported by the library but,
+      // historically, we would parse them, and not other unsupported types, due
+      // to quirks of |ASN1_tag2bit|.
+      {7, "", V_ASN1_OBJECT_DESCRIPTOR, ""},
+      {8, "", V_ASN1_EXTERNAL, ""},
+      {9, "", V_ASN1_REAL, ""},
+      {11, "", 11 /* EMBEDDED PDV */, ""},
+      {13, "", 13 /* RELATIVE-OID */, ""},
+      {14, "", 14 /* TIME */, ""},
+      {15, "", 15 /* not a type; reserved value */, ""},
+      {29, "", 29 /* CHARACTER STRING */, ""},
+
+      // TODO(crbug.com/boringssl/412): Attribute values are an ANY DEFINED BY
+      // type, so we actually shoudl be accepting all ASN.1 types. We currently
+      // do not and only accept the above types. Extend this test when we fix
+      // this.
+  };
+  for (const auto &t : kTests) {
+    SCOPED_TRACE(t.der_tag);
+    SCOPED_TRACE(Bytes(t.der_contents));
+
+    // Construct an X.509 name containing a single RDN with a single attribute:
+    // kOID with the specified value.
+    bssl::ScopedCBB cbb;
+    ASSERT_TRUE(CBB_init(cbb.get(), 128));
+    CBB seq, rdn, attr, attr_type, attr_value;
+    ASSERT_TRUE(CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE));
+    ASSERT_TRUE(CBB_add_asn1(&seq, &rdn, CBS_ASN1_SET));
+    ASSERT_TRUE(CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE));
+    ASSERT_TRUE(CBB_add_asn1(&attr, &attr_type, CBS_ASN1_OBJECT));
+    ASSERT_TRUE(CBB_add_bytes(&attr_type, kOID, sizeof(kOID)));
+    ASSERT_TRUE(CBB_add_asn1(&attr, &attr_value, t.der_tag));
+    ASSERT_TRUE(CBB_add_bytes(
+        &attr_value, reinterpret_cast<const uint8_t *>(t.der_contents.data()),
+        t.der_contents.size()));
+    ASSERT_TRUE(CBB_flush(cbb.get()));
+    SCOPED_TRACE(Bytes(CBB_data(cbb.get()), CBB_len(cbb.get())));
+
+    // The input should parse.
+    const uint8_t *inp = CBB_data(cbb.get());
+    bssl::UniquePtr<X509_NAME> name(
+        d2i_X509_NAME(nullptr, &inp, CBB_len(cbb.get())));
+    ASSERT_TRUE(name);
+    EXPECT_EQ(inp, CBB_data(cbb.get()) + CBB_len(cbb.get()))
+        << "input was not fully consumed";
+
+    // Check there is a single attribute with the expected in-memory
+    // representation.
+    ASSERT_EQ(1, X509_NAME_entry_count(name.get()));
+    const X509_NAME_ENTRY *entry = X509_NAME_get_entry(name.get(), 0);
+    const ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(entry);
+    EXPECT_EQ(Bytes(OBJ_get0_data(obj), OBJ_length(obj)), Bytes(kOID));
+    const ASN1_STRING *value = X509_NAME_ENTRY_get_data(entry);
+    EXPECT_EQ(ASN1_STRING_type(value), t.str_type);
+    EXPECT_EQ(Bytes(ASN1_STRING_get0_data(value), ASN1_STRING_length(value)),
+              Bytes(t.str_contents));
+
+    // The name should re-encode with the same input.
+    uint8_t *der = nullptr;
+    int der_len = i2d_X509_NAME(name.get(), &der);
+    ASSERT_GE(der_len, 0);
+    bssl::UniquePtr<uint8_t> free_der(der);
+    EXPECT_EQ(Bytes(der, der_len),
+              (Bytes(CBB_data(cbb.get()), CBB_len(cbb.get()))));
+  }
+}
diff --git a/src/crypto/x509/x509name.c b/src/crypto/x509/x509name.c
index cc86e28..25f7b8b 100644
--- a/src/crypto/x509/x509name.c
+++ b/src/crypto/x509/x509name.c
@@ -178,8 +178,8 @@
 }
 
 int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
-                               int type, const unsigned char *bytes, int len,
-                               int loc, int set) {
+                               int type, const unsigned char *bytes,
+                               ossl_ssize_t len, int loc, int set) {
   X509_NAME_ENTRY *ne =
       X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
   if (!ne) {
@@ -191,8 +191,8 @@
 }
 
 int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
-                               const unsigned char *bytes, int len, int loc,
-                               int set) {
+                               const unsigned char *bytes, ossl_ssize_t len,
+                               int loc, int set) {
   X509_NAME_ENTRY *ne =
       X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
   if (!ne) {
@@ -204,8 +204,8 @@
 }
 
 int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
-                               const unsigned char *bytes, int len, int loc,
-                               int set) {
+                               const unsigned char *bytes, ossl_ssize_t len,
+                               int loc, int set) {
   X509_NAME_ENTRY *ne =
       X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
   if (!ne) {
@@ -282,7 +282,7 @@
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
                                                const char *field, int type,
                                                const unsigned char *bytes,
-                                               int len) {
+                                               ossl_ssize_t len) {
   ASN1_OBJECT *obj;
   X509_NAME_ENTRY *nentry;
 
@@ -300,7 +300,7 @@
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
                                                int type,
                                                const unsigned char *bytes,
-                                               int len) {
+                                               ossl_ssize_t len) {
   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
   if (obj == NULL) {
     OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
@@ -312,7 +312,7 @@
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
                                                const ASN1_OBJECT *obj, int type,
                                                const unsigned char *bytes,
-                                               int len) {
+                                               ossl_ssize_t len) {
   X509_NAME_ENTRY *ret;
 
   if ((ne == NULL) || (*ne == NULL)) {
@@ -352,9 +352,7 @@
 }
 
 int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
-                             const unsigned char *bytes, int len) {
-  int i;
-
+                             const unsigned char *bytes, ossl_ssize_t len) {
   if ((ne == NULL) || ((bytes == NULL) && (len != 0))) {
     return 0;
   }
@@ -367,8 +365,7 @@
   if (len < 0) {
     len = strlen((const char *)bytes);
   }
-  i = ASN1_STRING_set(ne->value, bytes, len);
-  if (!i) {
+  if (!ASN1_STRING_set(ne->value, bytes, len)) {
     return 0;
   }
   if (type != V_ASN1_UNDEF) {
diff --git a/src/crypto/x509/x509spki.c b/src/crypto/x509/x509spki.c
index 8ff2053..2b9b904 100644
--- a/src/crypto/x509/x509spki.c
+++ b/src/crypto/x509/x509spki.c
@@ -77,7 +77,7 @@
 
 // Load a Netscape SPKI from a base64 encoded string
 
-NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) {
+NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, ossl_ssize_t len) {
   unsigned char *spki_der;
   const unsigned char *p;
   size_t spki_len;
diff --git a/src/crypto/x509/x_x509a.c b/src/crypto/x509/x_x509a.c
index c473f93..4b34caa 100644
--- a/src/crypto/x509/x_x509a.c
+++ b/src/crypto/x509/x_x509a.c
@@ -90,7 +90,7 @@
   return x->aux;
 }
 
-int X509_alias_set1(X509 *x, const unsigned char *name, int len) {
+int X509_alias_set1(X509 *x, const unsigned char *name, ossl_ssize_t len) {
   X509_CERT_AUX *aux;
   // TODO(davidben): Empty aliases are not meaningful in PKCS#12, and the
   // getters cannot quite represent them. Also erase the object if |len| is
@@ -112,7 +112,7 @@
   return ASN1_STRING_set(aux->alias, name, len);
 }
 
-int X509_keyid_set1(X509 *x, const unsigned char *id, int len) {
+int X509_keyid_set1(X509 *x, const unsigned char *id, ossl_ssize_t len) {
   X509_CERT_AUX *aux;
   // TODO(davidben): Empty key IDs are not meaningful in PKCS#12, and the
   // getters cannot quite represent them. Also erase the object if |len| is
diff --git a/src/crypto/x509v3/internal.h b/src/crypto/x509v3/internal.h
index e9d601b..315d934 100644
--- a/src/crypto/x509v3/internal.h
+++ b/src/crypto/x509v3/internal.h
@@ -90,7 +90,7 @@
 //
 // This function was historically named |string_to_hex| in OpenSSL. Despite the
 // name, |string_to_hex| converted from hex.
-unsigned char *x509v3_hex_to_bytes(const char *str, long *len);
+unsigned char *x509v3_hex_to_bytes(const char *str, size_t *len);
 
 // x509v3_conf_name_matches returns one if |name| is equal to |cmp| or begins
 // with |cmp| followed by '.', and zero otherwise.
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
index ebf33f1..7904c7f 100644
--- a/src/crypto/x509v3/v3_conf.c
+++ b/src/crypto/x509v3/v3_conf.c
@@ -57,6 +57,7 @@
 // extension creation utilities
 
 #include <ctype.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -81,7 +82,7 @@
 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
                                   int crit, void *ext_struc);
 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
-                                   long *ext_len);
+                                   size_t *ext_len);
 
 X509_EXTENSION *X509V3_EXT_nconf(const CONF *conf, const X509V3_CTX *ctx,
                                  const char *name, const char *value) {
@@ -191,52 +192,30 @@
   }
 
   ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
-  if (method->it) {
-    ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
-  } else {
-    method->ext_free(ext_struc);
-  }
+  ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
   return ext;
 }
 
 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
                                   int crit, void *ext_struc) {
-  unsigned char *ext_der;
-  int ext_len;
-  ASN1_OCTET_STRING *ext_oct;
-  X509_EXTENSION *ext;
-  // Convert internal representation to DER
-  if (method->it) {
-    ext_der = NULL;
-    ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
-    if (ext_len < 0) {
-      goto merr;
-    }
-  } else {
-    unsigned char *p;
-    ext_len = method->i2d(ext_struc, NULL);
-    if (!(ext_der = OPENSSL_malloc(ext_len))) {
-      goto merr;
-    }
-    p = ext_der;
-    method->i2d(ext_struc, &p);
+  // Convert the extension's internal representation to DER.
+  unsigned char *ext_der = NULL;
+  int ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
+  if (ext_len < 0) {
+    return NULL;
   }
-  if (!(ext_oct = ASN1_OCTET_STRING_new())) {
-    goto merr;
-  }
-  ext_oct->data = ext_der;
-  ext_oct->length = ext_len;
 
-  ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
-  if (!ext) {
-    goto merr;
+  ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
+  if (ext_oct == NULL) {
+    OPENSSL_free(ext_der);
+    return NULL;
   }
+  ASN1_STRING_set0(ext_oct, ext_der, ext_len);
+
+  X509_EXTENSION *ext =
+      X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
   ASN1_OCTET_STRING_free(ext_oct);
-
   return ext;
-
-merr:
-  return NULL;
 }
 
 // Given an internal structure, nid and critical flag create an extension
@@ -290,7 +269,7 @@
                                             int crit, int gen_type,
                                             const X509V3_CTX *ctx) {
   unsigned char *ext_der = NULL;
-  long ext_len = 0;
+  size_t ext_len = 0;
   ASN1_OBJECT *obj = NULL;
   ASN1_OCTET_STRING *oct = NULL;
   X509_EXTENSION *extension = NULL;
@@ -312,12 +291,17 @@
     goto err;
   }
 
-  if (!(oct = ASN1_OCTET_STRING_new())) {
+  if (ext_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
     goto err;
   }
 
-  oct->data = ext_der;
-  oct->length = ext_len;
+  oct = ASN1_OCTET_STRING_new();
+  if (oct == NULL) {
+    goto err;
+  }
+
+  ASN1_STRING_set0(oct, ext_der, (int)ext_len);
   ext_der = NULL;
 
   extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
@@ -330,15 +314,18 @@
 }
 
 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
-                                   long *ext_len) {
-  ASN1_TYPE *typ;
-  unsigned char *ext_der = NULL;
-  typ = ASN1_generate_v3(value, ctx);
+                                   size_t *ext_len) {
+  ASN1_TYPE *typ = ASN1_generate_v3(value, ctx);
   if (typ == NULL) {
     return NULL;
   }
-  *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
+  unsigned char *ext_der = NULL;
+  int len = i2d_ASN1_TYPE(typ, &ext_der);
   ASN1_TYPE_free(typ);
+  if (len < 0) {
+    return NULL;
+  }
+  *ext_len = len;
   return ext_der;
 }
 
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index e66e260..7464a42 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -356,6 +356,7 @@
       if (!nos || !sk_CONF_VALUE_num(nos)) {
         OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS);
         X509V3_conf_err(cnf);
+        sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
         goto err;
       }
       int ret = nref_nos(nref->noticenos, nos);
diff --git a/src/crypto/x509v3/v3_info.c b/src/crypto/x509v3/v3_info.c
index 2ac9221..5e14b76 100644
--- a/src/crypto/x509v3/v3_info.c
+++ b/src/crypto/x509v3/v3_info.c
@@ -168,7 +168,6 @@
                                        const STACK_OF(CONF_VALUE) *nval) {
   AUTHORITY_INFO_ACCESS *ainfo = NULL;
   ACCESS_DESCRIPTION *acc;
-  char *objtmp, *ptmp;
   if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
     return NULL;
   }
@@ -178,22 +177,21 @@
         !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
       goto err;
     }
-    ptmp = strchr(cnf->name, ';');
+    char *ptmp = strchr(cnf->name, ';');
     if (!ptmp) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
       goto err;
     }
-    int objlen = ptmp - cnf->name;
     CONF_VALUE ctmp;
     ctmp.name = ptmp + 1;
     ctmp.value = cnf->value;
     if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) {
       goto err;
     }
-    if (!(objtmp = OPENSSL_malloc(objlen + 1))) {
+    char *objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name);
+    if (objtmp == NULL) {
       goto err;
     }
-    OPENSSL_strlcpy(objtmp, cnf->name, objlen + 1);
     acc->method = OBJ_txt2obj(objtmp, 0);
     if (!acc->method) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
diff --git a/src/crypto/x509v3/v3_lib.c b/src/crypto/x509v3/v3_lib.c
index d33b51f..61cbeea 100644
--- a/src/crypto/x509v3/v3_lib.c
+++ b/src/crypto/x509v3/v3_lib.c
@@ -57,6 +57,7 @@
  */
 /* X509 v3 extension utilities */
 
+#include <assert.h>
 #include <stdio.h>
 
 #include <openssl/conf.h>
@@ -70,21 +71,20 @@
 #include "ext_dat.h"
 static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
 
-static void ext_list_free(X509V3_EXT_METHOD *ext);
-
 static int ext_stack_cmp(const X509V3_EXT_METHOD *const *a,
                          const X509V3_EXT_METHOD *const *b) {
   return ((*a)->ext_nid - (*b)->ext_nid);
 }
 
 int X509V3_EXT_add(X509V3_EXT_METHOD *ext) {
+  // We only support |ASN1_ITEM|-based extensions.
+  assert(ext->it != NULL);
+
   // TODO(davidben): This should be locked. Also check for duplicates.
   if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
-    ext_list_free(ext);
     return 0;
   }
   if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
-    ext_list_free(ext);
     return 0;
   }
   sk_X509V3_EXT_METHOD_sort(ext_list);
@@ -136,28 +136,12 @@
     return 0;
   }
 
-  if (ext_method->it != NULL) {
-    ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
-  } else if (ext_method->ext_free != NULL) {
-    ext_method->ext_free(ext_data);
-  } else {
-    OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
-    return 0;
-  }
-
-  return 1;
-}
-
-int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) {
-  for (; extlist->ext_nid != -1; extlist++) {
-    if (!X509V3_EXT_add(extlist)) {
-      return 0;
-    }
-  }
+  ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
   return 1;
 }
 
 int X509V3_EXT_add_alias(int nid_to, int nid_from) {
+OPENSSL_BEGIN_ALLOW_DEPRECATED
   const X509V3_EXT_METHOD *ext;
   X509V3_EXT_METHOD *tmpext;
 
@@ -171,19 +155,12 @@
   }
   *tmpext = *ext;
   tmpext->ext_nid = nid_to;
-  tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
-  return X509V3_EXT_add(tmpext);
-}
-
-void X509V3_EXT_cleanup(void) {
-  sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
-  ext_list = NULL;
-}
-
-static void ext_list_free(X509V3_EXT_METHOD *ext) {
-  if (ext->ext_flags & X509V3_EXT_DYNAMIC) {
-    OPENSSL_free(ext);
+  if (!X509V3_EXT_add(tmpext)) {
+    OPENSSL_free(tmpext);
+    return 0;
   }
+  return 1;
+OPENSSL_END_ALLOW_DEPRECATED
 }
 
 // Legacy function: we don't need to add standard extensions any more because
@@ -201,23 +178,14 @@
     return NULL;
   }
   p = ext->value->data;
-  void *ret;
-  if (method->it) {
-    ret =
-        ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
-  } else {
-    ret = method->d2i(NULL, &p, ext->value->length);
-  }
+  void *ret =
+      ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
   if (ret == NULL) {
     return NULL;
   }
   // Check for trailing data.
   if (p != ext->value->data + ext->value->length) {
-    if (method->it) {
-      ASN1_item_free(ret, ASN1_ITEM_ptr(method->it));
-    } else {
-      method->ext_free(ret);
-    }
+    ASN1_item_free(ret, ASN1_ITEM_ptr(method->it));
     OPENSSL_PUT_ERROR(X509V3, X509V3_R_TRAILING_DATA_IN_EXTENSION);
     return NULL;
   }
diff --git a/src/crypto/x509v3/v3_prn.c b/src/crypto/x509v3/v3_prn.c
index ce9c187..f6260e2 100644
--- a/src/crypto/x509v3/v3_prn.c
+++ b/src/crypto/x509v3/v3_prn.c
@@ -105,59 +105,47 @@
 
 int X509V3_EXT_print(BIO *out, const X509_EXTENSION *ext, unsigned long flag,
                      int indent) {
-  void *ext_str = NULL;
-  char *value = NULL;
-  const X509V3_EXT_METHOD *method;
-  STACK_OF(CONF_VALUE) *nval = NULL;
-  int ok = 1;
-
-  if (!(method = X509V3_EXT_get(ext))) {
+  const X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
+  if (method == NULL) {
     return unknown_ext_print(out, ext, flag, indent, 0);
   }
   const ASN1_STRING *ext_data = X509_EXTENSION_get_data(ext);
   const unsigned char *p = ASN1_STRING_get0_data(ext_data);
-  if (method->it) {
-    ext_str = ASN1_item_d2i(NULL, &p, ASN1_STRING_length(ext_data),
-                            ASN1_ITEM_ptr(method->it));
-  } else {
-    ext_str = method->d2i(NULL, &p, ASN1_STRING_length(ext_data));
-  }
-
+  void *ext_str = ASN1_item_d2i(NULL, &p, ASN1_STRING_length(ext_data),
+                                ASN1_ITEM_ptr(method->it));
   if (!ext_str) {
     return unknown_ext_print(out, ext, flag, indent, 1);
   }
 
+  char *value = NULL;
+  STACK_OF(CONF_VALUE) *nval = NULL;
+  int ok = 0;
   if (method->i2s) {
     if (!(value = method->i2s(method, ext_str))) {
-      ok = 0;
       goto err;
     }
     BIO_printf(out, "%*s%s", indent, "", value);
   } else if (method->i2v) {
     if (!(nval = method->i2v(method, ext_str, NULL))) {
-      ok = 0;
       goto err;
     }
     X509V3_EXT_val_prn(out, nval, indent,
                        method->ext_flags & X509V3_EXT_MULTILINE);
   } else if (method->i2r) {
     if (!method->i2r(method, ext_str, out, indent)) {
-      ok = 0;
+      goto err;
     }
   } else {
-    ok = 0;
+    OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+    goto err;
   }
 
+  ok = 1;
+
 err:
   sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
-  if (value) {
-    OPENSSL_free(value);
-  }
-  if (method->it) {
-    ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
-  } else {
-    method->ext_free(ext_str);
-  }
+  OPENSSL_free(value);
+  ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
   return ok;
 }
 
diff --git a/src/crypto/x509v3/v3_skey.c b/src/crypto/x509v3/v3_skey.c
index cae776f..caa7fe5 100644
--- a/src/crypto/x509v3/v3_skey.c
+++ b/src/crypto/x509v3/v3_skey.c
@@ -54,12 +54,14 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/obj.h>
+#include <openssl/mem.h>
 #include <openssl/x509v3.h>
 
 #include "../x509/internal.h"
@@ -74,21 +76,26 @@
 ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method,
                                          const X509V3_CTX *ctx,
                                          const char *str) {
-  ASN1_OCTET_STRING *oct;
-  long length;
-
-  if (!(oct = ASN1_OCTET_STRING_new())) {
+  size_t len;
+  uint8_t *data = x509v3_hex_to_bytes(str, &len);
+  if (data == NULL) {
     return NULL;
   }
-
-  if (!(oct->data = x509v3_hex_to_bytes(str, &length))) {
-    ASN1_OCTET_STRING_free(oct);
-    return NULL;
+  if (len > INT_MAX) {
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
+    goto err;
   }
 
-  oct->length = length;
-
+  ASN1_OCTET_STRING *oct = ASN1_OCTET_STRING_new();
+  if (oct == NULL) {
+    goto err;
+  }
+  ASN1_STRING_set0(oct, data, (int)len);
   return oct;
+
+err:
+  OPENSSL_free(data);
+  return NULL;
 }
 
 static char *i2s_ASN1_OCTET_STRING_cb(const X509V3_EXT_METHOD *method,
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index 183cf6a..bbc82e2 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -494,7 +494,7 @@
   return NULL;
 }
 
-unsigned char *x509v3_hex_to_bytes(const char *str, long *len) {
+unsigned char *x509v3_hex_to_bytes(const char *str, size_t *len) {
   unsigned char *hexbuf, *q;
   unsigned char ch, cl, *p;
   uint8_t high, low;
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
index 131cfec..2633880 100644
--- a/src/include/openssl/aead.h
+++ b/src/include/openssl/aead.h
@@ -408,8 +408,6 @@
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
 
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void);
-
 // EVP_aead_aes_128_gcm_tls12 is AES-128 in Galois Counter Mode using the TLS
 // 1.2 nonce construction.
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_tls12(void);
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 5df6816..d128c8d 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -740,15 +740,17 @@
 // the result. If |out| is NULL, it returns the selected output type without
 // constructing an |ASN1_STRING|. On error, this function returns -1.
 OPENSSL_EXPORT int ASN1_mbstring_copy(ASN1_STRING **out, const uint8_t *in,
-                                      int len, int inform, unsigned long mask);
+                                      ossl_ssize_t len, int inform,
+                                      unsigned long mask);
 
 // ASN1_mbstring_ncopy behaves like |ASN1_mbstring_copy| but returns an error if
 // the input is less than |minsize| or greater than |maxsize| codepoints long. A
 // |maxsize| value of zero is ignored. Note the sizes are measured in
 // codepoints, not output bytes.
 OPENSSL_EXPORT int ASN1_mbstring_ncopy(ASN1_STRING **out, const uint8_t *in,
-                                       int len, int inform, unsigned long mask,
-                                       long minsize, long maxsize);
+                                       ossl_ssize_t len, int inform,
+                                       unsigned long mask, ossl_ssize_t minsize,
+                                       ossl_ssize_t maxsize);
 
 // ASN1_STRING_set_by_NID behaves like |ASN1_mbstring_ncopy|, but determines
 // |mask|, |minsize|, and |maxsize| based on |nid|. When |nid| is a recognized
@@ -774,7 +776,7 @@
 // to call |ASN1_mbstring_ncopy| directly instead.
 OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
                                                    const unsigned char *in,
-                                                   int len, int inform,
+                                                   ossl_ssize_t len, int inform,
                                                    int nid);
 
 // STABLE_NO_MASK causes |ASN1_STRING_TABLE_add| to allow types other than
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index fb1815f..80d18a7 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -221,6 +221,33 @@
 
 #endif  // defined(BORINGSSL_SHARED_LIBRARY)
 
+#if defined(_MSC_VER)
+
+// OPENSSL_DEPRECATED is used to mark a function as deprecated. Use
+// of any functions so marked in caller code will produce a warning.
+// OPENSSL_BEGIN_ALLOW_DEPRECATED and OPENSSL_END_ALLOW_DEPRECATED
+// can be used to suppress the warning in regions of caller code.
+#define OPENSSL_DEPRECATED __declspec(deprecated)
+#define OPENSSL_BEGIN_ALLOW_DEPRECATED \
+  __pragma(warning(push)) __pragma(warning(disable : 4996))
+#define OPENSSL_END_ALLOW_DEPRECATED __pragma(warning(pop))
+
+#elif defined(__GNUC__) || defined(__clang__)
+
+#define OPENSSL_DEPRECATED __attribute__((__deprecated__))
+#define OPENSSL_BEGIN_ALLOW_DEPRECATED \
+  _Pragma("GCC diagnostic push")       \
+      _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define OPENSSL_END_ALLOW_DEPRECATED _Pragma("GCC diagnostic pop")
+
+#else
+
+#define OPENSSL_DEPRECATED
+#define OPENSSL_BEGIN_ALLOW_DEPRECATED
+#define OPENSSL_END_ALLOW_DEPRECATED
+
+#endif
+
 
 #if defined(__GNUC__) || defined(__clang__)
 // MinGW has two different printf implementations. Ensure the format macro
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 01ea69c..707a4b1 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -107,14 +107,14 @@
 // bytes read, zero on EOF, or a negative number on error.
 OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len);
 
-// BIO_gets "reads a line" from |bio| and puts at most |size| bytes into |buf|.
-// It returns the number of bytes read or a negative number on error. The
-// phrase "reads a line" is in quotes in the previous sentence because the
-// exact operation depends on the BIO's method. For example, a digest BIO will
-// return the digest in response to a |BIO_gets| call.
+// BIO_gets reads a line from |bio| and writes at most |size| bytes into |buf|.
+// It returns the number of bytes read or a negative number on error. This
+// function's output always includes a trailing NUL byte, so it will read at
+// most |size - 1| bytes.
 //
-// TODO(fork): audit the set of BIOs that we end up needing. If all actually
-// return a line for this call, remove the warning above.
+// If the function read a complete line, the output will include the newline
+// character, '\n'. If no newline was found before |size - 1| bytes or EOF, it
+// outputs the bytes which were available.
 OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size);
 
 // BIO_write writes |len| bytes from |data| to |bio|. It returns the number of
@@ -873,7 +873,6 @@
 #define BIO_C_GET_FILE_PTR 107
 #define BIO_C_SET_FILENAME 108
 #define BIO_C_SET_SSL 109
-#define BIO_C_GET_SSL 110
 #define BIO_C_SET_MD 111
 #define BIO_C_GET_MD 112
 #define BIO_C_GET_CIPHER_STATUS 113
@@ -887,9 +886,6 @@
 #define BIO_C_GET_PROXY_PARAM 121
 #define BIO_C_SET_BUFF_READ_DATA 122  // data to read first
 #define BIO_C_GET_ACCEPT 124
-#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125
-#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126
-#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
 #define BIO_C_FILE_SEEK 128
 #define BIO_C_GET_CIPHER_CTX 129
 #define BIO_C_SET_BUF_MEM_EOF_RETURN 130  // return end of input value
diff --git a/src/include/openssl/nid.h b/src/include/openssl/nid.h
index cf5691d..64c9c9c 100644
--- a/src/include/openssl/nid.h
+++ b/src/include/openssl/nid.h
@@ -4235,9 +4235,6 @@
 #define LN_auth_any "auth-any"
 #define NID_auth_any 958
 
-#define SN_CECPQ2 "CECPQ2"
-#define NID_CECPQ2 959
-
 #define SN_ED448 "ED448"
 #define NID_ED448 960
 #define OBJ_ED448 1L, 3L, 101L, 113L
diff --git a/src/include/openssl/pem.h b/src/include/openssl/pem.h
index 9319ac8..21885ba 100644
--- a/src/include/openssl/pem.h
+++ b/src/include/openssl/pem.h
@@ -372,9 +372,6 @@
 // password.
 OPENSSL_EXPORT int PEM_def_callback(char *buf, int size, int rwflag,
                                     void *userdata);
-OPENSSL_EXPORT void PEM_proc_type(char *buf, int type);
-OPENSSL_EXPORT void PEM_dek_info(char *buf, const char *type, int len,
-                                 char *str);
 
 
 DECLARE_PEM_rw(X509, X509)
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index a3b6a86..5b5e3fe 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -1449,9 +1449,6 @@
 //
 //   |SHA1|, and its alias |SHA|, match legacy cipher suites using HMAC-SHA1.
 //
-// Although implemented, authentication-only ciphers match no rules and must be
-// explicitly selected by name.
-//
 // Deprecated cipher rules:
 //
 //   |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|,
@@ -2334,7 +2331,6 @@
 #define SSL_CURVE_SECP384R1 24
 #define SSL_CURVE_SECP521R1 25
 #define SSL_CURVE_X25519 29
-#define SSL_CURVE_CECPQ2 16696
 #define SSL_CURVE_X25519KYBER768 0x6399
 #define SSL_CURVE_P256KYBER768 0xfe32
 
@@ -2411,21 +2407,51 @@
 
 // SSL_CTX_set_verify configures certificate verification behavior. |mode| is
 // one of the |SSL_VERIFY_*| values defined above. |callback|, if not NULL, is
-// used to customize certificate verification. See the behavior of
-// |X509_STORE_CTX_set_verify_cb|.
+// used to customize certificate verification, but is deprecated. See
+// |X509_STORE_CTX_set_verify_cb| for details.
 //
 // The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| with
 // |X509_STORE_CTX_get_ex_data| to look up the |SSL| from |store_ctx|.
+//
+// WARNING: |callback| should be NULL. This callback does not replace the
+// default certificate verification process and is, instead, called multiple
+// times in the course of that process. It is very difficult to implement this
+// callback safely, without inadvertently relying on implementation details or
+// making incorrect assumptions about when the callback is called.
+//
+// Instead, use |SSL_CTX_set_custom_verify| or
+// |SSL_CTX_set_cert_verify_callback| to customize certificate verification.
+// Those callbacks can inspect the peer-sent chain, call |X509_verify_cert| and
+// inspect the result, or perform other operations more straightforwardly.
+//
+// TODO(crbug.com/boringssl/426): We cite |X509_STORE_CTX_set_verify_cb| but
+// haven't documented it yet. Later that will have a more detailed warning about
+// why one should not use this callback.
 OPENSSL_EXPORT void SSL_CTX_set_verify(
     SSL_CTX *ctx, int mode, int (*callback)(int ok, X509_STORE_CTX *store_ctx));
 
 // SSL_set_verify configures certificate verification behavior. |mode| is one of
 // the |SSL_VERIFY_*| values defined above. |callback|, if not NULL, is used to
-// customize certificate verification. See the behavior of
+// customize certificate verification, but is deprecated. See the behavior of
 // |X509_STORE_CTX_set_verify_cb|.
 //
 // The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| with
 // |X509_STORE_CTX_get_ex_data| to look up the |SSL| from |store_ctx|.
+//
+// WARNING: |callback| should be NULL. This callback does not replace the
+// default certificate verification process and is, instead, called multiple
+// times in the course of that process. It is very difficult to implement this
+// callback safely, without inadvertently relying on implementation details or
+// making incorrect assumptions about when the callback is called.
+//
+// Instead, use |SSL_set_custom_verify| or |SSL_CTX_set_cert_verify_callback| to
+// customize certificate verification. Those callbacks can inspect the peer-sent
+// chain, call |X509_verify_cert| and inspect the result, or perform other
+// operations more straightforwardly.
+//
+// TODO(crbug.com/boringssl/426): We cite |X509_STORE_CTX_set_verify_cb| but
+// haven't documented it yet. Later that will have a more detailed warning about
+// why one should not use this callback.
 OPENSSL_EXPORT void SSL_set_verify(SSL *ssl, int mode,
                                    int (*callback)(int ok,
                                                    X509_STORE_CTX *store_ctx));
@@ -4528,13 +4554,6 @@
 // SSL_CIPHER_get_version returns the string "TLSv1/SSLv3".
 OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
 
-// SSL_CIPHER_get_rfc_name returns a newly-allocated string containing the
-// result of |SSL_CIPHER_standard_name| or NULL on error. The caller is
-// responsible for calling |OPENSSL_free| on the result.
-//
-// Use |SSL_CIPHER_standard_name| instead.
-OPENSSL_EXPORT char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher);
-
 typedef void COMP_METHOD;
 typedef struct ssl_comp_st SSL_COMP;
 
@@ -5168,6 +5187,10 @@
 // parameters of a TLS connection.
 
 enum ssl_compliance_policy_t BORINGSSL_ENUM_INT {
+  // ssl_compliance_policy_none does nothing. However, since setting this
+  // doesn't undo other policies it's an error to try and set it.
+  ssl_compliance_policy_none,
+
   // ssl_policy_fips_202205 configures a TLS connection to use:
   //   * TLS 1.2 or 1.3
   //   * For TLS 1.2, only ECDHE_[RSA|ECDSA]_WITH_AES_*_GCM_SHA*.
@@ -5182,12 +5205,32 @@
   // Note: this setting aids with compliance with NIST requirements but does not
   // guarantee it. Careful reading of SP 800-52r2 is recommended.
   ssl_compliance_policy_fips_202205,
+
+  // ssl_compliance_policy_wpa3_192_202304 configures a TLS connection to use:
+  //   * TLS 1.2 or 1.3.
+  //   * For TLS 1.2, only TLS_ECDHE_[ECDSA|RSA]_WITH_AES_256_GCM_SHA384.
+  //   * For TLS 1.3, only AES-256-GCM.
+  //   * P-384 for key agreement.
+  //   * For handshake signatures, only ECDSA with P-384 and SHA-384, or RSA
+  //     with SHA-384 or SHA-512.
+  //
+  // No limitations on the certificate chain nor leaf public key are imposed,
+  // other than by the supported signature algorithms. But WPA3's "192-bit"
+  // mode requires at least P-384 or 3072-bit along the chain. The caller must
+  // enforce this themselves on the verified chain using functions such as
+  // `X509_STORE_CTX_get0_chain`.
+  //
+  // Note that this setting is less secure than the default. The
+  // implementation risks of using a more obscure primitive like P-384
+  // dominate other considerations.
+  ssl_compliance_policy_wpa3_192_202304,
 };
 
 // SSL_CTX_set_compliance_policy configures various aspects of |ctx| based on
 // the given policy requirements. Subsequently calling other functions that
 // configure |ctx| may override |policy|, or may not. This should be the final
-// configuration function called in order to have defined behaviour.
+// configuration function called in order to have defined behaviour. It's a
+// fatal error if |policy| is |ssl_compliance_policy_none|.
 OPENSSL_EXPORT int SSL_CTX_set_compliance_policy(
     SSL_CTX *ctx, enum ssl_compliance_policy_t policy);
 
@@ -5420,6 +5463,18 @@
     const SSL *ssl, Span<const uint8_t> *out_read_traffic_secret,
     Span<const uint8_t> *out_write_traffic_secret);
 
+// SSL_CTX_set_aes_hw_override_for_testing sets |override_value| to
+// override checking for aes hardware support for testing. If |override_value|
+// is set to true, the library will behave as if aes hardware support is
+// present. If it is set to false, the library will behave as if aes hardware
+// support is not present.
+OPENSSL_EXPORT void SSL_CTX_set_aes_hw_override_for_testing(
+    SSL_CTX *ctx, bool override_value);
+
+// SSL_set_aes_hw_override_for_testing acts the same as
+// |SSL_CTX_set_aes_override_for_testing| but only configures a single |SSL*|.
+OPENSSL_EXPORT void SSL_set_aes_hw_override_for_testing(SSL *ssl,
+                                                        bool override_value);
 
 BSSL_NAMESPACE_END
 
diff --git a/src/include/openssl/trust_token.h b/src/include/openssl/trust_token.h
index 03ce4b8..b6aa6b3 100644
--- a/src/include/openssl/trust_token.h
+++ b/src/include/openssl/trust_token.h
@@ -48,6 +48,14 @@
 // PMBTokens and P-384 with up to 3 keys, without RR verification.
 OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v2_pmb(void);
 
+// TRUST_TOKEN_pst_v1_voprf is an experimental Trust Tokens protocol
+// using VOPRFs and P-384 with up to 6 keys, without RR verification.
+OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_voprf(void);
+
+// TRUST_TOKEN_pst_v1_pmb is an experimental Trust Tokens protocol using
+// PMBTokens and P-384 with up to 3 keys, without RR verification.
+OPENSSL_EXPORT const TRUST_TOKEN_METHOD *TRUST_TOKEN_pst_v1_pmb(void);
+
 // trust_token_st represents a single-use token for the Trust Token protocol.
 // For the client, this is the token and its corresponding signature. For the
 // issuer, this is the token itself.
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 9e9e5b1..8deb767 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -277,6 +277,12 @@
 // |i2d_re_X509_tbs| instead.
 OPENSSL_EXPORT int i2d_X509_tbs(X509 *x509, unsigned char **outp);
 
+// X509_verify checks that |x509| has a valid signature by |pkey|. It returns
+// one if the signature is valid and zero otherwise. Note this function only
+// checks the signature itself and does not perform a full certificate
+// validation.
+OPENSSL_EXPORT int X509_verify(X509 *x509, EVP_PKEY *pkey);
+
 
 // Issuing certificates.
 //
@@ -342,16 +348,17 @@
 OPENSSL_EXPORT int X509_add_ext(X509 *x, const X509_EXTENSION *ex, int loc);
 
 // X509_sign signs |x509| with |pkey| and replaces the signature algorithm and
-// signature fields. It returns one on success and zero on error. This function
-// uses digest algorithm |md|, or |pkey|'s default if NULL. Other signing
-// parameters use |pkey|'s defaults. To customize them, use |X509_sign_ctx|.
+// signature fields. It returns the length of the signature on success and zero
+// on error. This function uses digest algorithm |md|, or |pkey|'s default if
+// NULL. Other signing parameters use |pkey|'s defaults. To customize them, use
+// |X509_sign_ctx|.
 OPENSSL_EXPORT int X509_sign(X509 *x509, EVP_PKEY *pkey, const EVP_MD *md);
 
 // X509_sign_ctx signs |x509| with |ctx| and replaces the signature algorithm
-// and signature fields. It returns one on success and zero on error. The
-// signature algorithm and parameters come from |ctx|, which must have been
-// initialized with |EVP_DigestSignInit|. The caller should configure the
-// corresponding |EVP_PKEY_CTX| before calling this function.
+// and signature fields. It returns the length of the signature on success and
+// zero on error. The signature algorithm and parameters come from |ctx|, which
+// must have been initialized with |EVP_DigestSignInit|. The caller should
+// configure the corresponding |EVP_PKEY_CTX| before calling this function.
 OPENSSL_EXPORT int X509_sign_ctx(X509 *x509, EVP_MD_CTX *ctx);
 
 // i2d_re_X509_tbs serializes the TBSCertificate portion of |x509|, as described
@@ -413,13 +420,13 @@
 // NULL, the alias is cleared instead. Aliases are not part of the certificate
 // itself and will not be serialized by |i2d_X509|.
 OPENSSL_EXPORT int X509_alias_set1(X509 *x509, const unsigned char *name,
-                                   int len);
+                                   ossl_ssize_t len);
 
 // X509_keyid_set1 sets |x509|'s key ID to |len| bytes from |id|. If |id| is
 // NULL, the key ID is cleared instead. Key IDs are not part of the certificate
 // itself and will not be serialized by |i2d_X509|.
 OPENSSL_EXPORT int X509_keyid_set1(X509 *x509, const unsigned char *id,
-                                   int len);
+                                   ossl_ssize_t len);
 
 // X509_alias_get0 looks up |x509|'s alias. If found, it sets |*out_len| to the
 // alias's length and returns a pointer to a buffer containing the contents. If
@@ -576,6 +583,10 @@
 // instead.
 OPENSSL_EXPORT int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp);
 
+// X509_CRL_verify checks that |crl| has a valid signature by |pkey|. It returns
+// one if the signature is valid and zero otherwise.
+OPENSSL_EXPORT int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey);
+
 
 // Issuing certificate revocation lists.
 //
@@ -624,18 +635,18 @@
                                     int loc);
 
 // X509_CRL_sign signs |crl| with |pkey| and replaces the signature algorithm
-// and signature fields. It returns one on success and zero on error. This
-// function uses digest algorithm |md|, or |pkey|'s default if NULL. Other
-// signing parameters use |pkey|'s defaults. To customize them, use
-// |X509_CRL_sign_ctx|.
+// and signature fields. It returns the length of the signature on success and
+// zero on error. This function uses digest algorithm |md|, or |pkey|'s default
+// if NULL. Other signing parameters use |pkey|'s defaults. To customize them,
+// use |X509_CRL_sign_ctx|.
 OPENSSL_EXPORT int X509_CRL_sign(X509_CRL *crl, EVP_PKEY *pkey,
                                  const EVP_MD *md);
 
 // X509_CRL_sign_ctx signs |crl| with |ctx| and replaces the signature algorithm
-// and signature fields. It returns one on success and zero on error. The
-// signature algorithm and parameters come from |ctx|, which must have been
-// initialized with |EVP_DigestSignInit|. The caller should configure the
-// corresponding |EVP_PKEY_CTX| before calling this function.
+// and signature fields. It returns the length of the signature on success and
+// zero on error. The signature algorithm and parameters come from |ctx|, which
+// must have been initialized with |EVP_DigestSignInit|. The caller should
+// configure the corresponding |EVP_PKEY_CTX| before calling this function.
 OPENSSL_EXPORT int X509_CRL_sign_ctx(X509_CRL *crl, EVP_MD_CTX *ctx);
 
 // i2d_re_X509_CRL_tbs serializes the TBSCertList portion of |crl|, as described
@@ -710,7 +721,6 @@
 // mutated.
 OPENSSL_EXPORT int i2d_X509_REQ(X509_REQ *req, uint8_t **outp);
 
-
 // X509_REQ_VERSION_1 is the version constant for |X509_REQ| objects. No other
 // versions are defined.
 #define X509_REQ_VERSION_1 0
@@ -731,6 +741,46 @@
 // |EVP_PKEY_free| when done.
 OPENSSL_EXPORT EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req);
 
+// X509_REQ_get_attr_count returns the number of attributes in |req|.
+OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req);
+
+// X509_REQ_get_attr returns the attribute at index |loc| in |req|, or NULL if
+// out of bounds.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+
+// X509_REQ_get_attr_by_NID returns the index of the attribute in |req| of type
+// |nid|, or a negative number if not found. If found, callers can use
+// |X509_REQ_get_attr| to look up the attribute by index.
+//
+// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers
+// can thus loop over all matching attributes by first passing -1 and then
+// passing the previously-returned value until no match is returned.
+OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+                                            int lastpos);
+
+// X509_REQ_get_attr_by_OBJ behaves like |X509_REQ_get_attr_by_NID| but looks
+// for attributes of type |obj|.
+OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req,
+                                            const ASN1_OBJECT *obj,
+                                            int lastpos);
+
+// X509_REQ_extension_nid returns one if |nid| is a supported CSR attribute type
+// for carrying extensions and zero otherwise. The supported types are
+// |NID_ext_req| (pkcs-9-at-extensionRequest from RFC 2985) and |NID_ms_ext_req|
+// (a Microsoft szOID_CERT_EXTENSIONS variant).
+OPENSSL_EXPORT int X509_REQ_extension_nid(int nid);
+
+// X509_REQ_get_extensions decodes the list of requested extensions in |req| and
+// returns a newly-allocated |STACK_OF(X509_EXTENSION)| containing the result.
+// It returns NULL on error, or if |req| did not request extensions.
+//
+// CSRs do not store extensions directly. Instead there are attribute types
+// which are defined to hold extensions. See |X509_REQ_extension_nid|. This
+// function supports both pkcs-9-at-extensionRequest from RFC 2985 and the
+// Microsoft szOID_CERT_EXTENSIONS variant. If both are present,
+// pkcs-9-at-extensionRequest is preferred.
+OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+
 // X509_REQ_get0_signature sets |*out_sig| and |*out_alg| to the signature and
 // signature algorithm of |req|, respectively. Either output pointer may be NULL
 // to ignore the value.
@@ -743,6 +793,10 @@
 // a known NID.
 OPENSSL_EXPORT int X509_REQ_get_signature_nid(const X509_REQ *req);
 
+// X509_REQ_verify checks that |req| has a valid signature by |pkey|. It returns
+// one if the signature is valid and zero otherwise.
+OPENSSL_EXPORT int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey);
+
 
 // Issuing certificate requests.
 //
@@ -770,19 +824,68 @@
 // and internally copies and updates reference counts as needed.
 OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *req, EVP_PKEY *pkey);
 
+// X509_REQ_delete_attr removes the attribute at index |loc| in |req|. It
+// returns the removed attribute to the caller, or NULL if |loc| was out of
+// bounds. If non-NULL, the caller must release the result with
+// |X509_ATTRIBUTE_free| when done. It is also safe, but not necessary, to call
+// |X509_ATTRIBUTE_free| if the result is NULL.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+
+// X509_REQ_add1_attr appends a copy of |attr| to |req|'s list of attributes. It
+// returns one on success and zero on error.
+OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req,
+                                      const X509_ATTRIBUTE *attr);
+
+// X509_REQ_add1_attr_by_OBJ appends a new attribute to |req| with type |obj|.
+// It returns one on success and zero on error. The value is determined by
+// |X509_ATTRIBUTE_set1_data|.
+//
+// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and
+// error-prone. See |X509_ATTRIBUTE_set1_data| for details.
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+                                             const ASN1_OBJECT *obj,
+                                             int attrtype,
+                                             const unsigned char *data,
+                                             int len);
+
+// X509_REQ_add1_attr_by_NID behaves like |X509_REQ_add1_attr_by_OBJ| except the
+// attribute type is determined by |nid|.
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid,
+                                             int attrtype,
+                                             const unsigned char *data,
+                                             int len);
+
+// X509_REQ_add1_attr_by_txt behaves like |X509_REQ_add1_attr_by_OBJ| except the
+// attribute type is determined by calling |OBJ_txt2obj| with |attrname|.
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+                                             const char *attrname, int attrtype,
+                                             const unsigned char *data,
+                                             int len);
+
+// X509_REQ_add_extensions_nid adds an attribute to |req| of type |nid|, to
+// request the certificate extensions in |exts|. It returns one on success and
+// zero on error. |nid| should be |NID_ext_req| or |NID_ms_ext_req|.
+OPENSSL_EXPORT int X509_REQ_add_extensions_nid(
+    X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid);
+
+// X509_REQ_add_extensions behaves like |X509_REQ_add_extensions_nid|, using the
+// standard |NID_ext_req| for the attribute type.
+OPENSSL_EXPORT int X509_REQ_add_extensions(
+    X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts);
+
 // X509_REQ_sign signs |req| with |pkey| and replaces the signature algorithm
-// and signature fields. It returns one on success and zero on error. This
-// function uses digest algorithm |md|, or |pkey|'s default if NULL. Other
-// signing parameters use |pkey|'s defaults. To customize them, use
-// |X509_REQ_sign_ctx|.
+// and signature fields. It returns the length of the signature on success and
+// zero on error. This function uses digest algorithm |md|, or |pkey|'s default
+// if NULL. Other signing parameters use |pkey|'s defaults. To customize them,
+// use |X509_REQ_sign_ctx|.
 OPENSSL_EXPORT int X509_REQ_sign(X509_REQ *req, EVP_PKEY *pkey,
                                  const EVP_MD *md);
 
 // X509_REQ_sign_ctx signs |req| with |ctx| and replaces the signature algorithm
-// and signature fields. It returns one on success and zero on error. The
-// signature algorithm and parameters come from |ctx|, which must have been
-// initialized with |EVP_DigestSignInit|. The caller should configure the
-// corresponding |EVP_PKEY_CTX| before calling this function.
+// and signature fields. It returns the length of the signature on success and
+// zero on error. The signature algorithm and parameters come from |ctx|, which
+// must have been initialized with |EVP_DigestSignInit|. The caller should
+// configure the corresponding |EVP_PKEY_CTX| before calling this function.
 OPENSSL_EXPORT int X509_REQ_sign_ctx(X509_REQ *req, EVP_MD_CTX *ctx);
 
 // i2d_re_X509_REQ_tbs serializes the CertificationRequestInfo (see RFC 2986)
@@ -940,22 +1043,25 @@
 // |set| as in |X509_NAME_add_entry|.
 OPENSSL_EXPORT int X509_NAME_add_entry_by_OBJ(X509_NAME *name,
                                               const ASN1_OBJECT *obj, int type,
-                                              const uint8_t *bytes, int len,
-                                              int loc, int set);
+                                              const uint8_t *bytes,
+                                              ossl_ssize_t len, int loc,
+                                              int set);
 
 // X509_NAME_add_entry_by_NID behaves like |X509_NAME_add_entry_by_OBJ| but sets
 // the entry's attribute type to |nid|, which should be one of the |NID_*|
 // constants.
 OPENSSL_EXPORT int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid,
                                               int type, const uint8_t *bytes,
-                                              int len, int loc, int set);
+                                              ossl_ssize_t len, int loc,
+                                              int set);
 
 // X509_NAME_add_entry_by_txt behaves like |X509_NAME_add_entry_by_OBJ| but sets
 // the entry's attribute type to |field|, which is passed to |OBJ_txt2obj|.
 OPENSSL_EXPORT int X509_NAME_add_entry_by_txt(X509_NAME *name,
                                               const char *field, int type,
-                                              const uint8_t *bytes, int len,
-                                              int loc, int set);
+                                              const uint8_t *bytes,
+                                              ossl_ssize_t len, int loc,
+                                              int set);
 
 // X509_NAME_ENTRY is an |ASN1_ITEM| whose ASN.1 type is AttributeTypeAndValue
 // (RFC 5280) and C type is |X509_NAME_ENTRY*|.
@@ -1021,7 +1127,8 @@
 // See |ASN1_STRING| for how to format ASN.1 types as an |ASN1_STRING|. If
 // |type| is |V_ASN1_UNDEF| the previous |ASN1_STRING| type is reused.
 OPENSSL_EXPORT int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *entry, int type,
-                                            const uint8_t *bytes, int len);
+                                            const uint8_t *bytes,
+                                            ossl_ssize_t len);
 
 // X509_NAME_ENTRY_set returns the zero-based index of the RDN which contains
 // |entry|. Consecutive entries with the same index are part of the same RDN.
@@ -1037,19 +1144,20 @@
 // object at |*out| instead of allocating a new one.
 OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(
     X509_NAME_ENTRY **out, const ASN1_OBJECT *obj, int type,
-    const uint8_t *bytes, int len);
+    const uint8_t *bytes, ossl_ssize_t len);
 
 // X509_NAME_ENTRY_create_by_NID behaves like |X509_NAME_ENTRY_create_by_OBJ|
 // except the attribute type is |nid|, which should be one of the |NID_*|
 // constants.
 OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(
-    X509_NAME_ENTRY **out, int nid, int type, const uint8_t *bytes, int len);
+    X509_NAME_ENTRY **out, int nid, int type, const uint8_t *bytes,
+    ossl_ssize_t len);
 
 // X509_NAME_ENTRY_create_by_txt behaves like |X509_NAME_ENTRY_create_by_OBJ|
 // except the attribute type is |field|, which is passed to |OBJ_txt2obj|.
 OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(
     X509_NAME_ENTRY **out, const char *field, int type, const uint8_t *bytes,
-    int len);
+    ossl_ssize_t len);
 
 
 // Extensions.
@@ -1291,11 +1399,442 @@
 OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
 
 
+// Attributes.
+//
+// Unlike certificates and CRLs, CSRs use a separate Attribute structure (RFC
+// 2985, RFC 2986) for extensibility. This is represented by the library as
+// |X509_ATTRIBUTE|.
+
+DEFINE_STACK_OF(X509_ATTRIBUTE)
+
+// X509_ATTRIBUTE is an |ASN1_ITEM| whose ASN.1 type is Attribute (RFC 2986) and
+// C type is |X509_ATTRIBUTE*|.
+DECLARE_ASN1_ITEM(X509_ATTRIBUTE)
+
+// X509_ATTRIBUTE_new returns a newly-allocated, empty |X509_ATTRIBUTE| object,
+// or NULL on error. |X509_ATTRIBUTE_set1_*| may be used to finish initializing
+// it.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_new(void);
+
+// X509_ATTRIBUTE_dup returns a newly-allocated copy of |attr|, or NULL on
+// error. This function works by serializing the structure, so if |attr| is
+// incomplete, it may fail.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(const X509_ATTRIBUTE *attr);
+
+// X509_ATTRIBUTE_free releases memory associated with |attr|.
+OPENSSL_EXPORT void X509_ATTRIBUTE_free(X509_ATTRIBUTE *attr);
+
+// d2i_X509_ATTRIBUTE parses up to |len| bytes from |*inp| as a DER-encoded
+// Attribute (RFC 2986), as described in |d2i_SAMPLE|.
+OPENSSL_EXPORT X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **out,
+                                                  const uint8_t **inp,
+                                                  long len);
+
+// i2d_X509_ATTRIBUTE marshals |alg| as a DER-encoded Attribute (RFC 2986), as
+// described in |i2d_SAMPLE|.
+OPENSSL_EXPORT int i2d_X509_ATTRIBUTE(const X509_ATTRIBUTE *alg,
+                                      uint8_t **outp);
+
+// X509_ATTRIBUTE_create returns a newly-allocated |X509_ATTRIBUTE|, or NULL on
+// error. The attribute has type |nid| and contains a single value determined by
+// |attrtype| and |value|, which are interpreted as in |ASN1_TYPE_set|. Note
+// this function takes ownership of |value|.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype,
+                                                     void *value);
+
+// X509_ATTRIBUTE_create_by_NID returns a newly-allocated |X509_ATTRIBUTE| of
+// type |nid|, or NULL on error. The value is determined as in
+// |X509_ATTRIBUTE_set1_data|.
+//
+// If |attr| is non-NULL, the resulting |X509_ATTRIBUTE| is also written to
+// |*attr|. If |*attr| was non-NULL when the function was called, |*attr| is
+// reused instead of creating a new object.
+//
+// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and
+// error-prone. See |X509_ATTRIBUTE_set1_data| for details.
+//
+// WARNING: The object reuse form is deprecated and may be removed in the
+// future. It also currently incorrectly appends to the reused object's value
+// set rather than overwriting it.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(
+    X509_ATTRIBUTE **attr, int nid, int attrtype, const void *data, int len);
+
+// X509_ATTRIBUTE_create_by_OBJ behaves like |X509_ATTRIBUTE_create_by_NID|
+// except the attribute's type is determined by |obj|.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(
+    X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int attrtype,
+    const void *data, int len);
+
+// X509_ATTRIBUTE_create_by_txt behaves like |X509_ATTRIBUTE_create_by_NID|
+// except the attribute's type is determined by calling |OBJ_txt2obj| with
+// |attrname|.
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(
+    X509_ATTRIBUTE **attr, const char *attrname, int type,
+    const unsigned char *bytes, int len);
+
+// X509_ATTRIBUTE_set1_object sets |attr|'s type to |obj|. It returns one on
+// success and zero on error.
+OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr,
+                                              const ASN1_OBJECT *obj);
+
+// X509_ATTRIBUTE_set1_data appends a value to |attr|'s value set and returns
+// one on success or zero on error. The value is determined as follows:
+//
+// If |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 string. The
+// string is determined by decoding |len| bytes from |data| in the encoding
+// specified by |attrtype|, and then re-encoding it in a form appropriate for
+// |attr|'s type. If |len| is -1, |strlen(data)| is used instead. See
+// |ASN1_STRING_set_by_NID| for details.
+//
+// Otherwise, if |len| is not -1, the value is an ASN.1 string. |attrtype| is an
+// |ASN1_STRING| type value and the |len| bytes from |data| are copied as the
+// type-specific representation of |ASN1_STRING|. See |ASN1_STRING| for details.
+//
+// WARNING: If this form is used to construct a negative INTEGER or ENUMERATED,
+// |attrtype| includes the |V_ASN1_NEG| flag for |ASN1_STRING|, but the function
+// forgets to clear the flag for |ASN1_TYPE|. This matches OpenSSL but is
+// probably a bug. For now, do not use this form with negative values.
+//
+// Otherwise, if |len| is -1, the value is constructed by passing |attrtype| and
+// |data| to |ASN1_TYPE_set1|. That is, |attrtype| is an |ASN1_TYPE| type value,
+// and |data| is cast to the corresponding pointer type.
+//
+// WARNING: Despite the name, this function appends to |attr|'s value set,
+// rather than overwriting it. To overwrite the value set, create a new
+// |X509_ATTRIBUTE| with |X509_ATTRIBUTE_new|.
+//
+// WARNING: If using the |MBSTRING_*| form, pass a length rather than relying on
+// |strlen|. In particular, |strlen| will not behave correctly if the input is
+// |MBSTRING_BMP| or |MBSTRING_UNIV|.
+//
+// WARNING: This function currently misinterprets |V_ASN1_OTHER| as an
+// |MBSTRING_*| constant. This matches OpenSSL but means it is impossible to
+// construct a value with a non-universal tag.
+OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
+                                            const void *data, int len);
+
+// X509_ATTRIBUTE_get0_data returns the |idx|th value of |attr| in a
+// type-specific representation to |attrtype|, or NULL if out of bounds or the
+// type does not match. |attrtype| is one of the type values in |ASN1_TYPE|. On
+// match, the return value uses the same representation as |ASN1_TYPE_set0|. See
+// |ASN1_TYPE| for details.
+OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+                                              int attrtype, void *unused);
+
+// X509_ATTRIBUTE_count returns the number of values in |attr|.
+OPENSSL_EXPORT int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr);
+
+// X509_ATTRIBUTE_get0_object returns the type of |attr|.
+OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+
+// X509_ATTRIBUTE_get0_type returns the |idx|th value in |attr|, or NULL if out
+// of bounds. Note this function returns one of |attr|'s values, not the type.
+OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr,
+                                                   int idx);
+
+
+// SignedPublicKeyAndChallenge structures.
+//
+// The SignedPublicKeyAndChallenge (SPKAC) is a legacy structure to request
+// certificates, primarily in the legacy <keygen> HTML tag. An SPKAC structure
+// is represented by a |NETSCAPE_SPKI| structure.
+//
+// The structure is described in
+// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen
+
+// A Netscape_spki_st, or |NETSCAPE_SPKI|, represents a
+// SignedPublicKeyAndChallenge structure. Although this structure contains a
+// |spkac| field of type |NETSCAPE_SPKAC|, these are misnamed. The SPKAC is the
+// entire structure, not the signed portion.
+struct Netscape_spki_st {
+  NETSCAPE_SPKAC *spkac;
+  X509_ALGOR *sig_algor;
+  ASN1_BIT_STRING *signature;
+} /* NETSCAPE_SPKI */;
+
+// NETSCAPE_SPKI is an |ASN1_ITEM| whose ASN.1 type is
+// SignedPublicKeyAndChallenge and C type is |NETSCAPE_SPKI*|.
+DECLARE_ASN1_ITEM(NETSCAPE_SPKI)
+
+// NETSCAPE_SPKI_new returns a newly-allocated, empty |NETSCAPE_SPKI| object, or
+// NULL on error.
+OPENSSL_EXPORT NETSCAPE_SPKI *NETSCAPE_SPKI_new(void);
+
+// NETSCAPE_SPKI_free releases memory associated with |spki|.
+OPENSSL_EXPORT void NETSCAPE_SPKI_free(NETSCAPE_SPKI *spki);
+
+// d2i_NETSCAPE_SPKI parses up to |len| bytes from |*inp| as a DER-encoded
+// SignedPublicKeyAndChallenge structure, as described in |d2i_SAMPLE|.
+OPENSSL_EXPORT NETSCAPE_SPKI *d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **out,
+                                                const uint8_t **inp, long len);
+
+// i2d_NETSCAPE_SPKI marshals |spki| as a DER-encoded
+// SignedPublicKeyAndChallenge structure, as described in |i2d_SAMPLE|.
+OPENSSL_EXPORT int i2d_NETSCAPE_SPKI(const NETSCAPE_SPKI *spki, uint8_t **outp);
+
+// NETSCAPE_SPKI_verify checks that |spki| has a valid signature by |pkey|. It
+// returns one if the signature is valid and zero otherwise.
+OPENSSL_EXPORT int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey);
+
+// NETSCAPE_SPKI_b64_decode decodes |len| bytes from |str| as a base64-encoded
+// SignedPublicKeyAndChallenge structure. It returns a newly-allocated
+// |NETSCAPE_SPKI| structure with the result, or NULL on error. If |len| is 0 or
+// negative, the length is calculated with |strlen| and |str| must be a
+// NUL-terminated C string.
+OPENSSL_EXPORT NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str,
+                                                       ossl_ssize_t len);
+
+// NETSCAPE_SPKI_b64_encode encodes |spki| as a base64-encoded
+// SignedPublicKeyAndChallenge structure. It returns a newly-allocated
+// NUL-terminated C string with the result, or NULL on error. The caller must
+// release the memory with |OPENSSL_free| when done.
+OPENSSL_EXPORT char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki);
+
+// NETSCAPE_SPKI_get_pubkey decodes and returns the public key in |spki| as an
+// |EVP_PKEY|, or NULL on error. The caller takes ownership of the resulting
+// pointer and must call |EVP_PKEY_free| when done.
+OPENSSL_EXPORT EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *spki);
+
+// NETSCAPE_SPKI_set_pubkey sets |spki|'s public key to |pkey|. It returns one
+// on success or zero on error. This function does not take ownership of |pkey|,
+// so the caller may continue to manage its lifetime independently of |spki|.
+OPENSSL_EXPORT int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *spki,
+                                            EVP_PKEY *pkey);
+
+// NETSCAPE_SPKI_sign signs |spki| with |pkey| and replaces the signature
+// algorithm and signature fields. It returns the length of the signature on
+// success and zero on error. This function uses digest algorithm |md|, or
+// |pkey|'s default if NULL. Other signing parameters use |pkey|'s defaults.
+OPENSSL_EXPORT int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *spki, EVP_PKEY *pkey,
+                                      const EVP_MD *md);
+
+// A Netscape_spkac_st, or |NETSCAPE_SPKAC|, represents a PublicKeyAndChallenge
+// structure. This type is misnamed. The full SPKAC includes the signature,
+// which is represented with the |NETSCAPE_SPKI| type.
+struct Netscape_spkac_st {
+  X509_PUBKEY *pubkey;
+  ASN1_IA5STRING *challenge;
+} /* NETSCAPE_SPKAC */;
+
+// NETSCAPE_SPKAC is an |ASN1_ITEM| whose ASN.1 type is PublicKeyAndChallenge
+// and C type is |NETSCAPE_SPKAC*|.
+DECLARE_ASN1_ITEM(NETSCAPE_SPKAC)
+
+// NETSCAPE_SPKAC_new returns a newly-allocated, empty |NETSCAPE_SPKAC| object,
+// or NULL on error.
+OPENSSL_EXPORT NETSCAPE_SPKAC *NETSCAPE_SPKAC_new(void);
+
+// NETSCAPE_SPKAC_free releases memory associated with |spkac|.
+OPENSSL_EXPORT void NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *spkac);
+
+// d2i_NETSCAPE_SPKAC parses up to |len| bytes from |*inp| as a DER-encoded
+// PublicKeyAndChallenge structure, as described in |d2i_SAMPLE|.
+OPENSSL_EXPORT NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **out,
+                                                  const uint8_t **inp,
+                                                  long len);
+
+// i2d_NETSCAPE_SPKAC marshals |spkac| as a DER-encoded PublicKeyAndChallenge
+// structure, as described in |i2d_SAMPLE|.
+OPENSSL_EXPORT int i2d_NETSCAPE_SPKAC(const NETSCAPE_SPKAC *spkac,
+                                      uint8_t **outp);
+
+
 // Printing functions.
 //
 // The following functions output human-readable representations of
 // X.509-related structures. They should only be used for debugging or logging
-// and not parsed programmatically.
+// and not parsed programmatically. In many cases, the outputs are ambiguous, so
+// attempting to parse them can lead to string injection vulnerabilities.
+
+// The following flags control |X509_print_ex| and |X509_REQ_print_ex|.
+
+// X509_FLAG_COMPAT disables all flags. It additionally causes names to be
+// printed with a 16-byte indent.
+#define X509_FLAG_COMPAT 0
+
+// X509_FLAG_NO_HEADER skips a header identifying the type of object printed.
+#define X509_FLAG_NO_HEADER 1L
+
+// X509_FLAG_NO_VERSION skips printing the X.509 version number.
+#define X509_FLAG_NO_VERSION (1L << 1)
+
+// X509_FLAG_NO_SERIAL skips printing the serial number. It is ignored in
+// |X509_REQ_print_fp|.
+#define X509_FLAG_NO_SERIAL (1L << 2)
+
+// X509_FLAG_NO_SIGNAME skips printing the signature algorithm in the
+// TBSCertificate. It is ignored in |X509_REQ_print_fp|.
+#define X509_FLAG_NO_SIGNAME (1L << 3)
+
+// X509_FLAG_NO_ISSUER skips printing the issuer.
+#define X509_FLAG_NO_ISSUER (1L << 4)
+
+// X509_FLAG_NO_VALIDITY skips printing the notBefore and notAfter times. It is
+// ignored in |X509_REQ_print_fp|.
+#define X509_FLAG_NO_VALIDITY (1L << 5)
+
+// X509_FLAG_NO_SUBJECT skips printing the subject.
+#define X509_FLAG_NO_SUBJECT (1L << 6)
+
+// X509_FLAG_NO_PUBKEY skips printing the public key.
+#define X509_FLAG_NO_PUBKEY (1L << 7)
+
+// X509_FLAG_NO_EXTENSIONS skips printing the extension list. It is ignored in
+// |X509_REQ_print_fp|. CSRs instead have attributes, which is controlled by
+// |X509_FLAG_NO_ATTRIBUTES|.
+#define X509_FLAG_NO_EXTENSIONS (1L << 8)
+
+// X509_FLAG_NO_SIGDUMP skips printing the signature and outer signature
+// algorithm.
+#define X509_FLAG_NO_SIGDUMP (1L << 9)
+
+// X509_FLAG_NO_AUX skips printing auxiliary properties. (See |d2i_X509_AUX| and
+// related functions.)
+#define X509_FLAG_NO_AUX (1L << 10)
+
+// X509_FLAG_NO_ATTRIBUTES skips printing CSR attributes. It does nothing for
+// certificates and CRLs.
+#define X509_FLAG_NO_ATTRIBUTES (1L << 11)
+
+// X509_FLAG_NO_IDS skips printing the issuerUniqueID and subjectUniqueID in a
+// certificate. It is ignored in |X509_REQ_print_fp|.
+#define X509_FLAG_NO_IDS (1L << 12)
+
+// X509_print_ex writes a human-readable representation of |x| to |bp|. It
+// returns one on success and zero on error. |nmflags| is the flags parameter
+// for |X509_NAME_print_ex| when printing the subject and issuer. |cflag| should
+// be some combination of the |X509_FLAG_*| constants.
+OPENSSL_EXPORT int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag,
+                                 unsigned long cflag);
+
+// X509_print_ex_fp behaves like |X509_print_ex| but writes to |fp|.
+OPENSSL_EXPORT int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
+                                    unsigned long cflag);
+
+// X509_print calls |X509_print_ex| with |XN_FLAG_COMPAT| and |X509_FLAG_COMPAT|
+// flags.
+OPENSSL_EXPORT int X509_print(BIO *bp, X509 *x);
+
+// X509_print_fp behaves like |X509_print| but writes to |fp|.
+OPENSSL_EXPORT int X509_print_fp(FILE *fp, X509 *x);
+
+// X509_CRL_print writes a human-readable representation of |x| to |bp|. It
+// returns one on success and zero on error.
+OPENSSL_EXPORT int X509_CRL_print(BIO *bp, X509_CRL *x);
+
+// X509_CRL_print_fp behaves like |X509_CRL_print| but writes to |fp|.
+OPENSSL_EXPORT int X509_CRL_print_fp(FILE *fp, X509_CRL *x);
+
+// X509_REQ_print_ex writes a human-readable representation of |x| to |bp|. It
+// returns one on success and zero on error. |nmflags| is the flags parameter
+// for |X509_NAME_print_ex|, when printing the subject. |cflag| should be some
+// combination of the |X509_FLAG_*| constants.
+OPENSSL_EXPORT int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag,
+                                     unsigned long cflag);
+
+// X509_REQ_print calls |X509_REQ_print_ex| with |XN_FLAG_COMPAT| and
+// |X509_FLAG_COMPAT| flags.
+OPENSSL_EXPORT int X509_REQ_print(BIO *bp, X509_REQ *req);
+
+// X509_REQ_print_fp behaves like |X509_REQ_print| but writes to |fp|.
+OPENSSL_EXPORT int X509_REQ_print_fp(FILE *fp, X509_REQ *req);
+
+// The following flags are control |X509_NAME_print_ex|. They must not collide
+// with |ASN1_STRFLGS_*|.
+//
+// TODO(davidben): This is far, far too many options and most of them are
+// useless. Trim this down.
+
+// XN_FLAG_COMPAT prints with |X509_NAME_print|'s format and return value
+// convention.
+#define XN_FLAG_COMPAT 0
+
+// XN_FLAG_SEP_MASK determines the separators to use between attributes.
+#define XN_FLAG_SEP_MASK (0xf << 16)
+
+// XN_FLAG_SEP_COMMA_PLUS separates RDNs with "," and attributes within an RDN
+// with "+", as in RFC 2253.
+#define XN_FLAG_SEP_COMMA_PLUS (1 << 16)
+
+// XN_FLAG_SEP_CPLUS_SPC behaves like |XN_FLAG_SEP_COMMA_PLUS| but adds spaces
+// between the separators.
+#define XN_FLAG_SEP_CPLUS_SPC (2 << 16)
+
+// XN_FLAG_SEP_SPLUS_SPC separates RDNs with "; " and attributes within an RDN
+// with " + ".
+#define XN_FLAG_SEP_SPLUS_SPC (3 << 16)
+
+// XN_FLAG_SEP_MULTILINE prints each attribute on one line.
+#define XN_FLAG_SEP_MULTILINE (4 << 16)
+
+// XN_FLAG_DN_REV prints RDNs in reverse, from least significant to most
+// significant, as RFC 2253.
+#define XN_FLAG_DN_REV (1 << 20)
+
+// XN_FLAG_FN_MASK determines how attribute types are displayed.
+#define XN_FLAG_FN_MASK (0x3 << 21)
+
+// XN_FLAG_FN_SN uses the attribute type's short name, when available.
+#define XN_FLAG_FN_SN 0
+
+// XN_FLAG_SPC_EQ wraps the "=" operator with spaces when printing attributes.
+#define XN_FLAG_SPC_EQ (1 << 23)
+
+// XN_FLAG_DUMP_UNKNOWN_FIELDS causes unknown attribute types to be printed in
+// hex, as in RFC 2253.
+#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
+
+// XN_FLAG_RFC2253 prints like RFC 2253.
+#define XN_FLAG_RFC2253                                             \
+  (ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | \
+   XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS)
+
+// XN_FLAG_ONELINE prints a one-line representation of the name.
+#define XN_FLAG_ONELINE                                                    \
+  (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | \
+   XN_FLAG_SPC_EQ | XN_FLAG_FN_SN)
+
+// X509_NAME_print_ex writes a human-readable representation of |nm| to |out|.
+// Each line of output is indented by |indent| spaces. It returns the number of
+// bytes written on success, and -1 on error. If |out| is NULL, it returns the
+// number of bytes it would have written but does not write anything. |flags|
+// should be some combination of |XN_FLAG_*| and |ASN1_STRFLGS_*| values and
+// determines the output. If unsure, use |XN_FLAG_RFC2253|.
+//
+// If |flags| is |XN_FLAG_COMPAT|, or zero, this function calls
+// |X509_NAME_print| instead. In that case, it returns one on success, rather
+// than the output length.
+OPENSSL_EXPORT int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
+                                      unsigned long flags);
+
+// X509_NAME_print prints a human-readable representation of |name| to |bp|. It
+// returns one on success and zero on error. |obase| is ignored.
+//
+// This function outputs a legacy format that does not correctly handle string
+// encodings and other cases. Prefer |X509_NAME_print_ex| if printing a name for
+// debugging purposes.
+OPENSSL_EXPORT int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
+
+// X509_NAME_oneline writes a human-readable representation to |name| to a
+// buffer as a NUL-terminated C string.
+//
+// If |buf| is NULL, returns a newly-allocated buffer containing the result on
+// success, or NULL on error. The buffer must be released with |OPENSSL_free|
+// when done.
+//
+// If |buf| is non-NULL, at most |size| bytes of output are written to |buf|
+// instead. |size| includes the trailing NUL. The function then returns |buf| on
+// success or NULL on error. If the output does not fit in |size| bytes, the
+// output is silently truncated at an attribute boundary.
+//
+// This function outputs a legacy format that does not correctly handle string
+// encodings and other cases. Prefer |X509_NAME_print_ex| if printing a name for
+// debugging purposes.
+OPENSSL_EXPORT char *X509_NAME_oneline(const X509_NAME *name, char *buf, int size);
+
+// X509_NAME_print_ex_fp behaves like |X509_NAME_print_ex| but writes to |fp|.
+OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm,
+                                         int indent, unsigned long flags);
 
 // X509_signature_dump writes a human-readable representation of |sig| to |bio|,
 // indented with |indent| spaces. It returns one on success and zero on error.
@@ -1454,6 +1993,39 @@
 OPENSSL_EXPORT X509 *X509_find_by_subject(const STACK_OF(X509) *sk,
                                           X509_NAME *name);
 
+// X509_cmp_time compares |s| against |*t|. On success, it returns a negative
+// number if |s| <= |*t| and a positive number if |s| > |*t|. On error, it
+// returns zero. If |t| is NULL, it uses the current time instead of |*t|.
+//
+// WARNING: Unlike most comparison functions, this function returns zero on
+// error, not equality.
+OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t);
+
+// X509_cmp_time_posix compares |s| against |t|. On success, it returns a
+// negative number if |s| <= |t| and a positive number if |s| > |t|. On error,
+// it returns zero.
+//
+// WARNING: Unlike most comparison functions, this function returns zero on
+// error, not equality.
+OPENSSL_EXPORT int X509_cmp_time_posix(const ASN1_TIME *s, int64_t t);
+
+// X509_cmp_current_time behaves like |X509_cmp_time| but compares |s| against
+// the current time.
+OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s);
+
+// X509_time_adj calls |X509_time_adj_ex| with |offset_day| equal to zero.
+OPENSSL_EXPORT ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec,
+                                        time_t *t);
+
+// X509_time_adj_ex behaves like |ASN1_TIME_adj|, but adds an offset to |*t|. If
+// |t| is NULL, it uses the current time instead of |*t|.
+OPENSSL_EXPORT ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day,
+                                           long offset_sec, time_t *t);
+
+// X509_gmtime_adj behaves like |X509_time_adj_ex| but adds |offset_sec| to the
+// current time.
+OPENSSL_EXPORT ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec);
+
 
 // ex_data functions.
 //
@@ -1575,8 +2147,6 @@
 #define X509v3_KU_DECIPHER_ONLY 0x8000
 #define X509v3_KU_UNDEF 0xffff
 
-DEFINE_STACK_OF(X509_ATTRIBUTE)
-
 // This stuff is certificate "auxiliary info"
 // it contains details which are useful in certificate
 // stores and databases. When used this is tagged onto
@@ -1626,74 +2196,6 @@
 #define X509_TRUST_REJECTED 2
 #define X509_TRUST_UNTRUSTED 3
 
-// Flags for X509_print_ex()
-
-#define X509_FLAG_COMPAT 0
-#define X509_FLAG_NO_HEADER 1L
-#define X509_FLAG_NO_VERSION (1L << 1)
-#define X509_FLAG_NO_SERIAL (1L << 2)
-#define X509_FLAG_NO_SIGNAME (1L << 3)
-#define X509_FLAG_NO_ISSUER (1L << 4)
-#define X509_FLAG_NO_VALIDITY (1L << 5)
-#define X509_FLAG_NO_SUBJECT (1L << 6)
-#define X509_FLAG_NO_PUBKEY (1L << 7)
-#define X509_FLAG_NO_EXTENSIONS (1L << 8)
-#define X509_FLAG_NO_SIGDUMP (1L << 9)
-#define X509_FLAG_NO_AUX (1L << 10)
-#define X509_FLAG_NO_ATTRIBUTES (1L << 11)
-#define X509_FLAG_NO_IDS (1L << 12)
-
-// Flags specific to X509_NAME_print_ex(). These flags must not collide with
-// |ASN1_STRFLGS_*|.
-
-// The field separator information
-
-#define XN_FLAG_SEP_MASK (0xf << 16)
-
-#define XN_FLAG_COMPAT 0  // Traditional SSLeay: use old X509_NAME_print
-#define XN_FLAG_SEP_COMMA_PLUS (1 << 16)  // RFC 2253 ,+
-#define XN_FLAG_SEP_CPLUS_SPC (2 << 16)   // ,+ spaced: more readable
-#define XN_FLAG_SEP_SPLUS_SPC (3 << 16)   // ;+ spaced
-#define XN_FLAG_SEP_MULTILINE (4 << 16)   // One line per field
-
-#define XN_FLAG_DN_REV (1 << 20)  // Reverse DN order
-
-// How the field name is shown
-
-#define XN_FLAG_FN_MASK (0x3 << 21)
-
-#define XN_FLAG_FN_SN 0            // Object short name
-#define XN_FLAG_FN_LN (1 << 21)    // Object long name
-#define XN_FLAG_FN_OID (2 << 21)   // Always use OIDs
-#define XN_FLAG_FN_NONE (3 << 21)  // No field names
-
-#define XN_FLAG_SPC_EQ (1 << 23)  // Put spaces round '='
-
-// This determines if we dump fields we don't recognise:
-// RFC 2253 requires this.
-
-#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
-
-#define XN_FLAG_FN_ALIGN (1 << 25)  // Align field names to 20 characters
-
-// Complete set of RFC 2253 flags
-
-#define XN_FLAG_RFC2253                                             \
-  (ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | \
-   XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS)
-
-// readable oneline form
-
-#define XN_FLAG_ONELINE                                                    \
-  (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | \
-   XN_FLAG_SPC_EQ | XN_FLAG_FN_SN)
-
-// readable multiline form
-
-#define XN_FLAG_MULTILINE                                                 \
-  (ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE | \
-   XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN)
-
 DEFINE_STACK_OF(X509_REVOKED)
 
 DECLARE_STACK_OF(GENERAL_NAMES)
@@ -1729,20 +2231,6 @@
 
 DEFINE_STACK_OF(X509_INFO)
 
-// The next 2 structures and their 8 routines were sent to me by
-// Pat Richard <patr@x509.com> and are used to manipulate
-// Netscapes spki structures - useful if you are writing a CA web page
-struct Netscape_spkac_st {
-  X509_PUBKEY *pubkey;
-  ASN1_IA5STRING *challenge;  // challenge sent in atlas >= PR2
-} /* NETSCAPE_SPKAC */;
-
-struct Netscape_spki_st {
-  NETSCAPE_SPKAC *spkac;  // signed public key and challenge
-  X509_ALGOR *sig_algor;
-  ASN1_BIT_STRING *signature;
-} /* NETSCAPE_SPKI */;
-
 // X509_get_pathlen returns path length constraint from the basic constraints
 // extension in |x509|. (See RFC 5280, section 4.2.1.9.) It returns -1 if the
 // constraint is not present, or if some extension in |x509| was invalid.
@@ -1768,99 +2256,11 @@
 // a default description.
 OPENSSL_EXPORT const char *X509_verify_cert_error_string(long err);
 
-// X509_verify checks that |x509| has a valid signature by |pkey|. It returns
-// one if the signature is valid and zero otherwise. Note this function only
-// checks the signature itself and does not perform a full certificate
-// validation.
-OPENSSL_EXPORT int X509_verify(X509 *x509, EVP_PKEY *pkey);
-
-// X509_REQ_verify checks that |req| has a valid signature by |pkey|. It returns
-// one if the signature is valid and zero otherwise.
-OPENSSL_EXPORT int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey);
-
-// X509_CRL_verify checks that |crl| has a valid signature by |pkey|. It returns
-// one if the signature is valid and zero otherwise.
-OPENSSL_EXPORT int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey);
-
-// NETSCAPE_SPKI_verify checks that |spki| has a valid signature by |pkey|. It
-// returns one if the signature is valid and zero otherwise.
-OPENSSL_EXPORT int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey);
-
-// NETSCAPE_SPKI_b64_decode decodes |len| bytes from |str| as a base64-encoded
-// Netscape signed public key and challenge (SPKAC) structure. It returns a
-// newly-allocated |NETSCAPE_SPKI| structure with the result, or NULL on error.
-// If |len| is 0 or negative, the length is calculated with |strlen| and |str|
-// must be a NUL-terminated C string.
-OPENSSL_EXPORT NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str,
-                                                       int len);
-
-// NETSCAPE_SPKI_b64_encode encodes |spki| as a base64-encoded Netscape signed
-// public key and challenge (SPKAC) structure. It returns a newly-allocated
-// NUL-terminated C string with the result, or NULL on error. The caller must
-// release the memory with |OPENSSL_free| when done.
-OPENSSL_EXPORT char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki);
-
-// NETSCAPE_SPKI_get_pubkey decodes and returns the public key in |spki| as an
-// |EVP_PKEY|, or NULL on error. The caller takes ownership of the resulting
-// pointer and must call |EVP_PKEY_free| when done.
-OPENSSL_EXPORT EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *spki);
-
-// NETSCAPE_SPKI_set_pubkey sets |spki|'s public key to |pkey|. It returns one
-// on success or zero on error. This function does not take ownership of |pkey|,
-// so the caller may continue to manage its lifetime independently of |spki|.
-OPENSSL_EXPORT int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *spki,
-                                            EVP_PKEY *pkey);
-
-// NETSCAPE_SPKI_sign signs |spki| with |pkey| and replaces the signature
-// algorithm and signature fields. It returns one on success and zero on error.
-// This function uses digest algorithm |md|, or |pkey|'s default if NULL. Other
-// signing parameters use |pkey|'s defaults.
-OPENSSL_EXPORT int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *spki, EVP_PKEY *pkey,
-                                      const EVP_MD *md);
-
-// X509_ATTRIBUTE_dup returns a newly-allocated copy of |xa|, or NULL on error.
-// This function works by serializing the structure, so if |xa| is incomplete,
-// it may fail.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(const X509_ATTRIBUTE *xa);
-
 // X509_REVOKED_dup returns a newly-allocated copy of |rev|, or NULL on error.
 // This function works by serializing the structure, so if |rev| is incomplete,
 // it may fail.
 OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(const X509_REVOKED *rev);
 
-// X509_cmp_time compares |s| against |*t|. On success, it returns a negative
-// number if |s| <= |*t| and a positive number if |s| > |*t|. On error, it
-// returns zero. If |t| is NULL, it uses the current time instead of |*t|.
-//
-// WARNING: Unlike most comparison functions, this function returns zero on
-// error, not equality.
-OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t);
-
-// X509_cmp_time_posix compares |s| against |t|. On success, it returns a
-// negative number if |s| <= |t| and a positive number if |s| > |t|. On error,
-// it returns zero.
-//
-// WARNING: Unlike most comparison functions, this function returns zero on
-// error, not equality.
-OPENSSL_EXPORT int X509_cmp_time_posix(const ASN1_TIME *s, int64_t t);
-
-// X509_cmp_current_time behaves like |X509_cmp_time| but compares |s| against
-// the current time.
-OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s);
-
-// X509_time_adj calls |X509_time_adj_ex| with |offset_day| equal to zero.
-OPENSSL_EXPORT ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec,
-                                        time_t *t);
-
-// X509_time_adj_ex behaves like |ASN1_TIME_adj|, but adds an offset to |*t|. If
-// |t| is NULL, it uses the current time instead of |*t|.
-OPENSSL_EXPORT ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day,
-                                           long offset_sec, time_t *t);
-
-// X509_gmtime_adj behaves like |X509_time_adj_ex| but adds |offset_sec| to the
-// current time.
-OPENSSL_EXPORT ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec);
-
 OPENSSL_EXPORT const char *X509_get_default_cert_area(void);
 OPENSSL_EXPORT const char *X509_get_default_cert_dir(void);
 OPENSSL_EXPORT const char *X509_get_default_cert_file(void);
@@ -1883,15 +2283,6 @@
 
 DECLARE_ASN1_FUNCTIONS_const(X509_SIG)
 
-DECLARE_ASN1_FUNCTIONS_const(X509_ATTRIBUTE)
-
-// X509_ATTRIBUTE_create returns a newly-allocated |X509_ATTRIBUTE|, or NULL on
-// error. The attribute has type |nid| and contains a single value determined by
-// |attrtype| and |value|, which are interpreted as in |ASN1_TYPE_set|. Note
-// this function takes ownership of |value|.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype,
-                                                     void *value);
-
 OPENSSL_EXPORT int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
 OPENSSL_EXPORT int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
 OPENSSL_EXPORT void X509_trust_clear(X509 *x);
@@ -1911,12 +2302,8 @@
 OPENSSL_EXPORT X509_PKEY *X509_PKEY_new(void);
 OPENSSL_EXPORT void X509_PKEY_free(X509_PKEY *a);
 
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_SPKI)
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_SPKAC)
-
 OPENSSL_EXPORT X509_INFO *X509_INFO_new(void);
 OPENSSL_EXPORT void X509_INFO_free(X509_INFO *a);
-OPENSSL_EXPORT char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size);
 
 OPENSSL_EXPORT int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
                                unsigned char *md, unsigned int *len);
@@ -1939,93 +2326,6 @@
                                       ASN1_BIT_STRING *signature, void *asn,
                                       EVP_MD_CTX *ctx);
 
-// X509_REQ_extension_nid returns one if |nid| is a supported CSR attribute type
-// for carrying extensions and zero otherwise. The supported types are
-// |NID_ext_req| (pkcs-9-at-extensionRequest from RFC 2985) and |NID_ms_ext_req|
-// (a Microsoft szOID_CERT_EXTENSIONS variant).
-OPENSSL_EXPORT int X509_REQ_extension_nid(int nid);
-
-// X509_REQ_get_extensions decodes the list of requested extensions in |req| and
-// returns a newly-allocated |STACK_OF(X509_EXTENSION)| containing the result.
-// It returns NULL on error, or if |req| did not request extensions.
-//
-// This function supports both pkcs-9-at-extensionRequest from RFC 2985 and the
-// Microsoft szOID_CERT_EXTENSIONS variant.
-OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
-
-// X509_REQ_add_extensions_nid adds an attribute to |req| of type |nid|, to
-// request the certificate extensions in |exts|. It returns one on success and
-// zero on error. |nid| should be |NID_ext_req| or |NID_ms_ext_req|.
-OPENSSL_EXPORT int X509_REQ_add_extensions_nid(
-    X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid);
-
-// X509_REQ_add_extensions behaves like |X509_REQ_add_extensions_nid|, using the
-// standard |NID_ext_req| for the attribute type.
-OPENSSL_EXPORT int X509_REQ_add_extensions(
-    X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts);
-
-// X509_REQ_get_attr_count returns the number of attributes in |req|.
-OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req);
-
-// X509_REQ_get_attr_by_NID returns the index of the attribute in |req| of type
-// |nid|, or a negative number if not found. If found, callers can use
-// |X509_REQ_get_attr| to look up the attribute by index.
-//
-// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers
-// can thus loop over all matching attributes by first passing -1 and then
-// passing the previously-returned value until no match is returned.
-OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
-                                            int lastpos);
-
-// X509_REQ_get_attr_by_OBJ behaves like |X509_REQ_get_attr_by_NID| but looks
-// for attributes of type |obj|.
-OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req,
-                                            const ASN1_OBJECT *obj,
-                                            int lastpos);
-
-// X509_REQ_get_attr returns the attribute at index |loc| in |req|, or NULL if
-// out of bounds.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
-
-// X509_REQ_delete_attr removes the attribute at index |loc| in |req|. It
-// returns the removed attribute to the caller, or NULL if |loc| was out of
-// bounds. If non-NULL, the caller must release the result with
-// |X509_ATTRIBUTE_free| when done. It is also safe, but not necessary, to call
-// |X509_ATTRIBUTE_free| if the result is NULL.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
-
-// X509_REQ_add1_attr appends a copy of |attr| to |req|'s list of attributes. It
-// returns one on success and zero on error.
-//
-// TODO(https://crbug.com/boringssl/407): |attr| should be const.
-OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
-
-// X509_REQ_add1_attr_by_OBJ appends a new attribute to |req| with type |obj|.
-// It returns one on success and zero on error. The value is determined by
-// |X509_ATTRIBUTE_set1_data|.
-//
-// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and
-// error-prone. See |X509_ATTRIBUTE_set1_data| for details.
-OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
-                                             const ASN1_OBJECT *obj,
-                                             int attrtype,
-                                             const unsigned char *data,
-                                             int len);
-
-// X509_REQ_add1_attr_by_NID behaves like |X509_REQ_add1_attr_by_OBJ| except the
-// attribute type is determined by |nid|.
-OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid,
-                                             int attrtype,
-                                             const unsigned char *data,
-                                             int len);
-
-// X509_REQ_add1_attr_by_txt behaves like |X509_REQ_add1_attr_by_OBJ| except the
-// attribute type is determined by calling |OBJ_txt2obj| with |attrname|.
-OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req,
-                                             const char *attrname, int attrtype,
-                                             const unsigned char *data,
-                                             int len);
-
 OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl);
 
 // X509_REVOKED_get0_serialNumber returns the serial number of the certificate
@@ -2077,24 +2377,6 @@
 
 OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
 OPENSSL_EXPORT int X509_CRL_match(const X509_CRL *a, const X509_CRL *b);
-OPENSSL_EXPORT int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag,
-                                    unsigned long cflag);
-OPENSSL_EXPORT int X509_print_fp(FILE *bp, X509 *x);
-OPENSSL_EXPORT int X509_CRL_print_fp(FILE *bp, X509_CRL *x);
-OPENSSL_EXPORT int X509_REQ_print_fp(FILE *bp, X509_REQ *req);
-OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm,
-                                         int indent, unsigned long flags);
-
-OPENSSL_EXPORT int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
-OPENSSL_EXPORT int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
-                                      unsigned long flags);
-OPENSSL_EXPORT int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag,
-                                 unsigned long cflag);
-OPENSSL_EXPORT int X509_print(BIO *bp, X509 *x);
-OPENSSL_EXPORT int X509_CRL_print(BIO *bp, X509_CRL *x);
-OPENSSL_EXPORT int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag,
-                                     unsigned long cflag);
-OPENSSL_EXPORT int X509_REQ_print(BIO *bp, X509_REQ *req);
 
 // X509_get_ext_d2i behaves like |X509V3_get_d2i| but looks for the extension in
 // |x509|'s extension list.
@@ -2190,153 +2472,6 @@
                                              void *value, int crit,
                                              unsigned long flags);
 
-// X509at_get_attr_count returns the number of attributes in |x|.
-OPENSSL_EXPORT int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
-
-// X509at_get_attr_by_NID returns the index of the attribute in |x| of type
-// |nid|, or a negative number if not found. If found, callers can use
-// |X509at_get_attr| to look up the attribute by index.
-//
-// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers
-// can thus loop over all matching attributes by first passing -1 and then
-// passing the previously-returned value until no match is returned.
-OPENSSL_EXPORT int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x,
-                                          int nid, int lastpos);
-
-// X509at_get_attr_by_OBJ behaves like |X509at_get_attr_by_NID| but looks for
-// attributes of type |obj|.
-OPENSSL_EXPORT int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
-                                          const ASN1_OBJECT *obj, int lastpos);
-
-// X509at_get_attr returns the attribute at index |loc| in |x|, or NULL if
-// out of bounds.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509at_get_attr(
-    const STACK_OF(X509_ATTRIBUTE) *x, int loc);
-
-// X509at_delete_attr removes the attribute at index |loc| in |x|. It returns
-// the removed attribute to the caller, or NULL if |loc| was out of bounds. If
-// non-NULL, the caller must release the result with |X509_ATTRIBUTE_free| when
-// done. It is also safe, but not necessary, to call |X509_ATTRIBUTE_free| if
-// the result is NULL.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x,
-                                                  int loc);
-
-// X509at_add1_attr appends a copy of |attr| to the attribute list in |*x|. If
-// |*x| is NULL, it allocates a new |STACK_OF(X509_ATTRIBUTE)| to hold the copy
-// and sets |*x| to the new list. It returns |*x| on success and NULL on error.
-// The caller retains ownership of |attr| and can release it independently of
-// |*x|.
-OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(
-    STACK_OF(X509_ATTRIBUTE) **x, X509_ATTRIBUTE *attr);
-
-// X509at_add1_attr_by_OBJ behaves like |X509at_add1_attr|, but adds an
-// attribute created by |X509_ATTRIBUTE_create_by_OBJ|.
-OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(
-    STACK_OF(X509_ATTRIBUTE) **x, const ASN1_OBJECT *obj, int type,
-    const unsigned char *bytes, int len);
-
-// X509at_add1_attr_by_NID behaves like |X509at_add1_attr|, but adds an
-// attribute created by |X509_ATTRIBUTE_create_by_NID|.
-OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(
-    STACK_OF(X509_ATTRIBUTE) **x, int nid, int type, const unsigned char *bytes,
-    int len);
-
-// X509at_add1_attr_by_txt behaves like |X509at_add1_attr|, but adds an
-// attribute created by |X509_ATTRIBUTE_create_by_txt|.
-OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(
-    STACK_OF(X509_ATTRIBUTE) **x, const char *attrname, int type,
-    const unsigned char *bytes, int len);
-
-// X509_ATTRIBUTE_create_by_NID returns a newly-allocated |X509_ATTRIBUTE| of
-// type |nid|, or NULL on error. The value is determined as in
-// |X509_ATTRIBUTE_set1_data|.
-//
-// If |attr| is non-NULL, the resulting |X509_ATTRIBUTE| is also written to
-// |*attr|. If |*attr| was non-NULL when the function was called, |*attr| is
-// reused instead of creating a new object.
-//
-// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and
-// error-prone. See |X509_ATTRIBUTE_set1_data| for details.
-//
-// WARNING: The object reuse form is deprecated and may be removed in the
-// future. It also currently incorrectly appends to the reused object's value
-// set rather than overwriting it.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(
-    X509_ATTRIBUTE **attr, int nid, int attrtype, const void *data, int len);
-
-// X509_ATTRIBUTE_create_by_OBJ behaves like |X509_ATTRIBUTE_create_by_NID|
-// except the attribute's type is determined by |obj|.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(
-    X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int attrtype,
-    const void *data, int len);
-
-// X509_ATTRIBUTE_create_by_txt behaves like |X509_ATTRIBUTE_create_by_NID|
-// except the attribute's type is determined by calling |OBJ_txt2obj| with
-// |attrname|.
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(
-    X509_ATTRIBUTE **attr, const char *attrname, int type,
-    const unsigned char *bytes, int len);
-
-// X509_ATTRIBUTE_set1_object sets |attr|'s type to |obj|. It returns one on
-// success and zero on error.
-OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr,
-                                              const ASN1_OBJECT *obj);
-
-// X509_ATTRIBUTE_set1_data appends a value to |attr|'s value set and returns
-// one on success or zero on error. The value is determined as follows:
-//
-// If |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 string. The
-// string is determined by decoding |len| bytes from |data| in the encoding
-// specified by |attrtype|, and then re-encoding it in a form appropriate for
-// |attr|'s type. If |len| is -1, |strlen(data)| is used instead. See
-// |ASN1_STRING_set_by_NID| for details.
-//
-// Otherwise, if |len| is not -1, the value is an ASN.1 string. |attrtype| is an
-// |ASN1_STRING| type value and the |len| bytes from |data| are copied as the
-// type-specific representation of |ASN1_STRING|. See |ASN1_STRING| for details.
-//
-// WARNING: If this form is used to construct a negative INTEGER or ENUMERATED,
-// |attrtype| includes the |V_ASN1_NEG| flag for |ASN1_STRING|, but the function
-// forgets to clear the flag for |ASN1_TYPE|. This matches OpenSSL but is
-// probably a bug. For now, do not use this form with negative values.
-//
-// Otherwise, if |len| is -1, the value is constructed by passing |attrtype| and
-// |data| to |ASN1_TYPE_set1|. That is, |attrtype| is an |ASN1_TYPE| type value,
-// and |data| is cast to the corresponding pointer type.
-//
-// WARNING: Despite the name, this function appends to |attr|'s value set,
-// rather than overwriting it. To overwrite the value set, create a new
-// |X509_ATTRIBUTE| with |X509_ATTRIBUTE_new|.
-//
-// WARNING: If using the |MBSTRING_*| form, pass a length rather than relying on
-// |strlen|. In particular, |strlen| will not behave correctly if the input is
-// |MBSTRING_BMP| or |MBSTRING_UNIV|.
-//
-// WARNING: This function currently misinterprets |V_ASN1_OTHER| as an
-// |MBSTRING_*| constant. This matches OpenSSL but means it is impossible to
-// construct a value with a non-universal tag.
-OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
-                                            const void *data, int len);
-
-// X509_ATTRIBUTE_get0_data returns the |idx|th value of |attr| in a
-// type-specific representation to |attrtype|, or NULL if out of bounds or the
-// type does not match. |attrtype| is one of the type values in |ASN1_TYPE|. On
-// match, the return value uses the same representation as |ASN1_TYPE_set0|. See
-// |ASN1_TYPE| for details.
-OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
-                                              int attrtype, void *unused);
-
-// X509_ATTRIBUTE_count returns the number of values in |attr|.
-OPENSSL_EXPORT int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr);
-
-// X509_ATTRIBUTE_get0_object returns the type of |attr|.
-OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
-
-// X509_ATTRIBUTE_get0_type returns the |idx|th value in |attr|, or NULL if out
-// of bounds. Note this function returns one of |attr|'s values, not the type.
-OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr,
-                                                   int idx);
-
 OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx);
 
 // PKCS#8 utilities
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index c8548f7..d9c862d 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -104,9 +104,13 @@
 struct v3_ext_method {
   int ext_nid;
   int ext_flags;
-  // If this is set the following four fields are ignored
+
+  // it determines how values of this extension are allocated, released, parsed,
+  // and marshalled. This must be non-NULL.
   ASN1_ITEM_EXP *it;
-  // Old style ASN1 calls
+
+  // The following functions are ignored in favor of |it|. They are retained in
+  // the struct only for source compatibility with existing struct definitions.
   X509V3_EXT_NEW ext_new;
   X509V3_EXT_FREE ext_free;
   X509V3_EXT_D2I d2i;
@@ -130,7 +134,6 @@
 DEFINE_STACK_OF(X509V3_EXT_METHOD)
 
 // ext_flags values
-#define X509V3_EXT_DYNAMIC 0x1
 #define X509V3_EXT_CTX_DEP 0x2
 #define X509V3_EXT_MULTILINE 0x4
 
@@ -663,10 +666,37 @@
                                               const char *value);
 OPENSSL_EXPORT char *i2s_ASN1_ENUMERATED(const X509V3_EXT_METHOD *meth,
                                          const ASN1_ENUMERATED *aint);
-OPENSSL_EXPORT int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
-OPENSSL_EXPORT int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
-OPENSSL_EXPORT int X509V3_EXT_add_alias(int nid_to, int nid_from);
-OPENSSL_EXPORT void X509V3_EXT_cleanup(void);
+
+// X509V3_EXT_add registers |ext| as a custom extension for the extension type
+// |ext->ext_nid|. |ext| must be valid for the remainder of the address space's
+// lifetime. It returns one on success and zero on error.
+//
+// WARNING: This function modifies global state. If other code in the same
+// address space also registers an extension with type |ext->ext_nid|, the two
+// registrations will conflict. Which registration takes effect is undefined. If
+// the two registrations use incompatible in-memory representations, code
+// expecting the other registration will then cast a type to the wrong type,
+// resulting in a potentially exploitable memory error. This conflict can also
+// occur if BoringSSL later adds support for |ext->ext_nid|, with a different
+// in-memory representation than the one expected by |ext|.
+//
+// This function, additionally, is not thread-safe and cannot be called
+// concurrently with any other BoringSSL function.
+//
+// As a result, it is impossible to safely use this function. Registering a
+// custom extension has no impact on certificate verification so, instead,
+// callers should simply handle the custom extension with the byte-based
+// |X509_EXTENSION| APIs directly. Registering |ext| with the library has little
+// practical value.
+OPENSSL_EXPORT OPENSSL_DEPRECATED int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+
+// X509V3_EXT_add_alias registers a custom extension with NID |nid_to|. The
+// corresponding ASN.1 type is copied from |nid_from|. It returns one on success
+// and zero on error.
+//
+// WARNING: Do not use this function. See |X509V3_EXT_add|.
+OPENSSL_EXPORT OPENSSL_DEPRECATED int X509V3_EXT_add_alias(int nid_to,
+                                                           int nid_from);
 
 OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get(
     const X509_EXTENSION *ext);
diff --git a/src/rust/bssl-crypto/Cargo.toml b/src/rust/bssl-crypto/Cargo.toml
index 57a6440..c60e9ca 100644
--- a/src/rust/bssl-crypto/Cargo.toml
+++ b/src/rust/bssl-crypto/Cargo.toml
@@ -6,6 +6,4 @@
 license = "MIT"
 
 [dependencies]
-# the crate will need to be generated at this path by running this command at root
-# `mkdir build && cd build && cmake -G Ninja .. -DRUST_BINDINGS="$(gcc -dumpmachine)" && ninja`
-bssl-sys = {path = "../../build/rust/bssl-sys"}
\ No newline at end of file
+bssl-sys = {path = "../bssl-sys"}
diff --git a/src/rust/bssl-crypto/README.md b/src/rust/bssl-crypto/README.md
index 9e10fad..dff669b 100644
--- a/src/rust/bssl-crypto/README.md
+++ b/src/rust/bssl-crypto/README.md
@@ -1,14 +1,9 @@
 bssl-crypto
 ============
 
-rust bindings to boringssl which wrap bssl-sys, a low level autogenerated binding
-
-Before using this crate, first generate the bssl-sys bindings by running this command from the root of the repo:
-```
-mkdir build && cd build && cmake -G Ninja .. -DRUST_BINDINGS="$(gcc -dumpmachine)" && ninja
-```
+Rust bindings to BoringSSL which wrap bssl-sys. Before using this crate, first [set up `bssl-sys`](../bssl-sys/README.md).
 
 Then to run all tests:
 ```
 cd rust/bssl-crypto && cargo clippy && cargo deny check && cargo test
-```
\ No newline at end of file
+```
diff --git a/src/rust/bssl-crypto/src/hmac.rs b/src/rust/bssl-crypto/src/hmac.rs
index 3da5f31..7dbf39b 100644
--- a/src/rust/bssl-crypto/src/hmac.rs
+++ b/src/rust/bssl-crypto/src/hmac.rs
@@ -79,6 +79,11 @@
     pub fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
         self.0.verify_truncated_left(tag)
     }
+
+    /// Resets the hmac instance to its initial state
+    pub fn reset(&mut self) {
+        self.0.reset()
+    }
 }
 
 /// The BoringSSL HMAC-SHA512 implementation. The operations may panic if memory allocation fails
@@ -120,6 +125,11 @@
     pub fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
         self.0.verify_truncated_left(tag)
     }
+
+    /// Resets the hmac instance to its initial state
+    pub fn reset(&mut self) {
+        self.0.reset()
+    }
 }
 
 /// Error type for when the output of the hmac operation is not equal to the expected value.
@@ -268,6 +278,27 @@
         .then_some(())
         .ok_or(MacError)
     }
+
+    /// Resets the hmac instance to its original state
+    fn reset(&mut self) {
+        // Passing a null ptr for the key will re-use the existing key
+        // Safety:
+        // - HMAC_Init_ex must be called with a context previously created with HMAC_CTX_new,
+        //   which will always be the case if it is coming from self
+        // - HMAC_Init_ex may return an error if key is null but the md is different from
+        //   before. The MD is guaranteed to be the same because it comes from the same generic param
+        // - HMAC_Init_ex returns 0 on allocation failure in which case we panic
+        let result = unsafe {
+            bssl_sys::HMAC_Init_ex(
+                self.ctx,
+                ptr::null_mut(),
+                0,
+                M::get_md().as_ptr(),
+                ptr::null_mut(),
+            )
+        };
+        assert!(result > 0, "Allocation failure in bssl_sys::HMAC_Init_ex");
+    }
 }
 
 impl<const N: usize, M: Md> Drop for Hmac<N, M> {
@@ -295,8 +326,29 @@
         hmac.update(data);
         let hmac_result: [u8; 32] = hmac.finalize();
 
-        // let hmac_result =
-        //     hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
+        assert_eq!(&hmac_result, &expected_hmac);
+    }
+
+    #[test]
+    fn hmac_sha256_reset_test() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+
+        let key: [u8; 20] = [0x0b; 20];
+        let data = b"Hi There";
+        let incorrect_data = b"This data does not match the expected mac";
+
+        let mut hmac = HmacSha256::new_from_slice(&key);
+        hmac.update(incorrect_data);
+        hmac.reset();
+
+        // hmac should be back to original state, so now when we update with the correct data it
+        // should work
+        hmac.update(data);
+        let hmac_result: [u8; 32] = hmac.finalize();
         assert_eq!(&hmac_result, &expected_hmac);
     }
 
diff --git a/src/rust/bssl-crypto/src/lib.rs b/src/rust/bssl-crypto/src/lib.rs
index 9024ed4..6ccf09c 100644
--- a/src/rust/bssl-crypto/src/lib.rs
+++ b/src/rust/bssl-crypto/src/lib.rs
@@ -15,6 +15,7 @@
 
 #![deny(
     missing_docs,
+    unsafe_op_in_unsafe_fn,
     clippy::indexing_slicing,
     clippy::unwrap_used,
     clippy::panic,
@@ -107,7 +108,7 @@
     #[inline]
     unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self {
         debug_assert!(!ptr.is_null());
-        &*(ptr as *mut _)
+        unsafe { &*(ptr as *mut _) }
     }
 
     /// Constructs a mutable reference of this type from its raw type.
@@ -118,7 +119,7 @@
     #[inline]
     unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self {
         debug_assert!(!ptr.is_null());
-        &mut *(ptr as *mut _)
+        unsafe { &mut *(ptr as *mut _) }
     }
 
     /// Returns a raw pointer to the wrapped value.
diff --git a/src/rust/bssl-sys/CMakeLists.txt b/src/rust/bssl-sys/CMakeLists.txt
index 9b5c841..d17a8f1 100644
--- a/src/rust/bssl-sys/CMakeLists.txt
+++ b/src/rust/bssl-sys/CMakeLists.txt
@@ -2,39 +2,48 @@
 add_library(rust_wrapper STATIC rust_wrapper.c)
 target_link_libraries(rust_wrapper crypto)
 
+# Generate architecture-specific wrappers. bindgen must be called from
+# ${CMAKE_BINARY_DIR}, with the output path as a relative path. bindgen writes
+# the depfile using the same syntax as the command-line argument, and ninja
+# requires a path relative to the top-level build directory.
+set(wrapper wrapper_${RUST_BINDINGS}.rs)
+binary_dir_relative_path(${wrapper} wrapper_relative)
+binary_dir_relative_path(${wrapper}.d depfile_relative)
 
-# Generate architecture-specific wrappers.
-set(WRAPPER_TARGET ${CMAKE_BINARY_DIR}/rust/bssl-sys/src/wrapper_${RUST_BINDINGS}.rs)
-set(COMMAND ${BINDGEN_EXECUTABLE} "wrapper.h"
-            -o ${WRAPPER_TARGET}
-            --no-derive-default
-            --enable-function-attribute-detection
-            --use-core
-            --size_t-is-usize
-            --default-macro-constant-type="signed"
-            --rustified-enum="point_conversion_form_t"
-            --allowlist-file=".*/include/openssl/.*\\.h"
-            --allowlist-file=".*/rust_wrapper\\.h"
-            -- # these are LLVM arg passthroughs
-            -I../../include
-            # https://doc.rust-lang.org/nightly/rustc/platform-support.html
-            --target=${RUST_BINDINGS})
-
-set(INCLUDES "include!(\"wrapper_${RUST_BINDINGS}.rs\");\n")
-
-add_custom_target(
-  bindgen_rust_${RUST_BINDINGS}
-  ALL
-  ${COMMAND}
-  BYPRODUCTS ${WRAPPER_TARGET}
-  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+add_custom_command(
+  OUTPUT ${wrapper}
+  COMMAND ${BINDGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wrapper.h
+          -o ${wrapper_relative}
+          --depfile=${depfile_relative}
+          --no-derive-default
+          --enable-function-attribute-detection
+          --use-core
+          --default-macro-constant-type=signed
+          --rustified-enum=point_conversion_form_t
+          # These regexes need to accept both / and \ to handle Windows file
+          # path differences, due a bindgen issue. See
+          # https://crbug.com/boringssl/595. Ideally, we would write [/\\], but
+          # there are many layers of escaping here. First, CMake interprets
+          # backslashes. Then CMake generates a Ninja or Make file. That, in
+          # turn, uses the shell on POSIX, and does something else on Windows.
+          #
+          # It is unlikely that every layer here has sufficiently well-defined
+          # escaping and correctly handled the next layer's escaping. On top of
+          # that, we'd likely need to detect Windows vs POSIX hosts and change
+          # the input. Instead, just use [[:punct:]] which is more permissive
+          # than necessary, but we only need to exclude unwanted libc headers.
+          #
+          # If bindgen ever supports some file-based config (see
+          # https://github.com/rust-lang/rust-bindgen/issues/2508), we can
+          # switch to that.
+          --allowlist-file=".*[[:punct:]]include[[:punct:]]openssl[[:punct:]].*\\.h"
+          --allowlist-file=".*[[:punct:]]rust_wrapper\\.h"
+          -- # these are LLVM arg passthroughs
+          -I${PROJECT_SOURCE_DIR}/include
+          # https://doc.rust-lang.org/nightly/rustc/platform-support.html
+          --target=${RUST_BINDINGS}
+  DEPENDS wrapper.h
+  DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${wrapper}.d
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 )
-
-# move files into build directory
-configure_file("src/lib.rs" "src/lib.rs")
-
-if(NOT BUILD_SHARED_LIBS)
-  configure_file("build.rs" "build.rs" COPYONLY)
-endif()
-
-configure_file("Cargo.toml" "Cargo.toml" COPYONLY)
\ No newline at end of file
+add_custom_target(bssl_sys ALL DEPENDS ${wrapper})
diff --git a/src/rust/bssl-sys/README.md b/src/rust/bssl-sys/README.md
index fb5230a..e2efd6c 100644
--- a/src/rust/bssl-sys/README.md
+++ b/src/rust/bssl-sys/README.md
@@ -4,10 +4,9 @@
 A low-level binding crate for Rust that moves in lockstop with BoringSSL. BoringSSL explicitly does not have a stable ABI, `bssl-sys` is the solution for preventing subtle-memory corruption bugs due to version skew.
 
 ### How it works
-`bssl-sys` uses `bindgen` as part of the cmake build process to generate Rust compatibility shims for the targeted platform. It is important to generate it for the correct platform because `bindgen` uses LLVM information for alignment which varies depending on architecture. These files are then packaged into a Rust crate.
+`bssl-sys` uses `bindgen` as part of the cmake build process to generate Rust compatibility shims for the targeted platform. It is important to generate it for the correct platform because `bindgen` uses LLVM information for alignment which varies depending on architecture.
 
 ### To Use
-Build `boringssl` with `-DRUST_BINDINGS=<rust-triple>` and ensure that you have `bindgen` installed.
+Build `boringssl` with `-DRUST_BINDINGS=<rust-triple>` and ensure that you have `bindgen` installed. The `rust-triple` option should match the [Rust target triple](https://doc.rust-lang.org/nightly/rustc/platform-support.html) when building `bssl-sys`.
 
-The `rust-triple` option should be one of the supported targets at https://doc.rust-lang.org/nightly/rustc/platform-support.html.
-
+From there, the `bssl-sys` crate can be built. By default, it looks for `bindgen` output and BoringSSL static libraries in the `build` directory. This can be reconfigured with `BORINGSSL_BUILD_DIR` environment variable. Note the environment variable is evaluated relative to `rust/bssl-sys/src`, so using an absolute path may be more convenient.
diff --git a/src/rust/bssl-sys/build.rs b/src/rust/bssl-sys/build.rs
index 955eae3..2d7461a 100644
--- a/src/rust/bssl-sys/build.rs
+++ b/src/rust/bssl-sys/build.rs
@@ -15,28 +15,43 @@
 
 use std::env;
 use std::path::Path;
+use std::path::PathBuf;
+
+fn get_bssl_build_dir() -> PathBuf {
+    println!("cargo:rerun-if-env-changed=BORINGSSL_BUILD_DIR");
+    if let Some(build_dir) = env::var_os("BORINGSSL_BUILD_DIR") {
+        return PathBuf::from(build_dir);
+    }
+
+    let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
+    return Path::new(&crate_dir).join("../../build");
+}
 
 fn main() {
-    let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
-    let crate_path = Path::new(&dir);
+    let bssl_build_dir = get_bssl_build_dir();
+    let bssl_sys_build_dir = bssl_build_dir.join("rust/bssl-sys");
+    let target = env::var("TARGET").unwrap();
 
-    // building bssl-sys with: `mkdir build && cd build && cmake -G Ninja .. -DRUST_BINDINGS="$(gcc -dumpmachine)" && ninja`
-    // outputs this crate to /build/rust/bssl-sys/ so need to go up 3 levels to the root of the repo
-    let repo_root = crate_path.parent().unwrap().parent().unwrap();
+    // Find the bindgen generated target platform bindings file and set BINDGEN_RS_FILE
+    let bindgen_file = bssl_sys_build_dir.join(format!("wrapper_{}.rs", target));
+    println!("cargo:rustc-env=BINDGEN_RS_FILE={}", bindgen_file.display());
 
     // Statically link libraries.
     println!(
         "cargo:rustc-link-search=native={}",
-        repo_root.join("crypto").display()
+        bssl_build_dir.join("crypto").display()
     );
     println!("cargo:rustc-link-lib=static=crypto");
 
     println!(
         "cargo:rustc-link-search=native={}",
-        repo_root.join("ssl").display()
+        bssl_build_dir.join("ssl").display()
     );
     println!("cargo:rustc-link-lib=static=ssl");
 
-    println!("cargo:rustc-link-search=native={}", crate_path.display());
+    println!(
+        "cargo:rustc-link-search=native={}",
+        bssl_sys_build_dir.display()
+    );
     println!("cargo:rustc-link-lib=static=rust_wrapper");
 }
diff --git a/src/rust/bssl-sys/src/lib.rs b/src/rust/bssl-sys/src/lib.rs
index d8c2c00..31f5cf4 100644
--- a/src/rust/bssl-sys/src/lib.rs
+++ b/src/rust/bssl-sys/src/lib.rs
@@ -18,5 +18,7 @@
 }
 
 pub fn init() {
-    unsafe { CRYPTO_library_init(); }
+    unsafe {
+        CRYPTO_library_init();
+    }
 }
diff --git a/src/rust/bssl-sys/wrapper.h b/src/rust/bssl-sys/wrapper.h
index 101b455..bd74049 100644
--- a/src/rust/bssl-sys/wrapper.h
+++ b/src/rust/bssl-sys/wrapper.h
@@ -1,79 +1,79 @@
-#include "../../include/openssl/aes.h"
-#include "../../include/openssl/asn1.h"
-#include "../../include/openssl/asn1_mac.h"
-#include "../../include/openssl/asn1t.h"
-#include "../../include/openssl/base.h"
-#include "../../include/openssl/base64.h"
-#include "../../include/openssl/bio.h"
-#include "../../include/openssl/blake2.h"
-#include "../../include/openssl/blowfish.h"
-#include "../../include/openssl/bn.h"
-#include "../../include/openssl/buf.h"
-#include "../../include/openssl/buffer.h"
-#include "../../include/openssl/bytestring.h"
-#include "../../include/openssl/cast.h"
-#include "../../include/openssl/chacha.h"
-#include "../../include/openssl/cipher.h"
-#include "../../include/openssl/cmac.h"
-#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"
-#include "../../include/openssl/digest.h"
-#include "../../include/openssl/dsa.h"
-#include "../../include/openssl/dtls1.h"
-#include "../../include/openssl/e_os2.h"
-#include "../../include/openssl/ec.h"
-#include "../../include/openssl/ec_key.h"
-#include "../../include/openssl/ecdh.h"
-#include "../../include/openssl/ecdsa.h"
-#include "../../include/openssl/engine.h"
-#include "../../include/openssl/err.h"
-#include "../../include/openssl/evp.h"
-#include "../../include/openssl/evp_errors.h"
-#include "../../include/openssl/ex_data.h"
-#include "../../include/openssl/hkdf.h"
-#include "../../include/openssl/hmac.h"
-#include "../../include/openssl/hpke.h"
-#include "../../include/openssl/hrss.h"
-#include "../../include/openssl/is_boringssl.h"
-#include "../../include/openssl/kdf.h"
-#include "../../include/openssl/lhash.h"
-#include "../../include/openssl/md4.h"
-#include "../../include/openssl/md5.h"
-#include "../../include/openssl/mem.h"
-#include "../../include/openssl/obj.h"
-#include "../../include/openssl/obj_mac.h"
-#include "../../include/openssl/objects.h"
-#include "../../include/openssl/opensslconf.h"
-#include "../../include/openssl/opensslv.h"
-#include "../../include/openssl/ossl_typ.h"
-#include "../../include/openssl/pem.h"
-#include "../../include/openssl/pkcs12.h"
-#include "../../include/openssl/pkcs7.h"
-#include "../../include/openssl/pkcs8.h"
-#include "../../include/openssl/poly1305.h"
-#include "../../include/openssl/pool.h"
-#include "../../include/openssl/rand.h"
-#include "../../include/openssl/rc4.h"
-#include "../../include/openssl/ripemd.h"
-#include "../../include/openssl/rsa.h"
-#include "../../include/openssl/safestack.h"
-#include "../../include/openssl/sha.h"
-#include "../../include/openssl/siphash.h"
-#include "../../include/openssl/span.h"
-#include "../../include/openssl/srtp.h"
-#include "../../include/openssl/ssl.h"
-#include "../../include/openssl/ssl3.h"
-#include "../../include/openssl/stack.h"
-#include "../../include/openssl/thread.h"
-#include "../../include/openssl/tls1.h"
-#include "../../include/openssl/trust_token.h"
-#include "../../include/openssl/x509.h"
-#include "../../include/openssl/x509_vfy.h"
-#include "../../include/openssl/x509v3.h"
+#include <openssl/aes.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1_mac.h>
+#include <openssl/asn1t.h>
+#include <openssl/base.h>
+#include <openssl/base64.h>
+#include <openssl/bio.h>
+#include <openssl/blake2.h>
+#include <openssl/blowfish.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/buffer.h>
+#include <openssl/bytestring.h>
+#include <openssl/cast.h>
+#include <openssl/chacha.h>
+#include <openssl/cipher.h>
+#include <openssl/cmac.h>
+#include <openssl/conf.h>
+#include <openssl/cpu.h>
+#include <openssl/crypto.h>
+#include <openssl/ctrdrbg.h>
+#include <openssl/curve25519.h>
+#include <openssl/des.h>
+#include <openssl/dh.h>
+#include <openssl/digest.h>
+#include <openssl/dsa.h>
+#include <openssl/dtls1.h>
+#include <openssl/e_os2.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/evp_errors.h>
+#include <openssl/ex_data.h>
+#include <openssl/hkdf.h>
+#include <openssl/hmac.h>
+#include <openssl/hpke.h>
+#include <openssl/hrss.h>
+#include <openssl/is_boringssl.h>
+#include <openssl/kdf.h>
+#include <openssl/lhash.h>
+#include <openssl/md4.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/obj_mac.h>
+#include <openssl/objects.h>
+#include <openssl/opensslconf.h>
+#include <openssl/opensslv.h>
+#include <openssl/ossl_typ.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs8.h>
+#include <openssl/poly1305.h>
+#include <openssl/pool.h>
+#include <openssl/rand.h>
+#include <openssl/rc4.h>
+#include <openssl/ripemd.h>
+#include <openssl/rsa.h>
+#include <openssl/safestack.h>
+#include <openssl/sha.h>
+#include <openssl/siphash.h>
+#include <openssl/span.h>
+#include <openssl/srtp.h>
+#include <openssl/ssl.h>
+#include <openssl/ssl3.h>
+#include <openssl/stack.h>
+#include <openssl/thread.h>
+#include <openssl/tls1.h>
+#include <openssl/trust_token.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
 
 #include "rust_wrapper.h"
diff --git a/src/ssl/encrypted_client_hello.cc b/src/ssl/encrypted_client_hello.cc
index 8d35f18..a5492e9 100644
--- a/src/ssl/encrypted_client_hello.cc
+++ b/src/ssl/encrypted_client_hello.cc
@@ -601,8 +601,8 @@
 
 static bool select_ech_cipher_suite(const EVP_HPKE_KDF **out_kdf,
                                     const EVP_HPKE_AEAD **out_aead,
-                                    Span<const uint8_t> cipher_suites) {
-  const bool has_aes_hardware = EVP_has_aes_hardware();
+                                    Span<const uint8_t> cipher_suites,
+                                    const bool has_aes_hardware) {
   const EVP_HPKE_AEAD *aead = nullptr;
   CBS cbs = cipher_suites;
   while (CBS_len(&cbs) != 0) {
@@ -660,7 +660,10 @@
       const EVP_HPKE_AEAD *aead;
       if (supported &&  //
           ech_config.kem_id == EVP_HPKE_DHKEM_X25519_HKDF_SHA256 &&
-          select_ech_cipher_suite(&kdf, &aead, ech_config.cipher_suites)) {
+          select_ech_cipher_suite(&kdf, &aead, ech_config.cipher_suites,
+                                  hs->ssl->config->aes_hw_override
+                                      ? hs->ssl->config->aes_hw_override_value
+                                      : EVP_has_aes_hardware())) {
         ScopedCBB info;
         static const uint8_t kInfoLabel[] = "tls ech";  // includes trailing NUL
         if (!CBB_init(info.get(), sizeof(kInfoLabel) + ech_config.raw.size()) ||
@@ -714,9 +717,11 @@
   }
 
   const uint16_t kdf_id = EVP_HPKE_HKDF_SHA256;
-  const EVP_HPKE_AEAD *aead = EVP_has_aes_hardware()
-                                  ? EVP_hpke_aes_128_gcm()
-                                  : EVP_hpke_chacha20_poly1305();
+  const bool has_aes_hw = hs->ssl->config->aes_hw_override
+                              ? hs->ssl->config->aes_hw_override_value
+                              : EVP_has_aes_hardware();
+  const EVP_HPKE_AEAD *aead =
+      has_aes_hw ? EVP_hpke_aes_128_gcm() : EVP_hpke_chacha20_poly1305();
   static_assert(ssl_grease_ech_config_id < sizeof(hs->grease_seed),
                 "hs->grease_seed is too small");
   uint8_t config_id = hs->grease_seed[ssl_grease_ech_config_id];
diff --git a/src/ssl/extensions.cc b/src/ssl/extensions.cc
index ba92360..4d9651b 100644
--- a/src/ssl/extensions.cc
+++ b/src/ssl/extensions.cc
@@ -206,7 +206,6 @@
 
 static bool is_post_quantum_group(uint16_t id) {
   switch (id) {
-    case SSL_CURVE_CECPQ2:
     case SSL_CURVE_X25519KYBER768:
     case SSL_CURVE_P256KYBER768:
       return true;
@@ -414,7 +413,7 @@
 bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
   if (is_post_quantum_group(group_id) &&
       ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
-    // CECPQ2(b) requires TLS 1.3.
+    // Post-quantum "groups" require TLS 1.3.
     return false;
   }
 
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index e7dca1b..971ebd0 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -215,6 +215,14 @@
   }
 }
 
+static bool ssl_add_tls13_cipher(CBB *cbb, uint16_t cipher_id,
+                                 ssl_compliance_policy_t policy) {
+  if (ssl_tls13_cipher_meets_policy(cipher_id, policy)) {
+    return CBB_add_u16(cbb, cipher_id);
+  }
+  return true;
+}
+
 static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
                                          ssl_client_hello_type_t type) {
   const SSL *const ssl = hs->ssl;
@@ -235,22 +243,22 @@
   // Add TLS 1.3 ciphers. Order ChaCha20-Poly1305 relative to AES-GCM based on
   // hardware support.
   if (hs->max_version >= TLS1_3_VERSION) {
-    const bool include_chacha20 = ssl_tls13_cipher_meets_policy(
-        TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
-        ssl->config->only_fips_cipher_suites_in_tls13);
+    const bool has_aes_hw = ssl->config->aes_hw_override
+                                ? ssl->config->aes_hw_override_value
+                                : EVP_has_aes_hardware();
 
-    if (!EVP_has_aes_hardware() &&  //
-        include_chacha20 &&         //
-        !CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
-      return false;
-    }
-    if (!CBB_add_u16(&child, TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff) ||
-        !CBB_add_u16(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff)) {
-      return false;
-    }
-    if (EVP_has_aes_hardware() &&  //
-        include_chacha20 &&        //
-        !CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
+    if ((!has_aes_hw &&  //
+         !ssl_add_tls13_cipher(&child,
+                               TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
+                               ssl->config->tls13_cipher_policy)) ||
+        !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
+                              ssl->config->tls13_cipher_policy) ||
+        !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
+                              ssl->config->tls13_cipher_policy) ||
+        (has_aes_hw &&  //
+         !ssl_add_tls13_cipher(&child,
+                               TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
+                               ssl->config->tls13_cipher_policy))) {
       return false;
     }
   }
@@ -833,11 +841,18 @@
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
       return ssl_hs_error;
     }
-    // Note: session_id could be empty.
-    hs->new_session->session_id_length = CBS_len(&server_hello.session_id);
+
+    // Save the session ID from the server. This may be empty if the session
+    // isn't resumable, or if we'll receive a session ticket later.
+    assert(CBS_len(&server_hello.session_id) <= SSL3_SESSION_ID_SIZE);
+    static_assert(SSL3_SESSION_ID_SIZE <= UINT8_MAX,
+                  "max session ID is too large");
+    hs->new_session->session_id_length =
+        static_cast<uint8_t>(CBS_len(&server_hello.session_id));
     OPENSSL_memcpy(hs->new_session->session_id,
                    CBS_data(&server_hello.session_id),
                    CBS_len(&server_hello.session_id));
+
     hs->new_session->cipher = hs->new_cipher;
   }
 
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index e71dd0c..01decb0 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -547,8 +547,7 @@
 #define SSL_AES256 0x00000004u
 #define SSL_AES128GCM 0x00000008u
 #define SSL_AES256GCM 0x00000010u
-#define SSL_eNULL 0x00000020u
-#define SSL_CHACHA20POLY1305 0x00000040u
+#define SSL_CHACHA20POLY1305 0x00000020u
 
 #define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM)
 
@@ -633,9 +632,11 @@
 // newly-allocated |SSLCipherPreferenceList| containing the result. It returns
 // true on success and false on failure. If |strict| is true, nonsense will be
 // rejected. If false, nonsense will be silently ignored. An empty result is
-// considered an error regardless of |strict|.
+// considered an error regardless of |strict|. |has_aes_hw| indicates if the
+// list should be ordered based on having support for AES in hardware or not.
 bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
-                            const char *rule_str, bool strict);
+                            const bool has_aes_hw, const char *rule_str,
+                            bool strict);
 
 // ssl_cipher_auth_mask_for_key returns the mask of cipher |algorithm_auth|
 // values suitable for use with |key| in TLS 1.2 and below.
@@ -659,14 +660,17 @@
 
 // ssl_choose_tls13_cipher returns an |SSL_CIPHER| corresponding with the best
 // available from |cipher_suites| compatible with |version|, |group_id|, and
-// |only_fips|. It returns NULL if there isn't a compatible cipher.
-const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version,
-                                          uint16_t group_id, bool only_fips);
+// |policy|. It returns NULL if there isn't a compatible cipher. |has_aes_hw|
+// indicates if the choice should be made as if support for AES in hardware
+// is available.
+const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw,
+                                          uint16_t version, uint16_t group_id,
+                                          enum ssl_compliance_policy_t policy);
 
 // ssl_tls13_cipher_meets_policy returns true if |cipher_id| is acceptable given
-// |only_fips|. (For now there's only a single policy and so the policy argument
-// is just a bool.)
-bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id, bool only_fips);
+// |policy|.
+bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id,
+                                   enum ssl_compliance_policy_t policy);
 
 
 // Transcript layer.
@@ -3059,6 +3063,10 @@
   // structure for the client to use when negotiating ECH.
   Array<uint8_t> client_ech_config_list;
 
+  // tls13_cipher_policy limits the set of ciphers that can be selected when
+  // negotiating a TLS 1.3 connection.
+  enum ssl_compliance_policy_t tls13_cipher_policy = ssl_compliance_policy_none;
+
   // verify_mode is a bitmask of |SSL_VERIFY_*| values.
   uint8_t verify_mode = SSL_VERIFY_NONE;
 
@@ -3108,9 +3116,14 @@
   // permute_extensions is whether to permute extensions when sending messages.
   bool permute_extensions : 1;
 
-  // only_fips_cipher_suites_in_tls13 constrains the selection of cipher suites
-  // in TLS 1.3 such that only FIPS approved ones will be selected.
-  bool only_fips_cipher_suites_in_tls13 : 1;
+  // aes_hw_override if set indicates we should override checking for aes
+  // hardware support, and use the value in aes_hw_override_value instead.
+  bool aes_hw_override : 1;
+
+  // aes_hw_override_value is used for testing to indicate the support or lack
+  // of support for AES hw. The value is only considered if |aes_hw_override| is
+  // true.
+  bool aes_hw_override_value : 1;
 };
 
 // From RFC 8446, used in determining PSK modes.
@@ -3132,8 +3145,9 @@
                                        const EVP_PKEY *privkey);
 bool ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
 bool ssl_get_new_session(SSL_HANDSHAKE *hs);
-int ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out, const SSL_SESSION *session);
-int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx);
+bool ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out,
+                        const SSL_SESSION *session);
+bool ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx);
 
 // ssl_session_new returns a newly-allocated blank |SSL_SESSION| or nullptr on
 // error.
@@ -3149,23 +3163,22 @@
     CBS *cbs, const SSL_X509_METHOD *x509_method, CRYPTO_BUFFER_POOL *pool);
 
 // ssl_session_serialize writes |in| to |cbb| as if it were serialising a
-// session for Session-ID resumption. It returns one on success and zero on
+// session for Session-ID resumption. It returns true on success and false on
 // error.
-OPENSSL_EXPORT int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb);
+OPENSSL_EXPORT bool ssl_session_serialize(const SSL_SESSION *in, CBB *cbb);
 
-// ssl_session_is_context_valid returns one if |session|'s session ID context
-// matches the one set on |hs| and zero otherwise.
-int ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
-                                 const SSL_SESSION *session);
+// ssl_session_is_context_valid returns whether |session|'s session ID context
+// matches the one set on |hs|.
+bool ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
+                                  const SSL_SESSION *session);
 
-// ssl_session_is_time_valid returns one if |session| is still valid and zero if
-// it has expired.
-int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session);
+// ssl_session_is_time_valid returns true if |session| is still valid and false
+// if it has expired.
+bool ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session);
 
-// ssl_session_is_resumable returns one if |session| is resumable for |hs| and
-// zero otherwise.
-int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
-                             const SSL_SESSION *session);
+// ssl_session_is_resumable returns whether |session| is resumable for |hs|.
+bool ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
+                              const SSL_SESSION *session);
 
 // ssl_session_protocol_version returns the protocol version associated with
 // |session|. Note that despite the name, this is not the same as
@@ -3671,6 +3684,10 @@
   int (*legacy_ocsp_callback)(SSL *ssl, void *arg) = nullptr;
   void *legacy_ocsp_callback_arg = nullptr;
 
+  // tls13_cipher_policy limits the set of ciphers that can be selected when
+  // negotiating a TLS 1.3 connection.
+  enum ssl_compliance_policy_t tls13_cipher_policy = ssl_compliance_policy_none;
+
   // verify_sigalgs, if not empty, is the set of signature algorithms
   // accepted from the peer in decreasing order of preference.
   bssl::Array<uint16_t> verify_sigalgs;
@@ -3718,9 +3735,14 @@
   // If enable_early_data is true, early data can be sent and accepted.
   bool enable_early_data : 1;
 
-  // only_fips_cipher_suites_in_tls13 constrains the selection of cipher suites
-  // in TLS 1.3 such that only FIPS approved ones will be selected.
-  bool only_fips_cipher_suites_in_tls13 : 1;
+  // aes_hw_override if set indicates we should override checking for AES
+  // hardware support, and use the value in aes_hw_override_value instead.
+  bool aes_hw_override : 1;
+
+  // aes_hw_override_value is used for testing to indicate the support or lack
+  // of support for AES hardware. The value is only considered if
+  // |aes_hw_override| is true.
+  bool aes_hw_override_value : 1;
 
  private:
   ~ssl_ctx_st();
@@ -3838,11 +3860,11 @@
   // session. In TLS 1.3 and up, it is the resumption PSK for sessions handed to
   // the caller, but it stores the resumption secret when stored on |SSL|
   // objects.
-  int secret_length = 0;
+  uint8_t secret_length = 0;
   uint8_t secret[SSL_MAX_MASTER_KEY_LENGTH] = {0};
 
   // session_id - valid?
-  unsigned session_id_length = 0;
+  uint8_t session_id_length = 0;
   uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0};
   // this is used to determine whether the session is being reused in
   // the appropriate context. It is up to the application to set this,
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index eb9da0d..6d33c6d 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -663,7 +663,7 @@
 // the client.
 class CipherScorer {
  public:
-  CipherScorer() : aes_is_fine_(EVP_has_aes_hardware()) {}
+  CipherScorer(bool has_aes_hw) : aes_is_fine_(has_aes_hw) {}
 
   typedef std::tuple<bool, bool> Score;
 
@@ -685,31 +685,50 @@
   const bool aes_is_fine_;
 };
 
-bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id, bool only_fips) {
-  if (!only_fips) {
-    return true;
+bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id,
+                                   enum ssl_compliance_policy_t policy) {
+  switch (policy) {
+    case ssl_compliance_policy_none:
+      return true;
+
+    case ssl_compliance_policy_fips_202205:
+      switch (cipher_id) {
+        case TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff:
+        case TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff:
+          return true;
+        case TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff:
+          return false;
+        default:
+          assert(false);
+          return false;
+      }
+
+    case ssl_compliance_policy_wpa3_192_202304:
+      switch (cipher_id) {
+        case TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff:
+          return true;
+        case TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff:
+        case TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff:
+          return false;
+        default:
+          assert(false);
+          return false;
+      }
   }
 
-  switch (cipher_id) {
-    case TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff:
-    case TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff:
-      return true;
-    case TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff:
-      return false;
-    default:
-      assert(false);
-      return false;
-  }
+  assert(false);
+  return false;
 }
 
-const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version,
-                                          uint16_t group_id, bool only_fips) {
+const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw,
+                                          uint16_t version, uint16_t group_id,
+                                          enum ssl_compliance_policy_t policy) {
   if (CBS_len(&cipher_suites) % 2 != 0) {
     return nullptr;
   }
 
   const SSL_CIPHER *best = nullptr;
-  CipherScorer scorer;
+  CipherScorer scorer(has_aes_hw);
   CipherScorer::Score best_score = scorer.MinScore();
 
   while (CBS_len(&cipher_suites) > 0) {
@@ -727,7 +746,7 @@
     }
 
     if (!ssl_tls13_cipher_meets_policy(SSL_CIPHER_get_protocol_id(candidate),
-                                       only_fips)) {
+                                       policy)) {
       continue;
     }
 
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index 7c702fd..3311246 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -486,7 +486,7 @@
     return 0;
   }
   OPENSSL_memcpy(out, CBS_data(&value), CBS_len(&value));
-  *out_len = (uint8_t)CBS_len(&value);
+  *out_len = static_cast<uint8_t>(CBS_len(&value));
   return 1;
 }
 
@@ -578,9 +578,13 @@
     return nullptr;
   }
   OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
-  ret->session_id_length = CBS_len(&session_id);
+  static_assert(SSL3_MAX_SSL_SESSION_ID_LENGTH <= UINT8_MAX,
+                "max session ID is too large");
+  ret->session_id_length = static_cast<uint8_t>(CBS_len(&session_id));
   OPENSSL_memcpy(ret->secret, CBS_data(&secret), CBS_len(&secret));
-  ret->secret_length = CBS_len(&secret);
+  static_assert(SSL_MAX_MASTER_KEY_LENGTH <= UINT8_MAX,
+                "max secret is too large");
+  ret->secret_length = static_cast<uint8_t>(CBS_len(&secret));
 
   CBS child;
   uint64_t timeout;
@@ -782,7 +786,7 @@
   return ret;
 }
 
-int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb) {
+bool ssl_session_serialize(const SSL_SESSION *in, CBB *cbb) {
   return SSL_SESSION_to_bytes_full(in, cbb, 0);
 }
 
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index 391944a..f6259b2 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -157,17 +157,6 @@
 
 static constexpr SSL_CIPHER kCiphers[] = {
     // The RSA ciphers
-    // Cipher 02
-    {
-     SSL3_TXT_RSA_NULL_SHA,
-     "TLS_RSA_WITH_NULL_SHA",
-     SSL3_CK_RSA_NULL_SHA,
-     SSL_kRSA,
-     SSL_aRSA,
-     SSL_eNULL,
-     SSL_SHA1,
-     SSL_HANDSHAKE_MAC_DEFAULT,
-    },
 
     // Cipher 0A
     {
@@ -466,6 +455,16 @@
   return MakeConstSpan(kCiphers, OPENSSL_ARRAY_SIZE(kCiphers));
 }
 
+static constexpr size_t NumTLS13Ciphers() {
+  size_t num = 0;
+  for (const auto &cipher : kCiphers) {
+    if (cipher.algorithm_mkey == SSL_kGENERIC) {
+      num++;
+    }
+  }
+  return num;
+}
+
 #define CIPHER_ADD 1
 #define CIPHER_KILL 2
 #define CIPHER_DEL 3
@@ -498,7 +497,6 @@
 } CIPHER_ALIAS;
 
 static const CIPHER_ALIAS kCipherAliases[] = {
-    // "ALL" doesn't include eNULL. It must be explicitly enabled.
     {"ALL", ~0u, ~0u, ~0u, ~0u, 0},
 
     // The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing.
@@ -599,9 +597,7 @@
       *out_fixed_iv_len = EVP_AEAD_nonce_length(*out_aead);
     }
   } else if (cipher->algorithm_mac == SSL_SHA1) {
-    if (cipher->algorithm_enc == SSL_eNULL) {
-      *out_aead = EVP_aead_null_sha1_tls();
-    } else if (cipher->algorithm_enc == SSL_3DES) {
+    if (cipher->algorithm_enc == SSL_3DES) {
       if (version == TLS1_VERSION) {
         *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
         *out_fixed_iv_len = 8;
@@ -703,54 +699,6 @@
   *head = curr;
 }
 
-static bool ssl_cipher_collect_ciphers(Array<CIPHER_ORDER> *out_co_list,
-                                       CIPHER_ORDER **out_head,
-                                       CIPHER_ORDER **out_tail) {
-  Array<CIPHER_ORDER> co_list;
-  if (!co_list.Init(OPENSSL_ARRAY_SIZE(kCiphers))) {
-    return false;
-  }
-
-  size_t co_list_num = 0;
-  for (const SSL_CIPHER &cipher : kCiphers) {
-    // TLS 1.3 ciphers do not participate in this mechanism.
-    if (cipher.algorithm_mkey != SSL_kGENERIC) {
-      co_list[co_list_num].cipher = &cipher;
-      co_list[co_list_num].next = NULL;
-      co_list[co_list_num].prev = NULL;
-      co_list[co_list_num].active = false;
-      co_list[co_list_num].in_group = false;
-      co_list_num++;
-    }
-  }
-
-  // Prepare linked list from list entries.
-  if (co_list_num > 0) {
-    co_list[0].prev = NULL;
-
-    if (co_list_num > 1) {
-      co_list[0].next = &co_list[1];
-
-      for (size_t i = 1; i < co_list_num - 1; i++) {
-        co_list[i].prev = &co_list[i - 1];
-        co_list[i].next = &co_list[i + 1];
-      }
-
-      co_list[co_list_num - 1].prev = &co_list[co_list_num - 2];
-    }
-
-    co_list[co_list_num - 1].next = NULL;
-
-    *out_head = &co_list[0];
-    *out_tail = &co_list[co_list_num - 1];
-  } else {
-    *out_head = nullptr;
-    *out_tail = nullptr;
-  }
-  *out_co_list = std::move(co_list);
-  return true;
-}
-
 SSLCipherPreferenceList::~SSLCipherPreferenceList() {
   OPENSSL_free(in_group_flags);
 }
@@ -866,9 +814,7 @@
           !(alg_auth & cp->algorithm_auth) ||
           !(alg_enc & cp->algorithm_enc) ||
           !(alg_mac & cp->algorithm_mac) ||
-          (min_version != 0 && SSL_CIPHER_get_min_version(cp) != min_version) ||
-          // The NULL cipher must be selected explicitly.
-          cp->algorithm_enc == SSL_eNULL) {
+          (min_version != 0 && SSL_CIPHER_get_min_version(cp) != min_version)) {
         continue;
       }
     }
@@ -1148,73 +1094,86 @@
 }
 
 bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
-                            const char *rule_str, bool strict) {
+                            const bool has_aes_hw, const char *rule_str,
+                            bool strict) {
   // Return with error if nothing to do.
   if (rule_str == NULL || out_cipher_list == NULL) {
     return false;
   }
 
-  // Now we have to collect the available ciphers from the compiled in ciphers.
-  // We cannot get more than the number compiled in, so it is used for
-  // allocation.
-  Array<CIPHER_ORDER> co_list;
-  CIPHER_ORDER *head = nullptr, *tail = nullptr;
-  if (!ssl_cipher_collect_ciphers(&co_list, &head, &tail)) {
-    return false;
+  // We prefer ECDHE ciphers over non-PFS ciphers. Then we prefer AEAD over
+  // non-AEAD. The constants are masked by 0xffff to remove the vestigial 0x03
+  // byte from SSL 2.0.
+  static const uint16_t kAESCiphers[] = {
+      TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 & 0xffff,
+      TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 & 0xffff,
+      TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 & 0xffff,
+      TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 & 0xffff,
+  };
+  static const uint16_t kChaChaCiphers[] = {
+      TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 & 0xffff,
+      TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 & 0xffff,
+      TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 & 0xffff,
+  };
+  static const uint16_t kLegacyCiphers[] = {
+      TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA & 0xffff,
+      TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA & 0xffff,
+      TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA & 0xffff,
+      TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA & 0xffff,
+      TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA & 0xffff,
+      TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA & 0xffff,
+      TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 & 0xffff,
+      TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 & 0xffff,
+      TLS1_CK_RSA_WITH_AES_128_SHA & 0xffff,
+      TLS1_CK_PSK_WITH_AES_128_CBC_SHA & 0xffff,
+      TLS1_CK_RSA_WITH_AES_256_SHA & 0xffff,
+      TLS1_CK_PSK_WITH_AES_256_CBC_SHA & 0xffff,
+      SSL3_CK_RSA_DES_192_CBC3_SHA & 0xffff,
+  };
+
+  // Set up a linked list of ciphers.
+  CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kAESCiphers) +
+                       OPENSSL_ARRAY_SIZE(kChaChaCiphers) +
+                       OPENSSL_ARRAY_SIZE(kLegacyCiphers)];
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(co_list); i++) {
+    co_list[i].next =
+        i + 1 < OPENSSL_ARRAY_SIZE(co_list) ? &co_list[i + 1] : nullptr;
+    co_list[i].prev = i == 0 ? nullptr : &co_list[i - 1];
+    co_list[i].active = false;
+    co_list[i].in_group = false;
   }
+  CIPHER_ORDER *head = &co_list[0];
+  CIPHER_ORDER *tail = &co_list[OPENSSL_ARRAY_SIZE(co_list) - 1];
 
-  // Now arrange all ciphers by preference:
-  // TODO(davidben): Compute this order once and copy it.
-
-  // Everything else being equal, prefer ECDHE_ECDSA and ECDHE_RSA over other
-  // key exchange mechanisms
-  ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, 0, CIPHER_ADD, -1,
-                        false, &head, &tail);
-  ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, false,
-                        &head, &tail);
-  ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, false, &head,
-                        &tail);
-
-  // Order the bulk ciphers. First the preferred AEAD ciphers. We prefer
-  // CHACHA20 unless there is hardware support for fast and constant-time
-  // AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the
-  // old one.
-  if (EVP_has_aes_hardware()) {
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1,
-                          false, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1,
-                          false, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
-                          -1, false, &head, &tail);
-  } else {
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
-                          -1, false, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1,
-                          false, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1,
-                          false, &head, &tail);
+  // Order AES ciphers vs ChaCha ciphers based on whether we have AES hardware.
+  //
+  // TODO(crbug.com/boringssl/29): We should also set up equipreference groups
+  // as a server.
+  size_t num = 0;
+  if (has_aes_hw) {
+    for (uint16_t id : kAESCiphers) {
+      co_list[num++].cipher = SSL_get_cipher_by_value(id);
+      assert(co_list[num - 1].cipher != nullptr);
+    }
   }
-
-  // Then the legacy non-AEAD ciphers: AES_128_CBC, AES_256_CBC,
-  // 3DES_EDE_CBC_SHA.
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128, ~0u, 0, CIPHER_ADD, -1, false,
-                        &head, &tail);
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, false,
-                        &head, &tail);
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_3DES, ~0u, 0, CIPHER_ADD, -1, false,
-                        &head, &tail);
-
-  // Temporarily enable everything else for sorting
-  ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, false, &head,
-                        &tail);
-
-  // Move ciphers without forward secrecy to the end.
-  ssl_cipher_apply_rule(0, (SSL_kRSA | SSL_kPSK), ~0u, ~0u, ~0u, 0, CIPHER_ORD,
-                        -1, false, &head, &tail);
-
-  // Now disable everything (maintaining the ordering!)
-  ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, false, &head,
-                        &tail);
+  for (uint16_t id : kChaChaCiphers) {
+    co_list[num++].cipher = SSL_get_cipher_by_value(id);
+    assert(co_list[num - 1].cipher != nullptr);
+  }
+  if (!has_aes_hw) {
+    for (uint16_t id : kAESCiphers) {
+      co_list[num++].cipher = SSL_get_cipher_by_value(id);
+      assert(co_list[num - 1].cipher != nullptr);
+    }
+  }
+  for (uint16_t id : kLegacyCiphers) {
+    co_list[num++].cipher = SSL_get_cipher_by_value(id);
+    assert(co_list[num - 1].cipher != nullptr);
+  }
+  assert(num == OPENSSL_ARRAY_SIZE(co_list));
+  static_assert(OPENSSL_ARRAY_SIZE(co_list) + NumTLS13Ciphers() ==
+                    OPENSSL_ARRAY_SIZE(kCiphers),
+                "Not all ciphers are included in the cipher order");
 
   // If the rule_string begins with DEFAULT, apply the default rule before
   // using the (possibly available) additional rules.
@@ -1382,8 +1341,6 @@
 
 int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *cipher) {
   switch (cipher->algorithm_enc) {
-    case SSL_eNULL:
-      return NID_undef;
     case SSL_3DES:
       return NID_des_ede3_cbc;
     case SSL_AES128:
@@ -1456,8 +1413,7 @@
 }
 
 int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher) {
-  return (cipher->algorithm_enc & SSL_eNULL) == 0 &&
-      cipher->algorithm_mac != SSL_AEAD;
+  return cipher->algorithm_mac != SSL_AEAD;
 }
 
 uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher) {
@@ -1531,14 +1487,6 @@
   }
 }
 
-char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher) {
-  if (cipher == NULL) {
-    return NULL;
-  }
-
-  return OPENSSL_strdup(SSL_CIPHER_standard_name(cipher));
-}
-
 int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, int *out_alg_bits) {
   if (cipher == NULL) {
     return 0;
@@ -1564,11 +1512,6 @@
       strength_bits = 112;
       break;
 
-    case SSL_eNULL:
-      alg_bits = 0;
-      strength_bits = 0;
-      break;
-
     default:
       assert(0);
       alg_bits = 0;
@@ -1659,10 +1602,6 @@
       enc = "ChaCha20-Poly1305";
       break;
 
-    case SSL_eNULL:
-      enc="None";
-      break;
-
     default:
       enc = "unknown";
       break;
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 5741c6b..8885246 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -192,101 +192,6 @@
   uint8_t private_key_[32];
 };
 
-class CECPQ2KeyShare : public SSLKeyShare {
- public:
-  CECPQ2KeyShare() {}
-
-  uint16_t GroupID() const override { return SSL_CURVE_CECPQ2; }
-
-  bool Generate(CBB *out) override {
-    uint8_t x25519_public_key[32];
-    X25519_keypair(x25519_public_key, x25519_private_key_);
-
-    uint8_t hrss_entropy[HRSS_GENERATE_KEY_BYTES];
-    HRSS_public_key hrss_public_key;
-    RAND_bytes(hrss_entropy, sizeof(hrss_entropy));
-    if (!HRSS_generate_key(&hrss_public_key, &hrss_private_key_,
-                           hrss_entropy)) {
-      return false;
-    }
-
-    uint8_t hrss_public_key_bytes[HRSS_PUBLIC_KEY_BYTES];
-    HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key);
-
-    if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
-        !CBB_add_bytes(out, hrss_public_key_bytes,
-                       sizeof(hrss_public_key_bytes))) {
-      return false;
-    }
-
-    return true;
-  }
-
-  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
-             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
-    Array<uint8_t> secret;
-    if (!secret.Init(32 + HRSS_KEY_BYTES)) {
-      return false;
-    }
-
-    uint8_t x25519_public_key[32];
-    X25519_keypair(x25519_public_key, x25519_private_key_);
-
-    HRSS_public_key peer_public_key;
-    if (peer_key.size() != 32 + HRSS_PUBLIC_KEY_BYTES ||
-        !HRSS_parse_public_key(&peer_public_key, peer_key.data() + 32) ||
-        !X25519(secret.data(), x25519_private_key_, peer_key.data())) {
-      *out_alert = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
-      return false;
-    }
-
-    uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
-    uint8_t entropy[HRSS_ENCAP_BYTES];
-    RAND_bytes(entropy, sizeof(entropy));
-
-    if (!HRSS_encap(ciphertext, secret.data() + 32, &peer_public_key,
-                    entropy) ||
-        !CBB_add_bytes(out_ciphertext, x25519_public_key,
-                       sizeof(x25519_public_key)) ||
-        !CBB_add_bytes(out_ciphertext, ciphertext, sizeof(ciphertext))) {
-      return false;
-    }
-
-    *out_secret = std::move(secret);
-    return true;
-  }
-
-  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
-             Span<const uint8_t> ciphertext) override {
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-
-    Array<uint8_t> secret;
-    if (!secret.Init(32 + HRSS_KEY_BYTES)) {
-      return false;
-    }
-
-    if (ciphertext.size() != 32 + HRSS_CIPHERTEXT_BYTES ||
-        !X25519(secret.data(), x25519_private_key_, ciphertext.data())) {
-      *out_alert = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
-      return false;
-    }
-
-    if (!HRSS_decap(secret.data() + 32, &hrss_private_key_,
-                    ciphertext.data() + 32, ciphertext.size() - 32)) {
-      return false;
-    }
-
-    *out_secret = std::move(secret);
-    return true;
-  }
-
- private:
-  uint8_t x25519_private_key_[32];
-  HRSS_private_key hrss_private_key_;
-};
-
 class X25519Kyber768KeyShare : public SSLKeyShare {
  public:
   X25519Kyber768KeyShare() {}
@@ -405,7 +310,6 @@
     {NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
     {NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
     {NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
-    {NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
     {NID_X25519Kyber768, SSL_CURVE_X25519KYBER768, "X25519KYBER",
      "X25519Kyber"},
     {NID_P256Kyber768, SSL_CURVE_P256KYBER768, "P256KYBER", "P256Kyber"},
@@ -429,8 +333,6 @@
       return MakeUnique<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1);
     case SSL_CURVE_X25519:
       return MakeUnique<X25519KeyShare>();
-    case SSL_CURVE_CECPQ2:
-      return MakeUnique<CECPQ2KeyShare>();
     case SSL_CURVE_X25519KYBER768:
       return MakeUnique<X25519Kyber768KeyShare>();
     case SSL_CURVE_P256KYBER768:
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 86e8eb3..838761a 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -484,6 +484,17 @@
   return true;
 }
 
+void SSL_CTX_set_aes_hw_override_for_testing(SSL_CTX *ctx,
+                                             bool override_value) {
+  ctx->aes_hw_override = true;
+  ctx->aes_hw_override_value = override_value;
+}
+
+void SSL_set_aes_hw_override_for_testing(SSL *ssl, bool override_value) {
+  ssl->config->aes_hw_override = true;
+  ssl->config->aes_hw_override_value = override_value;
+}
+
 BSSL_NAMESPACE_END
 
 using namespace bssl;
@@ -525,7 +536,8 @@
       false_start_allowed_without_alpn(false),
       handoff(false),
       enable_early_data(false),
-      only_fips_cipher_suites_in_tls13(false) {
+      aes_hw_override(false),
+      aes_hw_override_value(false) {
   CRYPTO_MUTEX_init(&lock);
   CRYPTO_new_ex_data(&ex_data);
 }
@@ -645,8 +657,9 @@
   ssl->config->retain_only_sha256_of_client_certs =
       ctx->retain_only_sha256_of_client_certs;
   ssl->config->permute_extensions = ctx->permute_extensions;
-  ssl->config->only_fips_cipher_suites_in_tls13 =
-      ctx->only_fips_cipher_suites_in_tls13;
+  ssl->config->aes_hw_override = ctx->aes_hw_override;
+  ssl->config->aes_hw_override_value = ctx->aes_hw_override_value;
+  ssl->config->tls13_cipher_policy = ctx->tls13_cipher_policy;
 
   if (!ssl->config->supported_group_list.CopyFrom(ctx->supported_group_list) ||
       !ssl->config->alpn_client_proto_list.CopyFrom(
@@ -688,7 +701,7 @@
       signed_cert_timestamps_enabled(false),
       ocsp_stapling_enabled(false),
       channel_id_enabled(false),
-      enforce_rsa_key_usage(false),
+      enforce_rsa_key_usage(true),
       retain_only_sha256_of_client_certs(false),
       handoff(false),
       shed_handshake_config(false),
@@ -2026,18 +2039,27 @@
 }
 
 int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
-  return ssl_create_cipher_list(&ctx->cipher_list, str, false /* not strict */);
+  const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
+                                               : EVP_has_aes_hardware();
+  return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
+                                false /* not strict */);
 }
 
 int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, const char *str) {
-  return ssl_create_cipher_list(&ctx->cipher_list, str, true /* strict */);
+  const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
+                                               : EVP_has_aes_hardware();
+  return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
+                                true /* strict */);
 }
 
 int SSL_set_cipher_list(SSL *ssl, const char *str) {
   if (!ssl->config) {
     return 0;
   }
-  return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+  const bool has_aes_hw = ssl->config->aes_hw_override
+                              ? ssl->config->aes_hw_override_value
+                              : EVP_has_aes_hardware();
+  return ssl_create_cipher_list(&ssl->config->cipher_list, has_aes_hw, str,
                                 false /* not strict */);
 }
 
@@ -2045,7 +2067,10 @@
   if (!ssl->config) {
     return 0;
   }
-  return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+  const bool has_aes_hw = ssl->config->aes_hw_override
+                              ? ssl->config->aes_hw_override_value
+                              : EVP_has_aes_hardware();
+  return ssl_create_cipher_list(&ssl->config->cipher_list, has_aes_hw, str,
                                 true /* strict */);
 }
 
@@ -3148,7 +3173,7 @@
     "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
 
 static int Configure(SSL_CTX *ctx) {
-  ctx->only_fips_cipher_suites_in_tls13 = true;
+  ctx->tls13_cipher_policy = ssl_compliance_policy_fips_202205;
 
   return
       // Section 3.1:
@@ -3171,7 +3196,7 @@
 }
 
 static int Configure(SSL *ssl) {
-  ssl->config->only_fips_cipher_suites_in_tls13 = true;
+  ssl->config->tls13_cipher_policy = ssl_compliance_policy_fips_202205;
 
   // See |Configure(SSL_CTX)|, above, for reasoning.
   return SSL_set_min_proto_version(ssl, TLS1_2_VERSION) &&
@@ -3186,11 +3211,59 @@
 
 }  // namespace fips202205
 
+namespace wpa202304 {
+
+// See WPA version 3.1, section 3.5.
+
+static const int kCurves[] = {NID_secp384r1};
+
+static const uint16_t kSigAlgs[] = {
+    SSL_SIGN_RSA_PKCS1_SHA384,        //
+    SSL_SIGN_RSA_PKCS1_SHA512,        //
+    SSL_SIGN_ECDSA_SECP384R1_SHA384,  //
+    SSL_SIGN_RSA_PSS_RSAE_SHA384,     //
+    SSL_SIGN_RSA_PSS_RSAE_SHA512,     //
+};
+
+static const char kTLS12Ciphers[] =
+    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:"
+    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
+
+static int Configure(SSL_CTX *ctx) {
+  ctx->tls13_cipher_policy = ssl_compliance_policy_wpa3_192_202304;
+
+  return SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION) &&
+         SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION) &&
+         SSL_CTX_set_strict_cipher_list(ctx, kTLS12Ciphers) &&
+         SSL_CTX_set1_curves(ctx, kCurves, OPENSSL_ARRAY_SIZE(kCurves)) &&
+         SSL_CTX_set_signing_algorithm_prefs(ctx, kSigAlgs,
+                                             OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
+         SSL_CTX_set_verify_algorithm_prefs(ctx, kSigAlgs,
+                                            OPENSSL_ARRAY_SIZE(kSigAlgs));
+}
+
+static int Configure(SSL *ssl) {
+  ssl->config->tls13_cipher_policy = ssl_compliance_policy_wpa3_192_202304;
+
+  return SSL_set_min_proto_version(ssl, TLS1_2_VERSION) &&
+         SSL_set_max_proto_version(ssl, TLS1_3_VERSION) &&
+         SSL_set_strict_cipher_list(ssl, kTLS12Ciphers) &&
+         SSL_set1_curves(ssl, kCurves, OPENSSL_ARRAY_SIZE(kCurves)) &&
+         SSL_set_signing_algorithm_prefs(ssl, kSigAlgs,
+                                         OPENSSL_ARRAY_SIZE(kSigAlgs)) &&
+         SSL_set_verify_algorithm_prefs(ssl, kSigAlgs,
+                                        OPENSSL_ARRAY_SIZE(kSigAlgs));
+}
+
+}  // namespace wpa202304
+
 int SSL_CTX_set_compliance_policy(SSL_CTX *ctx,
                                   enum ssl_compliance_policy_t policy) {
   switch (policy) {
     case ssl_compliance_policy_fips_202205:
       return fips202205::Configure(ctx);
+    case ssl_compliance_policy_wpa3_192_202304:
+      return wpa202304::Configure(ctx);
     default:
       return 0;
   }
@@ -3200,6 +3273,8 @@
   switch (policy) {
     case ssl_compliance_policy_fips_202205:
       return fips202205::Configure(ssl);
+    case ssl_compliance_policy_wpa3_192_202304:
+      return wpa202304::Configure(ssl);
     default:
       return 0;
   }
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 5b61eba..979ac59 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -400,7 +400,7 @@
   return true;
 }
 
-int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx) {
+bool ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx) {
   OPENSSL_timeval now;
   ssl_ctx_get_current_time(ctx, &now);
   {
@@ -412,7 +412,7 @@
          ctx->ticket_key_current->next_rotation_tv_sec > now.tv_sec) &&
         (!ctx->ticket_key_prev ||
          ctx->ticket_key_prev->next_rotation_tv_sec > now.tv_sec)) {
-      return 1;
+      return true;
     }
   }
 
@@ -423,7 +423,7 @@
     // The current key has not been initialized or it is expired.
     auto new_key = bssl::MakeUnique<TicketKey>();
     if (!new_key) {
-      return 0;
+      return false;
     }
     RAND_bytes(new_key->name, 16);
     RAND_bytes(new_key->hmac_key, 16);
@@ -447,7 +447,7 @@
     ctx->ticket_key_prev.reset();
   }
 
-  return 1;
+  return true;
 }
 
 static int ssl_encrypt_ticket_with_cipher_ctx(SSL_HANDSHAKE *hs, CBB *out,
@@ -560,30 +560,28 @@
   return 1;
 }
 
-int ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out,
+bool ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out,
                        const SSL_SESSION *session) {
   // Serialize the SSL_SESSION to be encoded into the ticket.
-  uint8_t *session_buf = NULL;
+  uint8_t *session_buf = nullptr;
   size_t session_len;
   if (!SSL_SESSION_to_bytes_for_ticket(session, &session_buf, &session_len)) {
-    return -1;
+    return false;
   }
+  bssl::UniquePtr<uint8_t> free_session_buf(session_buf);
 
-  int ret = 0;
   if (hs->ssl->session_ctx->ticket_aead_method) {
-    ret = ssl_encrypt_ticket_with_method(hs, out, session_buf, session_len);
+    return ssl_encrypt_ticket_with_method(hs, out, session_buf, session_len);
   } else {
-    ret = ssl_encrypt_ticket_with_cipher_ctx(hs, out, session_buf, session_len);
+    return ssl_encrypt_ticket_with_cipher_ctx(hs, out, session_buf,
+                                              session_len);
   }
-
-  OPENSSL_free(session_buf);
-  return ret;
 }
 
-int ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
-                                 const SSL_SESSION *session) {
+bool ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
+                                  const SSL_SESSION *session) {
   if (session == NULL) {
-    return 0;
+    return false;
   }
 
   return session->sid_ctx_length == hs->config->cert->sid_ctx_length &&
@@ -591,9 +589,9 @@
                         hs->config->cert->sid_ctx_length) == 0;
 }
 
-int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
+bool ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
   if (session == NULL) {
-    return 0;
+    return false;
   }
 
   struct OPENSSL_timeval now;
@@ -601,14 +599,14 @@
 
   // Reject tickets from the future to avoid underflow.
   if (now.tv_sec < session->time) {
-    return 0;
+    return false;
   }
 
   return session->timeout > now.tv_sec - session->time;
 }
 
-int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
-                             const SSL_SESSION *session) {
+bool ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
+                              const SSL_SESSION *session) {
   const SSL *const ssl = hs->ssl;
   return ssl_session_is_context_valid(hs, session) &&
          // The session must have been created by the same type of end point as
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index f51c11e..854068f 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -12,6 +12,7 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
@@ -400,8 +401,8 @@
     { SSL_CURVE_SECP256R1 },
   },
   {
-    "P-256:CECPQ2",
-    { SSL_CURVE_SECP256R1, SSL_CURVE_CECPQ2 },
+    "P-256:X25519KYBER",
+    { SSL_CURVE_SECP256R1, SSL_CURVE_X25519KYBER768 },
   },
 
   {
@@ -1037,10 +1038,6 @@
     ASSERT_TRUE(cipher);
     EXPECT_STREQ(t.standard_name, SSL_CIPHER_standard_name(cipher));
 
-    bssl::UniquePtr<char> rfc_name(SSL_CIPHER_get_rfc_name(cipher));
-    ASSERT_TRUE(rfc_name);
-    EXPECT_STREQ(t.standard_name, rfc_name.get());
-
     EXPECT_EQ(t.cipher_nid, SSL_CIPHER_get_cipher_nid(cipher));
     EXPECT_EQ(t.digest_nid, SSL_CIPHER_get_digest_nid(cipher));
     EXPECT_EQ(t.kx_nid, SSL_CIPHER_get_kx_nid(cipher));
@@ -3435,8 +3432,10 @@
   const uint8_t *iv = ticket + 16;
   bssl::ScopedEVP_CIPHER_CTX ctx;
   int len1, len2;
-  if (!EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), nullptr, kZeros, iv) ||
-      !EVP_DecryptUpdate(ctx.get(), plaintext.get(), &len1, ciphertext, len) ||
+  if (len > INT_MAX ||
+      !EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), nullptr, kZeros, iv) ||
+      !EVP_DecryptUpdate(ctx.get(), plaintext.get(), &len1, ciphertext,
+                         static_cast<int>(len)) ||
       !EVP_DecryptFinal_ex(ctx.get(), plaintext.get() + len1, &len2)) {
     return false;
   }
@@ -7755,8 +7754,8 @@
     // |BIO_should_write|.
     int ret;
     for (int i = 0; i < 1024; i++) {
-      std::vector<uint8_t> buffer(1024);
-      ret = BIO_write(client_bio.get(), buffer.data(), buffer.size());
+      const uint8_t kZeros[1024] = {0};
+      ret = BIO_write(client_bio.get(), kZeros, sizeof(kZeros));
       if (ret <= 0) {
         break;
       }
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 684c254..c64bb16 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -583,16 +583,14 @@
   }
 
   uint16_t cipher_id = SSL_CIPHER_get_protocol_id(SSL_get_current_cipher(ssl));
-  if (config->expect_cipher_aes != 0 &&
-      EVP_has_aes_hardware() &&
+  if (config->expect_cipher_aes != 0 && EVP_has_aes_hardware() &&
       config->expect_cipher_aes != cipher_id) {
     fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
             cipher_id, config->expect_cipher_aes);
     return false;
   }
 
-  if (config->expect_cipher_no_aes != 0 &&
-      !EVP_has_aes_hardware() &&
+  if (config->expect_cipher_no_aes != 0 && !EVP_has_aes_hardware() &&
       config->expect_cipher_no_aes != cipher_id) {
     fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
             cipher_id, config->expect_cipher_no_aes);
diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h
index 00b5e84..e18a820 100644
--- a/src/ssl/test/fuzzer.h
+++ b/src/ssl/test/fuzzer.h
@@ -414,12 +414,13 @@
     SSL_CTX_enable_ocsp_stapling(ctx_.get());
 
     // Enable versions and ciphers that are off by default.
-    if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL:NULL-SHA")) {
+    if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL")) {
       return false;
     }
 
-    static const int kCurves[] = {NID_CECPQ2, NID_X25519, NID_X9_62_prime256v1,
-                                  NID_secp384r1, NID_secp521r1};
+    static const int kCurves[] = {NID_X25519Kyber768, NID_X25519,
+                                  NID_X9_62_prime256v1, NID_secp384r1,
+                                  NID_secp521r1};
     if (!SSL_CTX_set1_curves(ctx_.get(), kCurves,
                              OPENSSL_ARRAY_SIZE(kCurves))) {
       return false;
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index 5db5749..b86f515 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -127,11 +127,6 @@
 	{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
 	{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
 	{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_NULL_SHA, 0, 20, noIV, rsaKA, 0, cipherNull, macSHA1, nil},
-}
-
-func noIV(vers uint16) int {
-	return 0
 }
 
 func ivLenChaCha20Poly1305(vers uint16) int {
@@ -364,7 +359,6 @@
 // A list of the possible cipher suite ids. Taken from
 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
 const (
-	TLS_RSA_WITH_NULL_SHA                         uint16 = 0x0002
 	TLS_RSA_WITH_3DES_EDE_CBC_SHA                 uint16 = 0x000a
 	TLS_RSA_WITH_AES_128_CBC_SHA                  uint16 = 0x002f
 	TLS_RSA_WITH_AES_256_CBC_SHA                  uint16 = 0x0035
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 3854283..cb97498 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -148,12 +148,12 @@
 type CurveID uint16
 
 const (
-	CurveP224   CurveID = 21
-	CurveP256   CurveID = 23
-	CurveP384   CurveID = 24
-	CurveP521   CurveID = 25
-	CurveX25519 CurveID = 29
-	CurveCECPQ2 CurveID = 16696
+	CurveP224           CurveID = 21
+	CurveP256           CurveID = 23
+	CurveP384           CurveID = 24
+	CurveP521           CurveID = 25
+	CurveX25519         CurveID = 29
+	CurveX25519Kyber768 CurveID = 0x6399
 )
 
 // TLS Elliptic Curve Point Formats
@@ -222,9 +222,13 @@
 // algorithms.
 var supportedSignatureAlgorithms = []signatureAlgorithm{
 	signatureRSAPSSWithSHA256,
+	signatureRSAPSSWithSHA384,
 	signatureRSAPKCS1WithSHA256,
 	signatureECDSAWithP256AndSHA256,
+	signatureECDSAWithP384AndSHA384,
 	signatureRSAPKCS1WithSHA1,
+	signatureRSAPKCS1WithSHA256,
+	signatureRSAPKCS1WithSHA384,
 	signatureECDSAWithSHA1,
 	signatureEd25519,
 }
@@ -1890,9 +1894,9 @@
 	// hello retry.
 	FailIfHelloRetryRequested bool
 
-	// FailedIfCECPQ2Offered will cause a server to reject a ClientHello if CECPQ2
+	// FailedIfKyberOffered will cause a server to reject a ClientHello if Kyber
 	// is supported.
-	FailIfCECPQ2Offered bool
+	FailIfKyberOffered bool
 
 	// ExpectKeyShares, if not nil, lists (in order) the curves that a ClientHello
 	// should have key shares for.
@@ -1996,7 +2000,7 @@
 	return ret
 }
 
-var defaultCurvePreferences = []CurveID{CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
+var defaultCurvePreferences = []CurveID{CurveX25519, CurveP256, CurveP384, CurveP521}
 
 func (c *Config) curvePreferences() []CurveID {
 	if c == nil || len(c.CurvePreferences) == 0 {
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index de297a6..4f3cf75 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -280,10 +280,10 @@
 		}
 	}
 
-	if config.Bugs.FailIfCECPQ2Offered {
+	if config.Bugs.FailIfKyberOffered {
 		for _, offeredCurve := range hs.clientHello.supportedCurves {
 			if isPqGroup(offeredCurve) {
-				return errors.New("tls: CECPQ2 was offered")
+				return errors.New("tls: X25519Kyber768 was offered")
 			}
 		}
 	}
@@ -1467,7 +1467,7 @@
 Curves:
 	for _, curve := range hs.clientHello.supportedCurves {
 		if isPqGroup(curve) && c.vers < VersionTLS13 {
-			// CECPQ2 is TLS 1.3-only.
+			// Post-quantum is TLS 1.3 only.
 			continue
 		}
 
diff --git a/src/ssl/test/runner/hrss/hrss.go b/src/ssl/test/runner/hrss/hrss.go
deleted file mode 100644
index 9f4fdd7..0000000
--- a/src/ssl/test/runner/hrss/hrss.go
+++ /dev/null
@@ -1,1212 +0,0 @@
-package hrss
-
-import (
-	"crypto/hmac"
-	"crypto/sha256"
-	"crypto/subtle"
-	"encoding/binary"
-	"io"
-	"math/bits"
-)
-
-const (
-	PublicKeySize  = modQBytes
-	CiphertextSize = modQBytes
-)
-
-const (
-	N         = 701
-	Q         = 8192
-	mod3Bytes = 140
-	modQBytes = 1138
-)
-
-const (
-	bitsPerWord      = bits.UintSize
-	wordsPerPoly     = (N + bitsPerWord - 1) / bitsPerWord
-	fullWordsPerPoly = N / bitsPerWord
-	bitsInLastWord   = N % bitsPerWord
-)
-
-// poly3 represents a degree-N polynomial over GF(3). Each coefficient is
-// bitsliced across the |s| and |a| arrays, like this:
-//
-//   s  |  a  | value
-//  -----------------
-//   0  |  0  | 0
-//   0  |  1  | 1
-//   1  |  0  | 2 (aka -1)
-//   1  |  1  | <invalid>
-//
-// ('s' is for sign, and 'a' is just a letter.)
-//
-// Once bitsliced as such, the following circuits can be used to implement
-// addition and multiplication mod 3:
-//
-//   (s3, a3) = (s1, a1) × (s2, a2)
-//   s3 = (s2 ∧ a1) ⊕ (s1 ∧ a2)
-//   a3 = (s1 ∧ s2) ⊕ (a1 ∧ a2)
-//
-//   (s3, a3) = (s1, a1) + (s2, a2)
-//   t1 = ~(s1 ∨ a1)
-//   t2 = ~(s2 ∨ a2)
-//   s3 = (a1 ∧ a2) ⊕ (t1 ∧ s2) ⊕ (t2 ∧ s1)
-//   a3 = (s1 ∧ s2) ⊕ (t1 ∧ a2) ⊕ (t2 ∧ a1)
-//
-// Negating a value just involves swapping s and a.
-type poly3 struct {
-	s [wordsPerPoly]uint
-	a [wordsPerPoly]uint
-}
-
-func (p *poly3) trim() {
-	p.s[wordsPerPoly-1] &= (1 << bitsInLastWord) - 1
-	p.a[wordsPerPoly-1] &= (1 << bitsInLastWord) - 1
-}
-
-func (p *poly3) zero() {
-	for i := range p.a {
-		p.s[i] = 0
-		p.a[i] = 0
-	}
-}
-
-func (p *poly3) fromDiscrete(in *poly) {
-	var shift uint
-	s := p.s[:]
-	a := p.a[:]
-	s[0] = 0
-	a[0] = 0
-
-	for _, v := range in {
-		s[0] >>= 1
-		s[0] |= uint((v>>1)&1) << (bitsPerWord - 1)
-		a[0] >>= 1
-		a[0] |= uint(v&1) << (bitsPerWord - 1)
-		shift++
-		if shift == bitsPerWord {
-			s = s[1:]
-			a = a[1:]
-			s[0] = 0
-			a[0] = 0
-			shift = 0
-		}
-	}
-
-	a[0] >>= bitsPerWord - shift
-	s[0] >>= bitsPerWord - shift
-}
-
-func (p *poly3) fromModQ(in *poly) int {
-	var shift uint
-	s := p.s[:]
-	a := p.a[:]
-	s[0] = 0
-	a[0] = 0
-	ok := 1
-
-	for _, v := range in {
-		vMod3, vOk := modQToMod3(v)
-		ok &= vOk
-
-		s[0] >>= 1
-		s[0] |= uint((vMod3>>1)&1) << (bitsPerWord - 1)
-		a[0] >>= 1
-		a[0] |= uint(vMod3&1) << (bitsPerWord - 1)
-		shift++
-		if shift == bitsPerWord {
-			s = s[1:]
-			a = a[1:]
-			s[0] = 0
-			a[0] = 0
-			shift = 0
-		}
-	}
-
-	a[0] >>= bitsPerWord - shift
-	s[0] >>= bitsPerWord - shift
-
-	return ok
-}
-
-func (p *poly3) fromDiscreteMod3(in *poly) {
-	var shift uint
-	s := p.s[:]
-	a := p.a[:]
-	s[0] = 0
-	a[0] = 0
-
-	for _, v := range in {
-		// This duplicates the 13th bit upwards to the top of the
-		// uint16, essentially treating it as a sign bit and converting
-		// into a signed int16. The signed value is reduced mod 3,
-		// yeilding {-2, -1, 0, 1, 2}.
-		v = uint16((int16(v<<3)>>3)%3) & 7
-
-		// We want to map v thus:
-		// {-2, -1, 0, 1, 2} -> {1, 2, 0, 1, 2}. We take the bottom
-		// three bits and then the constants below, when shifted by
-		// those three bits, perform the required mapping.
-		s[0] >>= 1
-		s[0] |= (0xbc >> v) << (bitsPerWord - 1)
-		a[0] >>= 1
-		a[0] |= (0x7a >> v) << (bitsPerWord - 1)
-		shift++
-		if shift == bitsPerWord {
-			s = s[1:]
-			a = a[1:]
-			s[0] = 0
-			a[0] = 0
-			shift = 0
-		}
-	}
-
-	a[0] >>= bitsPerWord - shift
-	s[0] >>= bitsPerWord - shift
-}
-
-func (p *poly3) marshal(out []byte) {
-	s := p.s[:]
-	a := p.a[:]
-	sw := s[0]
-	aw := a[0]
-	var shift int
-
-	for i := 0; i < 700; i += 5 {
-		acc, scale := 0, 1
-		for j := 0; j < 5; j++ {
-			v := int(aw&1) | int(sw&1)<<1
-			acc += scale * v
-			scale *= 3
-
-			shift++
-			if shift == bitsPerWord {
-				s = s[1:]
-				a = a[1:]
-				sw = s[0]
-				aw = a[0]
-				shift = 0
-			} else {
-				sw >>= 1
-				aw >>= 1
-			}
-		}
-
-		out[0] = byte(acc)
-		out = out[1:]
-	}
-}
-
-func (p *poly) fromMod2(in *poly2) {
-	var shift uint
-	words := in[:]
-	word := words[0]
-
-	for i := range p {
-		p[i] = uint16(word & 1)
-		word >>= 1
-		shift++
-		if shift == bitsPerWord {
-			words = words[1:]
-			word = words[0]
-			shift = 0
-		}
-	}
-}
-
-func (p *poly) fromMod3(in *poly3) {
-	var shift uint
-	s := in.s[:]
-	a := in.a[:]
-	sw := s[0]
-	aw := a[0]
-
-	for i := range p {
-		p[i] = uint16(aw&1 | (sw&1)<<1)
-		aw >>= 1
-		sw >>= 1
-		shift++
-		if shift == bitsPerWord {
-			a = a[1:]
-			s = s[1:]
-			aw = a[0]
-			sw = s[0]
-			shift = 0
-		}
-	}
-}
-
-func (p *poly) fromMod3ToModQ(in *poly3) {
-	var shift uint
-	s := in.s[:]
-	a := in.a[:]
-	sw := s[0]
-	aw := a[0]
-
-	for i := range p {
-		p[i] = mod3ToModQ(uint16(aw&1 | (sw&1)<<1))
-		aw >>= 1
-		sw >>= 1
-		shift++
-		if shift == bitsPerWord {
-			a = a[1:]
-			s = s[1:]
-			aw = a[0]
-			sw = s[0]
-			shift = 0
-		}
-	}
-}
-
-func lsbToAll(v uint) uint {
-	return uint(int(v<<(bitsPerWord-1)) >> (bitsPerWord - 1))
-}
-
-func (p *poly3) mulConst(ms, ma uint) {
-	ms = lsbToAll(ms)
-	ma = lsbToAll(ma)
-
-	for i := range p.a {
-		p.s[i], p.a[i] = (ma&p.s[i])^(ms&p.a[i]), (ma&p.a[i])^(ms&p.s[i])
-	}
-}
-
-func cmovWords(out, in *[wordsPerPoly]uint, mov uint) {
-	for i := range out {
-		out[i] = (out[i] & ^mov) | (in[i] & mov)
-	}
-}
-
-func rotWords(out, in *[wordsPerPoly]uint, bits uint) {
-	start := bits / bitsPerWord
-	n := (N - bits) / bitsPerWord
-
-	for i := uint(0); i < n; i++ {
-		out[i] = in[start+i]
-	}
-
-	carry := in[wordsPerPoly-1]
-
-	for i := uint(0); i < start; i++ {
-		out[n+i] = carry | in[i]<<bitsInLastWord
-		carry = in[i] >> (bitsPerWord - bitsInLastWord)
-	}
-
-	out[wordsPerPoly-1] = carry
-}
-
-// rotBits right-rotates the bits in |in|. bits must be a non-zero power of two
-// and less than bitsPerWord.
-func rotBits(out, in *[wordsPerPoly]uint, bits uint) {
-	if (bits == 0 || (bits & (bits - 1)) != 0 || bits > bitsPerWord/2 || bitsInLastWord < bitsPerWord/2) {
-		panic("internal error");
-	}
-
-	carry := in[wordsPerPoly-1] << (bitsPerWord - bits)
-
-	for i := wordsPerPoly - 2; i >= 0; i-- {
-		out[i] = carry | in[i]>>bits
-		carry = in[i] << (bitsPerWord - bits)
-	}
-
-	out[wordsPerPoly-1] = carry>>(bitsPerWord-bitsInLastWord) | in[wordsPerPoly-1]>>bits
-}
-
-func (p *poly3) rotWords(bits uint, in *poly3) {
-	rotWords(&p.s, &in.s, bits)
-	rotWords(&p.a, &in.a, bits)
-}
-
-func (p *poly3) rotBits(bits uint, in *poly3) {
-	rotBits(&p.s, &in.s, bits)
-	rotBits(&p.a, &in.a, bits)
-}
-
-func (p *poly3) cmov(in *poly3, mov uint) {
-	cmovWords(&p.s, &in.s, mov)
-	cmovWords(&p.a, &in.a, mov)
-}
-
-func (p *poly3) rot(bits uint) {
-	if bits > N {
-		panic("invalid")
-	}
-	var shifted poly3
-
-	shift := uint(9)
-	for ; (1 << shift) >= bitsPerWord; shift-- {
-		shifted.rotWords(1<<shift, p)
-		p.cmov(&shifted, lsbToAll(bits>>shift))
-	}
-	for ; shift < 9; shift-- {
-		shifted.rotBits(1<<shift, p)
-		p.cmov(&shifted, lsbToAll(bits>>shift))
-	}
-}
-
-func (p *poly3) fmadd(ms, ma uint, in *poly3) {
-	ms = lsbToAll(ms)
-	ma = lsbToAll(ma)
-
-	for i := range p.a {
-		products := (ma & in.s[i]) ^ (ms & in.a[i])
-		producta := (ma & in.a[i]) ^ (ms & in.s[i])
-
-		ns1Ana1 := ^p.s[i] & ^p.a[i]
-		ns2Ana2 := ^products & ^producta
-
-		p.s[i], p.a[i] = (p.a[i]&producta)^(ns1Ana1&products)^(p.s[i]&ns2Ana2), (p.s[i]&products)^(ns1Ana1&producta)^(p.a[i]&ns2Ana2)
-	}
-}
-
-func (p *poly3) modPhiN() {
-	factora := uint(int(p.s[wordsPerPoly-1]<<(bitsPerWord-bitsInLastWord)) >> (bitsPerWord - 1))
-	factors := uint(int(p.a[wordsPerPoly-1]<<(bitsPerWord-bitsInLastWord)) >> (bitsPerWord - 1))
-	ns2Ana2 := ^factors & ^factora
-
-	for i := range p.s {
-		ns1Ana1 := ^p.s[i] & ^p.a[i]
-		p.s[i], p.a[i] = (p.a[i]&factora)^(ns1Ana1&factors)^(p.s[i]&ns2Ana2), (p.s[i]&factors)^(ns1Ana1&factora)^(p.a[i]&ns2Ana2)
-	}
-}
-
-func (p *poly3) cswap(other *poly3, swap uint) {
-	for i := range p.s {
-		sums := swap & (p.s[i] ^ other.s[i])
-		p.s[i] ^= sums
-		other.s[i] ^= sums
-
-		suma := swap & (p.a[i] ^ other.a[i])
-		p.a[i] ^= suma
-		other.a[i] ^= suma
-	}
-}
-
-func (p *poly3) mulx() {
-	carrys := (p.s[wordsPerPoly-1] >> (bitsInLastWord - 1)) & 1
-	carrya := (p.a[wordsPerPoly-1] >> (bitsInLastWord - 1)) & 1
-
-	for i := range p.s {
-		outCarrys := p.s[i] >> (bitsPerWord - 1)
-		outCarrya := p.a[i] >> (bitsPerWord - 1)
-		p.s[i] <<= 1
-		p.a[i] <<= 1
-		p.s[i] |= carrys
-		p.a[i] |= carrya
-		carrys = outCarrys
-		carrya = outCarrya
-	}
-}
-
-func (p *poly3) divx() {
-	var carrys, carrya uint
-
-	for i := len(p.s) - 1; i >= 0; i-- {
-		outCarrys := p.s[i] & 1
-		outCarrya := p.a[i] & 1
-		p.s[i] >>= 1
-		p.a[i] >>= 1
-		p.s[i] |= carrys << (bitsPerWord - 1)
-		p.a[i] |= carrya << (bitsPerWord - 1)
-		carrys = outCarrys
-		carrya = outCarrya
-	}
-}
-
-type poly2 [wordsPerPoly]uint
-
-func (p *poly2) fromDiscrete(in *poly) {
-	var shift uint
-	words := p[:]
-	words[0] = 0
-
-	for _, v := range in {
-		words[0] >>= 1
-		words[0] |= uint(v&1) << (bitsPerWord - 1)
-		shift++
-		if shift == bitsPerWord {
-			words = words[1:]
-			words[0] = 0
-			shift = 0
-		}
-	}
-
-	words[0] >>= bitsPerWord - shift
-}
-
-func (p *poly2) setPhiN() {
-	for i := range p {
-		p[i] = ^uint(0)
-	}
-	p[wordsPerPoly-1] &= (1 << bitsInLastWord) - 1
-}
-
-func (p *poly2) cswap(other *poly2, swap uint) {
-	for i := range p {
-		sum := swap & (p[i] ^ other[i])
-		p[i] ^= sum
-		other[i] ^= sum
-	}
-}
-
-func (p *poly2) fmadd(m uint, in *poly2) {
-	m = ^(m - 1)
-
-	for i := range p {
-		p[i] ^= in[i] & m
-	}
-}
-
-func (p *poly2) lshift1() {
-	var carry uint
-	for i := range p {
-		nextCarry := p[i] >> (bitsPerWord - 1)
-		p[i] <<= 1
-		p[i] |= carry
-		carry = nextCarry
-	}
-}
-
-func (p *poly2) rshift1() {
-	var carry uint
-	for i := len(p) - 1; i >= 0; i-- {
-		nextCarry := p[i] & 1
-		p[i] >>= 1
-		p[i] |= carry << (bitsPerWord - 1)
-		carry = nextCarry
-	}
-}
-
-func (p *poly2) rot(bits uint) {
-	if bits > N {
-		panic("invalid")
-	}
-	var shifted [wordsPerPoly]uint
-	out := (*[wordsPerPoly]uint)(p)
-
-	shift := uint(9)
-	for ; (1 << shift) >= bitsPerWord; shift-- {
-		rotWords(&shifted, out, 1<<shift)
-		cmovWords(out, &shifted, lsbToAll(bits>>shift))
-	}
-	for ; shift < 9; shift-- {
-		rotBits(&shifted, out, 1<<shift)
-		cmovWords(out, &shifted, lsbToAll(bits>>shift))
-	}
-}
-
-type poly [N]uint16
-
-func (in *poly) marshal(out []byte) {
-	p := in[:]
-
-	for len(p) >= 8 {
-		out[0] = byte(p[0])
-		out[1] = byte(p[0]>>8) | byte((p[1]&0x07)<<5)
-		out[2] = byte(p[1] >> 3)
-		out[3] = byte(p[1]>>11) | byte((p[2]&0x3f)<<2)
-		out[4] = byte(p[2]>>6) | byte((p[3]&0x01)<<7)
-		out[5] = byte(p[3] >> 1)
-		out[6] = byte(p[3]>>9) | byte((p[4]&0x0f)<<4)
-		out[7] = byte(p[4] >> 4)
-		out[8] = byte(p[4]>>12) | byte((p[5]&0x7f)<<1)
-		out[9] = byte(p[5]>>7) | byte((p[6]&0x03)<<6)
-		out[10] = byte(p[6] >> 2)
-		out[11] = byte(p[6]>>10) | byte((p[7]&0x1f)<<3)
-		out[12] = byte(p[7] >> 5)
-
-		p = p[8:]
-		out = out[13:]
-	}
-
-	// There are four remaining values.
-	out[0] = byte(p[0])
-	out[1] = byte(p[0]>>8) | byte((p[1]&0x07)<<5)
-	out[2] = byte(p[1] >> 3)
-	out[3] = byte(p[1]>>11) | byte((p[2]&0x3f)<<2)
-	out[4] = byte(p[2]>>6) | byte((p[3]&0x01)<<7)
-	out[5] = byte(p[3] >> 1)
-	out[6] = byte(p[3] >> 9)
-}
-
-func (out *poly) unmarshal(in []byte) bool {
-	p := out[:]
-	for i := 0; i < 87; i++ {
-		p[0] = uint16(in[0]) | uint16(in[1]&0x1f)<<8
-		p[1] = uint16(in[1]>>5) | uint16(in[2])<<3 | uint16(in[3]&3)<<11
-		p[2] = uint16(in[3]>>2) | uint16(in[4]&0x7f)<<6
-		p[3] = uint16(in[4]>>7) | uint16(in[5])<<1 | uint16(in[6]&0xf)<<9
-		p[4] = uint16(in[6]>>4) | uint16(in[7])<<4 | uint16(in[8]&1)<<12
-		p[5] = uint16(in[8]>>1) | uint16(in[9]&0x3f)<<7
-		p[6] = uint16(in[9]>>6) | uint16(in[10])<<2 | uint16(in[11]&7)<<10
-		p[7] = uint16(in[11]>>3) | uint16(in[12])<<5
-
-		p = p[8:]
-		in = in[13:]
-	}
-
-	// There are four coefficients left over
-	p[0] = uint16(in[0]) | uint16(in[1]&0x1f)<<8
-	p[1] = uint16(in[1]>>5) | uint16(in[2])<<3 | uint16(in[3]&3)<<11
-	p[2] = uint16(in[3]>>2) | uint16(in[4]&0x7f)<<6
-	p[3] = uint16(in[4]>>7) | uint16(in[5])<<1 | uint16(in[6]&0xf)<<9
-
-	if in[6]&0xf0 != 0 {
-		return false
-	}
-
-	out[N-1] = 0
-	var top int
-	for _, v := range out {
-		top += int(v)
-	}
-
-	out[N-1] = uint16(-top) % Q
-	return true
-}
-
-func (in *poly) marshalS3(out []byte) {
-	p := in[:]
-	for len(p) >= 5 {
-		out[0] = byte(p[0] + p[1]*3 + p[2]*9 + p[3]*27 + p[4]*81)
-		out = out[1:]
-		p = p[5:]
-	}
-}
-
-func (out *poly) unmarshalS3(in []byte) bool {
-	p := out[:]
-	for i := 0; i < 140; i++ {
-		c := in[0]
-		if c >= 243 {
-			return false
-		}
-		p[0] = uint16(c % 3)
-		p[1] = uint16((c / 3) % 3)
-		p[2] = uint16((c / 9) % 3)
-		p[3] = uint16((c / 27) % 3)
-		p[4] = uint16((c / 81) % 3)
-
-		p = p[5:]
-		in = in[1:]
-	}
-
-	out[N-1] = 0
-	return true
-}
-
-func (p *poly) modPhiN() {
-	for i := range p {
-		p[i] = (p[i] + Q - p[N-1]) % Q
-	}
-}
-
-func (out *poly) shortSample(in []byte) {
-	//  b  a  result
-	// 00 00 00
-	// 00 01 01
-	// 00 10 10
-	// 00 11 11
-	// 01 00 10
-	// 01 01 00
-	// 01 10 01
-	// 01 11 11
-	// 10 00 01
-	// 10 01 10
-	// 10 10 00
-	// 10 11 11
-	// 11 00 11
-	// 11 01 11
-	// 11 10 11
-	// 11 11 11
-
-	// 1111 1111 1100 1001 1101 0010 1110 0100
-	//   f    f    c    9    d    2    e    4
-	const lookup = uint32(0xffc9d2e4)
-
-	p := out[:]
-	for i := 0; i < 87; i++ {
-		v := binary.LittleEndian.Uint32(in)
-		v2 := (v & 0x55555555) + ((v >> 1) & 0x55555555)
-		for j := 0; j < 8; j++ {
-			p[j] = uint16(lookup >> ((v2 & 15) << 1) & 3)
-			v2 >>= 4
-		}
-		p = p[8:]
-		in = in[4:]
-	}
-
-	// There are four values remaining.
-	v := binary.LittleEndian.Uint32(in)
-	v2 := (v & 0x55555555) + ((v >> 1) & 0x55555555)
-	for j := 0; j < 4; j++ {
-		p[j] = uint16(lookup >> ((v2 & 15) << 1) & 3)
-		v2 >>= 4
-	}
-
-	out[N-1] = 0
-}
-
-func (out *poly) shortSamplePlus(in []byte) {
-	out.shortSample(in)
-
-	var sum uint16
-	for i := 0; i < N-1; i++ {
-		sum += mod3ResultToModQ(out[i] * out[i+1])
-	}
-
-	scale := 1 + (1 & (sum >> 12))
-	for i := 0; i < len(out); i += 2 {
-		out[i] = (out[i] * scale) % 3
-	}
-}
-
-func mul(out, scratch, a, b []uint16) {
-	const schoolbookLimit = 32
-	if len(a) < schoolbookLimit {
-		for i := 0; i < len(a)*2; i++ {
-			out[i] = 0
-		}
-		for i := range a {
-			for j := range b {
-				out[i+j] += a[i] * b[j]
-			}
-		}
-		return
-	}
-
-	lowLen := len(a) / 2
-	highLen := len(a) - lowLen
-	aLow, aHigh := a[:lowLen], a[lowLen:]
-	bLow, bHigh := b[:lowLen], b[lowLen:]
-
-	for i := 0; i < lowLen; i++ {
-		out[i] = aHigh[i] + aLow[i]
-	}
-	if highLen != lowLen {
-		out[lowLen] = aHigh[lowLen]
-	}
-
-	for i := 0; i < lowLen; i++ {
-		out[highLen+i] = bHigh[i] + bLow[i]
-	}
-	if highLen != lowLen {
-		out[highLen+lowLen] = bHigh[lowLen]
-	}
-
-	mul(scratch, scratch[2*highLen:], out[:highLen], out[highLen:highLen*2])
-	mul(out[lowLen*2:], scratch[2*highLen:], aHigh, bHigh)
-	mul(out, scratch[2*highLen:], aLow, bLow)
-
-	for i := 0; i < lowLen*2; i++ {
-		scratch[i] -= out[i] + out[lowLen*2+i]
-	}
-	if lowLen != highLen {
-		scratch[lowLen*2] -= out[lowLen*4]
-	}
-
-	for i := 0; i < 2*highLen; i++ {
-		out[lowLen+i] += scratch[i]
-	}
-}
-
-func (out *poly) mul(a, b *poly) {
-	var prod, scratch [2 * N]uint16
-	mul(prod[:], scratch[:], a[:], b[:])
-	for i := range out {
-		out[i] = (prod[i] + prod[i+N]) % Q
-	}
-}
-
-func (p3 *poly3) mulMod3(x, y *poly3) {
-	// (𝑥^n - 1) is a multiple of Φ(N) so we can work mod (𝑥^n - 1) here and
-	// (reduce mod Φ(N) afterwards.
-	x3 := *x
-	y3 := *y
-	s := x3.s[:]
-	a := x3.a[:]
-	sw := s[0]
-	aw := a[0]
-	p3.zero()
-	var shift uint
-	for i := 0; i < N; i++ {
-		p3.fmadd(sw, aw, &y3)
-		sw >>= 1
-		aw >>= 1
-		shift++
-		if shift == bitsPerWord {
-			s = s[1:]
-			a = a[1:]
-			sw = s[0]
-			aw = a[0]
-			shift = 0
-		}
-		y3.mulx()
-	}
-	p3.modPhiN()
-}
-
-// mod3ToModQ maps {0, 1, 2, 3} to {0, 1, Q-1, 0xffff}
-// The case of n == 3 should never happen but is included so that modQToMod3
-// can easily catch invalid inputs.
-func mod3ToModQ(n uint16) uint16 {
-	return uint16(uint64(0xffff1fff00010000) >> (16 * n))
-}
-
-// modQToMod3 maps {0, 1, Q-1} to {(0, 0), (0, 1), (1, 0)} and also returns an int
-// which is one if the input is in range and zero otherwise.
-func modQToMod3(n uint16) (uint16, int) {
-	result := (n&3 - (n>>1)&1)
-	return result, subtle.ConstantTimeEq(int32(mod3ToModQ(result)), int32(n))
-}
-
-// mod3ResultToModQ maps {0, 1, 2, 4} to {0, 1, Q-1, 1}
-func mod3ResultToModQ(n uint16) uint16 {
-	return ((((uint16(0x13) >> n) & 1) - 1) & 0x1fff) | ((uint16(0x12) >> n) & 1)
-	//shift := (uint(0x324) >> (2 * n)) & 3
-	//return uint16(uint64(0x00011fff00010000) >> (16 * shift))
-}
-
-// mulXMinus1 sets out to a×(𝑥 - 1) mod (𝑥^n - 1)
-func (out *poly) mulXMinus1() {
-	// Multiplying by (𝑥 - 1) means negating each coefficient and adding in
-	// the value of the previous one.
-	origOut700 := out[700]
-
-	for i := N - 1; i > 0; i-- {
-		out[i] = (Q - out[i] + out[i-1]) % Q
-	}
-	out[0] = (Q - out[0] + origOut700) % Q
-}
-
-func (out *poly) lift(a *poly) {
-	// We wish to calculate a/(𝑥-1) mod Φ(N) over GF(3), where Φ(N) is the
-	// Nth cyclotomic polynomial, i.e. 1 + 𝑥 + … + 𝑥^700 (since N is prime).
-
-	// 1/(𝑥-1) has a fairly basic structure that we can exploit to speed this up:
-	//
-	// R.<x> = PolynomialRing(GF(3)…)
-	// inv = R.cyclotomic_polynomial(1).inverse_mod(R.cyclotomic_polynomial(n))
-	// list(inv)[:15]
-	//   [1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2]
-	//
-	// This three-element pattern of coefficients repeats for the whole
-	// polynomial.
-	//
-	// Next define the overbar operator such that z̅ = z[0] +
-	// reverse(z[1:]). (Index zero of a polynomial here is the coefficient
-	// of the constant term. So index one is the coefficient of 𝑥 and so
-	// on.)
-	//
-	// A less odd way to define this is to see that z̅ negates the indexes,
-	// so z̅[0] = z[-0], z̅[1] = z[-1] and so on.
-	//
-	// The use of z̅  is that, when working mod (𝑥^701 - 1), vz[0] = <v,
-	// z̅>, vz[1] = <v, 𝑥z̅>, …. (Where <a, b> is the inner product: the sum
-	// of the point-wise products.) Although we calculated the inverse mod
-	// Φ(N), we can work mod (𝑥^N - 1) and reduce mod Φ(N) at the end.
-	// (That's because (𝑥^N - 1) is a multiple of Φ(N).)
-	//
-	// When working mod (𝑥^N - 1), multiplication by 𝑥 is a right-rotation
-	// of the list of coefficients.
-	//
-	// Thus we can consider what the pattern of z̅, 𝑥z̅, 𝑥^2z̅, … looks like:
-	//
-	// def reverse(xs):
-	//   suffix = list(xs[1:])
-	//   suffix.reverse()
-	//   return [xs[0]] + suffix
-	//
-	// def rotate(xs):
-	//   return [xs[-1]] + xs[:-1]
-	//
-	// zoverbar = reverse(list(inv) + [0])
-	// xzoverbar = rotate(reverse(list(inv) + [0]))
-	// x2zoverbar = rotate(rotate(reverse(list(inv) + [0])))
-	//
-	// zoverbar[:15]
-	//   [1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1]
-	// xzoverbar[:15]
-	//   [0, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0]
-	// x2zoverbar[:15]
-	//   [2, 0, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
-	//
-	// (For a formula for z̅, see lemma two of appendix B.)
-	//
-	// After the first three elements have been taken care of, all then have
-	// a repeating three-element cycle. The next value (𝑥^3z̅) involves
-	// three rotations of the first pattern, thus the three-element cycle
-	// lines up. However, the discontinuity in the first three elements
-	// obviously moves to a different position. Consider the difference
-	// between 𝑥^3z̅ and z̅:
-	//
-	// [x-y for (x,y) in zip(zoverbar, x3zoverbar)][:15]
-	//    [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-	//
-	// This pattern of differences is the same for all elements, although it
-	// obviously moves right with the rotations.
-	//
-	// From this, we reach algorithm eight of appendix B.
-
-	// Handle the first three elements of the inner products.
-	out[0] = a[0] + a[2]
-	out[1] = a[1]
-	out[2] = 2*a[0] + a[2]
-
-	// Use the repeating pattern to complete the first three inner products.
-	for i := 3; i < 699; i += 3 {
-		out[0] += 2*a[i] + a[i+2]
-		out[1] += a[i] + 2*a[i+1]
-		out[2] += a[i+1] + 2*a[i+2]
-	}
-
-	// Handle the fact that the three-element pattern doesn't fill the
-	// polynomial exactly (since 701 isn't a multiple of three).
-	out[2] += a[700]
-	out[0] += 2 * a[699]
-	out[1] += a[699] + 2*a[700]
-
-	out[0] = out[0] % 3
-	out[1] = out[1] % 3
-	out[2] = out[2] % 3
-
-	// Calculate the remaining inner products by taking advantage of the
-	// fact that the pattern repeats every three cycles and the pattern of
-	// differences is moves with the rotation.
-	for i := 3; i < N; i++ {
-		// Add twice something is the same as subtracting when working
-		// mod 3. Doing it this way avoids underflow. Underflow is bad
-		// because "% 3" doesn't work correctly for negative numbers
-		// here since underflow will wrap to 2^16-1 and 2^16 isn't a
-		// multiple of three.
-		out[i] = (out[i-3] + 2*(a[i-2]+a[i-1]+a[i])) % 3
-	}
-
-	// Reduce mod Φ(N) by subtracting a multiple of out[700] from every
-	// element and convert to mod Q. (See above about adding twice as
-	// subtraction.)
-	v := out[700] * 2
-	for i := range out {
-		out[i] = mod3ToModQ((out[i] + v) % 3)
-	}
-
-	out.mulXMinus1()
-}
-
-func (a *poly) cswap(b *poly, swap uint16) {
-	for i := range a {
-		sum := swap & (a[i] ^ b[i])
-		a[i] ^= sum
-		b[i] ^= sum
-	}
-}
-
-func lt(a, b uint) uint {
-	if a < b {
-		return ^uint(0)
-	}
-	return 0
-}
-
-func bsMul(s1, a1, s2, a2 uint) (s3, a3 uint) {
-	s3 = (a1 & s2) ^ (s1 & a2)
-	a3 = (a1 & a2) ^ (s1 & s2)
-	return
-}
-
-func (out *poly3) invertMod3(in *poly3) {
-	// This algorithm follows algorithm 10 in the paper. (Although note that
-	// the paper appears to have a bug: k should start at zero, not one.)
-	// The best explanation for why it works is in the "Why it works"
-	// section of
-	// https://assets.onboardsecurity.com/static/downloads/NTRU/resources/NTRUTech014.pdf.
-	var k uint
-	degF, degG := uint(N-1), uint(N-1)
-
-	var b, c, g poly3
-	f := *in
-
-	for i := range g.a {
-		g.a[i] = ^uint(0)
-	}
-
-	b.a[0] = 1
-
-	var f0s, f0a uint
-	stillGoing := ^uint(0)
-	for i := 0; i < 2*(N-1)-1; i++ {
-		ss, sa := bsMul(f.s[0], f.a[0], g.s[0], g.a[0])
-		ss, sa = sa&stillGoing&1, ss&stillGoing&1
-		shouldSwap := ^uint(int((ss|sa)-1)>>(bitsPerWord-1)) & lt(degF, degG)
-		f.cswap(&g, shouldSwap)
-		b.cswap(&c, shouldSwap)
-		degF, degG = (degG&shouldSwap)|(degF & ^shouldSwap), (degF&shouldSwap)|(degG&^shouldSwap)
-		f.fmadd(ss, sa, &g)
-		b.fmadd(ss, sa, &c)
-
-		f.divx()
-		f.s[wordsPerPoly-1] &= ((1 << bitsInLastWord) - 1) >> 1
-		f.a[wordsPerPoly-1] &= ((1 << bitsInLastWord) - 1) >> 1
-		c.mulx()
-		c.s[0] &= ^uint(1)
-		c.a[0] &= ^uint(1)
-
-		degF--
-		k += 1 & stillGoing
-		f0s = (stillGoing & f.s[0]) | (^stillGoing & f0s)
-		f0a = (stillGoing & f.a[0]) | (^stillGoing & f0a)
-		stillGoing = ^uint(int(degF-1) >> (bitsPerWord - 1))
-	}
-
-	k -= N & lt(N, k)
-	*out = b
-	out.rot(k)
-	out.mulConst(f0s, f0a)
-	out.modPhiN()
-}
-
-func (out *poly) invertMod2(a *poly) {
-	// This algorithm follows mix of algorithm 10 in the paper and the first
-	// page of the PDF linked below. (Although note that the paper appears
-	// to have a bug: k should start at zero, not one.) The best explanation
-	// for why it works is in the "Why it works" section of
-	// https://assets.onboardsecurity.com/static/downloads/NTRU/resources/NTRUTech014.pdf.
-	var k uint
-	degF, degG := uint(N-1), uint(N-1)
-
-	var f poly2
-	f.fromDiscrete(a)
-	var b, c, g poly2
-	g.setPhiN()
-	b[0] = 1
-
-	stillGoing := ^uint(0)
-	for i := 0; i < 2*(N-1)-1; i++ {
-		s := uint(f[0]&1) & stillGoing
-		shouldSwap := ^(s - 1) & lt(degF, degG)
-		f.cswap(&g, shouldSwap)
-		b.cswap(&c, shouldSwap)
-		degF, degG = (degG&shouldSwap)|(degF & ^shouldSwap), (degF&shouldSwap)|(degG&^shouldSwap)
-		f.fmadd(s, &g)
-		b.fmadd(s, &c)
-
-		f.rshift1()
-		c.lshift1()
-
-		degF--
-		k += 1 & stillGoing
-		stillGoing = ^uint(int(degF-1) >> (bitsPerWord - 1))
-	}
-
-	k -= N & lt(N, k)
-	b.rot(k)
-	out.fromMod2(&b)
-}
-
-func (out *poly) invert(origA *poly) {
-	// Inversion mod Q, which is done based on the result of inverting mod
-	// 2. See the NTRU paper, page three.
-	var a, tmp, tmp2, b poly
-	b.invertMod2(origA)
-
-	// Negate a.
-	for i := range a {
-		a[i] = Q - origA[i]
-	}
-
-	// We are working mod Q=2**13 and we need to iterate ceil(log_2(13))
-	// times, which is four.
-	for i := 0; i < 4; i++ {
-		tmp.mul(&a, &b)
-		tmp[0] += 2
-		tmp2.mul(&b, &tmp)
-		b = tmp2
-	}
-
-	*out = b
-}
-
-type PublicKey struct {
-	h poly
-}
-
-func ParsePublicKey(in []byte) (*PublicKey, bool) {
-	ret := new(PublicKey)
-	if !ret.h.unmarshal(in) {
-		return nil, false
-	}
-	return ret, true
-}
-
-func (pub *PublicKey) Marshal() []byte {
-	ret := make([]byte, modQBytes)
-	pub.h.marshal(ret)
-	return ret
-}
-
-func (pub *PublicKey) Encap(rand io.Reader) (ciphertext []byte, sharedKey []byte) {
-	var randBytes [352 + 352]byte
-	if _, err := io.ReadFull(rand, randBytes[:]); err != nil {
-		panic("rand failed")
-	}
-
-	var m, r poly
-	m.shortSample(randBytes[:352])
-	r.shortSample(randBytes[352:])
-
-	var mBytes, rBytes [mod3Bytes]byte
-	m.marshalS3(mBytes[:])
-	r.marshalS3(rBytes[:])
-
-	ciphertext = pub.owf(&m, &r)
-
-	h := sha256.New()
-	h.Write([]byte("shared key\x00"))
-	h.Write(mBytes[:])
-	h.Write(rBytes[:])
-	h.Write(ciphertext)
-	sharedKey = h.Sum(nil)
-
-	return ciphertext, sharedKey
-}
-
-func (pub *PublicKey) owf(m, r *poly) []byte {
-	for i := range r {
-		r[i] = mod3ToModQ(r[i])
-	}
-
-	var mq poly
-	mq.lift(m)
-
-	var e poly
-	e.mul(r, &pub.h)
-	for i := range e {
-		e[i] = (e[i] + mq[i]) % Q
-	}
-
-	ret := make([]byte, modQBytes)
-	e.marshal(ret[:])
-	return ret
-}
-
-type PrivateKey struct {
-	PublicKey
-	f, fp   poly3
-	hInv    poly
-	hmacKey [32]byte
-}
-
-func (priv *PrivateKey) Marshal() []byte {
-	var ret [2*mod3Bytes + modQBytes]byte
-	priv.f.marshal(ret[:])
-	priv.fp.marshal(ret[mod3Bytes:])
-	priv.h.marshal(ret[2*mod3Bytes:])
-	return ret[:]
-}
-
-func (priv *PrivateKey) Decap(ciphertext []byte) (sharedKey []byte, ok bool) {
-	if len(ciphertext) != modQBytes {
-		return nil, false
-	}
-
-	var e poly
-	if !e.unmarshal(ciphertext) {
-		return nil, false
-	}
-
-	var f poly
-	f.fromMod3ToModQ(&priv.f)
-
-	var v1, m poly
-	v1.mul(&e, &f)
-
-	var v13 poly3
-	v13.fromDiscreteMod3(&v1)
-	// Note: v13 is not reduced mod phi(n).
-
-	var m3 poly3
-	m3.mulMod3(&v13, &priv.fp)
-	m3.modPhiN()
-	m.fromMod3(&m3)
-
-	var mLift, delta poly
-	mLift.lift(&m)
-	for i := range delta {
-		delta[i] = (e[i] - mLift[i] + Q) % Q
-	}
-	delta.mul(&delta, &priv.hInv)
-	delta.modPhiN()
-
-	var r poly3
-	allOk := r.fromModQ(&delta)
-
-	var mBytes, rBytes [mod3Bytes]byte
-	m.marshalS3(mBytes[:])
-	r.marshal(rBytes[:])
-
-	var rPoly poly
-	rPoly.fromMod3(&r)
-	expectedCiphertext := priv.PublicKey.owf(&m, &rPoly)
-
-	allOk &= subtle.ConstantTimeCompare(ciphertext, expectedCiphertext)
-
-	hmacHash := hmac.New(sha256.New, priv.hmacKey[:])
-	hmacHash.Write(ciphertext)
-	hmacDigest := hmacHash.Sum(nil)
-
-	h := sha256.New()
-	h.Write([]byte("shared key\x00"))
-	h.Write(mBytes[:])
-	h.Write(rBytes[:])
-	h.Write(ciphertext)
-	sharedKey = h.Sum(nil)
-
-	mask := uint8(allOk - 1)
-	for i := range sharedKey {
-		sharedKey[i] = (sharedKey[i] & ^mask) | (hmacDigest[i] & mask)
-	}
-
-	return sharedKey, true
-}
-
-func GenerateKey(rand io.Reader) PrivateKey {
-	var randBytes [352 + 352]byte
-	if _, err := io.ReadFull(rand, randBytes[:]); err != nil {
-		panic("rand failed")
-	}
-
-	var f poly
-	f.shortSamplePlus(randBytes[:352])
-	var priv PrivateKey
-	priv.f.fromDiscrete(&f)
-	priv.fp.invertMod3(&priv.f)
-
-	var g poly
-	g.shortSamplePlus(randBytes[352:])
-
-	var pgPhi1 poly
-	for i := range g {
-		pgPhi1[i] = mod3ToModQ(g[i])
-	}
-	for i := range pgPhi1 {
-		pgPhi1[i] = (pgPhi1[i] * 3) % Q
-	}
-	pgPhi1.mulXMinus1()
-
-	var fModQ poly
-	fModQ.fromMod3ToModQ(&priv.f)
-
-	var pfgPhi1 poly
-	pfgPhi1.mul(&fModQ, &pgPhi1)
-
-	var i poly
-	i.invert(&pfgPhi1)
-
-	priv.h.mul(&i, &pgPhi1)
-	priv.h.mul(&priv.h, &pgPhi1)
-
-	priv.hInv.mul(&i, &fModQ)
-	priv.hInv.mul(&priv.hInv, &fModQ)
-
-	return priv
-}
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index 47cdbb8..5739888 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -17,7 +17,6 @@
 	"io"
 	"math/big"
 
-	"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
 	"golang.org/x/crypto/curve25519"
 )
 
@@ -341,90 +340,6 @@
 	return out[:], nil
 }
 
-// cecpq2KEM implements CECPQ2, which is HRSS+SXY combined with X25519.
-type cecpq2KEM struct {
-	x25519PrivateKey [32]byte
-	hrssPrivateKey   hrss.PrivateKey
-}
-
-func (e *cecpq2KEM) generate(rand io.Reader) (publicKey []byte, err error) {
-	if _, err := io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
-		return nil, err
-	}
-
-	var x25519Public [32]byte
-	curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
-
-	e.hrssPrivateKey = hrss.GenerateKey(rand)
-	hrssPublic := e.hrssPrivateKey.PublicKey.Marshal()
-
-	var ret []byte
-	ret = append(ret, x25519Public[:]...)
-	ret = append(ret, hrssPublic...)
-	return ret, nil
-}
-
-func (e *cecpq2KEM) encap(rand io.Reader, peerKey []byte) (ciphertext []byte, secret []byte, err error) {
-	if len(peerKey) != 32+hrss.PublicKeySize {
-		return nil, nil, errors.New("tls: bad length CECPQ2 offer")
-	}
-
-	if _, err := io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
-		return nil, nil, err
-	}
-
-	var x25519Shared, x25519PeerKey, x25519Public [32]byte
-	copy(x25519PeerKey[:], peerKey)
-	curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
-	curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
-
-	// Per RFC 7748, reject the all-zero value in constant time.
-	var zeros [32]byte
-	if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
-		return nil, nil, errors.New("tls: X25519 value with wrong order")
-	}
-
-	hrssPublicKey, ok := hrss.ParsePublicKey(peerKey[32:])
-	if !ok {
-		return nil, nil, errors.New("tls: bad CECPQ2 offer")
-	}
-
-	hrssCiphertext, hrssShared := hrssPublicKey.Encap(rand)
-
-	ciphertext = append(ciphertext, x25519Public[:]...)
-	ciphertext = append(ciphertext, hrssCiphertext...)
-	secret = append(secret, x25519Shared[:]...)
-	secret = append(secret, hrssShared...)
-
-	return ciphertext, secret, nil
-}
-
-func (e *cecpq2KEM) decap(ciphertext []byte) (secret []byte, err error) {
-	if len(ciphertext) != 32+hrss.CiphertextSize {
-		return nil, errors.New("tls: bad length CECPQ2 reply")
-	}
-
-	var x25519Shared, x25519PeerKey [32]byte
-	copy(x25519PeerKey[:], ciphertext)
-	curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
-
-	// Per RFC 7748, reject the all-zero value in constant time.
-	var zeros [32]byte
-	if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
-		return nil, errors.New("tls: X25519 value with wrong order")
-	}
-
-	hrssShared, ok := e.hrssPrivateKey.Decap(ciphertext[32:])
-	if !ok {
-		return nil, errors.New("tls: invalid HRSS ciphertext")
-	}
-
-	secret = append(secret, x25519Shared[:]...)
-	secret = append(secret, hrssShared...)
-
-	return secret, nil
-}
-
 func kemForCurveID(id CurveID, config *Config) (kemImplementation, bool) {
 	switch id {
 	case CurveP224:
@@ -437,8 +352,6 @@
 		return &ecdhKEM{curve: elliptic.P521(), sendCompressed: config.Bugs.SendCompressedCoordinates}, true
 	case CurveX25519:
 		return &x25519KEM{setHighBit: config.Bugs.SetX25519HighBit}, true
-	case CurveCECPQ2:
-		return &cecpq2KEM{}, true
 	default:
 		return nil, false
 	}
@@ -587,7 +500,7 @@
 NextCandidate:
 	for _, candidate := range preferredCurves {
 		if isPqGroup(candidate) && version < VersionTLS13 {
-			// CECPQ2 is TLS 1.3-only.
+			// Post-quantum "groups" require TLS 1.3.
 			continue
 		}
 
diff --git a/src/ssl/test/runner/mock_quic_transport.go b/src/ssl/test/runner/mock_quic_transport.go
index 709f7d1..2939274 100644
--- a/src/ssl/test/runner/mock_quic_transport.go
+++ b/src/ssl/test/runner/mock_quic_transport.go
@@ -54,16 +54,16 @@
 // Messages from TLS that are sent over a mockQUICTransport are a series of
 // records in the following format:
 //
-//   enum {
-//       initial(0), early_data(1), handshake(2), application(3), (255)
-//   } EncryptionLevel;
+//	enum {
+//	    initial(0), early_data(1), handshake(2), application(3), (255)
+//	} EncryptionLevel;
 //
-//   struct {
-//       ContentType record_type;
-//       EncryptionLevel level;
-//       CipherSuite cipher_suite;
-//       opaque encrypted_record<0..2^32-1>;
-//   } MockQUICRecord;
+//	struct {
+//	    ContentType record_type;
+//	    EncryptionLevel level;
+//	    CipherSuite cipher_suite;
+//	    opaque encrypted_record<0..2^32-1>;
+//	} MockQUICRecord;
 //
 // The "encrypted" record is the concatenation of the encryption key and
 // plaintext. It and the cipher suite exist only to check both sides agree on
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index d33fbc5..b361e19 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -65,6 +65,7 @@
 	allowHintMismatch  = flag.String("allow-hint-mismatch", "", "Semicolon-separated patterns of tests where hints may mismatch")
 	numWorkersFlag     = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
 	shimPath           = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
+	shimExtraFlags     = flag.String("shim-extra-flags", "", "Semicolon-separated extra flags to pass to the shim binary on each invocation.")
 	handshakerPath     = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
 	resourceDir        = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
 	fuzzer             = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
@@ -1433,6 +1434,9 @@
 	}()
 
 	var flags []string
+	if len(*shimExtraFlags) > 0 {
+		flags = strings.Split(*shimExtraFlags, ";")
+	}
 	if test.testType == serverTest {
 		flags = append(flags, "-server")
 
@@ -1850,7 +1854,6 @@
 	{"CHACHA20_POLY1305_SHA256", TLS_CHACHA20_POLY1305_SHA256},
 	{"AES_128_GCM_SHA256", TLS_AES_128_GCM_SHA256},
 	{"AES_256_GCM_SHA384", TLS_AES_256_GCM_SHA384},
-	{"RSA_WITH_NULL_SHA", TLS_RSA_WITH_NULL_SHA},
 }
 
 func hasComponent(suiteName, component string) bool {
@@ -1878,7 +1881,12 @@
 
 func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
 	var stdout bytes.Buffer
-	shim := exec.Command(*shimPath, "-is-handshaker-supported")
+	var flags []string
+	if len(*shimExtraFlags) > 0 {
+		flags = strings.Split(*shimExtraFlags, ";")
+	}
+	flags = append(flags, "-is-handshaker-supported")
+	shim := exec.Command(*shimPath, flags...)
 	shim.Stdout = &stdout
 	if err := shim.Run(); err != nil {
 		return nil, err
@@ -3673,10 +3681,6 @@
 			"-psk", psk,
 			"-psk-identity", pskIdentity)
 	}
-	if hasComponent(suite.name, "NULL") {
-		// NULL ciphers must be explicitly enabled.
-		flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
-	}
 
 	var shouldFail bool
 	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
@@ -9720,26 +9724,29 @@
 	name string
 	id   signatureAlgorithm
 	cert testCert
+	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
+	// accepted.
+	curve CurveID
 }{
-	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA},
-	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA},
-	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
-	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
-	{"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
+	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA, 0},
+	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA, 0},
+	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA, 0},
+	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA, 0},
+	{"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256, CurveP256},
 	// The “P256” in the following line is not a mistake. In TLS 1.2 the
 	// hash function doesn't have to match the curve and so the same
 	// signature algorithm works with P-224.
-	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224},
-	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
-	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
-	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
-	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, testCertRSA},
-	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, testCertRSA},
-	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, testCertRSA},
-	{"Ed25519", signatureEd25519, testCertEd25519},
+	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224, CurveP224},
+	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256, CurveP256},
+	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384, CurveP384},
+	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521, CurveP521},
+	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, testCertRSA, 0},
+	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, testCertRSA, 0},
+	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, testCertRSA, 0},
+	{"Ed25519", signatureEd25519, testCertEd25519, 0},
 	// Tests for key types prior to TLS 1.2.
-	{"RSA", 0, testCertRSA},
-	{"ECDSA", 0, testCertECDSAP256},
+	{"RSA", 0, testCertRSA, 0},
+	{"ECDSA", 0, testCertECDSAP256, CurveP256},
 }
 
 const fakeSigAlg1 signatureAlgorithm = 0x2a01
@@ -9791,6 +9798,14 @@
 				rejectByDefault = true
 			}
 
+			var curveFlags []string
+			if alg.curve != 0 && ver.version <= VersionTLS12 {
+				// In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
+				// corresponding curve is enabled on the shim. Also include X25519 to
+				// ensure the shim and runner have something in common for ECDH.
+				curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
+			}
+
 			var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string
 			if shouldFail {
 				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
@@ -9829,7 +9844,7 @@
 							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
 							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
 						},
-						flagInts("-curves", shimConfig.AllCurves)...,
+						curveFlags...,
 					),
 					shouldFail:         shouldFail,
 					expectedError:      signError,
@@ -9853,7 +9868,7 @@
 							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
 							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
 						},
-						flagInts("-curves", shimConfig.AllCurves)...,
+						curveFlags...,
 					),
 					expectations: connectionExpectations{
 						peerSignatureAlgorithm: alg.id,
@@ -9894,7 +9909,7 @@
 							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
 						},
 					},
-					flags: flagInts("-curves", shimConfig.AllCurves),
+					flags: curveFlags,
 					// Resume the session to assert the peer signature
 					// algorithm is reported on both handshakes.
 					resumeSession:      !shouldFail,
@@ -9927,7 +9942,7 @@
 					},
 					flags: append(
 						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
-						flagInts("-curves", shimConfig.AllCurves)...,
+						curveFlags...,
 					),
 					// Resume the session to assert the peer signature
 					// algorithm is reported on both handshakes.
@@ -9951,7 +9966,7 @@
 							InvalidSignature: true,
 						},
 					},
-					flags:         flagInts("-curves", shimConfig.AllCurves),
+					flags:         curveFlags,
 					shouldFail:    true,
 					expectedError: ":BAD_SIGNATURE:",
 				}
@@ -11371,13 +11386,12 @@
 	{"P-384", CurveP384},
 	{"P-521", CurveP521},
 	{"X25519", CurveX25519},
-	{"CECPQ2", CurveCECPQ2},
 }
 
 const bogusCurve = 0x1234
 
 func isPqGroup(r CurveID) bool {
-	return r == CurveCECPQ2
+	return r == CurveX25519Kyber768
 }
 
 func addCurveTests() {
@@ -11841,124 +11855,127 @@
 		},
 	})
 
-	// CECPQ2 should not be offered by a TLS < 1.3 client.
+	// Kyber should not be offered by a TLS < 1.3 client.
 	testCases = append(testCases, testCase{
-		name: "CECPQ2NotInTLS12",
+		name: "KyberNotInTLS12",
 		config: Config{
 			Bugs: ProtocolBugs{
-				FailIfCECPQ2Offered: true,
+				FailIfKyberOffered: true,
 			},
 		},
 		flags: []string{
 			"-max-version", strconv.Itoa(VersionTLS12),
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
 			"-curves", strconv.Itoa(int(CurveX25519)),
 		},
 	})
 
-	// CECPQ2 should not crash a TLS < 1.3 client if the server mistakenly
+	// Kyber should not crash a TLS < 1.3 client if the server mistakenly
 	// selects it.
 	testCases = append(testCases, testCase{
-		name: "CECPQ2NotAcceptedByTLS12Client",
+		name: "KyberNotAcceptedByTLS12Client",
 		config: Config{
 			Bugs: ProtocolBugs{
-				SendCurve: CurveCECPQ2,
+				SendCurve: CurveX25519Kyber768,
 			},
 		},
 		flags: []string{
 			"-max-version", strconv.Itoa(VersionTLS12),
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
 			"-curves", strconv.Itoa(int(CurveX25519)),
 		},
 		shouldFail:    true,
 		expectedError: ":WRONG_CURVE:",
 	})
 
-	// CECPQ2 should not be offered by default as a client.
+	// Kyber should not be offered by default as a client.
 	testCases = append(testCases, testCase{
-		name: "CECPQ2NotEnabledByDefaultInClients",
+		name: "KyberNotEnabledByDefaultInClients",
 		config: Config{
 			MinVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
-				FailIfCECPQ2Offered: true,
+				FailIfKyberOffered: true,
 			},
 		},
 	})
 
-	// If CECPQ2 is offered, both X25519 and CECPQ2 should have a key-share.
+	// If Kyber is offered, both X25519 and Kyber should have a key-share.
 	testCases = append(testCases, testCase{
-		name: "NotJustCECPQ2KeyShare",
+		name: "NotJustKyberKeyShare",
 		config: Config{
 			MinVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveCECPQ2, CurveX25519},
+				ExpectedKeyShares: []CurveID{CurveX25519Kyber768, CurveX25519},
 			},
 		},
 		flags: []string{
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
 			"-curves", strconv.Itoa(int(CurveX25519)),
-			"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
+			// Cannot expect Kyber until we have a Go implementation of it.
+			// "-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
 		},
 	})
 
 	// ... and the other way around
 	testCases = append(testCases, testCase{
-		name: "CECPQ2KeyShareIncludedSecond",
+		name: "KyberKeyShareIncludedSecond",
 		config: Config{
 			MinVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519, CurveCECPQ2},
+				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
 			},
 		},
 		flags: []string{
 			"-curves", strconv.Itoa(int(CurveX25519)),
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
 			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
 		},
 	})
 
-        // ... and even if there's another curve in the middle because it's the
-        // first classical and first post-quantum "curves" that get key shares
-        // included.
+	// ... and even if there's another curve in the middle because it's the
+	// first classical and first post-quantum "curves" that get key shares
+	// included.
 	testCases = append(testCases, testCase{
-		name: "CECPQ2KeyShareIncludedThird",
+		name: "KyberKeyShareIncludedThird",
 		config: Config{
 			MinVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519, CurveCECPQ2},
+				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
 			},
 		},
 		flags: []string{
 			"-curves", strconv.Itoa(int(CurveX25519)),
 			"-curves", strconv.Itoa(int(CurveP256)),
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
 			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
 		},
 	})
 
-	// If CECPQ2 is the only configured curve, the key share is sent.
+	// If Kyber is the only configured curve, the key share is sent.
 	testCases = append(testCases, testCase{
-		name: "JustConfiguringCECPQ2Works",
+		name: "JustConfiguringKyberWorks",
 		config: Config{
 			MinVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveCECPQ2},
+				ExpectedKeyShares: []CurveID{CurveX25519Kyber768},
 			},
 		},
 		flags: []string{
-			"-curves", strconv.Itoa(int(CurveCECPQ2)),
-			"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
 		},
+		shouldFail:         true,
+		expectedLocalError: "no curve supported by both client and server",
 	})
 
-	// As a server, CECPQ2 is not yet supported by default.
+	// As a server, Kyber is not yet supported by default.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "CECPQ2NotEnabledByDefaultForAServer",
+		name:     "KyberNotEnabledByDefaultForAServer",
 		config: Config{
 			MinVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveCECPQ2, CurveX25519},
-			DefaultCurves:    []CurveID{CurveCECPQ2},
+			CurvePreferences: []CurveID{CurveX25519Kyber768, CurveX25519},
+			DefaultCurves:    []CurveID{CurveX25519Kyber768},
 		},
 		flags: []string{
 			"-server-preference",
@@ -15603,9 +15620,6 @@
 			},
 			shouldFail:    true,
 			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-			flags: []string{
-				"-enforce-rsa-key-usage",
-			},
 		})
 
 		testCases = append(testCases, testCase{
@@ -15617,9 +15631,6 @@
 				Certificates: []Certificate{dsCert},
 				CipherSuites: dsSuites,
 			},
-			flags: []string{
-				"-enforce-rsa-key-usage",
-			},
 		})
 
 		// TLS 1.3 removes the encipherment suites.
@@ -15633,9 +15644,6 @@
 					Certificates: []Certificate{encCert},
 					CipherSuites: encSuites,
 				},
-				flags: []string{
-					"-enforce-rsa-key-usage",
-				},
 			})
 
 			testCases = append(testCases, testCase{
@@ -15649,9 +15657,6 @@
 				},
 				shouldFail:    true,
 				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-				flags: []string{
-					"-enforce-rsa-key-usage",
-				},
 			})
 
 			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
@@ -15664,7 +15669,7 @@
 					Certificates: []Certificate{dsCert},
 					CipherSuites: encSuites,
 				},
-				flags: []string{"-expect-key-usage-invalid"},
+				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
 			})
 
 			testCases = append(testCases, testCase{
@@ -15676,21 +15681,22 @@
 					Certificates: []Certificate{encCert},
 					CipherSuites: dsSuites,
 				},
-				flags: []string{"-expect-key-usage-invalid"},
+				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
 			})
 		}
 
 		if ver.version >= VersionTLS13 {
-			// In 1.3 and above, we enforce keyUsage even without the flag.
+			// In 1.3 and above, we enforce keyUsage even when disabled.
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Enforced-" + ver.name,
+				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
 					Certificates: []Certificate{encCert},
 					CipherSuites: dsSuites,
 				},
+				flags:         []string{"-ignore-rsa-key-usage"},
 				shouldFail:    true,
 				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
 			})
@@ -19188,13 +19194,21 @@
 				isFIPSCipherSuite = true
 			}
 
+			var isWPACipherSuite bool
+			switch suite.id {
+			case TLS_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+				isWPACipherSuite = true
+			}
+
 			var certFile string
 			var keyFile string
 			var certs []Certificate
 			if hasComponent(suite.name, "ECDSA") {
-				certFile = ecdsaP256CertificateFile
-				keyFile = ecdsaP256KeyFile
-				certs = []Certificate{ecdsaP256Certificate}
+				certFile = ecdsaP384CertificateFile
+				keyFile = ecdsaP384KeyFile
+				certs = []Certificate{ecdsaP384Certificate}
 			} else {
 				certFile = rsaCertificateFile
 				keyFile = rsaKeyFile
@@ -19209,38 +19223,48 @@
 				maxVersion = VersionTLS12
 			}
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Server-" + suite.name,
-				config: Config{
-					MinVersion:   VersionTLS12,
-					MaxVersion:   maxVersion,
-					CipherSuites: []uint16{suite.id},
-				},
-				certFile: certFile,
-				keyFile:  keyFile,
-				flags: []string{
-					"-fips-202205",
-				},
-				shouldFail: !isFIPSCipherSuite,
-			})
+			policies := []struct {
+				flag          string
+				cipherSuiteOk bool
+			}{
+				{"-fips-202205", isFIPSCipherSuite},
+				{"-wpa-202304", isWPACipherSuite},
+			}
 
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Client-" + suite.name,
-				config: Config{
-					MinVersion:   VersionTLS12,
-					MaxVersion:   maxVersion,
-					CipherSuites: []uint16{suite.id},
-					Certificates: certs,
-				},
-				flags: []string{
-					"-fips-202205",
-				},
-				shouldFail: !isFIPSCipherSuite,
-			})
+			for _, policy := range policies {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + suite.name,
+					config: Config{
+						MinVersion:   VersionTLS12,
+						MaxVersion:   maxVersion,
+						CipherSuites: []uint16{suite.id},
+					},
+					certFile: certFile,
+					keyFile:  keyFile,
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.cipherSuiteOk,
+				})
+
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + suite.name,
+					config: Config{
+						MinVersion:   VersionTLS12,
+						MaxVersion:   maxVersion,
+						CipherSuites: []uint16{suite.id},
+						Certificates: certs,
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.cipherSuiteOk,
+				})
+			}
 		}
 
 		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
@@ -19270,35 +19294,51 @@
 				isFIPSCurve = true
 			}
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Server-" + curve.name,
-				config: Config{
-					MinVersion:       VersionTLS12,
-					MaxVersion:       VersionTLS13,
-					CurvePreferences: []CurveID{curve.id},
-				},
-				flags: []string{
-					"-fips-202205",
-				},
-				shouldFail: !isFIPSCurve,
-			})
+			var isWPACurve bool
+			switch curve.id {
+			case CurveP384:
+				isWPACurve = true
+			}
 
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Client-" + curve.name,
-				config: Config{
-					MinVersion:       VersionTLS12,
-					MaxVersion:       VersionTLS13,
-					CurvePreferences: []CurveID{curve.id},
-				},
-				flags: []string{
-					"-fips-202205",
-				},
-				shouldFail: !isFIPSCurve,
-			})
+			policies := []struct {
+				flag    string
+				curveOk bool
+			}{
+				{"-fips-202205", isFIPSCurve},
+				{"-wpa-202304", isWPACurve},
+			}
+
+			for _, policy := range policies {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + curve.name,
+					config: Config{
+						MinVersion:       VersionTLS12,
+						MaxVersion:       VersionTLS13,
+						CurvePreferences: []CurveID{curve.id},
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.curveOk,
+				})
+
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + curve.name,
+					config: Config{
+						MinVersion:       VersionTLS12,
+						MaxVersion:       VersionTLS13,
+						CurvePreferences: []CurveID{curve.id},
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.curveOk,
+				})
+			}
 		}
 
 		for _, sigalg := range testSignatureAlgorithms {
@@ -19315,6 +19355,16 @@
 				isFIPSSigAlg = true
 			}
 
+			var isWPASigAlg bool
+			switch sigalg.id {
+			case signatureRSAPKCS1WithSHA384,
+				signatureRSAPKCS1WithSHA512,
+				signatureECDSAWithP384AndSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureRSAPSSWithSHA512:
+				isWPASigAlg = true
+			}
+
 			if sigalg.cert == testCertECDSAP224 {
 				// This can work in TLS 1.2, but not with TLS 1.3.
 				// For consistency it's not permitted in FIPS mode.
@@ -19329,38 +19379,48 @@
 				maxVersion = VersionTLS12
 			}
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Server-" + sigalg.name,
-				config: Config{
-					MinVersion:                VersionTLS12,
-					MaxVersion:                maxVersion,
-					VerifySignatureAlgorithms: []signatureAlgorithm{sigalg.id},
-				},
-				flags: []string{
-					"-fips-202205",
-					"-cert-file", path.Join(*resourceDir, getShimCertificate(sigalg.cert)),
-					"-key-file", path.Join(*resourceDir, getShimKey(sigalg.cert)),
-				},
-				shouldFail: !isFIPSSigAlg,
-			})
+			policies := []struct {
+				flag     string
+				sigAlgOk bool
+			}{
+				{"-fips-202205", isFIPSSigAlg},
+				{"-wpa-202304", isWPASigAlg},
+			}
 
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     "Compliance-fips202205-" + protocol.String() + "-Client-" + sigalg.name,
-				config: Config{
-					MinVersion:              VersionTLS12,
-					MaxVersion:              maxVersion,
-					SignSignatureAlgorithms: []signatureAlgorithm{sigalg.id},
-					Certificates:            []Certificate{getRunnerCertificate(sigalg.cert)},
-				},
-				flags: []string{
-					"-fips-202205",
-				},
-				shouldFail: !isFIPSSigAlg,
-			})
+			for _, policy := range policies {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + sigalg.name,
+					config: Config{
+						MinVersion:                VersionTLS12,
+						MaxVersion:                maxVersion,
+						VerifySignatureAlgorithms: []signatureAlgorithm{sigalg.id},
+					},
+					flags: []string{
+						policy.flag,
+						"-cert-file", path.Join(*resourceDir, getShimCertificate(sigalg.cert)),
+						"-key-file", path.Join(*resourceDir, getShimKey(sigalg.cert)),
+					},
+					shouldFail: !policy.sigAlgOk,
+				})
+
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + sigalg.name,
+					config: Config{
+						MinVersion:              VersionTLS12,
+						MaxVersion:              maxVersion,
+						SignSignatureAlgorithms: []signatureAlgorithm{sigalg.id},
+						Certificates:            []Certificate{getRunnerCertificate(sigalg.cert)},
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.sigAlgOk,
+				})
+			}
 		}
 	}
 }
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 94828c6..0ee5580 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -17,6 +17,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -365,7 +366,7 @@
       IntFlag("-install-one-cert-compression-alg",
               &TestConfig::install_one_cert_compression_alg),
       BoolFlag("-reverify-on-resume", &TestConfig::reverify_on_resume),
-      BoolFlag("-enforce-rsa-key-usage", &TestConfig::enforce_rsa_key_usage),
+      BoolFlag("-ignore-rsa-key-usage", &TestConfig::ignore_rsa_key_usage),
       BoolFlag("-expect-key-usage-invalid",
                &TestConfig::expect_key_usage_invalid),
       BoolFlag("-is-handshaker-supported",
@@ -389,6 +390,7 @@
       IntFlag("-early-write-after-message",
               &TestConfig::early_write_after_message),
       BoolFlag("-fips-202205", &TestConfig::fips_202205),
+      BoolFlag("-wpa-202304", &TestConfig::wpa_202304),
   };
   std::sort(flags.begin(), flags.end(), [](const Flag &a, const Flag &b) {
     return strcmp(a.name, b.name) < 0;
@@ -572,8 +574,13 @@
     return SSL_TLSEXT_ERR_NOACK;
   }
 
-  *out = (const uint8_t *)config->advertise_npn.data();
-  *out_len = config->advertise_npn.size();
+  if (config->advertise_npn.size() > UINT_MAX) {
+    fprintf(stderr, "NPN value too large.\n");
+    return SSL_TLSEXT_ERR_ALERT_FATAL;
+  }
+
+  *out = reinterpret_cast<const uint8_t *>(config->advertise_npn.data());
+  *out_len = static_cast<unsigned>(config->advertise_npn.size());
   return SSL_TLSEXT_ERR_OK;
 }
 
@@ -1735,8 +1742,8 @@
   if (reverify_on_resume) {
     SSL_CTX_set_reverify_on_resume(ssl_ctx, 1);
   }
-  if (enforce_rsa_key_usage) {
-    SSL_set_enforce_rsa_key_usage(ssl.get(), 1);
+  if (ignore_rsa_key_usage) {
+    SSL_set_enforce_rsa_key_usage(ssl.get(), 0);
   }
   if (no_tls13) {
     SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3);
@@ -1759,11 +1766,20 @@
   if (enable_ech_grease) {
     SSL_set_enable_ech_grease(ssl.get(), 1);
   }
+  if (static_cast<int>(fips_202205) + static_cast<int>(wpa_202304) > 1) {
+    fprintf(stderr, "Multiple policy options given\n");
+    return nullptr;
+  }
   if (fips_202205 && !SSL_set_compliance_policy(
                          ssl.get(), ssl_compliance_policy_fips_202205)) {
     fprintf(stderr, "SSL_set_compliance_policy failed\n");
     return nullptr;
   }
+  if (wpa_202304 && !SSL_set_compliance_policy(
+                         ssl.get(), ssl_compliance_policy_wpa3_192_202304)) {
+    fprintf(stderr, "SSL_set_compliance_policy failed\n");
+    return nullptr;
+  }
   if (!ech_config_list.empty() &&
       !SSL_set1_ech_config_list(
           ssl.get(), reinterpret_cast<const uint8_t *>(ech_config_list.data()),
@@ -1903,8 +1919,8 @@
           nids.push_back(NID_X25519);
           break;
 
-        case SSL_CURVE_CECPQ2:
-          nids.push_back(NID_CECPQ2);
+        case SSL_CURVE_X25519KYBER768:
+          nids.push_back(NID_X25519Kyber768);
           break;
       }
       if (!SSL_set1_curves(ssl.get(), &nids[0], nids.size())) {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 5608dab..e8c473a 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -177,7 +177,7 @@
   bool install_cert_compression_algs = false;
   int install_one_cert_compression_alg = 0;
   bool reverify_on_resume = false;
-  bool enforce_rsa_key_usage = false;
+  bool ignore_rsa_key_usage = false;
   bool expect_key_usage_invalid = false;
   bool is_handshaker_supported = false;
   bool handshaker_resume = false;
@@ -195,6 +195,7 @@
   std::string quic_early_data_context;
   int early_write_after_message = 0;
   bool fips_202205 = false;
+  bool wpa_202304 = false;
 
   int argc;
   char **argv;
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index f67c592..5ab5a1c 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -513,7 +513,8 @@
   if (!ssl->method->init_message(ssl, cbb.get(), body,
                                  SSL3_MT_COMPRESSED_CERTIFICATE) ||
       !CBB_add_u16(body, hs->cert_compression_alg_id) ||
-      !CBB_add_u24(body, msg.size()) ||
+      msg.size() > (1u << 24) - 1 ||  //
+      !CBB_add_u24(body, static_cast<uint32_t>(msg.size())) ||
       !CBB_add_u24_length_prefixed(body, &compressed)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 92e26f2..1971596 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -200,7 +200,7 @@
       SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl) ||
       !ssl_tls13_cipher_meets_policy(
           SSL_CIPHER_get_value(cipher),
-          ssl->config->only_fips_cipher_suites_in_tls13)) {
+          ssl->config->tls13_cipher_policy)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
     return ssl_hs_error;
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index ad023ef..3de10f4 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -27,6 +27,7 @@
 #include <openssl/hmac.h>
 #include <openssl/mem.h>
 
+#include "../crypto/fipsmodule/tls/internal.h"
 #include "../crypto/internal.h"
 #include "internal.h"
 
@@ -95,27 +96,10 @@
                               Span<const uint8_t> secret,
                               Span<const char> label,
                               Span<const uint8_t> hash) {
-  Span<const char> protocol_label = label_to_span("tls13 ");
-  ScopedCBB cbb;
-  CBB child;
-  Array<uint8_t> hkdf_label;
-  if (!CBB_init(cbb.get(), 2 + 1 + protocol_label.size() + label.size() + 1 +
-                               hash.size()) ||
-      !CBB_add_u16(cbb.get(), out.size()) ||
-      !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
-      !CBB_add_bytes(&child,
-                     reinterpret_cast<const uint8_t *>(protocol_label.data()),
-                     protocol_label.size()) ||
-      !CBB_add_bytes(&child, reinterpret_cast<const uint8_t *>(label.data()),
-                     label.size()) ||
-      !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
-      !CBB_add_bytes(&child, hash.data(), hash.size()) ||
-      !CBBFinishArray(cbb.get(), &hkdf_label)) {
-    return false;
-  }
-
-  return HKDF_expand(out.data(), out.size(), digest, secret.data(),
-                     secret.size(), hkdf_label.data(), hkdf_label.size());
+  return CRYPTO_tls13_hkdf_expand_label(
+      out.data(), out.size(), digest, secret.data(), secret.size(),
+      reinterpret_cast<const uint8_t *>(label.data()), label.size(),
+      hash.data(), hash.size()) == 1;
 }
 
 static const char kTLS13LabelDerived[] = "derived";
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 0bbe97f..9d26f4e 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -116,8 +116,11 @@
 
   const uint16_t version = ssl_protocol_version(ssl);
 
-  return ssl_choose_tls13_cipher(cipher_suites, version, group_id,
-                                 ssl->config->only_fips_cipher_suites_in_tls13);
+  return ssl_choose_tls13_cipher(
+      cipher_suites,
+      ssl->config->aes_hw_override ? ssl->config->aes_hw_override_value
+                                   : EVP_has_aes_hardware(),
+      version, group_id, ssl->config->tls13_cipher_policy);
 }
 
 static bool add_new_session_tickets(SSL_HANDSHAKE *hs, bool *out_sent_tickets) {
diff --git a/src/third_party/fiat/curve25519_64_msvc.h b/src/third_party/fiat/curve25519_64_msvc.h
new file mode 100644
index 0000000..d20ec85
--- /dev/null
+++ b/src/third_party/fiat/curve25519_64_msvc.h
@@ -0,0 +1,1281 @@
+/* Autogenerated: 'src/ExtractionOCaml/unsaturated_solinas' --inline --static --use-value-barrier --no-wide-int 25519 64 '(auto)' '2^255 - 19' carry_mul carry_square carry add sub opp selectznz to_bytes from_bytes relax carry_scmul121666 */
+/* curve description: 25519 */
+/* machine_wordsize = 64 (from "64") */
+/* requested operations: carry_mul, carry_square, carry, add, sub, opp, selectznz, to_bytes, from_bytes, relax, carry_scmul121666 */
+/* n = 5 (from "(auto)") */
+/* s-c = 2^255 - [(1, 19)] (from "2^255 - 19") */
+/* tight_bounds_multiplier = 1 (from "") */
+/*  */
+/* Computed values: */
+/*   carry_chain = [0, 1, 2, 3, 4, 0, 1] */
+/*   eval z = z[0] + (z[1] << 51) + (z[2] << 102) + (z[3] << 153) + (z[4] << 204) */
+/*   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) */
+/*   balance = [0xfffffffffffda, 0xffffffffffffe, 0xffffffffffffe, 0xffffffffffffe, 0xffffffffffffe] */
+
+#include <stdint.h>
+#include <intrin.h>
+#if defined(_M_X64)
+#include <immintrin.h>
+#endif
+
+typedef unsigned char fiat_25519_uint1;
+typedef signed char fiat_25519_int1;
+
+#define FIAT_25519_FIAT_INLINE inline
+
+/* The type fiat_25519_loose_field_element is a field element with loose bounds. */
+/* Bounds: [[0x0 ~> 0x18000000000000], [0x0 ~> 0x18000000000000], [0x0 ~> 0x18000000000000], [0x0 ~> 0x18000000000000], [0x0 ~> 0x18000000000000]] */
+typedef uint64_t fiat_25519_loose_field_element[5];
+
+/* The type fiat_25519_tight_field_element is a field element with tight bounds. */
+/* Bounds: [[0x0 ~> 0x8000000000000], [0x0 ~> 0x8000000000000], [0x0 ~> 0x8000000000000], [0x0 ~> 0x8000000000000], [0x0 ~> 0x8000000000000]] */
+typedef uint64_t fiat_25519_tight_field_element[5];
+
+#if (-1 & 3) != 3
+#error "This code only works on a two's complement system"
+#endif
+
+#define fiat_25519_value_barrier_u64(x) (x)
+
+/*
+ * The function fiat_25519_addcarryx_u64 is an addition with carry.
+ *
+ * Postconditions:
+ *   out1 = (arg1 + arg2 + arg3) mod 2^64
+ *   out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_addcarryx_u64(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+// NOTE: edited after generation
+#if defined(_M_X64)
+  *out2 = _addcarry_u64(arg1, arg2, arg3, out1);
+#else
+  arg2 += arg1;
+  arg1 = arg2 < arg1;
+  arg3 += arg2;
+  arg1 += arg3 < arg2;
+  *out1 = arg3;
+  *out2 = arg1;
+#endif
+}
+
+/*
+ * The function fiat_25519_subborrowx_u64 is a subtraction with borrow.
+ *
+ * Postconditions:
+ *   out1 = (-arg1 + arg2 + -arg3) mod 2^64
+ *   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_subborrowx_u64(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+#if defined(_M_X64)
+  *out2 = _subborrow_u64(arg1, arg2, arg3, out1); // NOTE: edited after generation
+#else
+  *out1 = arg2 - arg3 - arg1;
+  *out2 = (arg2 < arg3) | ((arg2 == arg3) & arg1);
+#endif
+}
+
+/*
+ * The function fiat_25519_addcarryx_u51 is an addition with carry.
+ *
+ * Postconditions:
+ *   out1 = (arg1 + arg2 + arg3) mod 2^51
+ *   out2 = ⌊(arg1 + arg2 + arg3) / 2^51⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0x7ffffffffffff]
+ *   arg3: [0x0 ~> 0x7ffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0x7ffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_addcarryx_u51(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+  uint64_t x1;
+  uint64_t x2;
+  fiat_25519_uint1 x3;
+  x1 = ((arg1 + arg2) + arg3);
+  x2 = (x1 & UINT64_C(0x7ffffffffffff));
+  x3 = (fiat_25519_uint1)(x1 >> 51);
+  *out1 = x2;
+  *out2 = x3;
+}
+
+/*
+ * The function fiat_25519_subborrowx_u51 is a subtraction with borrow.
+ *
+ * Postconditions:
+ *   out1 = (-arg1 + arg2 + -arg3) mod 2^51
+ *   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^51⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0x7ffffffffffff]
+ *   arg3: [0x0 ~> 0x7ffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0x7ffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_subborrowx_u51(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+  int64_t x1;
+  fiat_25519_int1 x2;
+  uint64_t x3;
+  x1 = ((int64_t)(arg2 - (int64_t)arg1) - (int64_t)arg3);
+  x2 = (fiat_25519_int1)(x1 >> 51);
+  x3 = (x1 & UINT64_C(0x7ffffffffffff));
+  *out1 = x3;
+  *out2 = (fiat_25519_uint1)(0x0 - x2);
+}
+
+/*
+ * The function fiat_25519_mulx_u64 is a multiplication, returning the full double-width result.
+ *
+ * Postconditions:
+ *   out1 = (arg1 * arg2) mod 2^64
+ *   out2 = ⌊arg1 * arg2 / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0xffffffffffffffff]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0xffffffffffffffff]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_mulx_u64(uint64_t* out1, uint64_t* out2, uint64_t arg1, uint64_t arg2) {
+// NOTE: edited after generation
+#if defined(_M_X64)
+  *out1 = _umul128(arg1, arg2, out2);
+#elif defined(_M_ARM64)
+  *out1 = arg1 * arg2;
+  *out2 = __umulh(arg1, arg2);
+#else
+#error "This file is intended for MSVC on X64 or ARM64"
+#endif
+}
+
+/*
+ * The function fiat_25519_cmovznz_u64 is a single-word conditional move.
+ *
+ * Postconditions:
+ *   out1 = (if arg1 = 0 then arg2 else arg3)
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_cmovznz_u64(uint64_t* out1, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+  fiat_25519_uint1 x1;
+  uint64_t x2;
+  uint64_t x3;
+  x1 = (!(!arg1));
+  x2 = ((fiat_25519_int1)(0x0 - x1) & UINT64_C(0xffffffffffffffff));
+  x3 = ((fiat_25519_value_barrier_u64(x2) & arg3) | (fiat_25519_value_barrier_u64((~x2)) & arg2));
+  *out1 = x3;
+}
+
+/*
+ * The function fiat_25519_carry_mul multiplies two field elements and reduces the result.
+ *
+ * Postconditions:
+ *   eval out1 mod m = (eval arg1 * eval arg2) mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_carry_mul(fiat_25519_tight_field_element out1, const fiat_25519_loose_field_element arg1, const fiat_25519_loose_field_element arg2) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  uint64_t x14;
+  uint64_t x15;
+  uint64_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  uint64_t x29;
+  uint64_t x30;
+  uint64_t x31;
+  uint64_t x32;
+  uint64_t x33;
+  uint64_t x34;
+  uint64_t x35;
+  uint64_t x36;
+  uint64_t x37;
+  uint64_t x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  uint64_t x46;
+  uint64_t x47;
+  uint64_t x48;
+  uint64_t x49;
+  uint64_t x50;
+  uint64_t x51;
+  fiat_25519_uint1 x52;
+  uint64_t x53;
+  fiat_25519_uint1 x54;
+  uint64_t x55;
+  fiat_25519_uint1 x56;
+  uint64_t x57;
+  fiat_25519_uint1 x58;
+  uint64_t x59;
+  fiat_25519_uint1 x60;
+  uint64_t x61;
+  fiat_25519_uint1 x62;
+  uint64_t x63;
+  fiat_25519_uint1 x64;
+  uint64_t x65;
+  fiat_25519_uint1 x66;
+  uint64_t x67;
+  uint64_t x68;
+  uint64_t x69;
+  fiat_25519_uint1 x70;
+  uint64_t x71;
+  fiat_25519_uint1 x72;
+  uint64_t x73;
+  fiat_25519_uint1 x74;
+  uint64_t x75;
+  fiat_25519_uint1 x76;
+  uint64_t x77;
+  fiat_25519_uint1 x78;
+  uint64_t x79;
+  fiat_25519_uint1 x80;
+  uint64_t x81;
+  fiat_25519_uint1 x82;
+  uint64_t x83;
+  fiat_25519_uint1 x84;
+  uint64_t x85;
+  fiat_25519_uint1 x86;
+  uint64_t x87;
+  fiat_25519_uint1 x88;
+  uint64_t x89;
+  fiat_25519_uint1 x90;
+  uint64_t x91;
+  fiat_25519_uint1 x92;
+  uint64_t x93;
+  fiat_25519_uint1 x94;
+  uint64_t x95;
+  fiat_25519_uint1 x96;
+  uint64_t x97;
+  fiat_25519_uint1 x98;
+  uint64_t x99;
+  fiat_25519_uint1 x100;
+  uint64_t x101;
+  fiat_25519_uint1 x102;
+  uint64_t x103;
+  fiat_25519_uint1 x104;
+  uint64_t x105;
+  fiat_25519_uint1 x106;
+  uint64_t x107;
+  fiat_25519_uint1 x108;
+  uint64_t x109;
+  fiat_25519_uint1 x110;
+  uint64_t x111;
+  fiat_25519_uint1 x112;
+  uint64_t x113;
+  fiat_25519_uint1 x114;
+  uint64_t x115;
+  fiat_25519_uint1 x116;
+  uint64_t x117;
+  fiat_25519_uint1 x118;
+  uint64_t x119;
+  fiat_25519_uint1 x120;
+  uint64_t x121;
+  fiat_25519_uint1 x122;
+  uint64_t x123;
+  fiat_25519_uint1 x124;
+  uint64_t x125;
+  fiat_25519_uint1 x126;
+  uint64_t x127;
+  fiat_25519_uint1 x128;
+  uint64_t x129;
+  fiat_25519_uint1 x130;
+  uint64_t x131;
+  fiat_25519_uint1 x132;
+  uint64_t x133;
+  fiat_25519_uint1 x134;
+  uint64_t x135;
+  uint64_t x136;
+  uint64_t x137;
+  uint64_t x138;
+  fiat_25519_uint1 x139;
+  uint64_t x140;
+  uint64_t x141;
+  uint64_t x142;
+  uint64_t x143;
+  fiat_25519_uint1 x144;
+  uint64_t x145;
+  uint64_t x146;
+  uint64_t x147;
+  uint64_t x148;
+  fiat_25519_uint1 x149;
+  uint64_t x150;
+  uint64_t x151;
+  uint64_t x152;
+  uint64_t x153;
+  uint64_t x154;
+  uint64_t x155;
+  uint64_t x156;
+  uint64_t x157;
+  fiat_25519_uint1 x158;
+  uint64_t x159;
+  uint64_t x160;
+  fiat_25519_mulx_u64(&x1, &x2, (arg1[4]), ((arg2[4]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x3, &x4, (arg1[4]), ((arg2[3]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x5, &x6, (arg1[4]), ((arg2[2]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x7, &x8, (arg1[4]), ((arg2[1]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x9, &x10, (arg1[3]), ((arg2[4]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x11, &x12, (arg1[3]), ((arg2[3]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x13, &x14, (arg1[3]), ((arg2[2]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x15, &x16, (arg1[2]), ((arg2[4]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x17, &x18, (arg1[2]), ((arg2[3]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x19, &x20, (arg1[1]), ((arg2[4]) * UINT8_C(0x13)));
+  fiat_25519_mulx_u64(&x21, &x22, (arg1[4]), (arg2[0]));
+  fiat_25519_mulx_u64(&x23, &x24, (arg1[3]), (arg2[1]));
+  fiat_25519_mulx_u64(&x25, &x26, (arg1[3]), (arg2[0]));
+  fiat_25519_mulx_u64(&x27, &x28, (arg1[2]), (arg2[2]));
+  fiat_25519_mulx_u64(&x29, &x30, (arg1[2]), (arg2[1]));
+  fiat_25519_mulx_u64(&x31, &x32, (arg1[2]), (arg2[0]));
+  fiat_25519_mulx_u64(&x33, &x34, (arg1[1]), (arg2[3]));
+  fiat_25519_mulx_u64(&x35, &x36, (arg1[1]), (arg2[2]));
+  fiat_25519_mulx_u64(&x37, &x38, (arg1[1]), (arg2[1]));
+  fiat_25519_mulx_u64(&x39, &x40, (arg1[1]), (arg2[0]));
+  fiat_25519_mulx_u64(&x41, &x42, (arg1[0]), (arg2[4]));
+  fiat_25519_mulx_u64(&x43, &x44, (arg1[0]), (arg2[3]));
+  fiat_25519_mulx_u64(&x45, &x46, (arg1[0]), (arg2[2]));
+  fiat_25519_mulx_u64(&x47, &x48, (arg1[0]), (arg2[1]));
+  fiat_25519_mulx_u64(&x49, &x50, (arg1[0]), (arg2[0]));
+  fiat_25519_addcarryx_u64(&x51, &x52, 0x0, x13, x7);
+  fiat_25519_addcarryx_u64(&x53, &x54, x52, x14, x8);
+  fiat_25519_addcarryx_u64(&x55, &x56, 0x0, x17, x51);
+  fiat_25519_addcarryx_u64(&x57, &x58, x56, x18, x53);
+  fiat_25519_addcarryx_u64(&x59, &x60, 0x0, x19, x55);
+  fiat_25519_addcarryx_u64(&x61, &x62, x60, x20, x57);
+  fiat_25519_addcarryx_u64(&x63, &x64, 0x0, x49, x59);
+  fiat_25519_addcarryx_u64(&x65, &x66, x64, x50, x61);
+  x67 = ((x63 >> 51) | ((x65 << 13) & UINT64_C(0xffffffffffffffff)));
+  x68 = (x63 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x69, &x70, 0x0, x23, x21);
+  fiat_25519_addcarryx_u64(&x71, &x72, x70, x24, x22);
+  fiat_25519_addcarryx_u64(&x73, &x74, 0x0, x27, x69);
+  fiat_25519_addcarryx_u64(&x75, &x76, x74, x28, x71);
+  fiat_25519_addcarryx_u64(&x77, &x78, 0x0, x33, x73);
+  fiat_25519_addcarryx_u64(&x79, &x80, x78, x34, x75);
+  fiat_25519_addcarryx_u64(&x81, &x82, 0x0, x41, x77);
+  fiat_25519_addcarryx_u64(&x83, &x84, x82, x42, x79);
+  fiat_25519_addcarryx_u64(&x85, &x86, 0x0, x25, x1);
+  fiat_25519_addcarryx_u64(&x87, &x88, x86, x26, x2);
+  fiat_25519_addcarryx_u64(&x89, &x90, 0x0, x29, x85);
+  fiat_25519_addcarryx_u64(&x91, &x92, x90, x30, x87);
+  fiat_25519_addcarryx_u64(&x93, &x94, 0x0, x35, x89);
+  fiat_25519_addcarryx_u64(&x95, &x96, x94, x36, x91);
+  fiat_25519_addcarryx_u64(&x97, &x98, 0x0, x43, x93);
+  fiat_25519_addcarryx_u64(&x99, &x100, x98, x44, x95);
+  fiat_25519_addcarryx_u64(&x101, &x102, 0x0, x9, x3);
+  fiat_25519_addcarryx_u64(&x103, &x104, x102, x10, x4);
+  fiat_25519_addcarryx_u64(&x105, &x106, 0x0, x31, x101);
+  fiat_25519_addcarryx_u64(&x107, &x108, x106, x32, x103);
+  fiat_25519_addcarryx_u64(&x109, &x110, 0x0, x37, x105);
+  fiat_25519_addcarryx_u64(&x111, &x112, x110, x38, x107);
+  fiat_25519_addcarryx_u64(&x113, &x114, 0x0, x45, x109);
+  fiat_25519_addcarryx_u64(&x115, &x116, x114, x46, x111);
+  fiat_25519_addcarryx_u64(&x117, &x118, 0x0, x11, x5);
+  fiat_25519_addcarryx_u64(&x119, &x120, x118, x12, x6);
+  fiat_25519_addcarryx_u64(&x121, &x122, 0x0, x15, x117);
+  fiat_25519_addcarryx_u64(&x123, &x124, x122, x16, x119);
+  fiat_25519_addcarryx_u64(&x125, &x126, 0x0, x39, x121);
+  fiat_25519_addcarryx_u64(&x127, &x128, x126, x40, x123);
+  fiat_25519_addcarryx_u64(&x129, &x130, 0x0, x47, x125);
+  fiat_25519_addcarryx_u64(&x131, &x132, x130, x48, x127);
+  fiat_25519_addcarryx_u64(&x133, &x134, 0x0, x67, x129);
+  x135 = (x134 + x131);
+  x136 = ((x133 >> 51) | ((x135 << 13) & UINT64_C(0xffffffffffffffff)));
+  x137 = (x133 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x138, &x139, 0x0, x136, x113);
+  x140 = (x139 + x115);
+  x141 = ((x138 >> 51) | ((x140 << 13) & UINT64_C(0xffffffffffffffff)));
+  x142 = (x138 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x143, &x144, 0x0, x141, x97);
+  x145 = (x144 + x99);
+  x146 = ((x143 >> 51) | ((x145 << 13) & UINT64_C(0xffffffffffffffff)));
+  x147 = (x143 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x148, &x149, 0x0, x146, x81);
+  x150 = (x149 + x83);
+  x151 = ((x148 >> 51) | ((x150 << 13) & UINT64_C(0xffffffffffffffff)));
+  x152 = (x148 & UINT64_C(0x7ffffffffffff));
+  x153 = (x151 * UINT8_C(0x13));
+  x154 = (x68 + x153);
+  x155 = (x154 >> 51);
+  x156 = (x154 & UINT64_C(0x7ffffffffffff));
+  x157 = (x155 + x137);
+  x158 = (fiat_25519_uint1)(x157 >> 51);
+  x159 = (x157 & UINT64_C(0x7ffffffffffff));
+  x160 = (x158 + x142);
+  out1[0] = x156;
+  out1[1] = x159;
+  out1[2] = x160;
+  out1[3] = x147;
+  out1[4] = x152;
+}
+
+/*
+ * The function fiat_25519_carry_square squares a field element and reduces the result.
+ *
+ * Postconditions:
+ *   eval out1 mod m = (eval arg1 * eval arg1) mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_carry_square(fiat_25519_tight_field_element out1, const fiat_25519_loose_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  uint64_t x14;
+  uint64_t x15;
+  uint64_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  uint64_t x29;
+  uint64_t x30;
+  uint64_t x31;
+  uint64_t x32;
+  uint64_t x33;
+  uint64_t x34;
+  uint64_t x35;
+  uint64_t x36;
+  uint64_t x37;
+  uint64_t x38;
+  uint64_t x39;
+  fiat_25519_uint1 x40;
+  uint64_t x41;
+  fiat_25519_uint1 x42;
+  uint64_t x43;
+  fiat_25519_uint1 x44;
+  uint64_t x45;
+  fiat_25519_uint1 x46;
+  uint64_t x47;
+  uint64_t x48;
+  uint64_t x49;
+  fiat_25519_uint1 x50;
+  uint64_t x51;
+  fiat_25519_uint1 x52;
+  uint64_t x53;
+  fiat_25519_uint1 x54;
+  uint64_t x55;
+  fiat_25519_uint1 x56;
+  uint64_t x57;
+  fiat_25519_uint1 x58;
+  uint64_t x59;
+  fiat_25519_uint1 x60;
+  uint64_t x61;
+  fiat_25519_uint1 x62;
+  uint64_t x63;
+  fiat_25519_uint1 x64;
+  uint64_t x65;
+  fiat_25519_uint1 x66;
+  uint64_t x67;
+  fiat_25519_uint1 x68;
+  uint64_t x69;
+  fiat_25519_uint1 x70;
+  uint64_t x71;
+  fiat_25519_uint1 x72;
+  uint64_t x73;
+  fiat_25519_uint1 x74;
+  uint64_t x75;
+  fiat_25519_uint1 x76;
+  uint64_t x77;
+  fiat_25519_uint1 x78;
+  uint64_t x79;
+  fiat_25519_uint1 x80;
+  uint64_t x81;
+  fiat_25519_uint1 x82;
+  uint64_t x83;
+  uint64_t x84;
+  uint64_t x85;
+  uint64_t x86;
+  fiat_25519_uint1 x87;
+  uint64_t x88;
+  uint64_t x89;
+  uint64_t x90;
+  uint64_t x91;
+  fiat_25519_uint1 x92;
+  uint64_t x93;
+  uint64_t x94;
+  uint64_t x95;
+  uint64_t x96;
+  fiat_25519_uint1 x97;
+  uint64_t x98;
+  uint64_t x99;
+  uint64_t x100;
+  uint64_t x101;
+  uint64_t x102;
+  uint64_t x103;
+  uint64_t x104;
+  uint64_t x105;
+  fiat_25519_uint1 x106;
+  uint64_t x107;
+  uint64_t x108;
+  x1 = ((arg1[4]) * UINT8_C(0x13));
+  x2 = (x1 * 0x2);
+  x3 = ((arg1[4]) * 0x2);
+  x4 = ((arg1[3]) * UINT8_C(0x13));
+  x5 = (x4 * 0x2);
+  x6 = ((arg1[3]) * 0x2);
+  x7 = ((arg1[2]) * 0x2);
+  x8 = ((arg1[1]) * 0x2);
+  fiat_25519_mulx_u64(&x9, &x10, (arg1[4]), x1);
+  fiat_25519_mulx_u64(&x11, &x12, (arg1[3]), x2);
+  fiat_25519_mulx_u64(&x13, &x14, (arg1[3]), x4);
+  fiat_25519_mulx_u64(&x15, &x16, (arg1[2]), x2);
+  fiat_25519_mulx_u64(&x17, &x18, (arg1[2]), x5);
+  fiat_25519_mulx_u64(&x19, &x20, (arg1[2]), (arg1[2]));
+  fiat_25519_mulx_u64(&x21, &x22, (arg1[1]), x2);
+  fiat_25519_mulx_u64(&x23, &x24, (arg1[1]), x6);
+  fiat_25519_mulx_u64(&x25, &x26, (arg1[1]), x7);
+  fiat_25519_mulx_u64(&x27, &x28, (arg1[1]), (arg1[1]));
+  fiat_25519_mulx_u64(&x29, &x30, (arg1[0]), x3);
+  fiat_25519_mulx_u64(&x31, &x32, (arg1[0]), x6);
+  fiat_25519_mulx_u64(&x33, &x34, (arg1[0]), x7);
+  fiat_25519_mulx_u64(&x35, &x36, (arg1[0]), x8);
+  fiat_25519_mulx_u64(&x37, &x38, (arg1[0]), (arg1[0]));
+  fiat_25519_addcarryx_u64(&x39, &x40, 0x0, x21, x17);
+  fiat_25519_addcarryx_u64(&x41, &x42, x40, x22, x18);
+  fiat_25519_addcarryx_u64(&x43, &x44, 0x0, x37, x39);
+  fiat_25519_addcarryx_u64(&x45, &x46, x44, x38, x41);
+  x47 = ((x43 >> 51) | ((x45 << 13) & UINT64_C(0xffffffffffffffff)));
+  x48 = (x43 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x49, &x50, 0x0, x23, x19);
+  fiat_25519_addcarryx_u64(&x51, &x52, x50, x24, x20);
+  fiat_25519_addcarryx_u64(&x53, &x54, 0x0, x29, x49);
+  fiat_25519_addcarryx_u64(&x55, &x56, x54, x30, x51);
+  fiat_25519_addcarryx_u64(&x57, &x58, 0x0, x25, x9);
+  fiat_25519_addcarryx_u64(&x59, &x60, x58, x26, x10);
+  fiat_25519_addcarryx_u64(&x61, &x62, 0x0, x31, x57);
+  fiat_25519_addcarryx_u64(&x63, &x64, x62, x32, x59);
+  fiat_25519_addcarryx_u64(&x65, &x66, 0x0, x27, x11);
+  fiat_25519_addcarryx_u64(&x67, &x68, x66, x28, x12);
+  fiat_25519_addcarryx_u64(&x69, &x70, 0x0, x33, x65);
+  fiat_25519_addcarryx_u64(&x71, &x72, x70, x34, x67);
+  fiat_25519_addcarryx_u64(&x73, &x74, 0x0, x15, x13);
+  fiat_25519_addcarryx_u64(&x75, &x76, x74, x16, x14);
+  fiat_25519_addcarryx_u64(&x77, &x78, 0x0, x35, x73);
+  fiat_25519_addcarryx_u64(&x79, &x80, x78, x36, x75);
+  fiat_25519_addcarryx_u64(&x81, &x82, 0x0, x47, x77);
+  x83 = (x82 + x79);
+  x84 = ((x81 >> 51) | ((x83 << 13) & UINT64_C(0xffffffffffffffff)));
+  x85 = (x81 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x86, &x87, 0x0, x84, x69);
+  x88 = (x87 + x71);
+  x89 = ((x86 >> 51) | ((x88 << 13) & UINT64_C(0xffffffffffffffff)));
+  x90 = (x86 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x91, &x92, 0x0, x89, x61);
+  x93 = (x92 + x63);
+  x94 = ((x91 >> 51) | ((x93 << 13) & UINT64_C(0xffffffffffffffff)));
+  x95 = (x91 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x96, &x97, 0x0, x94, x53);
+  x98 = (x97 + x55);
+  x99 = ((x96 >> 51) | ((x98 << 13) & UINT64_C(0xffffffffffffffff)));
+  x100 = (x96 & UINT64_C(0x7ffffffffffff));
+  x101 = (x99 * UINT8_C(0x13));
+  x102 = (x48 + x101);
+  x103 = (x102 >> 51);
+  x104 = (x102 & UINT64_C(0x7ffffffffffff));
+  x105 = (x103 + x85);
+  x106 = (fiat_25519_uint1)(x105 >> 51);
+  x107 = (x105 & UINT64_C(0x7ffffffffffff));
+  x108 = (x106 + x90);
+  out1[0] = x104;
+  out1[1] = x107;
+  out1[2] = x108;
+  out1[3] = x95;
+  out1[4] = x100;
+}
+
+/*
+ * The function fiat_25519_carry reduces a field element.
+ *
+ * Postconditions:
+ *   eval out1 mod m = eval arg1 mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_carry(fiat_25519_tight_field_element out1, const fiat_25519_loose_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  x1 = (arg1[0]);
+  x2 = ((x1 >> 51) + (arg1[1]));
+  x3 = ((x2 >> 51) + (arg1[2]));
+  x4 = ((x3 >> 51) + (arg1[3]));
+  x5 = ((x4 >> 51) + (arg1[4]));
+  x6 = ((x1 & UINT64_C(0x7ffffffffffff)) + ((x5 >> 51) * UINT8_C(0x13)));
+  x7 = ((fiat_25519_uint1)(x6 >> 51) + (x2 & UINT64_C(0x7ffffffffffff)));
+  x8 = (x6 & UINT64_C(0x7ffffffffffff));
+  x9 = (x7 & UINT64_C(0x7ffffffffffff));
+  x10 = ((fiat_25519_uint1)(x7 >> 51) + (x3 & UINT64_C(0x7ffffffffffff)));
+  x11 = (x4 & UINT64_C(0x7ffffffffffff));
+  x12 = (x5 & UINT64_C(0x7ffffffffffff));
+  out1[0] = x8;
+  out1[1] = x9;
+  out1[2] = x10;
+  out1[3] = x11;
+  out1[4] = x12;
+}
+
+/*
+ * The function fiat_25519_add adds two field elements.
+ *
+ * Postconditions:
+ *   eval out1 mod m = (eval arg1 + eval arg2) mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_add(fiat_25519_loose_field_element out1, const fiat_25519_tight_field_element arg1, const fiat_25519_tight_field_element arg2) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  x1 = ((arg1[0]) + (arg2[0]));
+  x2 = ((arg1[1]) + (arg2[1]));
+  x3 = ((arg1[2]) + (arg2[2]));
+  x4 = ((arg1[3]) + (arg2[3]));
+  x5 = ((arg1[4]) + (arg2[4]));
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+  out1[4] = x5;
+}
+
+/*
+ * The function fiat_25519_sub subtracts two field elements.
+ *
+ * Postconditions:
+ *   eval out1 mod m = (eval arg1 - eval arg2) mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_sub(fiat_25519_loose_field_element out1, const fiat_25519_tight_field_element arg1, const fiat_25519_tight_field_element arg2) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  x1 = ((UINT64_C(0xfffffffffffda) + (arg1[0])) - (arg2[0]));
+  x2 = ((UINT64_C(0xffffffffffffe) + (arg1[1])) - (arg2[1]));
+  x3 = ((UINT64_C(0xffffffffffffe) + (arg1[2])) - (arg2[2]));
+  x4 = ((UINT64_C(0xffffffffffffe) + (arg1[3])) - (arg2[3]));
+  x5 = ((UINT64_C(0xffffffffffffe) + (arg1[4])) - (arg2[4]));
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+  out1[4] = x5;
+}
+
+/*
+ * The function fiat_25519_opp negates a field element.
+ *
+ * Postconditions:
+ *   eval out1 mod m = -eval arg1 mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_opp(fiat_25519_loose_field_element out1, const fiat_25519_tight_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  x1 = (UINT64_C(0xfffffffffffda) - (arg1[0]));
+  x2 = (UINT64_C(0xffffffffffffe) - (arg1[1]));
+  x3 = (UINT64_C(0xffffffffffffe) - (arg1[2]));
+  x4 = (UINT64_C(0xffffffffffffe) - (arg1[3]));
+  x5 = (UINT64_C(0xffffffffffffe) - (arg1[4]));
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+  out1[4] = x5;
+}
+
+/*
+ * The function fiat_25519_selectznz is a multi-limb conditional select.
+ *
+ * Postconditions:
+ *   out1 = (if arg1 = 0 then arg2 else arg3)
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_selectznz(uint64_t out1[5], fiat_25519_uint1 arg1, const uint64_t arg2[5], const uint64_t arg3[5]) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  fiat_25519_cmovznz_u64(&x1, arg1, (arg2[0]), (arg3[0]));
+  fiat_25519_cmovznz_u64(&x2, arg1, (arg2[1]), (arg3[1]));
+  fiat_25519_cmovznz_u64(&x3, arg1, (arg2[2]), (arg3[2]));
+  fiat_25519_cmovznz_u64(&x4, arg1, (arg2[3]), (arg3[3]));
+  fiat_25519_cmovznz_u64(&x5, arg1, (arg2[4]), (arg3[4]));
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+  out1[4] = x5;
+}
+
+/*
+ * The function fiat_25519_to_bytes serializes a field element to bytes in little-endian order.
+ *
+ * Postconditions:
+ *   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
+ *
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_to_bytes(uint8_t out1[32], const fiat_25519_tight_field_element arg1) {
+  uint64_t x1;
+  fiat_25519_uint1 x2;
+  uint64_t x3;
+  fiat_25519_uint1 x4;
+  uint64_t x5;
+  fiat_25519_uint1 x6;
+  uint64_t x7;
+  fiat_25519_uint1 x8;
+  uint64_t x9;
+  fiat_25519_uint1 x10;
+  uint64_t x11;
+  uint64_t x12;
+  fiat_25519_uint1 x13;
+  uint64_t x14;
+  fiat_25519_uint1 x15;
+  uint64_t x16;
+  fiat_25519_uint1 x17;
+  uint64_t x18;
+  fiat_25519_uint1 x19;
+  uint64_t x20;
+  fiat_25519_uint1 x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint8_t x26;
+  uint64_t x27;
+  uint8_t x28;
+  uint64_t x29;
+  uint8_t x30;
+  uint64_t x31;
+  uint8_t x32;
+  uint64_t x33;
+  uint8_t x34;
+  uint64_t x35;
+  uint8_t x36;
+  uint8_t x37;
+  uint64_t x38;
+  uint8_t x39;
+  uint64_t x40;
+  uint8_t x41;
+  uint64_t x42;
+  uint8_t x43;
+  uint64_t x44;
+  uint8_t x45;
+  uint64_t x46;
+  uint8_t x47;
+  uint64_t x48;
+  uint8_t x49;
+  uint8_t x50;
+  uint64_t x51;
+  uint8_t x52;
+  uint64_t x53;
+  uint8_t x54;
+  uint64_t x55;
+  uint8_t x56;
+  uint64_t x57;
+  uint8_t x58;
+  uint64_t x59;
+  uint8_t x60;
+  uint64_t x61;
+  uint8_t x62;
+  uint64_t x63;
+  uint8_t x64;
+  fiat_25519_uint1 x65;
+  uint64_t x66;
+  uint8_t x67;
+  uint64_t x68;
+  uint8_t x69;
+  uint64_t x70;
+  uint8_t x71;
+  uint64_t x72;
+  uint8_t x73;
+  uint64_t x74;
+  uint8_t x75;
+  uint64_t x76;
+  uint8_t x77;
+  uint8_t x78;
+  uint64_t x79;
+  uint8_t x80;
+  uint64_t x81;
+  uint8_t x82;
+  uint64_t x83;
+  uint8_t x84;
+  uint64_t x85;
+  uint8_t x86;
+  uint64_t x87;
+  uint8_t x88;
+  uint64_t x89;
+  uint8_t x90;
+  uint8_t x91;
+  fiat_25519_subborrowx_u51(&x1, &x2, 0x0, (arg1[0]), UINT64_C(0x7ffffffffffed));
+  fiat_25519_subborrowx_u51(&x3, &x4, x2, (arg1[1]), UINT64_C(0x7ffffffffffff));
+  fiat_25519_subborrowx_u51(&x5, &x6, x4, (arg1[2]), UINT64_C(0x7ffffffffffff));
+  fiat_25519_subborrowx_u51(&x7, &x8, x6, (arg1[3]), UINT64_C(0x7ffffffffffff));
+  fiat_25519_subborrowx_u51(&x9, &x10, x8, (arg1[4]), UINT64_C(0x7ffffffffffff));
+  fiat_25519_cmovznz_u64(&x11, x10, 0x0, UINT64_C(0xffffffffffffffff));
+  fiat_25519_addcarryx_u51(&x12, &x13, 0x0, x1, (x11 & UINT64_C(0x7ffffffffffed)));
+  fiat_25519_addcarryx_u51(&x14, &x15, x13, x3, (x11 & UINT64_C(0x7ffffffffffff)));
+  fiat_25519_addcarryx_u51(&x16, &x17, x15, x5, (x11 & UINT64_C(0x7ffffffffffff)));
+  fiat_25519_addcarryx_u51(&x18, &x19, x17, x7, (x11 & UINT64_C(0x7ffffffffffff)));
+  fiat_25519_addcarryx_u51(&x20, &x21, x19, x9, (x11 & UINT64_C(0x7ffffffffffff)));
+  x22 = (x20 << 4);
+  x23 = (x18 * (uint64_t)0x2);
+  x24 = (x16 << 6);
+  x25 = (x14 << 3);
+  x26 = (uint8_t)(x12 & UINT8_C(0xff));
+  x27 = (x12 >> 8);
+  x28 = (uint8_t)(x27 & UINT8_C(0xff));
+  x29 = (x27 >> 8);
+  x30 = (uint8_t)(x29 & UINT8_C(0xff));
+  x31 = (x29 >> 8);
+  x32 = (uint8_t)(x31 & UINT8_C(0xff));
+  x33 = (x31 >> 8);
+  x34 = (uint8_t)(x33 & UINT8_C(0xff));
+  x35 = (x33 >> 8);
+  x36 = (uint8_t)(x35 & UINT8_C(0xff));
+  x37 = (uint8_t)(x35 >> 8);
+  x38 = (x25 + (uint64_t)x37);
+  x39 = (uint8_t)(x38 & UINT8_C(0xff));
+  x40 = (x38 >> 8);
+  x41 = (uint8_t)(x40 & UINT8_C(0xff));
+  x42 = (x40 >> 8);
+  x43 = (uint8_t)(x42 & UINT8_C(0xff));
+  x44 = (x42 >> 8);
+  x45 = (uint8_t)(x44 & UINT8_C(0xff));
+  x46 = (x44 >> 8);
+  x47 = (uint8_t)(x46 & UINT8_C(0xff));
+  x48 = (x46 >> 8);
+  x49 = (uint8_t)(x48 & UINT8_C(0xff));
+  x50 = (uint8_t)(x48 >> 8);
+  x51 = (x24 + (uint64_t)x50);
+  x52 = (uint8_t)(x51 & UINT8_C(0xff));
+  x53 = (x51 >> 8);
+  x54 = (uint8_t)(x53 & UINT8_C(0xff));
+  x55 = (x53 >> 8);
+  x56 = (uint8_t)(x55 & UINT8_C(0xff));
+  x57 = (x55 >> 8);
+  x58 = (uint8_t)(x57 & UINT8_C(0xff));
+  x59 = (x57 >> 8);
+  x60 = (uint8_t)(x59 & UINT8_C(0xff));
+  x61 = (x59 >> 8);
+  x62 = (uint8_t)(x61 & UINT8_C(0xff));
+  x63 = (x61 >> 8);
+  x64 = (uint8_t)(x63 & UINT8_C(0xff));
+  x65 = (fiat_25519_uint1)(x63 >> 8);
+  x66 = (x23 + (uint64_t)x65);
+  x67 = (uint8_t)(x66 & UINT8_C(0xff));
+  x68 = (x66 >> 8);
+  x69 = (uint8_t)(x68 & UINT8_C(0xff));
+  x70 = (x68 >> 8);
+  x71 = (uint8_t)(x70 & UINT8_C(0xff));
+  x72 = (x70 >> 8);
+  x73 = (uint8_t)(x72 & UINT8_C(0xff));
+  x74 = (x72 >> 8);
+  x75 = (uint8_t)(x74 & UINT8_C(0xff));
+  x76 = (x74 >> 8);
+  x77 = (uint8_t)(x76 & UINT8_C(0xff));
+  x78 = (uint8_t)(x76 >> 8);
+  x79 = (x22 + (uint64_t)x78);
+  x80 = (uint8_t)(x79 & UINT8_C(0xff));
+  x81 = (x79 >> 8);
+  x82 = (uint8_t)(x81 & UINT8_C(0xff));
+  x83 = (x81 >> 8);
+  x84 = (uint8_t)(x83 & UINT8_C(0xff));
+  x85 = (x83 >> 8);
+  x86 = (uint8_t)(x85 & UINT8_C(0xff));
+  x87 = (x85 >> 8);
+  x88 = (uint8_t)(x87 & UINT8_C(0xff));
+  x89 = (x87 >> 8);
+  x90 = (uint8_t)(x89 & UINT8_C(0xff));
+  x91 = (uint8_t)(x89 >> 8);
+  out1[0] = x26;
+  out1[1] = x28;
+  out1[2] = x30;
+  out1[3] = x32;
+  out1[4] = x34;
+  out1[5] = x36;
+  out1[6] = x39;
+  out1[7] = x41;
+  out1[8] = x43;
+  out1[9] = x45;
+  out1[10] = x47;
+  out1[11] = x49;
+  out1[12] = x52;
+  out1[13] = x54;
+  out1[14] = x56;
+  out1[15] = x58;
+  out1[16] = x60;
+  out1[17] = x62;
+  out1[18] = x64;
+  out1[19] = x67;
+  out1[20] = x69;
+  out1[21] = x71;
+  out1[22] = x73;
+  out1[23] = x75;
+  out1[24] = x77;
+  out1[25] = x80;
+  out1[26] = x82;
+  out1[27] = x84;
+  out1[28] = x86;
+  out1[29] = x88;
+  out1[30] = x90;
+  out1[31] = x91;
+}
+
+/*
+ * The function fiat_25519_from_bytes deserializes a field element from bytes in little-endian order.
+ *
+ * Postconditions:
+ *   eval out1 mod m = bytes_eval arg1 mod m
+ *
+ * Input Bounds:
+ *   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]]
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_from_bytes(fiat_25519_tight_field_element out1, const uint8_t arg1[32]) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  uint64_t x14;
+  uint64_t x15;
+  uint64_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  uint64_t x29;
+  uint64_t x30;
+  uint64_t x31;
+  uint8_t x32;
+  uint64_t x33;
+  uint64_t x34;
+  uint64_t x35;
+  uint64_t x36;
+  uint64_t x37;
+  uint64_t x38;
+  uint64_t x39;
+  uint8_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  uint64_t x46;
+  uint64_t x47;
+  uint8_t x48;
+  uint64_t x49;
+  uint64_t x50;
+  uint64_t x51;
+  uint64_t x52;
+  uint64_t x53;
+  uint64_t x54;
+  uint64_t x55;
+  uint64_t x56;
+  uint8_t x57;
+  uint64_t x58;
+  uint64_t x59;
+  uint64_t x60;
+  uint64_t x61;
+  uint64_t x62;
+  uint64_t x63;
+  uint64_t x64;
+  uint8_t x65;
+  uint64_t x66;
+  uint64_t x67;
+  uint64_t x68;
+  uint64_t x69;
+  uint64_t x70;
+  uint64_t x71;
+  x1 = ((uint64_t)(arg1[31]) << 44);
+  x2 = ((uint64_t)(arg1[30]) << 36);
+  x3 = ((uint64_t)(arg1[29]) << 28);
+  x4 = ((uint64_t)(arg1[28]) << 20);
+  x5 = ((uint64_t)(arg1[27]) << 12);
+  x6 = ((uint64_t)(arg1[26]) << 4);
+  x7 = ((uint64_t)(arg1[25]) << 47);
+  x8 = ((uint64_t)(arg1[24]) << 39);
+  x9 = ((uint64_t)(arg1[23]) << 31);
+  x10 = ((uint64_t)(arg1[22]) << 23);
+  x11 = ((uint64_t)(arg1[21]) << 15);
+  x12 = ((uint64_t)(arg1[20]) << 7);
+  x13 = ((uint64_t)(arg1[19]) << 50);
+  x14 = ((uint64_t)(arg1[18]) << 42);
+  x15 = ((uint64_t)(arg1[17]) << 34);
+  x16 = ((uint64_t)(arg1[16]) << 26);
+  x17 = ((uint64_t)(arg1[15]) << 18);
+  x18 = ((uint64_t)(arg1[14]) << 10);
+  x19 = ((uint64_t)(arg1[13]) << 2);
+  x20 = ((uint64_t)(arg1[12]) << 45);
+  x21 = ((uint64_t)(arg1[11]) << 37);
+  x22 = ((uint64_t)(arg1[10]) << 29);
+  x23 = ((uint64_t)(arg1[9]) << 21);
+  x24 = ((uint64_t)(arg1[8]) << 13);
+  x25 = ((uint64_t)(arg1[7]) << 5);
+  x26 = ((uint64_t)(arg1[6]) << 48);
+  x27 = ((uint64_t)(arg1[5]) << 40);
+  x28 = ((uint64_t)(arg1[4]) << 32);
+  x29 = ((uint64_t)(arg1[3]) << 24);
+  x30 = ((uint64_t)(arg1[2]) << 16);
+  x31 = ((uint64_t)(arg1[1]) << 8);
+  x32 = (arg1[0]);
+  x33 = (x31 + (uint64_t)x32);
+  x34 = (x30 + x33);
+  x35 = (x29 + x34);
+  x36 = (x28 + x35);
+  x37 = (x27 + x36);
+  x38 = (x26 + x37);
+  x39 = (x38 & UINT64_C(0x7ffffffffffff));
+  x40 = (uint8_t)(x38 >> 51);
+  x41 = (x25 + (uint64_t)x40);
+  x42 = (x24 + x41);
+  x43 = (x23 + x42);
+  x44 = (x22 + x43);
+  x45 = (x21 + x44);
+  x46 = (x20 + x45);
+  x47 = (x46 & UINT64_C(0x7ffffffffffff));
+  x48 = (uint8_t)(x46 >> 51);
+  x49 = (x19 + (uint64_t)x48);
+  x50 = (x18 + x49);
+  x51 = (x17 + x50);
+  x52 = (x16 + x51);
+  x53 = (x15 + x52);
+  x54 = (x14 + x53);
+  x55 = (x13 + x54);
+  x56 = (x55 & UINT64_C(0x7ffffffffffff));
+  x57 = (uint8_t)(x55 >> 51);
+  x58 = (x12 + (uint64_t)x57);
+  x59 = (x11 + x58);
+  x60 = (x10 + x59);
+  x61 = (x9 + x60);
+  x62 = (x8 + x61);
+  x63 = (x7 + x62);
+  x64 = (x63 & UINT64_C(0x7ffffffffffff));
+  x65 = (uint8_t)(x63 >> 51);
+  x66 = (x6 + (uint64_t)x65);
+  x67 = (x5 + x66);
+  x68 = (x4 + x67);
+  x69 = (x3 + x68);
+  x70 = (x2 + x69);
+  x71 = (x1 + x70);
+  out1[0] = x39;
+  out1[1] = x47;
+  out1[2] = x56;
+  out1[3] = x64;
+  out1[4] = x71;
+}
+
+/*
+ * The function fiat_25519_relax is the identity function converting from tight field elements to loose field elements.
+ *
+ * Postconditions:
+ *   out1 = arg1
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_relax(fiat_25519_loose_field_element out1, const fiat_25519_tight_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  x1 = (arg1[0]);
+  x2 = (arg1[1]);
+  x3 = (arg1[2]);
+  x4 = (arg1[3]);
+  x5 = (arg1[4]);
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+  out1[4] = x5;
+}
+
+/*
+ * The function fiat_25519_carry_scmul_121666 multiplies a field element by 121666 and reduces the result.
+ *
+ * Postconditions:
+ *   eval out1 mod m = (121666 * eval arg1) mod m
+ *
+ */
+static FIAT_25519_FIAT_INLINE void fiat_25519_carry_scmul_121666(fiat_25519_tight_field_element out1, const fiat_25519_loose_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  fiat_25519_uint1 x14;
+  uint64_t x15;
+  uint64_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  fiat_25519_uint1 x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  fiat_25519_uint1 x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  fiat_25519_uint1 x29;
+  uint64_t x30;
+  uint64_t x31;
+  uint64_t x32;
+  uint64_t x33;
+  uint64_t x34;
+  fiat_25519_uint1 x35;
+  uint64_t x36;
+  uint64_t x37;
+  fiat_25519_uint1 x38;
+  uint64_t x39;
+  uint64_t x40;
+  fiat_25519_mulx_u64(&x1, &x2, UINT32_C(0x1db42), (arg1[4]));
+  fiat_25519_mulx_u64(&x3, &x4, UINT32_C(0x1db42), (arg1[3]));
+  fiat_25519_mulx_u64(&x5, &x6, UINT32_C(0x1db42), (arg1[2]));
+  fiat_25519_mulx_u64(&x7, &x8, UINT32_C(0x1db42), (arg1[1]));
+  fiat_25519_mulx_u64(&x9, &x10, UINT32_C(0x1db42), (arg1[0]));
+  x11 = ((x9 >> 51) | ((x10 << 13) & UINT64_C(0xffffffffffffffff)));
+  x12 = (x9 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x13, &x14, 0x0, x11, x7);
+  x15 = (x14 + x8);
+  x16 = ((x13 >> 51) | ((x15 << 13) & UINT64_C(0xffffffffffffffff)));
+  x17 = (x13 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x18, &x19, 0x0, x16, x5);
+  x20 = (x19 + x6);
+  x21 = ((x18 >> 51) | ((x20 << 13) & UINT64_C(0xffffffffffffffff)));
+  x22 = (x18 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x23, &x24, 0x0, x21, x3);
+  x25 = (x24 + x4);
+  x26 = ((x23 >> 51) | ((x25 << 13) & UINT64_C(0xffffffffffffffff)));
+  x27 = (x23 & UINT64_C(0x7ffffffffffff));
+  fiat_25519_addcarryx_u64(&x28, &x29, 0x0, x26, x1);
+  x30 = (x29 + x2);
+  x31 = ((x28 >> 51) | ((x30 << 13) & UINT64_C(0xffffffffffffffff)));
+  x32 = (x28 & UINT64_C(0x7ffffffffffff));
+  x33 = (x31 * UINT8_C(0x13));
+  x34 = (x12 + x33);
+  x35 = (fiat_25519_uint1)(x34 >> 51);
+  x36 = (x34 & UINT64_C(0x7ffffffffffff));
+  x37 = (x35 + x17);
+  x38 = (fiat_25519_uint1)(x37 >> 51);
+  x39 = (x37 & UINT64_C(0x7ffffffffffff));
+  x40 = (x38 + x22);
+  out1[0] = x36;
+  out1[1] = x39;
+  out1[2] = x40;
+  out1[3] = x27;
+  out1[4] = x32;
+}
diff --git a/src/third_party/fiat/p256_64_msvc.h b/src/third_party/fiat/p256_64_msvc.h
new file mode 100644
index 0000000..8b65a37
--- /dev/null
+++ b/src/third_party/fiat/p256_64_msvc.h
@@ -0,0 +1,2002 @@
+/* Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --inline --static --use-value-barrier --no-wide-int p256 64 '2^256 - 2^224 + 2^192 + 2^96 - 1' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp */
+/* curve description: p256 */
+/* machine_wordsize = 64 (from "64") */
+/* requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp */
+/* m = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff (from "2^256 - 2^224 + 2^192 + 2^96 - 1") */
+/*                                                                    */
+/* NOTE: In addition to the bounds specified above each function, all */
+/*   functions synthesized for this Montgomery arithmetic require the */
+/*   input to be strictly less than the prime modulus (m), and also   */
+/*   require the input to be in the unique saturated representation.  */
+/*   All functions also ensure that these two properties are true of  */
+/*   return values.                                                   */
+/*  */
+/* Computed values: */
+/*   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) */
+/*   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) */
+/*   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in */
+/*                            if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 */
+
+#include <stdint.h>
+#include <intrin.h>
+#if defined(_M_X64)
+#include <immintrin.h>
+#endif
+
+typedef unsigned char fiat_p256_uint1;
+typedef signed char fiat_p256_int1;
+
+#define FIAT_P256_FIAT_INLINE inline
+
+/* The type fiat_p256_montgomery_domain_field_element is a field element in the Montgomery domain. */
+/* Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] */
+typedef uint64_t fiat_p256_montgomery_domain_field_element[4];
+
+/* The type fiat_p256_non_montgomery_domain_field_element is a field element NOT in the Montgomery domain. */
+/* Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] */
+typedef uint64_t fiat_p256_non_montgomery_domain_field_element[4];
+
+#if (-1 & 3) != 3
+#error "This code only works on a two's complement system"
+#endif
+
+#define fiat_p256_value_barrier_u64(x) (x)
+
+
+/*
+ * The function fiat_p256_addcarryx_u64 is an addition with carry.
+ *
+ * Postconditions:
+ *   out1 = (arg1 + arg2 + arg3) mod 2^64
+ *   out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_addcarryx_u64(uint64_t* out1, fiat_p256_uint1* out2, fiat_p256_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+#if defined(_M_X64)
+  *out2 = _addcarry_u64(arg1, arg2, arg3, out1);
+#else
+  arg2 += arg1;
+  arg1 = arg2 < arg1;
+  arg3 += arg2;
+  arg1 += arg3 < arg2;
+  *out1 = arg3;
+  *out2 = arg1;
+#endif
+}
+
+/*
+ * The function fiat_p256_subborrowx_u64 is a subtraction with borrow.
+ *
+ * Postconditions:
+ *   out1 = (-arg1 + arg2 + -arg3) mod 2^64
+ *   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0x1]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_subborrowx_u64(uint64_t* out1, fiat_p256_uint1* out2, fiat_p256_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+#if defined(_M_X64)
+  *out2 = _subborrow_u64(arg1, arg2, arg3, out1); // NOTE: edited after generation
+#else
+  *out1 = arg2 - arg3 - arg1;
+  *out2 = (arg2 < arg3) | ((arg2 == arg3) & arg1);
+#endif
+}
+
+/*
+ * The function fiat_p256_mulx_u64 is a multiplication, returning the full double-width result.
+ *
+ * Postconditions:
+ *   out1 = (arg1 * arg2) mod 2^64
+ *   out2 = ⌊arg1 * arg2 / 2^64⌋
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0xffffffffffffffff]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [0x0 ~> 0xffffffffffffffff]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_mulx_u64(uint64_t* out1, uint64_t* out2, uint64_t arg1, uint64_t arg2) {
+// NOTE: edited after generation
+#if defined(_M_X64)
+  *out1 = _umul128(arg1, arg2, out2);
+#elif defined(_M_ARM64)
+  *out1 = arg1 * arg2;
+  *out2 = __umulh(arg1, arg2);
+#else
+#error "This file is intended for MSVC on X64 or ARM64"
+#endif
+}
+
+/*
+ * The function fiat_p256_cmovznz_u64 is a single-word conditional move.
+ *
+ * Postconditions:
+ *   out1 = (if arg1 = 0 then arg2 else arg3)
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [0x0 ~> 0xffffffffffffffff]
+ *   arg3: [0x0 ~> 0xffffffffffffffff]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_cmovznz_u64(uint64_t* out1, fiat_p256_uint1 arg1, uint64_t arg2, uint64_t arg3) {
+  fiat_p256_uint1 x1;
+  uint64_t x2;
+  uint64_t x3;
+  x1 = (!(!arg1));
+  x2 = ((fiat_p256_int1)(0x0 - x1) & UINT64_C(0xffffffffffffffff));
+  x3 = ((fiat_p256_value_barrier_u64(x2) & arg3) | (fiat_p256_value_barrier_u64((~x2)) & arg2));
+  *out1 = x3;
+}
+
+/*
+ * The function fiat_p256_mul multiplies two field elements in the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ *   0 ≤ eval arg2 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_mul(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  fiat_p256_uint1 x14;
+  uint64_t x15;
+  fiat_p256_uint1 x16;
+  uint64_t x17;
+  fiat_p256_uint1 x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  fiat_p256_uint1 x27;
+  uint64_t x28;
+  uint64_t x29;
+  fiat_p256_uint1 x30;
+  uint64_t x31;
+  fiat_p256_uint1 x32;
+  uint64_t x33;
+  fiat_p256_uint1 x34;
+  uint64_t x35;
+  fiat_p256_uint1 x36;
+  uint64_t x37;
+  fiat_p256_uint1 x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  uint64_t x46;
+  uint64_t x47;
+  fiat_p256_uint1 x48;
+  uint64_t x49;
+  fiat_p256_uint1 x50;
+  uint64_t x51;
+  fiat_p256_uint1 x52;
+  uint64_t x53;
+  uint64_t x54;
+  fiat_p256_uint1 x55;
+  uint64_t x56;
+  fiat_p256_uint1 x57;
+  uint64_t x58;
+  fiat_p256_uint1 x59;
+  uint64_t x60;
+  fiat_p256_uint1 x61;
+  uint64_t x62;
+  fiat_p256_uint1 x63;
+  uint64_t x64;
+  uint64_t x65;
+  uint64_t x66;
+  uint64_t x67;
+  uint64_t x68;
+  uint64_t x69;
+  uint64_t x70;
+  fiat_p256_uint1 x71;
+  uint64_t x72;
+  uint64_t x73;
+  fiat_p256_uint1 x74;
+  uint64_t x75;
+  fiat_p256_uint1 x76;
+  uint64_t x77;
+  fiat_p256_uint1 x78;
+  uint64_t x79;
+  fiat_p256_uint1 x80;
+  uint64_t x81;
+  fiat_p256_uint1 x82;
+  uint64_t x83;
+  uint64_t x84;
+  uint64_t x85;
+  uint64_t x86;
+  uint64_t x87;
+  uint64_t x88;
+  uint64_t x89;
+  uint64_t x90;
+  uint64_t x91;
+  uint64_t x92;
+  fiat_p256_uint1 x93;
+  uint64_t x94;
+  fiat_p256_uint1 x95;
+  uint64_t x96;
+  fiat_p256_uint1 x97;
+  uint64_t x98;
+  uint64_t x99;
+  fiat_p256_uint1 x100;
+  uint64_t x101;
+  fiat_p256_uint1 x102;
+  uint64_t x103;
+  fiat_p256_uint1 x104;
+  uint64_t x105;
+  fiat_p256_uint1 x106;
+  uint64_t x107;
+  fiat_p256_uint1 x108;
+  uint64_t x109;
+  uint64_t x110;
+  uint64_t x111;
+  uint64_t x112;
+  uint64_t x113;
+  uint64_t x114;
+  uint64_t x115;
+  fiat_p256_uint1 x116;
+  uint64_t x117;
+  uint64_t x118;
+  fiat_p256_uint1 x119;
+  uint64_t x120;
+  fiat_p256_uint1 x121;
+  uint64_t x122;
+  fiat_p256_uint1 x123;
+  uint64_t x124;
+  fiat_p256_uint1 x125;
+  uint64_t x126;
+  fiat_p256_uint1 x127;
+  uint64_t x128;
+  uint64_t x129;
+  uint64_t x130;
+  uint64_t x131;
+  uint64_t x132;
+  uint64_t x133;
+  uint64_t x134;
+  uint64_t x135;
+  uint64_t x136;
+  uint64_t x137;
+  fiat_p256_uint1 x138;
+  uint64_t x139;
+  fiat_p256_uint1 x140;
+  uint64_t x141;
+  fiat_p256_uint1 x142;
+  uint64_t x143;
+  uint64_t x144;
+  fiat_p256_uint1 x145;
+  uint64_t x146;
+  fiat_p256_uint1 x147;
+  uint64_t x148;
+  fiat_p256_uint1 x149;
+  uint64_t x150;
+  fiat_p256_uint1 x151;
+  uint64_t x152;
+  fiat_p256_uint1 x153;
+  uint64_t x154;
+  uint64_t x155;
+  uint64_t x156;
+  uint64_t x157;
+  uint64_t x158;
+  uint64_t x159;
+  uint64_t x160;
+  fiat_p256_uint1 x161;
+  uint64_t x162;
+  uint64_t x163;
+  fiat_p256_uint1 x164;
+  uint64_t x165;
+  fiat_p256_uint1 x166;
+  uint64_t x167;
+  fiat_p256_uint1 x168;
+  uint64_t x169;
+  fiat_p256_uint1 x170;
+  uint64_t x171;
+  fiat_p256_uint1 x172;
+  uint64_t x173;
+  uint64_t x174;
+  fiat_p256_uint1 x175;
+  uint64_t x176;
+  fiat_p256_uint1 x177;
+  uint64_t x178;
+  fiat_p256_uint1 x179;
+  uint64_t x180;
+  fiat_p256_uint1 x181;
+  uint64_t x182;
+  fiat_p256_uint1 x183;
+  uint64_t x184;
+  uint64_t x185;
+  uint64_t x186;
+  uint64_t x187;
+  x1 = (arg1[1]);
+  x2 = (arg1[2]);
+  x3 = (arg1[3]);
+  x4 = (arg1[0]);
+  fiat_p256_mulx_u64(&x5, &x6, x4, (arg2[3]));
+  fiat_p256_mulx_u64(&x7, &x8, x4, (arg2[2]));
+  fiat_p256_mulx_u64(&x9, &x10, x4, (arg2[1]));
+  fiat_p256_mulx_u64(&x11, &x12, x4, (arg2[0]));
+  fiat_p256_addcarryx_u64(&x13, &x14, 0x0, x12, x9);
+  fiat_p256_addcarryx_u64(&x15, &x16, x14, x10, x7);
+  fiat_p256_addcarryx_u64(&x17, &x18, x16, x8, x5);
+  x19 = (x18 + x6);
+  fiat_p256_mulx_u64(&x20, &x21, x11, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x22, &x23, x11, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x24, &x25, x11, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x26, &x27, 0x0, x25, x22);
+  x28 = (x27 + x23);
+  fiat_p256_addcarryx_u64(&x29, &x30, 0x0, x11, x24);
+  fiat_p256_addcarryx_u64(&x31, &x32, x30, x13, x26);
+  fiat_p256_addcarryx_u64(&x33, &x34, x32, x15, x28);
+  fiat_p256_addcarryx_u64(&x35, &x36, x34, x17, x20);
+  fiat_p256_addcarryx_u64(&x37, &x38, x36, x19, x21);
+  fiat_p256_mulx_u64(&x39, &x40, x1, (arg2[3]));
+  fiat_p256_mulx_u64(&x41, &x42, x1, (arg2[2]));
+  fiat_p256_mulx_u64(&x43, &x44, x1, (arg2[1]));
+  fiat_p256_mulx_u64(&x45, &x46, x1, (arg2[0]));
+  fiat_p256_addcarryx_u64(&x47, &x48, 0x0, x46, x43);
+  fiat_p256_addcarryx_u64(&x49, &x50, x48, x44, x41);
+  fiat_p256_addcarryx_u64(&x51, &x52, x50, x42, x39);
+  x53 = (x52 + x40);
+  fiat_p256_addcarryx_u64(&x54, &x55, 0x0, x31, x45);
+  fiat_p256_addcarryx_u64(&x56, &x57, x55, x33, x47);
+  fiat_p256_addcarryx_u64(&x58, &x59, x57, x35, x49);
+  fiat_p256_addcarryx_u64(&x60, &x61, x59, x37, x51);
+  fiat_p256_addcarryx_u64(&x62, &x63, x61, x38, x53);
+  fiat_p256_mulx_u64(&x64, &x65, x54, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x66, &x67, x54, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x68, &x69, x54, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x70, &x71, 0x0, x69, x66);
+  x72 = (x71 + x67);
+  fiat_p256_addcarryx_u64(&x73, &x74, 0x0, x54, x68);
+  fiat_p256_addcarryx_u64(&x75, &x76, x74, x56, x70);
+  fiat_p256_addcarryx_u64(&x77, &x78, x76, x58, x72);
+  fiat_p256_addcarryx_u64(&x79, &x80, x78, x60, x64);
+  fiat_p256_addcarryx_u64(&x81, &x82, x80, x62, x65);
+  x83 = ((uint64_t)x82 + x63);
+  fiat_p256_mulx_u64(&x84, &x85, x2, (arg2[3]));
+  fiat_p256_mulx_u64(&x86, &x87, x2, (arg2[2]));
+  fiat_p256_mulx_u64(&x88, &x89, x2, (arg2[1]));
+  fiat_p256_mulx_u64(&x90, &x91, x2, (arg2[0]));
+  fiat_p256_addcarryx_u64(&x92, &x93, 0x0, x91, x88);
+  fiat_p256_addcarryx_u64(&x94, &x95, x93, x89, x86);
+  fiat_p256_addcarryx_u64(&x96, &x97, x95, x87, x84);
+  x98 = (x97 + x85);
+  fiat_p256_addcarryx_u64(&x99, &x100, 0x0, x75, x90);
+  fiat_p256_addcarryx_u64(&x101, &x102, x100, x77, x92);
+  fiat_p256_addcarryx_u64(&x103, &x104, x102, x79, x94);
+  fiat_p256_addcarryx_u64(&x105, &x106, x104, x81, x96);
+  fiat_p256_addcarryx_u64(&x107, &x108, x106, x83, x98);
+  fiat_p256_mulx_u64(&x109, &x110, x99, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x111, &x112, x99, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x113, &x114, x99, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x115, &x116, 0x0, x114, x111);
+  x117 = (x116 + x112);
+  fiat_p256_addcarryx_u64(&x118, &x119, 0x0, x99, x113);
+  fiat_p256_addcarryx_u64(&x120, &x121, x119, x101, x115);
+  fiat_p256_addcarryx_u64(&x122, &x123, x121, x103, x117);
+  fiat_p256_addcarryx_u64(&x124, &x125, x123, x105, x109);
+  fiat_p256_addcarryx_u64(&x126, &x127, x125, x107, x110);
+  x128 = ((uint64_t)x127 + x108);
+  fiat_p256_mulx_u64(&x129, &x130, x3, (arg2[3]));
+  fiat_p256_mulx_u64(&x131, &x132, x3, (arg2[2]));
+  fiat_p256_mulx_u64(&x133, &x134, x3, (arg2[1]));
+  fiat_p256_mulx_u64(&x135, &x136, x3, (arg2[0]));
+  fiat_p256_addcarryx_u64(&x137, &x138, 0x0, x136, x133);
+  fiat_p256_addcarryx_u64(&x139, &x140, x138, x134, x131);
+  fiat_p256_addcarryx_u64(&x141, &x142, x140, x132, x129);
+  x143 = (x142 + x130);
+  fiat_p256_addcarryx_u64(&x144, &x145, 0x0, x120, x135);
+  fiat_p256_addcarryx_u64(&x146, &x147, x145, x122, x137);
+  fiat_p256_addcarryx_u64(&x148, &x149, x147, x124, x139);
+  fiat_p256_addcarryx_u64(&x150, &x151, x149, x126, x141);
+  fiat_p256_addcarryx_u64(&x152, &x153, x151, x128, x143);
+  fiat_p256_mulx_u64(&x154, &x155, x144, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x156, &x157, x144, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x158, &x159, x144, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x160, &x161, 0x0, x159, x156);
+  x162 = (x161 + x157);
+  fiat_p256_addcarryx_u64(&x163, &x164, 0x0, x144, x158);
+  fiat_p256_addcarryx_u64(&x165, &x166, x164, x146, x160);
+  fiat_p256_addcarryx_u64(&x167, &x168, x166, x148, x162);
+  fiat_p256_addcarryx_u64(&x169, &x170, x168, x150, x154);
+  fiat_p256_addcarryx_u64(&x171, &x172, x170, x152, x155);
+  x173 = ((uint64_t)x172 + x153);
+  fiat_p256_subborrowx_u64(&x174, &x175, 0x0, x165, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x176, &x177, x175, x167, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x178, &x179, x177, x169, 0x0);
+  fiat_p256_subborrowx_u64(&x180, &x181, x179, x171, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x182, &x183, x181, x173, 0x0);
+  fiat_p256_cmovznz_u64(&x184, x183, x174, x165);
+  fiat_p256_cmovznz_u64(&x185, x183, x176, x167);
+  fiat_p256_cmovznz_u64(&x186, x183, x178, x169);
+  fiat_p256_cmovznz_u64(&x187, x183, x180, x171);
+  out1[0] = x184;
+  out1[1] = x185;
+  out1[2] = x186;
+  out1[3] = x187;
+}
+
+/*
+ * The function fiat_p256_square squares a field element in the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  fiat_p256_uint1 x14;
+  uint64_t x15;
+  fiat_p256_uint1 x16;
+  uint64_t x17;
+  fiat_p256_uint1 x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  fiat_p256_uint1 x27;
+  uint64_t x28;
+  uint64_t x29;
+  fiat_p256_uint1 x30;
+  uint64_t x31;
+  fiat_p256_uint1 x32;
+  uint64_t x33;
+  fiat_p256_uint1 x34;
+  uint64_t x35;
+  fiat_p256_uint1 x36;
+  uint64_t x37;
+  fiat_p256_uint1 x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  uint64_t x46;
+  uint64_t x47;
+  fiat_p256_uint1 x48;
+  uint64_t x49;
+  fiat_p256_uint1 x50;
+  uint64_t x51;
+  fiat_p256_uint1 x52;
+  uint64_t x53;
+  uint64_t x54;
+  fiat_p256_uint1 x55;
+  uint64_t x56;
+  fiat_p256_uint1 x57;
+  uint64_t x58;
+  fiat_p256_uint1 x59;
+  uint64_t x60;
+  fiat_p256_uint1 x61;
+  uint64_t x62;
+  fiat_p256_uint1 x63;
+  uint64_t x64;
+  uint64_t x65;
+  uint64_t x66;
+  uint64_t x67;
+  uint64_t x68;
+  uint64_t x69;
+  uint64_t x70;
+  fiat_p256_uint1 x71;
+  uint64_t x72;
+  uint64_t x73;
+  fiat_p256_uint1 x74;
+  uint64_t x75;
+  fiat_p256_uint1 x76;
+  uint64_t x77;
+  fiat_p256_uint1 x78;
+  uint64_t x79;
+  fiat_p256_uint1 x80;
+  uint64_t x81;
+  fiat_p256_uint1 x82;
+  uint64_t x83;
+  uint64_t x84;
+  uint64_t x85;
+  uint64_t x86;
+  uint64_t x87;
+  uint64_t x88;
+  uint64_t x89;
+  uint64_t x90;
+  uint64_t x91;
+  uint64_t x92;
+  fiat_p256_uint1 x93;
+  uint64_t x94;
+  fiat_p256_uint1 x95;
+  uint64_t x96;
+  fiat_p256_uint1 x97;
+  uint64_t x98;
+  uint64_t x99;
+  fiat_p256_uint1 x100;
+  uint64_t x101;
+  fiat_p256_uint1 x102;
+  uint64_t x103;
+  fiat_p256_uint1 x104;
+  uint64_t x105;
+  fiat_p256_uint1 x106;
+  uint64_t x107;
+  fiat_p256_uint1 x108;
+  uint64_t x109;
+  uint64_t x110;
+  uint64_t x111;
+  uint64_t x112;
+  uint64_t x113;
+  uint64_t x114;
+  uint64_t x115;
+  fiat_p256_uint1 x116;
+  uint64_t x117;
+  uint64_t x118;
+  fiat_p256_uint1 x119;
+  uint64_t x120;
+  fiat_p256_uint1 x121;
+  uint64_t x122;
+  fiat_p256_uint1 x123;
+  uint64_t x124;
+  fiat_p256_uint1 x125;
+  uint64_t x126;
+  fiat_p256_uint1 x127;
+  uint64_t x128;
+  uint64_t x129;
+  uint64_t x130;
+  uint64_t x131;
+  uint64_t x132;
+  uint64_t x133;
+  uint64_t x134;
+  uint64_t x135;
+  uint64_t x136;
+  uint64_t x137;
+  fiat_p256_uint1 x138;
+  uint64_t x139;
+  fiat_p256_uint1 x140;
+  uint64_t x141;
+  fiat_p256_uint1 x142;
+  uint64_t x143;
+  uint64_t x144;
+  fiat_p256_uint1 x145;
+  uint64_t x146;
+  fiat_p256_uint1 x147;
+  uint64_t x148;
+  fiat_p256_uint1 x149;
+  uint64_t x150;
+  fiat_p256_uint1 x151;
+  uint64_t x152;
+  fiat_p256_uint1 x153;
+  uint64_t x154;
+  uint64_t x155;
+  uint64_t x156;
+  uint64_t x157;
+  uint64_t x158;
+  uint64_t x159;
+  uint64_t x160;
+  fiat_p256_uint1 x161;
+  uint64_t x162;
+  uint64_t x163;
+  fiat_p256_uint1 x164;
+  uint64_t x165;
+  fiat_p256_uint1 x166;
+  uint64_t x167;
+  fiat_p256_uint1 x168;
+  uint64_t x169;
+  fiat_p256_uint1 x170;
+  uint64_t x171;
+  fiat_p256_uint1 x172;
+  uint64_t x173;
+  uint64_t x174;
+  fiat_p256_uint1 x175;
+  uint64_t x176;
+  fiat_p256_uint1 x177;
+  uint64_t x178;
+  fiat_p256_uint1 x179;
+  uint64_t x180;
+  fiat_p256_uint1 x181;
+  uint64_t x182;
+  fiat_p256_uint1 x183;
+  uint64_t x184;
+  uint64_t x185;
+  uint64_t x186;
+  uint64_t x187;
+  x1 = (arg1[1]);
+  x2 = (arg1[2]);
+  x3 = (arg1[3]);
+  x4 = (arg1[0]);
+  fiat_p256_mulx_u64(&x5, &x6, x4, (arg1[3]));
+  fiat_p256_mulx_u64(&x7, &x8, x4, (arg1[2]));
+  fiat_p256_mulx_u64(&x9, &x10, x4, (arg1[1]));
+  fiat_p256_mulx_u64(&x11, &x12, x4, (arg1[0]));
+  fiat_p256_addcarryx_u64(&x13, &x14, 0x0, x12, x9);
+  fiat_p256_addcarryx_u64(&x15, &x16, x14, x10, x7);
+  fiat_p256_addcarryx_u64(&x17, &x18, x16, x8, x5);
+  x19 = (x18 + x6);
+  fiat_p256_mulx_u64(&x20, &x21, x11, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x22, &x23, x11, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x24, &x25, x11, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x26, &x27, 0x0, x25, x22);
+  x28 = (x27 + x23);
+  fiat_p256_addcarryx_u64(&x29, &x30, 0x0, x11, x24);
+  fiat_p256_addcarryx_u64(&x31, &x32, x30, x13, x26);
+  fiat_p256_addcarryx_u64(&x33, &x34, x32, x15, x28);
+  fiat_p256_addcarryx_u64(&x35, &x36, x34, x17, x20);
+  fiat_p256_addcarryx_u64(&x37, &x38, x36, x19, x21);
+  fiat_p256_mulx_u64(&x39, &x40, x1, (arg1[3]));
+  fiat_p256_mulx_u64(&x41, &x42, x1, (arg1[2]));
+  fiat_p256_mulx_u64(&x43, &x44, x1, (arg1[1]));
+  fiat_p256_mulx_u64(&x45, &x46, x1, (arg1[0]));
+  fiat_p256_addcarryx_u64(&x47, &x48, 0x0, x46, x43);
+  fiat_p256_addcarryx_u64(&x49, &x50, x48, x44, x41);
+  fiat_p256_addcarryx_u64(&x51, &x52, x50, x42, x39);
+  x53 = (x52 + x40);
+  fiat_p256_addcarryx_u64(&x54, &x55, 0x0, x31, x45);
+  fiat_p256_addcarryx_u64(&x56, &x57, x55, x33, x47);
+  fiat_p256_addcarryx_u64(&x58, &x59, x57, x35, x49);
+  fiat_p256_addcarryx_u64(&x60, &x61, x59, x37, x51);
+  fiat_p256_addcarryx_u64(&x62, &x63, x61, x38, x53);
+  fiat_p256_mulx_u64(&x64, &x65, x54, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x66, &x67, x54, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x68, &x69, x54, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x70, &x71, 0x0, x69, x66);
+  x72 = (x71 + x67);
+  fiat_p256_addcarryx_u64(&x73, &x74, 0x0, x54, x68);
+  fiat_p256_addcarryx_u64(&x75, &x76, x74, x56, x70);
+  fiat_p256_addcarryx_u64(&x77, &x78, x76, x58, x72);
+  fiat_p256_addcarryx_u64(&x79, &x80, x78, x60, x64);
+  fiat_p256_addcarryx_u64(&x81, &x82, x80, x62, x65);
+  x83 = ((uint64_t)x82 + x63);
+  fiat_p256_mulx_u64(&x84, &x85, x2, (arg1[3]));
+  fiat_p256_mulx_u64(&x86, &x87, x2, (arg1[2]));
+  fiat_p256_mulx_u64(&x88, &x89, x2, (arg1[1]));
+  fiat_p256_mulx_u64(&x90, &x91, x2, (arg1[0]));
+  fiat_p256_addcarryx_u64(&x92, &x93, 0x0, x91, x88);
+  fiat_p256_addcarryx_u64(&x94, &x95, x93, x89, x86);
+  fiat_p256_addcarryx_u64(&x96, &x97, x95, x87, x84);
+  x98 = (x97 + x85);
+  fiat_p256_addcarryx_u64(&x99, &x100, 0x0, x75, x90);
+  fiat_p256_addcarryx_u64(&x101, &x102, x100, x77, x92);
+  fiat_p256_addcarryx_u64(&x103, &x104, x102, x79, x94);
+  fiat_p256_addcarryx_u64(&x105, &x106, x104, x81, x96);
+  fiat_p256_addcarryx_u64(&x107, &x108, x106, x83, x98);
+  fiat_p256_mulx_u64(&x109, &x110, x99, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x111, &x112, x99, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x113, &x114, x99, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x115, &x116, 0x0, x114, x111);
+  x117 = (x116 + x112);
+  fiat_p256_addcarryx_u64(&x118, &x119, 0x0, x99, x113);
+  fiat_p256_addcarryx_u64(&x120, &x121, x119, x101, x115);
+  fiat_p256_addcarryx_u64(&x122, &x123, x121, x103, x117);
+  fiat_p256_addcarryx_u64(&x124, &x125, x123, x105, x109);
+  fiat_p256_addcarryx_u64(&x126, &x127, x125, x107, x110);
+  x128 = ((uint64_t)x127 + x108);
+  fiat_p256_mulx_u64(&x129, &x130, x3, (arg1[3]));
+  fiat_p256_mulx_u64(&x131, &x132, x3, (arg1[2]));
+  fiat_p256_mulx_u64(&x133, &x134, x3, (arg1[1]));
+  fiat_p256_mulx_u64(&x135, &x136, x3, (arg1[0]));
+  fiat_p256_addcarryx_u64(&x137, &x138, 0x0, x136, x133);
+  fiat_p256_addcarryx_u64(&x139, &x140, x138, x134, x131);
+  fiat_p256_addcarryx_u64(&x141, &x142, x140, x132, x129);
+  x143 = (x142 + x130);
+  fiat_p256_addcarryx_u64(&x144, &x145, 0x0, x120, x135);
+  fiat_p256_addcarryx_u64(&x146, &x147, x145, x122, x137);
+  fiat_p256_addcarryx_u64(&x148, &x149, x147, x124, x139);
+  fiat_p256_addcarryx_u64(&x150, &x151, x149, x126, x141);
+  fiat_p256_addcarryx_u64(&x152, &x153, x151, x128, x143);
+  fiat_p256_mulx_u64(&x154, &x155, x144, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x156, &x157, x144, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x158, &x159, x144, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x160, &x161, 0x0, x159, x156);
+  x162 = (x161 + x157);
+  fiat_p256_addcarryx_u64(&x163, &x164, 0x0, x144, x158);
+  fiat_p256_addcarryx_u64(&x165, &x166, x164, x146, x160);
+  fiat_p256_addcarryx_u64(&x167, &x168, x166, x148, x162);
+  fiat_p256_addcarryx_u64(&x169, &x170, x168, x150, x154);
+  fiat_p256_addcarryx_u64(&x171, &x172, x170, x152, x155);
+  x173 = ((uint64_t)x172 + x153);
+  fiat_p256_subborrowx_u64(&x174, &x175, 0x0, x165, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x176, &x177, x175, x167, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x178, &x179, x177, x169, 0x0);
+  fiat_p256_subborrowx_u64(&x180, &x181, x179, x171, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x182, &x183, x181, x173, 0x0);
+  fiat_p256_cmovznz_u64(&x184, x183, x174, x165);
+  fiat_p256_cmovznz_u64(&x185, x183, x176, x167);
+  fiat_p256_cmovznz_u64(&x186, x183, x178, x169);
+  fiat_p256_cmovznz_u64(&x187, x183, x180, x171);
+  out1[0] = x184;
+  out1[1] = x185;
+  out1[2] = x186;
+  out1[3] = x187;
+}
+
+/*
+ * The function fiat_p256_add adds two field elements in the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ *   0 ≤ eval arg2 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) {
+  uint64_t x1;
+  fiat_p256_uint1 x2;
+  uint64_t x3;
+  fiat_p256_uint1 x4;
+  uint64_t x5;
+  fiat_p256_uint1 x6;
+  uint64_t x7;
+  fiat_p256_uint1 x8;
+  uint64_t x9;
+  fiat_p256_uint1 x10;
+  uint64_t x11;
+  fiat_p256_uint1 x12;
+  uint64_t x13;
+  fiat_p256_uint1 x14;
+  uint64_t x15;
+  fiat_p256_uint1 x16;
+  uint64_t x17;
+  fiat_p256_uint1 x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+  fiat_p256_addcarryx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+  fiat_p256_addcarryx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+  fiat_p256_addcarryx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+  fiat_p256_subborrowx_u64(&x9, &x10, 0x0, x1, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x11, &x12, x10, x3, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x13, &x14, x12, x5, 0x0);
+  fiat_p256_subborrowx_u64(&x15, &x16, x14, x7, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x17, &x18, x16, x8, 0x0);
+  fiat_p256_cmovznz_u64(&x19, x18, x9, x1);
+  fiat_p256_cmovznz_u64(&x20, x18, x11, x3);
+  fiat_p256_cmovznz_u64(&x21, x18, x13, x5);
+  fiat_p256_cmovznz_u64(&x22, x18, x15, x7);
+  out1[0] = x19;
+  out1[1] = x20;
+  out1[2] = x21;
+  out1[3] = x22;
+}
+
+/*
+ * The function fiat_p256_sub subtracts two field elements in the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ *   0 ≤ eval arg2 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_sub(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) {
+  uint64_t x1;
+  fiat_p256_uint1 x2;
+  uint64_t x3;
+  fiat_p256_uint1 x4;
+  uint64_t x5;
+  fiat_p256_uint1 x6;
+  uint64_t x7;
+  fiat_p256_uint1 x8;
+  uint64_t x9;
+  uint64_t x10;
+  fiat_p256_uint1 x11;
+  uint64_t x12;
+  fiat_p256_uint1 x13;
+  uint64_t x14;
+  fiat_p256_uint1 x15;
+  uint64_t x16;
+  fiat_p256_uint1 x17;
+  fiat_p256_subborrowx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+  fiat_p256_subborrowx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+  fiat_p256_subborrowx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+  fiat_p256_subborrowx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+  fiat_p256_cmovznz_u64(&x9, x8, 0x0, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x10, &x11, 0x0, x1, x9);
+  fiat_p256_addcarryx_u64(&x12, &x13, x11, x3, (x9 & UINT32_C(0xffffffff)));
+  fiat_p256_addcarryx_u64(&x14, &x15, x13, x5, 0x0);
+  fiat_p256_addcarryx_u64(&x16, &x17, x15, x7, (x9 & UINT64_C(0xffffffff00000001)));
+  out1[0] = x10;
+  out1[1] = x12;
+  out1[2] = x14;
+  out1[3] = x16;
+}
+
+/*
+ * The function fiat_p256_opp negates a field element in the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_opp(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1) {
+  uint64_t x1;
+  fiat_p256_uint1 x2;
+  uint64_t x3;
+  fiat_p256_uint1 x4;
+  uint64_t x5;
+  fiat_p256_uint1 x6;
+  uint64_t x7;
+  fiat_p256_uint1 x8;
+  uint64_t x9;
+  uint64_t x10;
+  fiat_p256_uint1 x11;
+  uint64_t x12;
+  fiat_p256_uint1 x13;
+  uint64_t x14;
+  fiat_p256_uint1 x15;
+  uint64_t x16;
+  fiat_p256_uint1 x17;
+  fiat_p256_subborrowx_u64(&x1, &x2, 0x0, 0x0, (arg1[0]));
+  fiat_p256_subborrowx_u64(&x3, &x4, x2, 0x0, (arg1[1]));
+  fiat_p256_subborrowx_u64(&x5, &x6, x4, 0x0, (arg1[2]));
+  fiat_p256_subborrowx_u64(&x7, &x8, x6, 0x0, (arg1[3]));
+  fiat_p256_cmovznz_u64(&x9, x8, 0x0, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x10, &x11, 0x0, x1, x9);
+  fiat_p256_addcarryx_u64(&x12, &x13, x11, x3, (x9 & UINT32_C(0xffffffff)));
+  fiat_p256_addcarryx_u64(&x14, &x15, x13, x5, 0x0);
+  fiat_p256_addcarryx_u64(&x16, &x17, x15, x7, (x9 & UINT64_C(0xffffffff00000001)));
+  out1[0] = x10;
+  out1[1] = x12;
+  out1[2] = x14;
+  out1[3] = x16;
+}
+
+/*
+ * The function fiat_p256_from_montgomery translates a field element out of the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_from_montgomery(fiat_p256_non_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  fiat_p256_uint1 x9;
+  uint64_t x10;
+  fiat_p256_uint1 x11;
+  uint64_t x12;
+  fiat_p256_uint1 x13;
+  uint64_t x14;
+  fiat_p256_uint1 x15;
+  uint64_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  fiat_p256_uint1 x23;
+  uint64_t x24;
+  fiat_p256_uint1 x25;
+  uint64_t x26;
+  fiat_p256_uint1 x27;
+  uint64_t x28;
+  fiat_p256_uint1 x29;
+  uint64_t x30;
+  fiat_p256_uint1 x31;
+  uint64_t x32;
+  fiat_p256_uint1 x33;
+  uint64_t x34;
+  fiat_p256_uint1 x35;
+  uint64_t x36;
+  fiat_p256_uint1 x37;
+  uint64_t x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  fiat_p256_uint1 x45;
+  uint64_t x46;
+  fiat_p256_uint1 x47;
+  uint64_t x48;
+  fiat_p256_uint1 x49;
+  uint64_t x50;
+  fiat_p256_uint1 x51;
+  uint64_t x52;
+  fiat_p256_uint1 x53;
+  uint64_t x54;
+  fiat_p256_uint1 x55;
+  uint64_t x56;
+  fiat_p256_uint1 x57;
+  uint64_t x58;
+  fiat_p256_uint1 x59;
+  uint64_t x60;
+  uint64_t x61;
+  uint64_t x62;
+  uint64_t x63;
+  uint64_t x64;
+  uint64_t x65;
+  uint64_t x66;
+  fiat_p256_uint1 x67;
+  uint64_t x68;
+  fiat_p256_uint1 x69;
+  uint64_t x70;
+  fiat_p256_uint1 x71;
+  uint64_t x72;
+  fiat_p256_uint1 x73;
+  uint64_t x74;
+  fiat_p256_uint1 x75;
+  uint64_t x76;
+  uint64_t x77;
+  fiat_p256_uint1 x78;
+  uint64_t x79;
+  fiat_p256_uint1 x80;
+  uint64_t x81;
+  fiat_p256_uint1 x82;
+  uint64_t x83;
+  fiat_p256_uint1 x84;
+  uint64_t x85;
+  fiat_p256_uint1 x86;
+  uint64_t x87;
+  uint64_t x88;
+  uint64_t x89;
+  uint64_t x90;
+  x1 = (arg1[0]);
+  fiat_p256_mulx_u64(&x2, &x3, x1, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x4, &x5, x1, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x6, &x7, x1, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x8, &x9, 0x0, x7, x4);
+  fiat_p256_addcarryx_u64(&x10, &x11, 0x0, x1, x6);
+  fiat_p256_addcarryx_u64(&x12, &x13, x11, 0x0, x8);
+  fiat_p256_addcarryx_u64(&x14, &x15, 0x0, x12, (arg1[1]));
+  fiat_p256_mulx_u64(&x16, &x17, x14, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x18, &x19, x14, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x20, &x21, x14, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x22, &x23, 0x0, x21, x18);
+  fiat_p256_addcarryx_u64(&x24, &x25, 0x0, x14, x20);
+  fiat_p256_addcarryx_u64(&x26, &x27, x25, (x15 + (x13 + (x9 + x5))), x22);
+  fiat_p256_addcarryx_u64(&x28, &x29, x27, x2, (x23 + x19));
+  fiat_p256_addcarryx_u64(&x30, &x31, x29, x3, x16);
+  fiat_p256_addcarryx_u64(&x32, &x33, 0x0, x26, (arg1[2]));
+  fiat_p256_addcarryx_u64(&x34, &x35, x33, x28, 0x0);
+  fiat_p256_addcarryx_u64(&x36, &x37, x35, x30, 0x0);
+  fiat_p256_mulx_u64(&x38, &x39, x32, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x40, &x41, x32, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x42, &x43, x32, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x44, &x45, 0x0, x43, x40);
+  fiat_p256_addcarryx_u64(&x46, &x47, 0x0, x32, x42);
+  fiat_p256_addcarryx_u64(&x48, &x49, x47, x34, x44);
+  fiat_p256_addcarryx_u64(&x50, &x51, x49, x36, (x45 + x41));
+  fiat_p256_addcarryx_u64(&x52, &x53, x51, (x37 + (x31 + x17)), x38);
+  fiat_p256_addcarryx_u64(&x54, &x55, 0x0, x48, (arg1[3]));
+  fiat_p256_addcarryx_u64(&x56, &x57, x55, x50, 0x0);
+  fiat_p256_addcarryx_u64(&x58, &x59, x57, x52, 0x0);
+  fiat_p256_mulx_u64(&x60, &x61, x54, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x62, &x63, x54, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x64, &x65, x54, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x66, &x67, 0x0, x65, x62);
+  fiat_p256_addcarryx_u64(&x68, &x69, 0x0, x54, x64);
+  fiat_p256_addcarryx_u64(&x70, &x71, x69, x56, x66);
+  fiat_p256_addcarryx_u64(&x72, &x73, x71, x58, (x67 + x63));
+  fiat_p256_addcarryx_u64(&x74, &x75, x73, (x59 + (x53 + x39)), x60);
+  x76 = (x75 + x61);
+  fiat_p256_subborrowx_u64(&x77, &x78, 0x0, x70, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x79, &x80, x78, x72, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x81, &x82, x80, x74, 0x0);
+  fiat_p256_subborrowx_u64(&x83, &x84, x82, x76, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x85, &x86, x84, 0x0, 0x0);
+  fiat_p256_cmovznz_u64(&x87, x86, x77, x70);
+  fiat_p256_cmovznz_u64(&x88, x86, x79, x72);
+  fiat_p256_cmovznz_u64(&x89, x86, x81, x74);
+  fiat_p256_cmovznz_u64(&x90, x86, x83, x76);
+  out1[0] = x87;
+  out1[1] = x88;
+  out1[2] = x89;
+  out1[3] = x90;
+}
+
+/*
+ * The function fiat_p256_to_montgomery translates a field element into the Montgomery domain.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = eval arg1 mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_to_montgomery(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_non_montgomery_domain_field_element arg1) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  fiat_p256_uint1 x14;
+  uint64_t x15;
+  fiat_p256_uint1 x16;
+  uint64_t x17;
+  fiat_p256_uint1 x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  fiat_p256_uint1 x26;
+  uint64_t x27;
+  fiat_p256_uint1 x28;
+  uint64_t x29;
+  fiat_p256_uint1 x30;
+  uint64_t x31;
+  fiat_p256_uint1 x32;
+  uint64_t x33;
+  fiat_p256_uint1 x34;
+  uint64_t x35;
+  fiat_p256_uint1 x36;
+  uint64_t x37;
+  uint64_t x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  fiat_p256_uint1 x46;
+  uint64_t x47;
+  fiat_p256_uint1 x48;
+  uint64_t x49;
+  fiat_p256_uint1 x50;
+  uint64_t x51;
+  fiat_p256_uint1 x52;
+  uint64_t x53;
+  fiat_p256_uint1 x54;
+  uint64_t x55;
+  fiat_p256_uint1 x56;
+  uint64_t x57;
+  fiat_p256_uint1 x58;
+  uint64_t x59;
+  uint64_t x60;
+  uint64_t x61;
+  uint64_t x62;
+  uint64_t x63;
+  uint64_t x64;
+  uint64_t x65;
+  fiat_p256_uint1 x66;
+  uint64_t x67;
+  fiat_p256_uint1 x68;
+  uint64_t x69;
+  fiat_p256_uint1 x70;
+  uint64_t x71;
+  fiat_p256_uint1 x72;
+  uint64_t x73;
+  fiat_p256_uint1 x74;
+  uint64_t x75;
+  fiat_p256_uint1 x76;
+  uint64_t x77;
+  uint64_t x78;
+  uint64_t x79;
+  uint64_t x80;
+  uint64_t x81;
+  uint64_t x82;
+  uint64_t x83;
+  uint64_t x84;
+  uint64_t x85;
+  fiat_p256_uint1 x86;
+  uint64_t x87;
+  fiat_p256_uint1 x88;
+  uint64_t x89;
+  fiat_p256_uint1 x90;
+  uint64_t x91;
+  fiat_p256_uint1 x92;
+  uint64_t x93;
+  fiat_p256_uint1 x94;
+  uint64_t x95;
+  fiat_p256_uint1 x96;
+  uint64_t x97;
+  fiat_p256_uint1 x98;
+  uint64_t x99;
+  uint64_t x100;
+  uint64_t x101;
+  uint64_t x102;
+  uint64_t x103;
+  uint64_t x104;
+  uint64_t x105;
+  fiat_p256_uint1 x106;
+  uint64_t x107;
+  fiat_p256_uint1 x108;
+  uint64_t x109;
+  fiat_p256_uint1 x110;
+  uint64_t x111;
+  fiat_p256_uint1 x112;
+  uint64_t x113;
+  fiat_p256_uint1 x114;
+  uint64_t x115;
+  fiat_p256_uint1 x116;
+  uint64_t x117;
+  uint64_t x118;
+  uint64_t x119;
+  uint64_t x120;
+  uint64_t x121;
+  uint64_t x122;
+  uint64_t x123;
+  uint64_t x124;
+  uint64_t x125;
+  fiat_p256_uint1 x126;
+  uint64_t x127;
+  fiat_p256_uint1 x128;
+  uint64_t x129;
+  fiat_p256_uint1 x130;
+  uint64_t x131;
+  fiat_p256_uint1 x132;
+  uint64_t x133;
+  fiat_p256_uint1 x134;
+  uint64_t x135;
+  fiat_p256_uint1 x136;
+  uint64_t x137;
+  fiat_p256_uint1 x138;
+  uint64_t x139;
+  uint64_t x140;
+  uint64_t x141;
+  uint64_t x142;
+  uint64_t x143;
+  uint64_t x144;
+  uint64_t x145;
+  fiat_p256_uint1 x146;
+  uint64_t x147;
+  fiat_p256_uint1 x148;
+  uint64_t x149;
+  fiat_p256_uint1 x150;
+  uint64_t x151;
+  fiat_p256_uint1 x152;
+  uint64_t x153;
+  fiat_p256_uint1 x154;
+  uint64_t x155;
+  fiat_p256_uint1 x156;
+  uint64_t x157;
+  fiat_p256_uint1 x158;
+  uint64_t x159;
+  fiat_p256_uint1 x160;
+  uint64_t x161;
+  fiat_p256_uint1 x162;
+  uint64_t x163;
+  fiat_p256_uint1 x164;
+  uint64_t x165;
+  fiat_p256_uint1 x166;
+  uint64_t x167;
+  uint64_t x168;
+  uint64_t x169;
+  uint64_t x170;
+  x1 = (arg1[1]);
+  x2 = (arg1[2]);
+  x3 = (arg1[3]);
+  x4 = (arg1[0]);
+  fiat_p256_mulx_u64(&x5, &x6, x4, UINT64_C(0x4fffffffd));
+  fiat_p256_mulx_u64(&x7, &x8, x4, UINT64_C(0xfffffffffffffffe));
+  fiat_p256_mulx_u64(&x9, &x10, x4, UINT64_C(0xfffffffbffffffff));
+  fiat_p256_mulx_u64(&x11, &x12, x4, 0x3);
+  fiat_p256_addcarryx_u64(&x13, &x14, 0x0, x12, x9);
+  fiat_p256_addcarryx_u64(&x15, &x16, x14, x10, x7);
+  fiat_p256_addcarryx_u64(&x17, &x18, x16, x8, x5);
+  fiat_p256_mulx_u64(&x19, &x20, x11, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x21, &x22, x11, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x23, &x24, x11, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x25, &x26, 0x0, x24, x21);
+  fiat_p256_addcarryx_u64(&x27, &x28, 0x0, x11, x23);
+  fiat_p256_addcarryx_u64(&x29, &x30, x28, x13, x25);
+  fiat_p256_addcarryx_u64(&x31, &x32, x30, x15, (x26 + x22));
+  fiat_p256_addcarryx_u64(&x33, &x34, x32, x17, x19);
+  fiat_p256_addcarryx_u64(&x35, &x36, x34, (x18 + x6), x20);
+  fiat_p256_mulx_u64(&x37, &x38, x1, UINT64_C(0x4fffffffd));
+  fiat_p256_mulx_u64(&x39, &x40, x1, UINT64_C(0xfffffffffffffffe));
+  fiat_p256_mulx_u64(&x41, &x42, x1, UINT64_C(0xfffffffbffffffff));
+  fiat_p256_mulx_u64(&x43, &x44, x1, 0x3);
+  fiat_p256_addcarryx_u64(&x45, &x46, 0x0, x44, x41);
+  fiat_p256_addcarryx_u64(&x47, &x48, x46, x42, x39);
+  fiat_p256_addcarryx_u64(&x49, &x50, x48, x40, x37);
+  fiat_p256_addcarryx_u64(&x51, &x52, 0x0, x29, x43);
+  fiat_p256_addcarryx_u64(&x53, &x54, x52, x31, x45);
+  fiat_p256_addcarryx_u64(&x55, &x56, x54, x33, x47);
+  fiat_p256_addcarryx_u64(&x57, &x58, x56, x35, x49);
+  fiat_p256_mulx_u64(&x59, &x60, x51, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x61, &x62, x51, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x63, &x64, x51, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x65, &x66, 0x0, x64, x61);
+  fiat_p256_addcarryx_u64(&x67, &x68, 0x0, x51, x63);
+  fiat_p256_addcarryx_u64(&x69, &x70, x68, x53, x65);
+  fiat_p256_addcarryx_u64(&x71, &x72, x70, x55, (x66 + x62));
+  fiat_p256_addcarryx_u64(&x73, &x74, x72, x57, x59);
+  fiat_p256_addcarryx_u64(&x75, &x76, x74, (((uint64_t)x58 + x36) + (x50 + x38)), x60);
+  fiat_p256_mulx_u64(&x77, &x78, x2, UINT64_C(0x4fffffffd));
+  fiat_p256_mulx_u64(&x79, &x80, x2, UINT64_C(0xfffffffffffffffe));
+  fiat_p256_mulx_u64(&x81, &x82, x2, UINT64_C(0xfffffffbffffffff));
+  fiat_p256_mulx_u64(&x83, &x84, x2, 0x3);
+  fiat_p256_addcarryx_u64(&x85, &x86, 0x0, x84, x81);
+  fiat_p256_addcarryx_u64(&x87, &x88, x86, x82, x79);
+  fiat_p256_addcarryx_u64(&x89, &x90, x88, x80, x77);
+  fiat_p256_addcarryx_u64(&x91, &x92, 0x0, x69, x83);
+  fiat_p256_addcarryx_u64(&x93, &x94, x92, x71, x85);
+  fiat_p256_addcarryx_u64(&x95, &x96, x94, x73, x87);
+  fiat_p256_addcarryx_u64(&x97, &x98, x96, x75, x89);
+  fiat_p256_mulx_u64(&x99, &x100, x91, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x101, &x102, x91, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x103, &x104, x91, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x105, &x106, 0x0, x104, x101);
+  fiat_p256_addcarryx_u64(&x107, &x108, 0x0, x91, x103);
+  fiat_p256_addcarryx_u64(&x109, &x110, x108, x93, x105);
+  fiat_p256_addcarryx_u64(&x111, &x112, x110, x95, (x106 + x102));
+  fiat_p256_addcarryx_u64(&x113, &x114, x112, x97, x99);
+  fiat_p256_addcarryx_u64(&x115, &x116, x114, (((uint64_t)x98 + x76) + (x90 + x78)), x100);
+  fiat_p256_mulx_u64(&x117, &x118, x3, UINT64_C(0x4fffffffd));
+  fiat_p256_mulx_u64(&x119, &x120, x3, UINT64_C(0xfffffffffffffffe));
+  fiat_p256_mulx_u64(&x121, &x122, x3, UINT64_C(0xfffffffbffffffff));
+  fiat_p256_mulx_u64(&x123, &x124, x3, 0x3);
+  fiat_p256_addcarryx_u64(&x125, &x126, 0x0, x124, x121);
+  fiat_p256_addcarryx_u64(&x127, &x128, x126, x122, x119);
+  fiat_p256_addcarryx_u64(&x129, &x130, x128, x120, x117);
+  fiat_p256_addcarryx_u64(&x131, &x132, 0x0, x109, x123);
+  fiat_p256_addcarryx_u64(&x133, &x134, x132, x111, x125);
+  fiat_p256_addcarryx_u64(&x135, &x136, x134, x113, x127);
+  fiat_p256_addcarryx_u64(&x137, &x138, x136, x115, x129);
+  fiat_p256_mulx_u64(&x139, &x140, x131, UINT64_C(0xffffffff00000001));
+  fiat_p256_mulx_u64(&x141, &x142, x131, UINT32_C(0xffffffff));
+  fiat_p256_mulx_u64(&x143, &x144, x131, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x145, &x146, 0x0, x144, x141);
+  fiat_p256_addcarryx_u64(&x147, &x148, 0x0, x131, x143);
+  fiat_p256_addcarryx_u64(&x149, &x150, x148, x133, x145);
+  fiat_p256_addcarryx_u64(&x151, &x152, x150, x135, (x146 + x142));
+  fiat_p256_addcarryx_u64(&x153, &x154, x152, x137, x139);
+  fiat_p256_addcarryx_u64(&x155, &x156, x154, (((uint64_t)x138 + x116) + (x130 + x118)), x140);
+  fiat_p256_subborrowx_u64(&x157, &x158, 0x0, x149, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x159, &x160, x158, x151, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x161, &x162, x160, x153, 0x0);
+  fiat_p256_subborrowx_u64(&x163, &x164, x162, x155, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x165, &x166, x164, x156, 0x0);
+  fiat_p256_cmovznz_u64(&x167, x166, x157, x149);
+  fiat_p256_cmovznz_u64(&x168, x166, x159, x151);
+  fiat_p256_cmovznz_u64(&x169, x166, x161, x153);
+  fiat_p256_cmovznz_u64(&x170, x166, x163, x155);
+  out1[0] = x167;
+  out1[1] = x168;
+  out1[2] = x169;
+  out1[3] = x170;
+}
+
+/*
+ * The function fiat_p256_nonzero outputs a single non-zero word if the input is non-zero and zero otherwise.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0
+ *
+ * Input Bounds:
+ *   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_nonzero(uint64_t* out1, const uint64_t arg1[4]) {
+  uint64_t x1;
+  x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
+  *out1 = x1;
+}
+
+/*
+ * The function fiat_p256_selectznz is a multi-limb conditional select.
+ *
+ * Postconditions:
+ *   out1 = (if arg1 = 0 then arg2 else arg3)
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0x1]
+ *   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_selectznz(uint64_t out1[4], fiat_p256_uint1 arg1, const uint64_t arg2[4], const uint64_t arg3[4]) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  fiat_p256_cmovznz_u64(&x1, arg1, (arg2[0]), (arg3[0]));
+  fiat_p256_cmovznz_u64(&x2, arg1, (arg2[1]), (arg3[1]));
+  fiat_p256_cmovznz_u64(&x3, arg1, (arg2[2]), (arg3[2]));
+  fiat_p256_cmovznz_u64(&x4, arg1, (arg2[3]), (arg3[3]));
+  out1[0] = x1;
+  out1[1] = x2;
+  out1[2] = x3;
+  out1[3] = x4;
+}
+
+/*
+ * The function fiat_p256_to_bytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg1 < m
+ * Postconditions:
+ *   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
+ *
+ * Input Bounds:
+ *   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_to_bytes(uint8_t out1[32], const uint64_t arg1[4]) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint8_t x5;
+  uint64_t x6;
+  uint8_t x7;
+  uint64_t x8;
+  uint8_t x9;
+  uint64_t x10;
+  uint8_t x11;
+  uint64_t x12;
+  uint8_t x13;
+  uint64_t x14;
+  uint8_t x15;
+  uint64_t x16;
+  uint8_t x17;
+  uint8_t x18;
+  uint8_t x19;
+  uint64_t x20;
+  uint8_t x21;
+  uint64_t x22;
+  uint8_t x23;
+  uint64_t x24;
+  uint8_t x25;
+  uint64_t x26;
+  uint8_t x27;
+  uint64_t x28;
+  uint8_t x29;
+  uint64_t x30;
+  uint8_t x31;
+  uint8_t x32;
+  uint8_t x33;
+  uint64_t x34;
+  uint8_t x35;
+  uint64_t x36;
+  uint8_t x37;
+  uint64_t x38;
+  uint8_t x39;
+  uint64_t x40;
+  uint8_t x41;
+  uint64_t x42;
+  uint8_t x43;
+  uint64_t x44;
+  uint8_t x45;
+  uint8_t x46;
+  uint8_t x47;
+  uint64_t x48;
+  uint8_t x49;
+  uint64_t x50;
+  uint8_t x51;
+  uint64_t x52;
+  uint8_t x53;
+  uint64_t x54;
+  uint8_t x55;
+  uint64_t x56;
+  uint8_t x57;
+  uint64_t x58;
+  uint8_t x59;
+  uint8_t x60;
+  x1 = (arg1[3]);
+  x2 = (arg1[2]);
+  x3 = (arg1[1]);
+  x4 = (arg1[0]);
+  x5 = (uint8_t)(x4 & UINT8_C(0xff));
+  x6 = (x4 >> 8);
+  x7 = (uint8_t)(x6 & UINT8_C(0xff));
+  x8 = (x6 >> 8);
+  x9 = (uint8_t)(x8 & UINT8_C(0xff));
+  x10 = (x8 >> 8);
+  x11 = (uint8_t)(x10 & UINT8_C(0xff));
+  x12 = (x10 >> 8);
+  x13 = (uint8_t)(x12 & UINT8_C(0xff));
+  x14 = (x12 >> 8);
+  x15 = (uint8_t)(x14 & UINT8_C(0xff));
+  x16 = (x14 >> 8);
+  x17 = (uint8_t)(x16 & UINT8_C(0xff));
+  x18 = (uint8_t)(x16 >> 8);
+  x19 = (uint8_t)(x3 & UINT8_C(0xff));
+  x20 = (x3 >> 8);
+  x21 = (uint8_t)(x20 & UINT8_C(0xff));
+  x22 = (x20 >> 8);
+  x23 = (uint8_t)(x22 & UINT8_C(0xff));
+  x24 = (x22 >> 8);
+  x25 = (uint8_t)(x24 & UINT8_C(0xff));
+  x26 = (x24 >> 8);
+  x27 = (uint8_t)(x26 & UINT8_C(0xff));
+  x28 = (x26 >> 8);
+  x29 = (uint8_t)(x28 & UINT8_C(0xff));
+  x30 = (x28 >> 8);
+  x31 = (uint8_t)(x30 & UINT8_C(0xff));
+  x32 = (uint8_t)(x30 >> 8);
+  x33 = (uint8_t)(x2 & UINT8_C(0xff));
+  x34 = (x2 >> 8);
+  x35 = (uint8_t)(x34 & UINT8_C(0xff));
+  x36 = (x34 >> 8);
+  x37 = (uint8_t)(x36 & UINT8_C(0xff));
+  x38 = (x36 >> 8);
+  x39 = (uint8_t)(x38 & UINT8_C(0xff));
+  x40 = (x38 >> 8);
+  x41 = (uint8_t)(x40 & UINT8_C(0xff));
+  x42 = (x40 >> 8);
+  x43 = (uint8_t)(x42 & UINT8_C(0xff));
+  x44 = (x42 >> 8);
+  x45 = (uint8_t)(x44 & UINT8_C(0xff));
+  x46 = (uint8_t)(x44 >> 8);
+  x47 = (uint8_t)(x1 & UINT8_C(0xff));
+  x48 = (x1 >> 8);
+  x49 = (uint8_t)(x48 & UINT8_C(0xff));
+  x50 = (x48 >> 8);
+  x51 = (uint8_t)(x50 & UINT8_C(0xff));
+  x52 = (x50 >> 8);
+  x53 = (uint8_t)(x52 & UINT8_C(0xff));
+  x54 = (x52 >> 8);
+  x55 = (uint8_t)(x54 & UINT8_C(0xff));
+  x56 = (x54 >> 8);
+  x57 = (uint8_t)(x56 & UINT8_C(0xff));
+  x58 = (x56 >> 8);
+  x59 = (uint8_t)(x58 & UINT8_C(0xff));
+  x60 = (uint8_t)(x58 >> 8);
+  out1[0] = x5;
+  out1[1] = x7;
+  out1[2] = x9;
+  out1[3] = x11;
+  out1[4] = x13;
+  out1[5] = x15;
+  out1[6] = x17;
+  out1[7] = x18;
+  out1[8] = x19;
+  out1[9] = x21;
+  out1[10] = x23;
+  out1[11] = x25;
+  out1[12] = x27;
+  out1[13] = x29;
+  out1[14] = x31;
+  out1[15] = x32;
+  out1[16] = x33;
+  out1[17] = x35;
+  out1[18] = x37;
+  out1[19] = x39;
+  out1[20] = x41;
+  out1[21] = x43;
+  out1[22] = x45;
+  out1[23] = x46;
+  out1[24] = x47;
+  out1[25] = x49;
+  out1[26] = x51;
+  out1[27] = x53;
+  out1[28] = x55;
+  out1[29] = x57;
+  out1[30] = x59;
+  out1[31] = x60;
+}
+
+/*
+ * The function fiat_p256_from_bytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+ *
+ * Preconditions:
+ *   0 ≤ bytes_eval arg1 < m
+ * Postconditions:
+ *   eval out1 mod m = bytes_eval arg1 mod m
+ *   0 ≤ eval out1 < m
+ *
+ * Input Bounds:
+ *   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_from_bytes(uint64_t out1[4], const uint8_t arg1[32]) {
+  uint64_t x1;
+  uint64_t x2;
+  uint64_t x3;
+  uint64_t x4;
+  uint64_t x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint8_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  uint64_t x13;
+  uint64_t x14;
+  uint64_t x15;
+  uint8_t x16;
+  uint64_t x17;
+  uint64_t x18;
+  uint64_t x19;
+  uint64_t x20;
+  uint64_t x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint8_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  uint64_t x29;
+  uint64_t x30;
+  uint64_t x31;
+  uint8_t x32;
+  uint64_t x33;
+  uint64_t x34;
+  uint64_t x35;
+  uint64_t x36;
+  uint64_t x37;
+  uint64_t x38;
+  uint64_t x39;
+  uint64_t x40;
+  uint64_t x41;
+  uint64_t x42;
+  uint64_t x43;
+  uint64_t x44;
+  uint64_t x45;
+  uint64_t x46;
+  uint64_t x47;
+  uint64_t x48;
+  uint64_t x49;
+  uint64_t x50;
+  uint64_t x51;
+  uint64_t x52;
+  uint64_t x53;
+  uint64_t x54;
+  uint64_t x55;
+  uint64_t x56;
+  uint64_t x57;
+  uint64_t x58;
+  uint64_t x59;
+  uint64_t x60;
+  x1 = ((uint64_t)(arg1[31]) << 56);
+  x2 = ((uint64_t)(arg1[30]) << 48);
+  x3 = ((uint64_t)(arg1[29]) << 40);
+  x4 = ((uint64_t)(arg1[28]) << 32);
+  x5 = ((uint64_t)(arg1[27]) << 24);
+  x6 = ((uint64_t)(arg1[26]) << 16);
+  x7 = ((uint64_t)(arg1[25]) << 8);
+  x8 = (arg1[24]);
+  x9 = ((uint64_t)(arg1[23]) << 56);
+  x10 = ((uint64_t)(arg1[22]) << 48);
+  x11 = ((uint64_t)(arg1[21]) << 40);
+  x12 = ((uint64_t)(arg1[20]) << 32);
+  x13 = ((uint64_t)(arg1[19]) << 24);
+  x14 = ((uint64_t)(arg1[18]) << 16);
+  x15 = ((uint64_t)(arg1[17]) << 8);
+  x16 = (arg1[16]);
+  x17 = ((uint64_t)(arg1[15]) << 56);
+  x18 = ((uint64_t)(arg1[14]) << 48);
+  x19 = ((uint64_t)(arg1[13]) << 40);
+  x20 = ((uint64_t)(arg1[12]) << 32);
+  x21 = ((uint64_t)(arg1[11]) << 24);
+  x22 = ((uint64_t)(arg1[10]) << 16);
+  x23 = ((uint64_t)(arg1[9]) << 8);
+  x24 = (arg1[8]);
+  x25 = ((uint64_t)(arg1[7]) << 56);
+  x26 = ((uint64_t)(arg1[6]) << 48);
+  x27 = ((uint64_t)(arg1[5]) << 40);
+  x28 = ((uint64_t)(arg1[4]) << 32);
+  x29 = ((uint64_t)(arg1[3]) << 24);
+  x30 = ((uint64_t)(arg1[2]) << 16);
+  x31 = ((uint64_t)(arg1[1]) << 8);
+  x32 = (arg1[0]);
+  x33 = (x31 + (uint64_t)x32);
+  x34 = (x30 + x33);
+  x35 = (x29 + x34);
+  x36 = (x28 + x35);
+  x37 = (x27 + x36);
+  x38 = (x26 + x37);
+  x39 = (x25 + x38);
+  x40 = (x23 + (uint64_t)x24);
+  x41 = (x22 + x40);
+  x42 = (x21 + x41);
+  x43 = (x20 + x42);
+  x44 = (x19 + x43);
+  x45 = (x18 + x44);
+  x46 = (x17 + x45);
+  x47 = (x15 + (uint64_t)x16);
+  x48 = (x14 + x47);
+  x49 = (x13 + x48);
+  x50 = (x12 + x49);
+  x51 = (x11 + x50);
+  x52 = (x10 + x51);
+  x53 = (x9 + x52);
+  x54 = (x7 + (uint64_t)x8);
+  x55 = (x6 + x54);
+  x56 = (x5 + x55);
+  x57 = (x4 + x56);
+  x58 = (x3 + x57);
+  x59 = (x2 + x58);
+  x60 = (x1 + x59);
+  out1[0] = x39;
+  out1[1] = x46;
+  out1[2] = x53;
+  out1[3] = x60;
+}
+
+/*
+ * The function fiat_p256_set_one returns the field element one in the Montgomery domain.
+ *
+ * Postconditions:
+ *   eval (from_montgomery out1) mod m = 1 mod m
+ *   0 ≤ eval out1 < m
+ *
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_set_one(fiat_p256_montgomery_domain_field_element out1) {
+  out1[0] = 0x1;
+  out1[1] = UINT64_C(0xffffffff00000000);
+  out1[2] = UINT64_C(0xffffffffffffffff);
+  out1[3] = UINT32_C(0xfffffffe);
+}
+
+/*
+ * The function fiat_p256_msat returns the saturated representation of the prime modulus.
+ *
+ * Postconditions:
+ *   twos_complement_eval out1 = m
+ *   0 ≤ eval out1 < m
+ *
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_msat(uint64_t out1[5]) {
+  out1[0] = UINT64_C(0xffffffffffffffff);
+  out1[1] = UINT32_C(0xffffffff);
+  out1[2] = 0x0;
+  out1[3] = UINT64_C(0xffffffff00000001);
+  out1[4] = 0x0;
+}
+
+/*
+ * The function fiat_p256_divstep computes a divstep.
+ *
+ * Preconditions:
+ *   0 ≤ eval arg4 < m
+ *   0 ≤ eval arg5 < m
+ * Postconditions:
+ *   out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1)
+ *   twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2)
+ *   twos_complement_eval out3 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then ⌊(twos_complement_eval arg3 - twos_complement_eval arg2) / 2⌋ else ⌊(twos_complement_eval arg3 + (twos_complement_eval arg3 mod 2) * twos_complement_eval arg2) / 2⌋)
+ *   eval (from_montgomery out4) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (2 * eval (from_montgomery arg5)) mod m else (2 * eval (from_montgomery arg4)) mod m)
+ *   eval (from_montgomery out5) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (eval (from_montgomery arg4) - eval (from_montgomery arg4)) mod m else (eval (from_montgomery arg5) + (twos_complement_eval arg3 mod 2) * eval (from_montgomery arg4)) mod m)
+ *   0 ≤ eval out5 < m
+ *   0 ≤ eval out5 < m
+ *   0 ≤ eval out2 < m
+ *   0 ≤ eval out3 < m
+ *
+ * Input Bounds:
+ *   arg1: [0x0 ~> 0xffffffffffffffff]
+ *   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ * Output Bounds:
+ *   out1: [0x0 ~> 0xffffffffffffffff]
+ *   out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ *   out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_divstep(uint64_t* out1, uint64_t out2[5], uint64_t out3[5], uint64_t out4[4], uint64_t out5[4], uint64_t arg1, const uint64_t arg2[5], const uint64_t arg3[5], const uint64_t arg4[4], const uint64_t arg5[4]) {
+  uint64_t x1;
+  fiat_p256_uint1 x2;
+  fiat_p256_uint1 x3;
+  uint64_t x4;
+  fiat_p256_uint1 x5;
+  uint64_t x6;
+  uint64_t x7;
+  uint64_t x8;
+  uint64_t x9;
+  uint64_t x10;
+  uint64_t x11;
+  uint64_t x12;
+  fiat_p256_uint1 x13;
+  uint64_t x14;
+  fiat_p256_uint1 x15;
+  uint64_t x16;
+  fiat_p256_uint1 x17;
+  uint64_t x18;
+  fiat_p256_uint1 x19;
+  uint64_t x20;
+  fiat_p256_uint1 x21;
+  uint64_t x22;
+  uint64_t x23;
+  uint64_t x24;
+  uint64_t x25;
+  uint64_t x26;
+  uint64_t x27;
+  uint64_t x28;
+  uint64_t x29;
+  uint64_t x30;
+  uint64_t x31;
+  fiat_p256_uint1 x32;
+  uint64_t x33;
+  fiat_p256_uint1 x34;
+  uint64_t x35;
+  fiat_p256_uint1 x36;
+  uint64_t x37;
+  fiat_p256_uint1 x38;
+  uint64_t x39;
+  fiat_p256_uint1 x40;
+  uint64_t x41;
+  fiat_p256_uint1 x42;
+  uint64_t x43;
+  fiat_p256_uint1 x44;
+  uint64_t x45;
+  fiat_p256_uint1 x46;
+  uint64_t x47;
+  fiat_p256_uint1 x48;
+  uint64_t x49;
+  uint64_t x50;
+  uint64_t x51;
+  uint64_t x52;
+  uint64_t x53;
+  fiat_p256_uint1 x54;
+  uint64_t x55;
+  fiat_p256_uint1 x56;
+  uint64_t x57;
+  fiat_p256_uint1 x58;
+  uint64_t x59;
+  fiat_p256_uint1 x60;
+  uint64_t x61;
+  uint64_t x62;
+  fiat_p256_uint1 x63;
+  uint64_t x64;
+  fiat_p256_uint1 x65;
+  uint64_t x66;
+  fiat_p256_uint1 x67;
+  uint64_t x68;
+  fiat_p256_uint1 x69;
+  uint64_t x70;
+  uint64_t x71;
+  uint64_t x72;
+  uint64_t x73;
+  fiat_p256_uint1 x74;
+  uint64_t x75;
+  uint64_t x76;
+  uint64_t x77;
+  uint64_t x78;
+  uint64_t x79;
+  uint64_t x80;
+  fiat_p256_uint1 x81;
+  uint64_t x82;
+  fiat_p256_uint1 x83;
+  uint64_t x84;
+  fiat_p256_uint1 x85;
+  uint64_t x86;
+  fiat_p256_uint1 x87;
+  uint64_t x88;
+  fiat_p256_uint1 x89;
+  uint64_t x90;
+  uint64_t x91;
+  uint64_t x92;
+  uint64_t x93;
+  uint64_t x94;
+  fiat_p256_uint1 x95;
+  uint64_t x96;
+  fiat_p256_uint1 x97;
+  uint64_t x98;
+  fiat_p256_uint1 x99;
+  uint64_t x100;
+  fiat_p256_uint1 x101;
+  uint64_t x102;
+  fiat_p256_uint1 x103;
+  uint64_t x104;
+  fiat_p256_uint1 x105;
+  uint64_t x106;
+  fiat_p256_uint1 x107;
+  uint64_t x108;
+  fiat_p256_uint1 x109;
+  uint64_t x110;
+  fiat_p256_uint1 x111;
+  uint64_t x112;
+  fiat_p256_uint1 x113;
+  uint64_t x114;
+  uint64_t x115;
+  uint64_t x116;
+  uint64_t x117;
+  uint64_t x118;
+  uint64_t x119;
+  uint64_t x120;
+  uint64_t x121;
+  uint64_t x122;
+  uint64_t x123;
+  uint64_t x124;
+  uint64_t x125;
+  uint64_t x126;
+  fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (~arg1), 0x1);
+  x3 = (fiat_p256_uint1)((fiat_p256_uint1)(x1 >> 63) & (fiat_p256_uint1)((arg3[0]) & 0x1));
+  fiat_p256_addcarryx_u64(&x4, &x5, 0x0, (~arg1), 0x1);
+  fiat_p256_cmovznz_u64(&x6, x3, arg1, x4);
+  fiat_p256_cmovznz_u64(&x7, x3, (arg2[0]), (arg3[0]));
+  fiat_p256_cmovznz_u64(&x8, x3, (arg2[1]), (arg3[1]));
+  fiat_p256_cmovznz_u64(&x9, x3, (arg2[2]), (arg3[2]));
+  fiat_p256_cmovznz_u64(&x10, x3, (arg2[3]), (arg3[3]));
+  fiat_p256_cmovznz_u64(&x11, x3, (arg2[4]), (arg3[4]));
+  fiat_p256_addcarryx_u64(&x12, &x13, 0x0, 0x1, (~(arg2[0])));
+  fiat_p256_addcarryx_u64(&x14, &x15, x13, 0x0, (~(arg2[1])));
+  fiat_p256_addcarryx_u64(&x16, &x17, x15, 0x0, (~(arg2[2])));
+  fiat_p256_addcarryx_u64(&x18, &x19, x17, 0x0, (~(arg2[3])));
+  fiat_p256_addcarryx_u64(&x20, &x21, x19, 0x0, (~(arg2[4])));
+  fiat_p256_cmovznz_u64(&x22, x3, (arg3[0]), x12);
+  fiat_p256_cmovznz_u64(&x23, x3, (arg3[1]), x14);
+  fiat_p256_cmovznz_u64(&x24, x3, (arg3[2]), x16);
+  fiat_p256_cmovznz_u64(&x25, x3, (arg3[3]), x18);
+  fiat_p256_cmovznz_u64(&x26, x3, (arg3[4]), x20);
+  fiat_p256_cmovznz_u64(&x27, x3, (arg4[0]), (arg5[0]));
+  fiat_p256_cmovznz_u64(&x28, x3, (arg4[1]), (arg5[1]));
+  fiat_p256_cmovznz_u64(&x29, x3, (arg4[2]), (arg5[2]));
+  fiat_p256_cmovznz_u64(&x30, x3, (arg4[3]), (arg5[3]));
+  fiat_p256_addcarryx_u64(&x31, &x32, 0x0, x27, x27);
+  fiat_p256_addcarryx_u64(&x33, &x34, x32, x28, x28);
+  fiat_p256_addcarryx_u64(&x35, &x36, x34, x29, x29);
+  fiat_p256_addcarryx_u64(&x37, &x38, x36, x30, x30);
+  fiat_p256_subborrowx_u64(&x39, &x40, 0x0, x31, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x41, &x42, x40, x33, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x43, &x44, x42, x35, 0x0);
+  fiat_p256_subborrowx_u64(&x45, &x46, x44, x37, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x47, &x48, x46, x38, 0x0);
+  x49 = (arg4[3]);
+  x50 = (arg4[2]);
+  x51 = (arg4[1]);
+  x52 = (arg4[0]);
+  fiat_p256_subborrowx_u64(&x53, &x54, 0x0, 0x0, x52);
+  fiat_p256_subborrowx_u64(&x55, &x56, x54, 0x0, x51);
+  fiat_p256_subborrowx_u64(&x57, &x58, x56, 0x0, x50);
+  fiat_p256_subborrowx_u64(&x59, &x60, x58, 0x0, x49);
+  fiat_p256_cmovznz_u64(&x61, x60, 0x0, UINT64_C(0xffffffffffffffff));
+  fiat_p256_addcarryx_u64(&x62, &x63, 0x0, x53, x61);
+  fiat_p256_addcarryx_u64(&x64, &x65, x63, x55, (x61 & UINT32_C(0xffffffff)));
+  fiat_p256_addcarryx_u64(&x66, &x67, x65, x57, 0x0);
+  fiat_p256_addcarryx_u64(&x68, &x69, x67, x59, (x61 & UINT64_C(0xffffffff00000001)));
+  fiat_p256_cmovznz_u64(&x70, x3, (arg5[0]), x62);
+  fiat_p256_cmovznz_u64(&x71, x3, (arg5[1]), x64);
+  fiat_p256_cmovznz_u64(&x72, x3, (arg5[2]), x66);
+  fiat_p256_cmovznz_u64(&x73, x3, (arg5[3]), x68);
+  x74 = (fiat_p256_uint1)(x22 & 0x1);
+  fiat_p256_cmovznz_u64(&x75, x74, 0x0, x7);
+  fiat_p256_cmovznz_u64(&x76, x74, 0x0, x8);
+  fiat_p256_cmovznz_u64(&x77, x74, 0x0, x9);
+  fiat_p256_cmovznz_u64(&x78, x74, 0x0, x10);
+  fiat_p256_cmovznz_u64(&x79, x74, 0x0, x11);
+  fiat_p256_addcarryx_u64(&x80, &x81, 0x0, x22, x75);
+  fiat_p256_addcarryx_u64(&x82, &x83, x81, x23, x76);
+  fiat_p256_addcarryx_u64(&x84, &x85, x83, x24, x77);
+  fiat_p256_addcarryx_u64(&x86, &x87, x85, x25, x78);
+  fiat_p256_addcarryx_u64(&x88, &x89, x87, x26, x79);
+  fiat_p256_cmovznz_u64(&x90, x74, 0x0, x27);
+  fiat_p256_cmovznz_u64(&x91, x74, 0x0, x28);
+  fiat_p256_cmovznz_u64(&x92, x74, 0x0, x29);
+  fiat_p256_cmovznz_u64(&x93, x74, 0x0, x30);
+  fiat_p256_addcarryx_u64(&x94, &x95, 0x0, x70, x90);
+  fiat_p256_addcarryx_u64(&x96, &x97, x95, x71, x91);
+  fiat_p256_addcarryx_u64(&x98, &x99, x97, x72, x92);
+  fiat_p256_addcarryx_u64(&x100, &x101, x99, x73, x93);
+  fiat_p256_subborrowx_u64(&x102, &x103, 0x0, x94, UINT64_C(0xffffffffffffffff));
+  fiat_p256_subborrowx_u64(&x104, &x105, x103, x96, UINT32_C(0xffffffff));
+  fiat_p256_subborrowx_u64(&x106, &x107, x105, x98, 0x0);
+  fiat_p256_subborrowx_u64(&x108, &x109, x107, x100, UINT64_C(0xffffffff00000001));
+  fiat_p256_subborrowx_u64(&x110, &x111, x109, x101, 0x0);
+  fiat_p256_addcarryx_u64(&x112, &x113, 0x0, x6, 0x1);
+  x114 = ((x80 >> 1) | ((x82 << 63) & UINT64_C(0xffffffffffffffff)));
+  x115 = ((x82 >> 1) | ((x84 << 63) & UINT64_C(0xffffffffffffffff)));
+  x116 = ((x84 >> 1) | ((x86 << 63) & UINT64_C(0xffffffffffffffff)));
+  x117 = ((x86 >> 1) | ((x88 << 63) & UINT64_C(0xffffffffffffffff)));
+  x118 = ((x88 & UINT64_C(0x8000000000000000)) | (x88 >> 1));
+  fiat_p256_cmovznz_u64(&x119, x48, x39, x31);
+  fiat_p256_cmovznz_u64(&x120, x48, x41, x33);
+  fiat_p256_cmovznz_u64(&x121, x48, x43, x35);
+  fiat_p256_cmovznz_u64(&x122, x48, x45, x37);
+  fiat_p256_cmovznz_u64(&x123, x111, x102, x94);
+  fiat_p256_cmovznz_u64(&x124, x111, x104, x96);
+  fiat_p256_cmovznz_u64(&x125, x111, x106, x98);
+  fiat_p256_cmovznz_u64(&x126, x111, x108, x100);
+  *out1 = x112;
+  out2[0] = x7;
+  out2[1] = x8;
+  out2[2] = x9;
+  out2[3] = x10;
+  out2[4] = x11;
+  out3[0] = x114;
+  out3[1] = x115;
+  out3[2] = x116;
+  out3[3] = x117;
+  out3[4] = x118;
+  out4[0] = x119;
+  out4[1] = x120;
+  out4[2] = x121;
+  out4[3] = x122;
+  out5[0] = x123;
+  out5[1] = x124;
+  out5[2] = x125;
+  out5[3] = x126;
+}
+
+/*
+ * The function fiat_p256_divstep_precomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form).
+ *
+ * Postconditions:
+ *   eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if ⌊log2 m⌋ + 1 < 46 then ⌊(49 * (⌊log2 m⌋ + 1) + 80) / 17⌋ else ⌊(49 * (⌊log2 m⌋ + 1) + 57) / 17⌋)
+ *   0 ≤ eval out1 < m
+ *
+ * Output Bounds:
+ *   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+ */
+static FIAT_P256_FIAT_INLINE void fiat_p256_divstep_precomp(uint64_t out1[4]) {
+  out1[0] = UINT64_C(0x67ffffffb8000000);
+  out1[1] = UINT64_C(0xc000000038000000);
+  out1[2] = UINT64_C(0xd80000007fffffff);
+  out1[3] = UINT64_C(0x2fffffffffffffff);
+}
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index 8d81463..c0dceba 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/util/check_filenames.go b/src/util/check_filenames.go
index 886c3f6..384c19f 100644
--- a/src/util/check_filenames.go
+++ b/src/util/check_filenames.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // check_filenames.go checks that filenames are unique. Some of our consumers do
 // not support multiple files with the same name in the same build target, even
 // if they are in different directories.
diff --git a/src/util/check_imported_libraries.go b/src/util/check_imported_libraries.go
index 187e514..f3803f1 100644
--- a/src/util/check_imported_libraries.go
+++ b/src/util/check_imported_libraries.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // check_imported_libraries.go checks that each of its arguments only imports
 // allowed libraries. This is used to avoid accidental dependencies on
 // libstdc++.so.
diff --git a/src/util/check_stack.go b/src/util/check_stack.go
index b718ea4..ad763e6 100644
--- a/src/util/check_stack.go
+++ b/src/util/check_stack.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // check_stack.go checks that each of its arguments has a non-executable stack.
 // See https://www.airs.com/blog/archives/518 for details.
 package main
diff --git a/src/util/compare_benchmarks.go b/src/util/compare_benchmarks.go
index d631f83..05e1b5d 100644
--- a/src/util/compare_benchmarks.go
+++ b/src/util/compare_benchmarks.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // compare_benchmarks takes the JSON-formatted output of bssl speed and
 // compares it against a baseline output.
 package main
diff --git a/src/util/convert_comments.go b/src/util/convert_comments.go
index 917f29c..df9e3d3 100644
--- a/src/util/convert_comments.go
+++ b/src/util/convert_comments.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/util/convert_wycheproof.go b/src/util/convert_wycheproof/convert_wycheproof.go
similarity index 98%
rename from src/util/convert_wycheproof.go
rename to src/util/convert_wycheproof/convert_wycheproof.go
index a7dfc81..076f8e4 100644
--- a/src/util/convert_wycheproof.go
+++ b/src/util/convert_wycheproof/convert_wycheproof.go
@@ -12,8 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-// convert_wycheproof.go converts Wycheproof test vectors into a format more
-// easily consumed by BoringSSL.
+// convert_wycheproof converts Wycheproof test vectors into a format more easily
+// consumed by BoringSSL.
 package main
 
 import (
diff --git a/src/util/diff_asm.go b/src/util/diff_asm.go
index 27c0aa2..5ac1c04 100644
--- a/src/util/diff_asm.go
+++ b/src/util/diff_asm.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/util/doc.go b/src/util/doc.go
index e7f1b59..4fb73ca 100644
--- a/src/util/doc.go
+++ b/src/util/doc.go
@@ -1,3 +1,5 @@
+//go:build ignore
+
 // doc generates HTML files from the comments in header files.
 //
 // doc expects to be given the path to a JSON file via the --config option.
diff --git a/src/util/embed_test_data.go b/src/util/embed_test_data.go
index 0a0d1e3..ae7135f 100644
--- a/src/util/embed_test_data.go
+++ b/src/util/embed_test_data.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // embed_test_data generates a C++ source file which exports a function,
 // GetTestData, which looks up the specified data files.
 package main
diff --git a/src/util/fetch_ech_config_list.go b/src/util/fetch_ech_config_list.go
index 8f09e66..732d0d3 100644
--- a/src/util/fetch_ech_config_list.go
+++ b/src/util/fetch_ech_config_list.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/util/fipstools/acvp/ACVP.md b/src/util/fipstools/acvp/ACVP.md
index d3578e2..1fd919f 100644
--- a/src/util/fipstools/acvp/ACVP.md
+++ b/src/util/fipstools/acvp/ACVP.md
@@ -77,6 +77,8 @@
 | ECDSA/sigVer         | Curve name, hash name, message, X, Y, R, S | Single-byte validity flag |
 | FFDH                 | p, q, g, peer public key, local private key (or empty),  local public key (or empty) | Local public key, shared key |
 | HKDF/&lt;HASH&gt;    | key, salt, info, num output bytes | Key |
+| HKDFExtract          | secret, salt | Key |
+| HKDFExpandLabel      | Output length, secret, label, transcript hash | Key |
 | HMAC-SHA-1           | Value to hash, key        | Digest  |
 | HMAC-SHA2-224        | Value to hash, key        | Digest  |
 | HMAC-SHA2-256        | Value to hash, key        | Digest  |
@@ -104,7 +106,7 @@
 | SHA2-384/MCT         | Initial seed¹             | Digest  |
 | SHA2-512/MCT         | Initial seed¹             | Digest  |
 | SHA2-512/256/MCT     | Initial seed¹             | Digest  |
-| TLSKDF/&lt;1.0\|1.2&gt;/&lt;HASH&gt; | Number output bytes, secret, label, seed1, seed2 | Output |
+| TLSKDF/1.2/&lt;HASH&gt; | Number output bytes, secret, label, seed1, seed2 | Output |
 
 ¹ The iterated tests would result in excessive numbers of round trips if the module wrapper handled only basic operations. Thus some ACVP logic is pushed down for these tests so that the inner loop can be handled locally. Either read the NIST documentation ([block-ciphers](https://pages.nist.gov/ACVP/draft-celi-acvp-symmetric.html#name-monte-carlo-tests-for-block) [hashes](https://pages.nist.gov/ACVP/draft-celi-acvp-sha.html#name-monte-carlo-tests-for-sha-1)) to understand the iteration count and return values or, probably more fruitfully, see how these functions are handled in the `modulewrapper` directory.
 
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go b/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go
index 3cd4c32..b124d79 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/hkdf.go
@@ -173,6 +173,9 @@
 			if err != nil {
 				return nil, fmt.Errorf("HKDF operation failed: %s", err)
 			}
+			if len(resp[0]) != int(outBytes) {
+				return nil, fmt.Errorf("HKDF operation resulted in %d bytes but wanted %d", len(resp[0]), outBytes)
+			}
 
 			if isValidationTest {
 				passed := bytes.Equal(expected, resp[0])
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
index 48d7083..84152cf 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
@@ -107,9 +107,10 @@
 		"hmacDRBG":          &drbg{"hmacDRBG", map[string]bool{"SHA-1": true, "SHA2-224": true, "SHA2-256": true, "SHA2-384": true, "SHA2-512": true}},
 		"KDF":               &kdfPrimitive{},
 		"KDA":               &hkdf{},
+		"TLS-v1.2":          &tlsKDF{},
+		"TLS-v1.3":          &tls13{},
 		"CMAC-AES":          &keyedMACPrimitive{"CMAC-AES"},
 		"RSA":               &rsa{},
-		"kdf-components":    &tlsKDF{},
 		"KAS-ECC-SSC":       &kas{},
 		"KAS-FFC-SSC":       &kasDH{},
 	}
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/tls13.go b/src/util/fipstools/acvp/acvptool/subprocess/tls13.go
new file mode 100644
index 0000000..b8b6e51
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/subprocess/tls13.go
@@ -0,0 +1,240 @@
+// Copyright (c) 2023, 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.
+
+package subprocess
+
+import (
+	"crypto/sha256"
+	"crypto/sha512"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+)
+
+// The following structures reflect the JSON of TLS 1.3 tests. See
+// https://pages.nist.gov/ACVP/draft-hammett-acvp-kdf-tls-v1.3.html
+
+type tls13TestVectorSet struct {
+	Groups []tls13TestGroup `json:"testGroups"`
+}
+
+type tls13TestGroup struct {
+	ID       uint64      `json:"tgId"`
+	HashFunc string      `json:"hmacAlg"`
+	Tests    []tls13Test `json:"tests"`
+}
+
+type tls13Test struct {
+	ID                uint64 `json:"tcId"`
+	// Although ACVP refers to these as client and server randoms, these
+	// fields are misnamed and really contain portions of the handshake
+	// transcript. Concatenated in order, they give the transcript up to
+	// the named message. In case of HelloRetryRequest, ClientHelloHex
+	// includes up to the second ClientHello.
+	ClientHelloHex    string `json:"helloClientRandom"`
+	ServerHelloHex    string `json:"helloServerRandom"`
+	ServerFinishedHex string `json:"finishedServerRandom"`
+	ClientFinishedHex string `json:"finishedClientRandom"`
+	DHEInputHex       string `json:"dhe"`
+	PSKInputHex       string `json:"psk"`
+}
+
+type tls13TestGroupResponse struct {
+	ID    uint64              `json:"tgId"`
+	Tests []tls13TestResponse `json:"tests"`
+}
+
+type tls13TestResponse struct {
+	ID                                uint64 `json:"tcId"`
+	ClientEarlyTrafficSecretHex       string `json:"clientEarlyTrafficSecret"`
+	EarlyExporterMasterSecretHex      string `json:"earlyExporterMasterSecret"`
+	ClientHandshakeTrafficSecretHex   string `json:"clientHandshakeTrafficSecret"`
+	ServerHandshakeTrafficSecretHex   string `json:"serverHandshakeTrafficSecret"`
+	ClientApplicationTrafficSecretHex string `json:"clientApplicationTrafficSecret"`
+	ServerApplicationTrafficSecretHex string `json:"serverApplicationTrafficSecret"`
+	ExporterMasterSecretHex           string `json:"exporterMasterSecret"`
+	ResumptionMasterSecretHex         string `json:"resumptionMasterSecret"`
+}
+
+type tls13 struct{}
+
+func (k *tls13) Process(vectorSet []byte, m Transactable) (interface{}, error) {
+	var parsed tls13TestVectorSet
+	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
+		return nil, err
+	}
+
+	var respGroups []tls13TestGroupResponse
+	for _, group := range parsed.Groups {
+		groupResp := tls13TestGroupResponse{ID: group.ID}
+
+		for _, test := range group.Tests {
+			testResp := tls13TestResponse{ID: test.ID}
+
+			clientHello, err := hex.DecodeString(test.ClientHelloHex)
+			if err != nil {
+				return nil, err
+			}
+			serverHello, err := hex.DecodeString(test.ServerHelloHex)
+			if err != nil {
+				return nil, err
+			}
+			serverFinished, err := hex.DecodeString(test.ServerFinishedHex)
+			if err != nil {
+				return nil, err
+			}
+			clientFinished, err := hex.DecodeString(test.ClientFinishedHex)
+			if err != nil {
+				return nil, err
+			}
+
+			// See https://www.rfc-editor.org/rfc/rfc8446#section-7.1
+			var hashLen int
+			var emptyHash []byte
+			switch group.HashFunc {
+			case "SHA2-256":
+				hashLen = 256 / 8
+				digest := sha256.Sum256(nil)
+				emptyHash = digest[:]
+			case "SHA2-384":
+				hashLen = 384 / 8
+				digest := sha512.Sum384(nil)
+				emptyHash = digest[:]
+			default:
+				return nil, fmt.Errorf("hash function %q is not supported for TLS v1.3", group.HashFunc)
+			}
+			hashLenBytes := uint32le(uint32(hashLen))
+
+			psk, err := hex.DecodeString(test.PSKInputHex)
+			if err != nil {
+				return nil, err
+			}
+			if len(psk) == 0 {
+				psk = make([]byte, hashLen)
+			}
+
+			dhe, err := hex.DecodeString(test.DHEInputHex)
+			if err != nil {
+				return nil, err
+			}
+			if len(dhe) == 0 {
+				dhe = make([]byte, hashLen)
+			}
+
+			zeros := make([]byte, hashLen)
+			earlySecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, psk, zeros)
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExtract operation failed: %s", err)
+			}
+
+			hashedToClientHello, err := m.Transact(group.HashFunc, 1, clientHello)
+			if err != nil {
+				return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err)
+			}
+			hashedToServerHello, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello))
+			if err != nil {
+				return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err)
+			}
+			hashedToServerFinished, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished))
+			if err != nil {
+				return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err)
+			}
+			hashedMessages, err := m.Transact(group.HashFunc, 1, concat(clientHello, serverHello, serverFinished, clientFinished))
+			if err != nil {
+				return nil, fmt.Errorf("%q operation failed: %s", group.HashFunc, err)
+			}
+
+			clientEarlyTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("c e traffic"), hashedToClientHello[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ClientEarlyTrafficSecretHex = hex.EncodeToString(clientEarlyTrafficSecret[0])
+
+			earlyExporter, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("e exp master"), hashedToClientHello[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.EarlyExporterMasterSecretHex = hex.EncodeToString(earlyExporter[0])
+
+			derivedSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, earlySecret[0], []byte("derived"), emptyHash[:])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+
+			handshakeSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, dhe, derivedSecret[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExtract operation failed: %s", err)
+			}
+
+			clientHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("c hs traffic"), hashedToServerHello[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ClientHandshakeTrafficSecretHex = hex.EncodeToString(clientHandshakeTrafficSecret[0])
+
+			serverHandshakeTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("s hs traffic"), hashedToServerHello[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ServerHandshakeTrafficSecretHex = hex.EncodeToString(serverHandshakeTrafficSecret[0])
+
+			derivedSecret, err = m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, handshakeSecret[0], []byte("derived"), emptyHash[:])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+
+			masterSecret, err := m.Transact("HKDFExtract/"+group.HashFunc, 1, zeros, derivedSecret[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExtract operation failed: %s", err)
+			}
+
+			clientAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("c ap traffic"), hashedToServerFinished[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ClientApplicationTrafficSecretHex = hex.EncodeToString(clientAppTrafficSecret[0])
+
+			serverAppTrafficSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("s ap traffic"), hashedToServerFinished[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ServerApplicationTrafficSecretHex = hex.EncodeToString(serverAppTrafficSecret[0])
+
+			exporterSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("exp master"), hashedToServerFinished[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ExporterMasterSecretHex = hex.EncodeToString(exporterSecret[0])
+
+			resumptionSecret, err := m.Transact("HKDFExpandLabel/"+group.HashFunc, 1, hashLenBytes, masterSecret[0], []byte("res master"), hashedMessages[0])
+			if err != nil {
+				return nil, fmt.Errorf("HKDFExpandLabel operation failed: %s", err)
+			}
+			testResp.ResumptionMasterSecretHex = hex.EncodeToString(resumptionSecret[0])
+
+			groupResp.Tests = append(groupResp.Tests, testResp)
+		}
+		respGroups = append(respGroups, groupResp)
+	}
+
+	return respGroups, nil
+}
+
+func concat(slices ...[]byte) []byte {
+	var ret []byte
+	for _, slice := range slices {
+		ret = append(ret, slice...)
+	}
+	return ret
+}
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/tlskdf.go b/src/util/fipstools/acvp/acvptool/subprocess/tlskdf.go
index 2e2b65d..ad27b54 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/tlskdf.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/tlskdf.go
@@ -35,17 +35,11 @@
 }
 
 type tlsKDFTest struct {
-	ID     uint64 `json:"tcId"`
-	PMSHex string `json:"preMasterSecret"`
-	// ClientHelloRandomHex and ServerHelloRandomHex are used for deriving the
-	// master secret. ClientRandomHex and ServerRandomHex are used for deriving the
-	// key block. Having different values for these is not possible in a TLS
-	// handshake unless you squint at a resumption handshake and somehow rederive
-	// the master secret from the session information during resumption.
-	ClientHelloRandomHex string `json:"clientHelloRandom"`
-	ServerHelloRandomHex string `json:"serverHelloRandom"`
-	ClientRandomHex      string `json:"clientRandom"`
-	ServerRandomHex      string `json:"serverRandom"`
+	ID              uint64 `json:"tcId"`
+	PMSHex          string `json:"preMasterSecret"`
+	ClientRandomHex string `json:"clientRandom"`
+	ServerRandomHex string `json:"serverRandom"`
+	SessionHashHex  string `json:"sessionHash"`
 }
 
 type tlsKDFTestGroupResponse struct {
@@ -74,35 +68,18 @@
 			ID: group.ID,
 		}
 
-		var tlsVer string
-		switch group.TLSVersion {
-		case "v1.0/1.1":
-			tlsVer = "1.0"
-		case "v1.2":
-			tlsVer = "1.2"
-		default:
-			return nil, fmt.Errorf("unknown TLS version %q", group.TLSVersion)
-		}
-
-		hashIsTLS10 := false
 		switch group.Hash {
-		case "SHA-1":
-			hashIsTLS10 = true
 		case "SHA2-256", "SHA2-384", "SHA2-512":
 			break
 		default:
 			return nil, fmt.Errorf("unknown hash %q", group.Hash)
 		}
 
-		if (tlsVer == "1.0") != hashIsTLS10 {
-			return nil, fmt.Errorf("hash %q not permitted with TLS version %q", group.Hash, group.TLSVersion)
-		}
-
 		if group.KeyBlockBits%8 != 0 {
 			return nil, fmt.Errorf("requested key-block length (%d bits) is not a whole number of bytes", group.KeyBlockBits)
 		}
 
-		method := "TLSKDF/" + tlsVer + "/" + group.Hash
+		method := "TLSKDF/1.2/" + group.Hash
 
 		for _, test := range group.Tests {
 			pms, err := hex.DecodeString(test.PMSHex)
@@ -110,16 +87,6 @@
 				return nil, err
 			}
 
-			clientHelloRandom, err := hex.DecodeString(test.ClientHelloRandomHex)
-			if err != nil {
-				return nil, err
-			}
-
-			serverHelloRandom, err := hex.DecodeString(test.ServerHelloRandomHex)
-			if err != nil {
-				return nil, err
-			}
-
 			clientRandom, err := hex.DecodeString(test.ClientRandomHex)
 			if err != nil {
 				return nil, err
@@ -130,15 +97,20 @@
 				return nil, err
 			}
 
+			sessionHash, err := hex.DecodeString(test.SessionHashHex)
+			if err != nil {
+				return nil, err
+			}
+
 			const (
 				masterSecretLength = 48
-				masterSecretLabel  = "master secret"
+				masterSecretLabel  = "extended master secret"
 				keyBlockLabel      = "key expansion"
 			)
 
 			var outLenBytes [4]byte
 			binary.LittleEndian.PutUint32(outLenBytes[:], uint32(masterSecretLength))
-			result, err := m.Transact(method, 1, outLenBytes[:], pms, []byte(masterSecretLabel), clientHelloRandom, serverHelloRandom)
+			result, err := m.Transact(method, 1, outLenBytes[:], pms, []byte(masterSecretLabel), sessionHash, nil)
 			if err != nil {
 				return nil, err
 			}
diff --git a/src/util/fipstools/acvp/acvptool/test/check_expected.go b/src/util/fipstools/acvp/acvptool/test/check_expected.go
index c5dc0f6..d02f272 100644
--- a/src/util/fipstools/acvp/acvptool/test/check_expected.go
+++ b/src/util/fipstools/acvp/acvptool/test/check_expected.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HKDF.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HKDF.bz2
new file mode 100644
index 0000000..791fa7a
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HKDF.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/TLS12.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/TLS12.bz2
new file mode 100644
index 0000000..d83b691
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/expected/TLS12.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/TLS13.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/TLS13.bz2
new file mode 100644
index 0000000..7693c5f
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/expected/TLS13.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/tests.json b/src/util/fipstools/acvp/acvptool/test/tests.json
index d1e8eb5..421e253 100644
--- a/src/util/fipstools/acvp/acvptool/test/tests.json
+++ b/src/util/fipstools/acvp/acvptool/test/tests.json
@@ -18,16 +18,18 @@
 {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-384.bz2", "Out": "expected/HMAC-SHA2-384.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-512.bz2", "Out": "expected/HMAC-SHA2-512.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-512-256.bz2", "Out": "expected/HMAC-SHA2-512-256.bz2"},
+{"Wrapper": "modulewrapper", "In": "vectors/HKDF.bz2", "Out": "expected/HKDF.bz2"},
 {"Wrapper": "testmodulewrapper", "In": "vectors/hmacDRBG.bz2", "Out": "expected/hmacDRBG.bz2"},
 {"Wrapper": "testmodulewrapper", "In": "vectors/KDA.bz2", "Out": "expected/KDA.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/KAS-ECC-SSC.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/KAS-FFC-SSC.bz2"},
 {"Wrapper": "testmodulewrapper", "In": "vectors/KDF.bz2"},
-{"Wrapper": "modulewrapper", "In": "vectors/kdf-components.bz2", "Out": "expected/kdf-components.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/RSA.bz2", "Out": "expected/RSA.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/SHA-1.bz2", "Out": "expected/SHA-1.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/SHA2-224.bz2", "Out": "expected/SHA2-224.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/SHA2-256.bz2", "Out": "expected/SHA2-256.bz2"},
 {"Wrapper": "modulewrapper", "In": "vectors/SHA2-384.bz2", "Out": "expected/SHA2-384.bz2"},
-{"Wrapper": "modulewrapper", "In": "vectors/SHA2-512.bz2", "Out": "expected/SHA2-512.bz2"}
+{"Wrapper": "modulewrapper", "In": "vectors/SHA2-512.bz2", "Out": "expected/SHA2-512.bz2"},
+{"Wrapper": "modulewrapper", "In": "vectors/TLS12.bz2", "Out": "expected/TLS12.bz2"},
+{"Wrapper": "modulewrapper", "In": "vectors/TLS13.bz2", "Out": "expected/TLS13.bz2"}
 ]
diff --git a/src/util/fipstools/acvp/acvptool/test/trim_vectors.go b/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
index 53e970e..703f75f 100644
--- a/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
+++ b/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // trimvectors takes an ACVP vector set file and discards all but a single test
 // from each test group. This hope is that this achieves good coverage without
 // having to check in megabytes worth of JSON files.
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HKDF.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HKDF.bz2
new file mode 100644
index 0000000..f69a461
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HKDF.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/TLS12.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/TLS12.bz2
new file mode 100644
index 0000000..d1911ab
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/TLS12.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/TLS13.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/TLS13.bz2
new file mode 100644
index 0000000..7e8ea08
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/TLS13.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
index 460a8e9..f417b64 100644
--- a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
+++ b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
@@ -37,6 +37,7 @@
 #include <openssl/ecdh.h>
 #include <openssl/ecdsa.h>
 #include <openssl/err.h>
+#include <openssl/hkdf.h>
 #include <openssl/hmac.h>
 #include <openssl/obj.h>
 #include <openssl/rsa.h>
@@ -834,20 +835,6 @@
         }]
       },
       {
-        "algorithm": "kdf-components",
-        "revision": "1.0",
-        "mode": "tls",
-        "tlsVersion": [
-          "v1.0/1.1",
-          "v1.2"
-        ],
-        "hashAlg": [
-          "SHA2-256",
-          "SHA2-384",
-          "SHA2-512"
-        ]
-      },
-      {
         "algorithm": "KAS-ECC-SSC",
         "revision": "Sp800-56Ar3",
         "scheme": {
@@ -885,6 +872,58 @@
           "FB",
           "FC"
         ]
+      },
+      {
+        "algorithm": "KDA",
+        "mode": "HKDF",
+        "revision": "Sp800-56Cr1",
+        "fixedInfoPattern": "uPartyInfo||vPartyInfo",
+        "encoding": [
+          "concatenation"
+        ],
+        "hmacAlg": [
+          "SHA2-224",
+          "SHA2-256",
+          "SHA2-384",
+          "SHA2-512",
+          "SHA2-512/256"
+        ],
+        "macSaltMethods": [
+          "default",
+          "random"
+        ],
+        "l": 2048,
+        "z": [
+          {
+            "min": 224,
+            "max": 65336,
+            "increment": 8
+          }
+        ]
+      },
+      {
+        "algorithm": "TLS-v1.2",
+        "mode": "KDF",
+        "revision": "RFC7627",
+        "hashAlg": [
+          "SHA2-256",
+          "SHA2-384",
+          "SHA2-512"
+        ]
+      },
+      {
+        "algorithm": "TLS-v1.3",
+        "mode": "KDF",
+        "revision": "RFC8446",
+        "hmacAlg": [
+          "SHA2-256",
+          "SHA2-384"
+        ],
+        "runningMode": [
+          "DHE",
+          "PSK",
+          "PSK-DHE"
+        ]
       }
     ])";
   return write_reply({Span<const uint8_t>(
@@ -1431,6 +1470,73 @@
   return write_reply({Span<const uint8_t>(digest, digest_len)});
 }
 
+template <const EVP_MD *HashFunc()>
+static bool HKDF(const Span<const uint8_t> args[], ReplyCallback write_reply) {
+  const EVP_MD *const md = HashFunc();
+  const auto key = args[0];
+  const auto salt = args[1];
+  const auto info = args[2];
+  const auto out_len_bytes = args[3];
+
+  if (out_len_bytes.size() != sizeof(uint32_t)) {
+    return false;
+  }
+  const uint32_t out_len = CRYPTO_load_u32_le(out_len_bytes.data());
+  if (out_len > (1 << 24)) {
+    return false;
+  }
+
+  std::vector<uint8_t> out(out_len);
+  if (!::HKDF(out.data(), out_len, md, key.data(), key.size(), salt.data(),
+              salt.size(), info.data(), info.size())) {
+    return false;
+  }
+  return write_reply({out});
+}
+
+template <const EVP_MD *HashFunc()>
+static bool HKDFExtract(const Span<const uint8_t> args[],
+                        ReplyCallback write_reply) {
+  const EVP_MD *const md = HashFunc();
+  const auto secret = args[0];
+  const auto salt = args[1];
+
+  std::vector<uint8_t> out(EVP_MD_size(md));
+  size_t out_len;
+  if (!HKDF_extract(out.data(), &out_len, md, secret.data(), secret.size(),
+                    salt.data(), salt.size())) {
+    return false;
+  }
+  assert(out_len == out.size());
+  return write_reply({out});
+}
+
+template <const EVP_MD *HashFunc()>
+static bool HKDFExpandLabel(const Span<const uint8_t> args[],
+                            ReplyCallback write_reply) {
+  const EVP_MD *const md = HashFunc();
+  const auto out_len_bytes = args[0];
+  const auto secret = args[1];
+  const auto label = args[2];
+  const auto hash = args[3];
+
+  if (out_len_bytes.size() != sizeof(uint32_t)) {
+    return false;
+  }
+  const uint32_t out_len = CRYPTO_load_u32_le(out_len_bytes.data());
+  if (out_len > (1 << 24)) {
+    return false;
+  }
+
+  std::vector<uint8_t> out(out_len);
+  if (!CRYPTO_tls13_hkdf_expand_label(out.data(), out_len, md, secret.data(),
+                                      secret.size(), label.data(), label.size(),
+                                      hash.data(), hash.size())) {
+    return false;
+  }
+  return write_reply({out});
+}
+
 template <bool WithReseed>
 static bool DRBG(const Span<const uint8_t> args[], ReplyCallback write_reply) {
   const auto out_len_bytes = args[0];
@@ -1971,6 +2077,15 @@
     {"3DES-ECB/decrypt", 3, TDES<false>},
     {"3DES-CBC/encrypt", 4, TDES_CBC<true>},
     {"3DES-CBC/decrypt", 4, TDES_CBC<false>},
+    {"HKDF/SHA2-224", 4, HKDF<EVP_sha224>},
+    {"HKDF/SHA2-256", 4, HKDF<EVP_sha256>},
+    {"HKDF/SHA2-384", 4, HKDF<EVP_sha384>},
+    {"HKDF/SHA2-512", 4, HKDF<EVP_sha512>},
+    {"HKDF/SHA2-512/256", 4, HKDF<EVP_sha512_256>},
+    {"HKDFExpandLabel/SHA2-256", 4, HKDFExpandLabel<EVP_sha256>},
+    {"HKDFExpandLabel/SHA2-384", 4, HKDFExpandLabel<EVP_sha384>},
+    {"HKDFExtract/SHA2-256", 2, HKDFExtract<EVP_sha256>},
+    {"HKDFExtract/SHA2-384", 2, HKDFExtract<EVP_sha384>},
     {"HMAC-SHA-1", 2, HMAC<EVP_sha1>},
     {"HMAC-SHA2-224", 2, HMAC<EVP_sha224>},
     {"HMAC-SHA2-256", 2, HMAC<EVP_sha256>},
@@ -2008,7 +2123,6 @@
     {"RSA/sigVer/SHA2-512/pss", 4, RSASigVer<EVP_sha512, true>},
     {"RSA/sigVer/SHA2-512/256/pss", 4, RSASigVer<EVP_sha512_256, true>},
     {"RSA/sigVer/SHA-1/pss", 4, RSASigVer<EVP_sha1, true>},
-    {"TLSKDF/1.0/SHA-1", 5, TLSKDF<EVP_md5_sha1>},
     {"TLSKDF/1.2/SHA2-256", 5, TLSKDF<EVP_sha256>},
     {"TLSKDF/1.2/SHA2-384", 5, TLSKDF<EVP_sha384>},
     {"TLSKDF/1.2/SHA2-512", 5, TLSKDF<EVP_sha512>},
diff --git a/src/util/fipstools/break-hash.go b/src/util/fipstools/break-hash.go
index e37da75..a4ab808 100644
--- a/src/util/fipstools/break-hash.go
+++ b/src/util/fipstools/break-hash.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // break-hash parses an ELF binary containing the FIPS module and corrupts the
 // first byte of the module. This should cause the integrity check to fail.
 package main
diff --git a/src/util/fipstools/break-kat.go b/src/util/fipstools/break-kat.go
index 6eace5b..e4d323a 100644
--- a/src/util/fipstools/break-kat.go
+++ b/src/util/fipstools/break-kat.go
@@ -1,3 +1,5 @@
+//go:build
+
 // break-kat corrupts a known-answer-test input in a binary and writes the
 // corrupted binary to stdout. This is used to demonstrate that the KATs in the
 // binary notice the error.
@@ -21,10 +23,12 @@
 		"AES-GCM-decrypt": "35f3058f875760ff09d3120f70c4bc9ed7a86872e13452202176f7371ae04faae1dd391920f5d13953d896785994823c",
 		"DRBG":            "c4da0740d505f1ee280b95e58c4931ac6de846a0152fbb4a3f174cf4787a4f1a40c2b50babe14aae530be5886d910a27",
 		"DRBG-reseed":     "c7161ca36c2309b716e9859bb96c6d49bdc8352103a18cd24ef42ec97ef46bf446eb1a4576c186e9351803763a7912fe",
+		"HKDF":            "68678504b9b3add17d5967a1a7bd37993fd8a33ce7303071f39c096d1635b3c9",
 		"SHA-1":           "132fd9bad5c1826263bafbb699f707a5",
 		"SHA-256":         "ff3b857da7236a2baa0f396b51522217",
 		"SHA-512":         "212512f8d2ad8322781c6c4d69a9daa1",
 		"TLS-KDF":         "abc3657b094c7628a0b282996fe75a75f4984fd94d4ecc2fcf53a2c469a3f731",
+		"TLS13-KDF":       "024a0d80f357f2499a1244dac26dab66fc13ed85fca71dace146211119525874",
 		"RSA-sign":        "d2b56e53306f720d7929d8708bf46f1c22300305582b115bedcac722d8aa5ab2",
 		"RSA-verify":      "abe2cbc13d6bd39d48db5334ddbf8d070a93bdcb104e2cc5d0ee486ee295f6b31bda126c41890b98b73e70e6b65d82f95c663121755a90744c8d1c21148a1960be0eca446e9ff497f1345c537ef8119b9a4398e95c5c6de2b1c955905c5299d8ce7a3b6ab76380d9babdd15f610237e1f3f2aa1c1f1e770b62fbb596381b2ebdd77ecef9c90d4c92f7b6b05fed2936285fa94826e62055322a33b6f04c74ce69e5d8d737fb838b79d2d48e3daf71387531882531a95ac964d02ea413bf85952982bbc089527daff5b845c9a0f4d14ef1956d9c3acae882d12da66da0f35794f5ee32232333517db9315232a183b991654dbea41615345c885325926744a53915",
 		"ECDSA-sign":      "1e35930be860d0942ca7bbd6f6ded87f157e4de24f81ed4b875c0e018e89a81f",
diff --git a/src/util/fipstools/break-tests.sh b/src/util/fipstools/break-tests.sh
index f9ae2e8..695b629 100644
--- a/src/util/fipstools/break-tests.sh
+++ b/src/util/fipstools/break-tests.sh
@@ -25,139 +25,147 @@
 set -e
 
 die () {
-    echo "ERROR: $@"
-    exit 1
+  echo "ERROR: $@"
+  exit 1
 }
 
 usage() {
-    echo "USAGE: $0 [local|device]"
-    exit 1
+  echo "USAGE: $0 [local|device]"
+  exit 1
 }
 
 inferred_mode() {
-    # Try and infer local or device mode based on makefiles and artifacts.
-    if [ -f Android.bp -o -f external/boringssl/Android.bp ]
-    then
-       echo device
-    elif [ -f CMakeLists.txt -a -d build/crypto -a -d build/ssl ]
-    then
-	echo local
-    else
-	echo "Unable to infer mode, please specify on the command line."
-	usage
-    fi
+  # Try and infer local or device mode based on makefiles and artifacts.
+  if [ -f Android.bp -o -f external/boringssl/Android.bp ]; then
+    echo device
+  elif [ -f CMakeLists.txt -a -d build/crypto -a -d build/ssl ]; then
+    echo local
+  else
+    echo "Unable to infer mode, please specify on the command line."
+    usage
+  fi
 }
 
 # Prefer mode from command line if present.
 case "$1" in
-    local|device)
-	MODE=$1
-	;;
+  local|device)
+    MODE=$1
+    ;;
 
-    "")
-	MODE=`inferred_mode`
-	;;
+  "")
+    MODE=`inferred_mode`
+    ;;
 
-    *)
-	usage
-	;;
+  *)
+    usage
+    ;;
 esac
 
 check_directory() {
-    test -d $1 || die "Directory $1 not found."
+  test -d "$1" || die "Directory $1 not found."
 }
 
 check_file() {
-    test -f $1 || die "File $1 not found."
+  test -f "$1" || die "File $1 not found."
 }
 
 run_test_locally() {
-    eval "$1" || true
+  eval "$1" || true
 }
 
 run_test_on_device() {
-    EXECFILE="$1"
-    LIBRARY="$2"
-    adb shell rm -rf $DEVICE_TMP
-    adb shell mkdir -p $DEVICE_TMP
-    adb push $EXECFILE $DEVICE_TMP > /dev/null
-    EXECPATH=$(basename $EXECFILE)
-    adb push $LIBRARY $DEVICE_TMP > /dev/null
-    adb shell "LD_LIBRARY_PATH=$DEVICE_TMP $DEVICE_TMP/$EXECPATH" || true
+  EXECFILE="$1"
+  LIBRARY="$2"
+  adb shell rm -rf "$DEVICE_TMP"
+  adb shell mkdir -p "$DEVICE_TMP"
+  adb push "$EXECFILE" "$DEVICE_TMP" > /dev/null
+  EXECPATH=$(basename "$EXECFILE")
+  adb push "$LIBRARY" "$DEVICE_TMP" > /dev/null
+  adb shell "LD_LIBRARY_PATH=$DEVICE_TMP" "$DEVICE_TMP/$EXECPATH" || true
 }
 
 device_integrity_break_test() {
-    go run $BORINGSSL/util/fipstools/break-hash.go $LIBCRYPTO_BIN ./libcrypto.so
-    $RUN $TEST_FIPS_BIN ./libcrypto.so
-    rm ./libcrypto.so
+  go run "$BORINGSSL/util/fipstools/break-hash.go" "$LIBCRYPTO_BIN" ./libcrypto.so
+  $RUN "$TEST_FIPS_BIN" ./libcrypto.so
+  rm ./libcrypto.so
 }
 
 local_integrity_break_test() {
-    go run $BORINGSSL/util/fipstools/break-hash.go $TEST_FIPS_BIN ./break-bin
-    chmod u+x ./break-bin
-    $RUN ./break-bin
-    rm ./break-bin
+  go run $BORINGSSL/util/fipstools/break-hash.go "$TEST_FIPS_BIN" ./break-bin
+  chmod u+x ./break-bin
+  $RUN ./break-bin
+  rm ./break-bin
+}
+
+local_runtime_break_test() {
+  BORINGSSL_FIPS_BREAK_TEST=$1 "$RUN" "$TEST_FIPS_BREAK_BIN"
 }
 
 # TODO(prb): make break-hash and break-kat take similar arguments to save having
 # separate functions for each.
 device_kat_break_test() {
-    KAT="$1"
-    go run $BORINGSSL/util/fipstools/break-kat.go $LIBCRYPTO_BIN $KAT > ./libcrypto.so
-    $RUN $TEST_FIPS_BIN ./libcrypto.so
-    rm ./libcrypto.so
+  KAT="$1"
+  go run "$BORINGSSL/util/fipstools/break-kat.go" "$LIBCRYPTO_BREAK_BIN" "$KAT" > ./libcrypto.so
+  $RUN "$TEST_FIPS_BIN" ./libcrypto.so
+  rm ./libcrypto.so
 }
 
 local_kat_break_test() {
-    KAT="$1"
-    go run $BORINGSSL/util/fipstools/break-kat.go $TEST_FIPS_BIN $KAT > ./break-bin
-    chmod u+x ./break-bin
-    $RUN ./break-bin
-    rm ./break-bin
+  KAT="$1"
+  go run "$BORINGSSL/util/fipstools/break-kat.go" "$TEST_FIPS_BREAK_BIN" "$KAT" > ./break-bin
+  chmod u+x ./break-bin
+  $RUN ./break-bin
+  rm ./break-bin
 }
 
 pause () {
-    echo -n "Press <Enter> "
-    read
+  echo -n "Press <Enter> "
+  read
 }
 
-if [ "$MODE" = "local" ]
-then
-    TEST_FIPS_BIN="build/util/fipstools/test_fips"
-    BORINGSSL=.
-    RUN=run_test_locally
-    BREAK_TEST=local_break_test
-    INTEGRITY_BREAK_TEST=local_integrity_break_test
-    KAT_BREAK_TEST=local_kat_break_test
-    if [ ! -f $TEST_FIPS_BIN ]; then
-	echo "$TEST_FIPS_BIN is missing. Run this script from the top level of a"
-	echo "BoringSSL checkout and ensure that BoringSSL has been built in"
-	echo "build/ with -DFIPS_BREAK_TEST=TESTS passed to CMake."
-	exit 1
-    fi
+if [ "$MODE" = "local" ]; then
+  TEST_FIPS_BIN=${TEST_FIPS_BIN:-build/util/fipstools/test_fips}
+  TEST_FIPS_BREAK_BIN=${TEST_FIPS_BREAK_BIN:-./test_fips_break}
+  check_file "$TEST_FIPS_BIN"
+  check_file "$TEST_FIPS_BREAK_BIN"
+
+  BORINGSSL=.
+  RUN=run_test_locally
+  BREAK_TEST=local_break_test
+  INTEGRITY_BREAK_TEST=local_integrity_break_test
+  KAT_BREAK_TEST=local_kat_break_test
+  RUNTIME_BREAK_TEST=local_runtime_break_test
+  if [ ! -f "$TEST_FIPS_BIN" ]; then
+    echo "$TEST_FIPS_BIN is missing. Run this script from the top level of a"
+    echo "BoringSSL checkout and ensure that BoringSSL has been built in"
+    echo "build/ with -DFIPS_BREAK_TEST=TESTS passed to CMake."
+    exit 1
+  fi
 else # Device mode
-    test "$ANDROID_BUILD_TOP" || die "'lunch aosp_arm64-eng' first"
-    check_directory "$ANDROID_PRODUCT_OUT"
+  test "$ANDROID_BUILD_TOP" || die "'lunch aosp_arm64-eng' first"
+  check_directory "$ANDROID_PRODUCT_OUT"
 
-    TEST_FIPS_BIN="$ANDROID_PRODUCT_OUT/system/bin/test_fips"
-    check_file "$TEST_FIPS_BIN"
-    LIBCRYPTO_BIN="$ANDROID_PRODUCT_OUT/system/lib64/libcrypto.so"
-    check_file "$LIBCRYPTO_BIN"
+  TEST_FIPS_BIN="$ANDROID_PRODUCT_OUT/system/bin/test_fips"
+  check_file "$TEST_FIPS_BIN"
+  LIBCRYPTO_BIN="$ANDROID_PRODUCT_OUT/system/lib64/libcrypto.so"
+  LIBCRYPTO_BREAK_BIN="libcrypto.so"
+  check_file "$LIBCRYPTO_BIN"
+  check_file "$LIBCRYPTO_BREAK_BIN"
 
-    test "$ANDROID_SERIAL" || die "ANDROID_SERIAL not set"
-    DEVICE_TMP=/data/local/tmp
+  test "$ANDROID_SERIAL" || die "ANDROID_SERIAL not set"
+  DEVICE_TMP=/data/local/tmp
 
-    BORINGSSL="$ANDROID_BUILD_TOP/external/boringssl/src"
-    RUN=run_test_on_device
-    INTEGRITY_BREAK_TEST=device_integrity_break_test
-    KAT_BREAK_TEST=device_kat_break_test
+  BORINGSSL="$ANDROID_BUILD_TOP/external/boringssl/src"
+  RUN=run_test_on_device
+  INTEGRITY_BREAK_TEST=device_integrity_break_test
+  KAT_BREAK_TEST=device_kat_break_test
 fi
 
 
-KATS=$(go run $BORINGSSL/util/fipstools/break-kat.go --list-tests)
+KATS=$(go run "$BORINGSSL/util/fipstools/break-kat.go" --list-tests)
 
 echo -e '\033[1mNormal output\033[0m'
-$RUN $TEST_FIPS_BIN $LIBCRYPTO_BIN
+$RUN "$TEST_FIPS_BIN" "$LIBCRYPTO_BIN"
 pause
 
 echo
@@ -171,3 +179,13 @@
   $KAT_BREAK_TEST $kat
   pause
 done
+
+if [ "$MODE" = "local" ]; then
+  # TODO(prb): add support for Android devices.
+  for runtime_test in ECDSA_PWCT RSA_PWCT CRNG; do
+    echo
+    echo -e "\033[1m${runtime_test} failure\033[0m"
+    $RUNTIME_BREAK_TEST ${runtime_test}
+    pause
+  done
+fi
diff --git a/src/util/fipstools/test_fips.c b/src/util/fipstools/test_fips.c
index ed95b8c..3a1f7fc 100644
--- a/src/util/fipstools/test_fips.c
+++ b/src/util/fipstools/test_fips.c
@@ -24,8 +24,9 @@
 #include <openssl/ctrdrbg.h>
 #include <openssl/des.h>
 #include <openssl/dh.h>
-#include <openssl/ecdsa.h>
 #include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/hkdf.h>
 #include <openssl/hmac.h>
 #include <openssl/nid.h>
 #include <openssl/rsa.h>
@@ -278,18 +279,43 @@
   hexdump(output, sizeof(output));
   CTR_DRBG_clear(&drbg);
 
-  /* TLS KDF */
-  printf("About to run TLS KDF\n");
-  uint8_t tls_output[32];
-  if (!CRYPTO_tls1_prf(EVP_sha256(), tls_output, sizeof(tls_output), kAESKey,
-                       sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
-                       sizeof(kPlaintextSHA256), kPlaintextSHA256,
-                       sizeof(kPlaintextSHA256))) {
-    fprintf(stderr, "TLS KDF failed.\n");
+  /* HKDF */
+  printf("About to run HKDF\n");
+  uint8_t hkdf_output[32];
+  if (!HKDF(hkdf_output, sizeof(hkdf_output), EVP_sha256(), kAESKey,
+            sizeof(kAESKey), (const uint8_t *)"salt", 4, kPlaintextSHA256,
+            sizeof(kPlaintextSHA256))) {
+    fprintf(stderr, "HKDF failed.\n");
     goto err;
   }
   printf("  got ");
-  hexdump(tls_output, sizeof(tls_output));
+  hexdump(hkdf_output, sizeof(hkdf_output));
+
+  /* TLS v1.2 KDF */
+  printf("About to run TLS v1.2 KDF\n");
+  uint8_t tls12_output[32];
+  if (!CRYPTO_tls1_prf(EVP_sha256(), tls12_output, sizeof(tls12_output),
+                       kAESKey, sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
+                       sizeof(kPlaintextSHA256), kPlaintextSHA256,
+                       sizeof(kPlaintextSHA256))) {
+    fprintf(stderr, "TLS v1.2 KDF failed.\n");
+    goto err;
+  }
+  printf("  got ");
+  hexdump(tls12_output, sizeof(tls12_output));
+
+  /* TLS v1.3 KDF */
+  printf("About to run TLS v1.3 KDF\n");
+  uint8_t tls13_output[32];
+  if (!CRYPTO_tls13_hkdf_expand_label(
+          tls13_output, sizeof(tls13_output), EVP_sha256(), kAESKey,
+          sizeof(kAESKey), (const uint8_t *)"foo", 3, kPlaintextSHA256,
+          sizeof(kPlaintextSHA256))) {
+    fprintf(stderr, "TLS v1.3 KDF failed.\n");
+    goto err;
+  }
+  printf("  got ");
+  hexdump(tls13_output, sizeof(tls13_output));
 
   /* FFDH */
   printf("About to compute FFDH key-agreement:\n");
diff --git a/src/util/godeps.go b/src/util/godeps.go
index 960faa4..56be559 100644
--- a/src/util/godeps.go
+++ b/src/util/godeps.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // godeps prints out dependencies of a package in either CMake or Make depfile
 // format, for incremental rebuilds.
 //
diff --git a/src/util/make_errors.go b/src/util/make_errors.go
index 4e2718b..874a001 100644
--- a/src/util/make_errors.go
+++ b/src/util/make_errors.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (
@@ -188,28 +190,13 @@
 	value int
 }
 
-type assignmentsSlice []assignment
-
-func (a assignmentsSlice) Len() int {
-	return len(a)
-}
-
-func (a assignmentsSlice) Less(i, j int) bool {
-	return a[i].value < a[j].value
-}
-
-func (a assignmentsSlice) Swap(i, j int) {
-	a[i], a[j] = a[j], a[i]
-}
-
 func outputAssignments(w io.Writer, assignments map[string]int) {
-	var sorted assignmentsSlice
-
+	sorted := make([]assignment, 0, len(assignments))
 	for key, value := range assignments {
 		sorted = append(sorted, assignment{key, value})
 	}
 
-	sort.Sort(sorted)
+	sort.Slice(sorted, func(i, j int) bool { return sorted[i].value < sorted[j].value })
 
 	for _, assignment := range sorted {
 		fmt.Fprintf(w, "#define %s %d\n", assignment.key, assignment.value)
diff --git a/src/util/make_prefix_headers.go b/src/util/make_prefix_headers.go
index b39e4ec..8787654 100644
--- a/src/util/make_prefix_headers.go
+++ b/src/util/make_prefix_headers.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // This program takes a file containing newline-separated symbols, and generates
 // boringssl_prefix_symbols.h, boringssl_prefix_symbols_asm.h, and
 // boringssl_prefix_symbols_nasm.inc. These header files can be used to build
diff --git a/src/util/read_symbols.go b/src/util/read_symbols.go
index b407ecb..ab2184c 100644
--- a/src/util/read_symbols.go
+++ b/src/util/read_symbols.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 // read_symbols scans one or more .a files and, for each object contained in
 // the .a files, reads the list of symbols in that object file.
 package main
diff --git a/src/util/run_android_tests.go b/src/util/run_android_tests.go
index 67a13e7..ce87819 100644
--- a/src/util/run_android_tests.go
+++ b/src/util/run_android_tests.go
@@ -12,6 +12,8 @@
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+//go:build ignore
+
 package main
 
 import (