update master-with-bazel from main branch
diff --git a/BUILD.generated.bzl b/BUILD.generated.bzl
index c844ae9..f3a0f01 100644
--- a/BUILD.generated.bzl
+++ b/BUILD.generated.bzl
@@ -19,7 +19,6 @@
     "src/crypto/fipsmodule/aes/key_wrap.cc.inc",
     "src/crypto/fipsmodule/aes/mode_wrappers.cc.inc",
     "src/crypto/fipsmodule/aes/ofb.cc.inc",
-    "src/crypto/fipsmodule/aes/polyval.cc.inc",
     "src/crypto/fipsmodule/bn/add.cc.inc",
     "src/crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
     "src/crypto/fipsmodule/bn/bn.cc.inc",
@@ -69,7 +68,9 @@
     "src/crypto/fipsmodule/hkdf/hkdf.cc.inc",
     "src/crypto/fipsmodule/hmac/hmac.cc.inc",
     "src/crypto/fipsmodule/keccak/keccak.cc.inc",
+    "src/crypto/fipsmodule/mldsa/fips_known_values.inc",
     "src/crypto/fipsmodule/mldsa/mldsa.cc.inc",
+    "src/crypto/fipsmodule/mlkem/fips_known_values.inc",
     "src/crypto/fipsmodule/mlkem/mlkem.cc.inc",
     "src/crypto/fipsmodule/rand/ctrdrbg.cc.inc",
     "src/crypto/fipsmodule/rand/rand.cc.inc",
@@ -83,6 +84,7 @@
     "src/crypto/fipsmodule/sha/sha1.cc.inc",
     "src/crypto/fipsmodule/sha/sha256.cc.inc",
     "src/crypto/fipsmodule/sha/sha512.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/fips_known_values.inc",
     "src/crypto/fipsmodule/slhdsa/fors.cc.inc",
     "src/crypto/fipsmodule/slhdsa/merkle.cc.inc",
     "src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
@@ -158,6 +160,7 @@
     "src/include/openssl/chacha.h",
     "src/include/openssl/cipher.h",
     "src/include/openssl/cmac.h",
+    "src/include/openssl/cms.h",
     "src/include/openssl/conf.h",
     "src/include/openssl/cpu.h",
     "src/include/openssl/crypto.h",
@@ -281,7 +284,7 @@
     "src/crypto/poly1305/internal.h",
     "src/crypto/pool/internal.h",
     "src/crypto/rand/getrandom_fillin.h",
-    "src/crypto/rand/sysrand_internal.h",
+    "src/crypto/rand/internal.h",
     "src/crypto/rsa/internal.h",
     "src/crypto/spake2plus/internal.h",
     "src/crypto/trust_token/internal.h",
@@ -297,6 +300,7 @@
 ]
 
 crypto_sources = [
+    "src/crypto/aes/aes.cc",
     "src/crypto/asn1/a_bitstr.cc",
     "src/crypto/asn1/a_bool.cc",
     "src/crypto/asn1/a_d2i_fp.cc",
@@ -339,6 +343,9 @@
     "src/crypto/blake2/blake2.cc",
     "src/crypto/bn/bn_asn1.cc",
     "src/crypto/bn/convert.cc",
+    "src/crypto/bn/div.cc",
+    "src/crypto/bn/exponentiation.cc",
+    "src/crypto/bn/sqrt.cc",
     "src/crypto/buf/buf.cc",
     "src/crypto/bytestring/asn1_compat.cc",
     "src/crypto/bytestring/ber.cc",
@@ -348,6 +355,7 @@
     "src/crypto/chacha/chacha.cc",
     "src/crypto/cipher/derive_key.cc",
     "src/crypto/cipher/e_aesctrhmac.cc",
+    "src/crypto/cipher/e_aeseax.cc",
     "src/crypto/cipher/e_aesgcmsiv.cc",
     "src/crypto/cipher/e_chacha20poly1305.cc",
     "src/crypto/cipher/e_des.cc",
@@ -357,6 +365,7 @@
     "src/crypto/cipher/e_tls.cc",
     "src/crypto/cipher/get_cipher.cc",
     "src/crypto/cipher/tls_cbc.cc",
+    "src/crypto/cms/cms.cc",
     "src/crypto/conf/conf.cc",
     "src/crypto/cpu_aarch64_apple.cc",
     "src/crypto/cpu_aarch64_fuchsia.cc",
@@ -406,6 +415,7 @@
     "src/crypto/ex_data.cc",
     "src/crypto/fipsmodule/bcm.cc",
     "src/crypto/fipsmodule/fips_shared_support.cc",
+    "src/crypto/fuzzer_mode.cc",
     "src/crypto/hpke/hpke.cc",
     "src/crypto/hrss/hrss.cc",
     "src/crypto/kyber/kyber.cc",
@@ -541,10 +551,10 @@
     "src/crypto/curve25519/asm/x25519-asm-arm.S",
     "src/crypto/hrss/asm/poly_rq_mul.S",
     "src/crypto/poly1305/poly1305_arm_asm.S",
-    "src/gen/bcm/aes-gcm-avx10-x86_64-apple.S",
-    "src/gen/bcm/aes-gcm-avx10-x86_64-linux.S",
     "src/gen/bcm/aes-gcm-avx2-x86_64-apple.S",
     "src/gen/bcm/aes-gcm-avx2-x86_64-linux.S",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-apple.S",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-linux.S",
     "src/gen/bcm/aesni-gcm-x86_64-apple.S",
     "src/gen/bcm/aesni-gcm-x86_64-linux.S",
     "src/gen/bcm/aesni-x86-apple.S",
@@ -672,8 +682,8 @@
 ]
 
 crypto_sources_nasm = [
-    "src/gen/bcm/aes-gcm-avx10-x86_64-win.asm",
     "src/gen/bcm/aes-gcm-avx2-x86_64-win.asm",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-win.asm",
     "src/gen/bcm/aesni-gcm-x86_64-win.asm",
     "src/gen/bcm/aesni-x86-win.asm",
     "src/gen/bcm/aesni-x86_64-win.asm",
diff --git a/BUILD.generated_tests.bzl b/BUILD.generated_tests.bzl
index cca454a..b072d75 100644
--- a/BUILD.generated_tests.bzl
+++ b/BUILD.generated_tests.bzl
@@ -55,7 +55,7 @@
     "src/crypto/poly1305/internal.h",
     "src/crypto/pool/internal.h",
     "src/crypto/rand/getrandom_fillin.h",
-    "src/crypto/rand/sysrand_internal.h",
+    "src/crypto/rand/internal.h",
     "src/crypto/rsa/internal.h",
     "src/crypto/spake2plus/internal.h",
     "src/crypto/test/abi_test.cc",
@@ -143,6 +143,7 @@
     "src/crypto/chacha/chacha_test.cc",
     "src/crypto/cipher/aead_test.cc",
     "src/crypto/cipher/cipher_test.cc",
+    "src/crypto/cms/cms_test.cc",
     "src/crypto/compiler_test.cc",
     "src/crypto/conf/conf_test.cc",
     "src/crypto/constant_time_test.cc",
@@ -260,6 +261,7 @@
     "src/crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt",
     "src/crypto/cipher/test/aes_128_ccm_matter_tests.txt",
     "src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt",
+    "src/crypto/cipher/test/aes_128_eax_test.txt",
     "src/crypto/cipher/test/aes_128_gcm_randnonce_tests.txt",
     "src/crypto/cipher/test/aes_128_gcm_siv_tests.txt",
     "src/crypto/cipher/test/aes_128_gcm_tests.txt",
@@ -267,6 +269,7 @@
     "src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt",
     "src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt",
     "src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt",
+    "src/crypto/cipher/test/aes_256_eax_test.txt",
     "src/crypto/cipher/test/aes_256_gcm_randnonce_tests.txt",
     "src/crypto/cipher/test/aes_256_gcm_siv_tests.txt",
     "src/crypto/cipher/test/aes_256_gcm_tests.txt",
@@ -328,6 +331,15 @@
     "src/crypto/mlkem/mlkem768_keygen_tests.txt",
     "src/crypto/mlkem/mlkem768_nist_decap_tests.txt",
     "src/crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+    "src/crypto/pkcs7/test/nss.p7c",
+    "src/crypto/pkcs7/test/openssl_crl.p7c",
+    "src/crypto/pkcs7/test/sign_cert.pem",
+    "src/crypto/pkcs7/test/sign_key.pem",
+    "src/crypto/pkcs7/test/sign_sha1.p7s",
+    "src/crypto/pkcs7/test/sign_sha1_key_id.p7s",
+    "src/crypto/pkcs7/test/sign_sha256.p7s",
+    "src/crypto/pkcs7/test/sign_sha256_key_id.p7s",
+    "src/crypto/pkcs7/test/windows.p7c",
     "src/crypto/pkcs8/test/bad1.p12",
     "src/crypto/pkcs8/test/bad2.p12",
     "src/crypto/pkcs8/test/bad3.p12",
@@ -436,6 +448,7 @@
     "src/crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
     "src/third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
     "src/third_party/wycheproof_testvectors/aes_cmac_test.txt",
+    "src/third_party/wycheproof_testvectors/aes_eax_test.txt",
     "src/third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
     "src/third_party/wycheproof_testvectors/aes_gcm_test.txt",
     "src/third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
@@ -1487,6 +1500,18 @@
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test",
@@ -1495,6 +1520,14 @@
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test",
     "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test",
@@ -1711,6 +1744,7 @@
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test",
@@ -1725,6 +1759,7 @@
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test",
@@ -1733,6 +1768,7 @@
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test",
     "src/pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f1a634..0e8bd77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -86,10 +86,10 @@
   src/crypto/curve25519/asm/x25519-asm-arm.S
   src/crypto/hrss/asm/poly_rq_mul.S
   src/crypto/poly1305/poly1305_arm_asm.S
-  src/gen/bcm/aes-gcm-avx10-x86_64-apple.S
-  src/gen/bcm/aes-gcm-avx10-x86_64-linux.S
   src/gen/bcm/aes-gcm-avx2-x86_64-apple.S
   src/gen/bcm/aes-gcm-avx2-x86_64-linux.S
+  src/gen/bcm/aes-gcm-avx512-x86_64-apple.S
+  src/gen/bcm/aes-gcm-avx512-x86_64-linux.S
   src/gen/bcm/aesni-gcm-x86_64-apple.S
   src/gen/bcm/aesni-gcm-x86_64-linux.S
   src/gen/bcm/aesni-x86-apple.S
@@ -219,8 +219,8 @@
 set(
   CRYPTO_SOURCES_NASM
 
-  src/gen/bcm/aes-gcm-avx10-x86_64-win.asm
   src/gen/bcm/aes-gcm-avx2-x86_64-win.asm
+  src/gen/bcm/aes-gcm-avx512-x86_64-win.asm
   src/gen/bcm/aesni-gcm-x86_64-win.asm
   src/gen/bcm/aesni-x86-win.asm
   src/gen/bcm/aesni-x86_64-win.asm
@@ -266,6 +266,7 @@
   crypto
 
   ${CRYPTO_SOURCES_ASM_USED}
+  src/crypto/aes/aes.cc
   src/crypto/asn1/a_bitstr.cc
   src/crypto/asn1/a_bool.cc
   src/crypto/asn1/a_d2i_fp.cc
@@ -308,6 +309,9 @@
   src/crypto/blake2/blake2.cc
   src/crypto/bn/bn_asn1.cc
   src/crypto/bn/convert.cc
+  src/crypto/bn/div.cc
+  src/crypto/bn/exponentiation.cc
+  src/crypto/bn/sqrt.cc
   src/crypto/buf/buf.cc
   src/crypto/bytestring/asn1_compat.cc
   src/crypto/bytestring/ber.cc
@@ -317,6 +321,7 @@
   src/crypto/chacha/chacha.cc
   src/crypto/cipher/derive_key.cc
   src/crypto/cipher/e_aesctrhmac.cc
+  src/crypto/cipher/e_aeseax.cc
   src/crypto/cipher/e_aesgcmsiv.cc
   src/crypto/cipher/e_chacha20poly1305.cc
   src/crypto/cipher/e_des.cc
@@ -326,6 +331,7 @@
   src/crypto/cipher/e_tls.cc
   src/crypto/cipher/get_cipher.cc
   src/crypto/cipher/tls_cbc.cc
+  src/crypto/cms/cms.cc
   src/crypto/conf/conf.cc
   src/crypto/cpu_aarch64_apple.cc
   src/crypto/cpu_aarch64_fuchsia.cc
@@ -375,6 +381,7 @@
   src/crypto/ex_data.cc
   src/crypto/fipsmodule/bcm.cc
   src/crypto/fipsmodule/fips_shared_support.cc
+  src/crypto/fuzzer_mode.cc
   src/crypto/hpke/hpke.cc
   src/crypto/hrss/hrss.cc
   src/crypto/kyber/kyber.cc
diff --git a/LICENSE b/LICENSE
index a0f82a1..37a5b74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -236,37 +236,3 @@
 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.
-
-
-BoringSSL uses the Chromium test infrastructure to run a continuous build,
-trybots etc. The scripts which manage this, and the script for generating build
-metadata, are under the Chromium license. Distributing code linked against
-BoringSSL does not trigger this license.
-
-Copyright 2015 The Chromium Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * 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.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"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 COPYRIGHT
-OWNER 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.
diff --git a/sources.json b/sources.json
index 960b065..dd5233e 100644
--- a/sources.json
+++ b/sources.json
@@ -1,2697 +1,2745 @@
 {
   "bcm_crypto": [
     "src/crypto/fipsmodule/bcm.cc"
-  ], 
+  ],
   "crypto": [
-    "src/crypto/asn1/a_bitstr.cc", 
-    "src/crypto/asn1/a_bool.cc", 
-    "src/crypto/asn1/a_d2i_fp.cc", 
-    "src/crypto/asn1/a_dup.cc", 
-    "src/crypto/asn1/a_gentm.cc", 
-    "src/crypto/asn1/a_i2d_fp.cc", 
-    "src/crypto/asn1/a_int.cc", 
-    "src/crypto/asn1/a_mbstr.cc", 
-    "src/crypto/asn1/a_object.cc", 
-    "src/crypto/asn1/a_octet.cc", 
-    "src/crypto/asn1/a_strex.cc", 
-    "src/crypto/asn1/a_strnid.cc", 
-    "src/crypto/asn1/a_time.cc", 
-    "src/crypto/asn1/a_type.cc", 
-    "src/crypto/asn1/a_utctm.cc", 
-    "src/crypto/asn1/asn1_lib.cc", 
-    "src/crypto/asn1/asn1_par.cc", 
-    "src/crypto/asn1/asn_pack.cc", 
-    "src/crypto/asn1/f_int.cc", 
-    "src/crypto/asn1/f_string.cc", 
-    "src/crypto/asn1/posix_time.cc", 
-    "src/crypto/asn1/tasn_dec.cc", 
-    "src/crypto/asn1/tasn_enc.cc", 
-    "src/crypto/asn1/tasn_fre.cc", 
-    "src/crypto/asn1/tasn_new.cc", 
-    "src/crypto/asn1/tasn_typ.cc", 
-    "src/crypto/asn1/tasn_utl.cc", 
-    "src/crypto/base64/base64.cc", 
-    "src/crypto/bio/bio.cc", 
-    "src/crypto/bio/bio_mem.cc", 
-    "src/crypto/bio/connect.cc", 
-    "src/crypto/bio/errno.cc", 
-    "src/crypto/bio/fd.cc", 
-    "src/crypto/bio/file.cc", 
-    "src/crypto/bio/hexdump.cc", 
-    "src/crypto/bio/pair.cc", 
-    "src/crypto/bio/printf.cc", 
-    "src/crypto/bio/socket.cc", 
-    "src/crypto/bio/socket_helper.cc", 
-    "src/crypto/blake2/blake2.cc", 
-    "src/crypto/bn/bn_asn1.cc", 
-    "src/crypto/bn/convert.cc", 
-    "src/crypto/buf/buf.cc", 
-    "src/crypto/bytestring/asn1_compat.cc", 
-    "src/crypto/bytestring/ber.cc", 
-    "src/crypto/bytestring/cbb.cc", 
-    "src/crypto/bytestring/cbs.cc", 
-    "src/crypto/bytestring/unicode.cc", 
-    "src/crypto/chacha/chacha.cc", 
-    "src/crypto/cipher/derive_key.cc", 
-    "src/crypto/cipher/e_aesctrhmac.cc", 
-    "src/crypto/cipher/e_aesgcmsiv.cc", 
-    "src/crypto/cipher/e_chacha20poly1305.cc", 
-    "src/crypto/cipher/e_des.cc", 
-    "src/crypto/cipher/e_null.cc", 
-    "src/crypto/cipher/e_rc2.cc", 
-    "src/crypto/cipher/e_rc4.cc", 
-    "src/crypto/cipher/e_tls.cc", 
-    "src/crypto/cipher/get_cipher.cc", 
-    "src/crypto/cipher/tls_cbc.cc", 
-    "src/crypto/conf/conf.cc", 
-    "src/crypto/cpu_aarch64_apple.cc", 
-    "src/crypto/cpu_aarch64_fuchsia.cc", 
-    "src/crypto/cpu_aarch64_linux.cc", 
-    "src/crypto/cpu_aarch64_openbsd.cc", 
-    "src/crypto/cpu_aarch64_sysreg.cc", 
-    "src/crypto/cpu_aarch64_win.cc", 
-    "src/crypto/cpu_arm_freebsd.cc", 
-    "src/crypto/cpu_arm_linux.cc", 
-    "src/crypto/cpu_intel.cc", 
-    "src/crypto/crypto.cc", 
-    "src/crypto/curve25519/curve25519.cc", 
-    "src/crypto/curve25519/curve25519_64_adx.cc", 
-    "src/crypto/curve25519/spake25519.cc", 
-    "src/crypto/des/des.cc", 
-    "src/crypto/dh/dh_asn1.cc", 
-    "src/crypto/dh/params.cc", 
-    "src/crypto/digest/digest_extra.cc", 
-    "src/crypto/dsa/dsa.cc", 
-    "src/crypto/dsa/dsa_asn1.cc", 
-    "src/crypto/ec/ec_asn1.cc", 
-    "src/crypto/ec/ec_derive.cc", 
-    "src/crypto/ec/hash_to_curve.cc", 
-    "src/crypto/ecdh/ecdh.cc", 
-    "src/crypto/ecdsa/ecdsa_asn1.cc", 
-    "src/crypto/engine/engine.cc", 
-    "src/crypto/err/err.cc", 
-    "src/crypto/evp/evp.cc", 
-    "src/crypto/evp/evp_asn1.cc", 
-    "src/crypto/evp/evp_ctx.cc", 
-    "src/crypto/evp/p_dh.cc", 
-    "src/crypto/evp/p_dh_asn1.cc", 
-    "src/crypto/evp/p_dsa_asn1.cc", 
-    "src/crypto/evp/p_ec.cc", 
-    "src/crypto/evp/p_ec_asn1.cc", 
-    "src/crypto/evp/p_ed25519.cc", 
-    "src/crypto/evp/p_ed25519_asn1.cc", 
-    "src/crypto/evp/p_hkdf.cc", 
-    "src/crypto/evp/p_rsa.cc", 
-    "src/crypto/evp/p_rsa_asn1.cc", 
-    "src/crypto/evp/p_x25519.cc", 
-    "src/crypto/evp/p_x25519_asn1.cc", 
-    "src/crypto/evp/pbkdf.cc", 
-    "src/crypto/evp/print.cc", 
-    "src/crypto/evp/scrypt.cc", 
-    "src/crypto/evp/sign.cc", 
-    "src/crypto/ex_data.cc", 
-    "src/crypto/fipsmodule/bcm.cc", 
-    "src/crypto/fipsmodule/fips_shared_support.cc", 
-    "src/crypto/hpke/hpke.cc", 
-    "src/crypto/hrss/hrss.cc", 
-    "src/crypto/kyber/kyber.cc", 
-    "src/crypto/lhash/lhash.cc", 
-    "src/crypto/md4/md4.cc", 
-    "src/crypto/md5/md5.cc", 
-    "src/crypto/mem.cc", 
-    "src/crypto/mldsa/mldsa.cc", 
-    "src/crypto/mlkem/mlkem.cc", 
-    "src/crypto/obj/obj.cc", 
-    "src/crypto/obj/obj_xref.cc", 
-    "src/crypto/pem/pem_all.cc", 
-    "src/crypto/pem/pem_info.cc", 
-    "src/crypto/pem/pem_lib.cc", 
-    "src/crypto/pem/pem_oth.cc", 
-    "src/crypto/pem/pem_pk8.cc", 
-    "src/crypto/pem/pem_pkey.cc", 
-    "src/crypto/pem/pem_x509.cc", 
-    "src/crypto/pem/pem_xaux.cc", 
-    "src/crypto/pkcs7/pkcs7.cc", 
-    "src/crypto/pkcs7/pkcs7_x509.cc", 
-    "src/crypto/pkcs8/p5_pbev2.cc", 
-    "src/crypto/pkcs8/pkcs8.cc", 
-    "src/crypto/pkcs8/pkcs8_x509.cc", 
-    "src/crypto/poly1305/poly1305.cc", 
-    "src/crypto/poly1305/poly1305_arm.cc", 
-    "src/crypto/poly1305/poly1305_vec.cc", 
-    "src/crypto/pool/pool.cc", 
-    "src/crypto/rand/deterministic.cc", 
-    "src/crypto/rand/fork_detect.cc", 
-    "src/crypto/rand/forkunsafe.cc", 
-    "src/crypto/rand/getentropy.cc", 
-    "src/crypto/rand/ios.cc", 
-    "src/crypto/rand/passive.cc", 
-    "src/crypto/rand/rand.cc", 
-    "src/crypto/rand/trusty.cc", 
-    "src/crypto/rand/urandom.cc", 
-    "src/crypto/rand/windows.cc", 
-    "src/crypto/rc4/rc4.cc", 
-    "src/crypto/refcount.cc", 
-    "src/crypto/rsa/rsa_asn1.cc", 
-    "src/crypto/rsa/rsa_crypt.cc", 
-    "src/crypto/rsa/rsa_extra.cc", 
-    "src/crypto/rsa/rsa_print.cc", 
-    "src/crypto/sha/sha1.cc", 
-    "src/crypto/sha/sha256.cc", 
-    "src/crypto/sha/sha512.cc", 
-    "src/crypto/siphash/siphash.cc", 
-    "src/crypto/slhdsa/slhdsa.cc", 
-    "src/crypto/spake2plus/spake2plus.cc", 
-    "src/crypto/stack/stack.cc", 
-    "src/crypto/thread.cc", 
-    "src/crypto/thread_none.cc", 
-    "src/crypto/thread_pthread.cc", 
-    "src/crypto/thread_win.cc", 
-    "src/crypto/trust_token/pmbtoken.cc", 
-    "src/crypto/trust_token/trust_token.cc", 
-    "src/crypto/trust_token/voprf.cc", 
-    "src/crypto/x509/a_digest.cc", 
-    "src/crypto/x509/a_sign.cc", 
-    "src/crypto/x509/a_verify.cc", 
-    "src/crypto/x509/algorithm.cc", 
-    "src/crypto/x509/asn1_gen.cc", 
-    "src/crypto/x509/by_dir.cc", 
-    "src/crypto/x509/by_file.cc", 
-    "src/crypto/x509/i2d_pr.cc", 
-    "src/crypto/x509/name_print.cc", 
-    "src/crypto/x509/policy.cc", 
-    "src/crypto/x509/rsa_pss.cc", 
-    "src/crypto/x509/t_crl.cc", 
-    "src/crypto/x509/t_req.cc", 
-    "src/crypto/x509/t_x509.cc", 
-    "src/crypto/x509/t_x509a.cc", 
-    "src/crypto/x509/v3_akey.cc", 
-    "src/crypto/x509/v3_akeya.cc", 
-    "src/crypto/x509/v3_alt.cc", 
-    "src/crypto/x509/v3_bcons.cc", 
-    "src/crypto/x509/v3_bitst.cc", 
-    "src/crypto/x509/v3_conf.cc", 
-    "src/crypto/x509/v3_cpols.cc", 
-    "src/crypto/x509/v3_crld.cc", 
-    "src/crypto/x509/v3_enum.cc", 
-    "src/crypto/x509/v3_extku.cc", 
-    "src/crypto/x509/v3_genn.cc", 
-    "src/crypto/x509/v3_ia5.cc", 
-    "src/crypto/x509/v3_info.cc", 
-    "src/crypto/x509/v3_int.cc", 
-    "src/crypto/x509/v3_lib.cc", 
-    "src/crypto/x509/v3_ncons.cc", 
-    "src/crypto/x509/v3_ocsp.cc", 
-    "src/crypto/x509/v3_pcons.cc", 
-    "src/crypto/x509/v3_pmaps.cc", 
-    "src/crypto/x509/v3_prn.cc", 
-    "src/crypto/x509/v3_purp.cc", 
-    "src/crypto/x509/v3_skey.cc", 
-    "src/crypto/x509/v3_utl.cc", 
-    "src/crypto/x509/x509.cc", 
-    "src/crypto/x509/x509_att.cc", 
-    "src/crypto/x509/x509_cmp.cc", 
-    "src/crypto/x509/x509_d2.cc", 
-    "src/crypto/x509/x509_def.cc", 
-    "src/crypto/x509/x509_ext.cc", 
-    "src/crypto/x509/x509_lu.cc", 
-    "src/crypto/x509/x509_obj.cc", 
-    "src/crypto/x509/x509_req.cc", 
-    "src/crypto/x509/x509_set.cc", 
-    "src/crypto/x509/x509_trs.cc", 
-    "src/crypto/x509/x509_txt.cc", 
-    "src/crypto/x509/x509_v3.cc", 
-    "src/crypto/x509/x509_vfy.cc", 
-    "src/crypto/x509/x509_vpm.cc", 
-    "src/crypto/x509/x509cset.cc", 
-    "src/crypto/x509/x509name.cc", 
-    "src/crypto/x509/x509rset.cc", 
-    "src/crypto/x509/x509spki.cc", 
-    "src/crypto/x509/x_algor.cc", 
-    "src/crypto/x509/x_all.cc", 
-    "src/crypto/x509/x_attrib.cc", 
-    "src/crypto/x509/x_crl.cc", 
-    "src/crypto/x509/x_exten.cc", 
-    "src/crypto/x509/x_name.cc", 
-    "src/crypto/x509/x_pubkey.cc", 
-    "src/crypto/x509/x_req.cc", 
-    "src/crypto/x509/x_sig.cc", 
-    "src/crypto/x509/x_spki.cc", 
-    "src/crypto/x509/x_val.cc", 
-    "src/crypto/x509/x_x509.cc", 
-    "src/crypto/x509/x_x509a.cc", 
+    "src/crypto/aes/aes.cc",
+    "src/crypto/asn1/a_bitstr.cc",
+    "src/crypto/asn1/a_bool.cc",
+    "src/crypto/asn1/a_d2i_fp.cc",
+    "src/crypto/asn1/a_dup.cc",
+    "src/crypto/asn1/a_gentm.cc",
+    "src/crypto/asn1/a_i2d_fp.cc",
+    "src/crypto/asn1/a_int.cc",
+    "src/crypto/asn1/a_mbstr.cc",
+    "src/crypto/asn1/a_object.cc",
+    "src/crypto/asn1/a_octet.cc",
+    "src/crypto/asn1/a_strex.cc",
+    "src/crypto/asn1/a_strnid.cc",
+    "src/crypto/asn1/a_time.cc",
+    "src/crypto/asn1/a_type.cc",
+    "src/crypto/asn1/a_utctm.cc",
+    "src/crypto/asn1/asn1_lib.cc",
+    "src/crypto/asn1/asn1_par.cc",
+    "src/crypto/asn1/asn_pack.cc",
+    "src/crypto/asn1/f_int.cc",
+    "src/crypto/asn1/f_string.cc",
+    "src/crypto/asn1/posix_time.cc",
+    "src/crypto/asn1/tasn_dec.cc",
+    "src/crypto/asn1/tasn_enc.cc",
+    "src/crypto/asn1/tasn_fre.cc",
+    "src/crypto/asn1/tasn_new.cc",
+    "src/crypto/asn1/tasn_typ.cc",
+    "src/crypto/asn1/tasn_utl.cc",
+    "src/crypto/base64/base64.cc",
+    "src/crypto/bio/bio.cc",
+    "src/crypto/bio/bio_mem.cc",
+    "src/crypto/bio/connect.cc",
+    "src/crypto/bio/errno.cc",
+    "src/crypto/bio/fd.cc",
+    "src/crypto/bio/file.cc",
+    "src/crypto/bio/hexdump.cc",
+    "src/crypto/bio/pair.cc",
+    "src/crypto/bio/printf.cc",
+    "src/crypto/bio/socket.cc",
+    "src/crypto/bio/socket_helper.cc",
+    "src/crypto/blake2/blake2.cc",
+    "src/crypto/bn/bn_asn1.cc",
+    "src/crypto/bn/convert.cc",
+    "src/crypto/bn/div.cc",
+    "src/crypto/bn/exponentiation.cc",
+    "src/crypto/bn/sqrt.cc",
+    "src/crypto/buf/buf.cc",
+    "src/crypto/bytestring/asn1_compat.cc",
+    "src/crypto/bytestring/ber.cc",
+    "src/crypto/bytestring/cbb.cc",
+    "src/crypto/bytestring/cbs.cc",
+    "src/crypto/bytestring/unicode.cc",
+    "src/crypto/chacha/chacha.cc",
+    "src/crypto/cipher/derive_key.cc",
+    "src/crypto/cipher/e_aesctrhmac.cc",
+    "src/crypto/cipher/e_aeseax.cc",
+    "src/crypto/cipher/e_aesgcmsiv.cc",
+    "src/crypto/cipher/e_chacha20poly1305.cc",
+    "src/crypto/cipher/e_des.cc",
+    "src/crypto/cipher/e_null.cc",
+    "src/crypto/cipher/e_rc2.cc",
+    "src/crypto/cipher/e_rc4.cc",
+    "src/crypto/cipher/e_tls.cc",
+    "src/crypto/cipher/get_cipher.cc",
+    "src/crypto/cipher/tls_cbc.cc",
+    "src/crypto/cms/cms.cc",
+    "src/crypto/conf/conf.cc",
+    "src/crypto/cpu_aarch64_apple.cc",
+    "src/crypto/cpu_aarch64_fuchsia.cc",
+    "src/crypto/cpu_aarch64_linux.cc",
+    "src/crypto/cpu_aarch64_openbsd.cc",
+    "src/crypto/cpu_aarch64_sysreg.cc",
+    "src/crypto/cpu_aarch64_win.cc",
+    "src/crypto/cpu_arm_freebsd.cc",
+    "src/crypto/cpu_arm_linux.cc",
+    "src/crypto/cpu_intel.cc",
+    "src/crypto/crypto.cc",
+    "src/crypto/curve25519/curve25519.cc",
+    "src/crypto/curve25519/curve25519_64_adx.cc",
+    "src/crypto/curve25519/spake25519.cc",
+    "src/crypto/des/des.cc",
+    "src/crypto/dh/dh_asn1.cc",
+    "src/crypto/dh/params.cc",
+    "src/crypto/digest/digest_extra.cc",
+    "src/crypto/dsa/dsa.cc",
+    "src/crypto/dsa/dsa_asn1.cc",
+    "src/crypto/ec/ec_asn1.cc",
+    "src/crypto/ec/ec_derive.cc",
+    "src/crypto/ec/hash_to_curve.cc",
+    "src/crypto/ecdh/ecdh.cc",
+    "src/crypto/ecdsa/ecdsa_asn1.cc",
+    "src/crypto/engine/engine.cc",
+    "src/crypto/err/err.cc",
+    "src/crypto/evp/evp.cc",
+    "src/crypto/evp/evp_asn1.cc",
+    "src/crypto/evp/evp_ctx.cc",
+    "src/crypto/evp/p_dh.cc",
+    "src/crypto/evp/p_dh_asn1.cc",
+    "src/crypto/evp/p_dsa_asn1.cc",
+    "src/crypto/evp/p_ec.cc",
+    "src/crypto/evp/p_ec_asn1.cc",
+    "src/crypto/evp/p_ed25519.cc",
+    "src/crypto/evp/p_ed25519_asn1.cc",
+    "src/crypto/evp/p_hkdf.cc",
+    "src/crypto/evp/p_rsa.cc",
+    "src/crypto/evp/p_rsa_asn1.cc",
+    "src/crypto/evp/p_x25519.cc",
+    "src/crypto/evp/p_x25519_asn1.cc",
+    "src/crypto/evp/pbkdf.cc",
+    "src/crypto/evp/print.cc",
+    "src/crypto/evp/scrypt.cc",
+    "src/crypto/evp/sign.cc",
+    "src/crypto/ex_data.cc",
+    "src/crypto/fipsmodule/bcm.cc",
+    "src/crypto/fipsmodule/fips_shared_support.cc",
+    "src/crypto/fuzzer_mode.cc",
+    "src/crypto/hpke/hpke.cc",
+    "src/crypto/hrss/hrss.cc",
+    "src/crypto/kyber/kyber.cc",
+    "src/crypto/lhash/lhash.cc",
+    "src/crypto/md4/md4.cc",
+    "src/crypto/md5/md5.cc",
+    "src/crypto/mem.cc",
+    "src/crypto/mldsa/mldsa.cc",
+    "src/crypto/mlkem/mlkem.cc",
+    "src/crypto/obj/obj.cc",
+    "src/crypto/obj/obj_xref.cc",
+    "src/crypto/pem/pem_all.cc",
+    "src/crypto/pem/pem_info.cc",
+    "src/crypto/pem/pem_lib.cc",
+    "src/crypto/pem/pem_oth.cc",
+    "src/crypto/pem/pem_pk8.cc",
+    "src/crypto/pem/pem_pkey.cc",
+    "src/crypto/pem/pem_x509.cc",
+    "src/crypto/pem/pem_xaux.cc",
+    "src/crypto/pkcs7/pkcs7.cc",
+    "src/crypto/pkcs7/pkcs7_x509.cc",
+    "src/crypto/pkcs8/p5_pbev2.cc",
+    "src/crypto/pkcs8/pkcs8.cc",
+    "src/crypto/pkcs8/pkcs8_x509.cc",
+    "src/crypto/poly1305/poly1305.cc",
+    "src/crypto/poly1305/poly1305_arm.cc",
+    "src/crypto/poly1305/poly1305_vec.cc",
+    "src/crypto/pool/pool.cc",
+    "src/crypto/rand/deterministic.cc",
+    "src/crypto/rand/fork_detect.cc",
+    "src/crypto/rand/forkunsafe.cc",
+    "src/crypto/rand/getentropy.cc",
+    "src/crypto/rand/ios.cc",
+    "src/crypto/rand/passive.cc",
+    "src/crypto/rand/rand.cc",
+    "src/crypto/rand/trusty.cc",
+    "src/crypto/rand/urandom.cc",
+    "src/crypto/rand/windows.cc",
+    "src/crypto/rc4/rc4.cc",
+    "src/crypto/refcount.cc",
+    "src/crypto/rsa/rsa_asn1.cc",
+    "src/crypto/rsa/rsa_crypt.cc",
+    "src/crypto/rsa/rsa_extra.cc",
+    "src/crypto/rsa/rsa_print.cc",
+    "src/crypto/sha/sha1.cc",
+    "src/crypto/sha/sha256.cc",
+    "src/crypto/sha/sha512.cc",
+    "src/crypto/siphash/siphash.cc",
+    "src/crypto/slhdsa/slhdsa.cc",
+    "src/crypto/spake2plus/spake2plus.cc",
+    "src/crypto/stack/stack.cc",
+    "src/crypto/thread.cc",
+    "src/crypto/thread_none.cc",
+    "src/crypto/thread_pthread.cc",
+    "src/crypto/thread_win.cc",
+    "src/crypto/trust_token/pmbtoken.cc",
+    "src/crypto/trust_token/trust_token.cc",
+    "src/crypto/trust_token/voprf.cc",
+    "src/crypto/x509/a_digest.cc",
+    "src/crypto/x509/a_sign.cc",
+    "src/crypto/x509/a_verify.cc",
+    "src/crypto/x509/algorithm.cc",
+    "src/crypto/x509/asn1_gen.cc",
+    "src/crypto/x509/by_dir.cc",
+    "src/crypto/x509/by_file.cc",
+    "src/crypto/x509/i2d_pr.cc",
+    "src/crypto/x509/name_print.cc",
+    "src/crypto/x509/policy.cc",
+    "src/crypto/x509/rsa_pss.cc",
+    "src/crypto/x509/t_crl.cc",
+    "src/crypto/x509/t_req.cc",
+    "src/crypto/x509/t_x509.cc",
+    "src/crypto/x509/t_x509a.cc",
+    "src/crypto/x509/v3_akey.cc",
+    "src/crypto/x509/v3_akeya.cc",
+    "src/crypto/x509/v3_alt.cc",
+    "src/crypto/x509/v3_bcons.cc",
+    "src/crypto/x509/v3_bitst.cc",
+    "src/crypto/x509/v3_conf.cc",
+    "src/crypto/x509/v3_cpols.cc",
+    "src/crypto/x509/v3_crld.cc",
+    "src/crypto/x509/v3_enum.cc",
+    "src/crypto/x509/v3_extku.cc",
+    "src/crypto/x509/v3_genn.cc",
+    "src/crypto/x509/v3_ia5.cc",
+    "src/crypto/x509/v3_info.cc",
+    "src/crypto/x509/v3_int.cc",
+    "src/crypto/x509/v3_lib.cc",
+    "src/crypto/x509/v3_ncons.cc",
+    "src/crypto/x509/v3_ocsp.cc",
+    "src/crypto/x509/v3_pcons.cc",
+    "src/crypto/x509/v3_pmaps.cc",
+    "src/crypto/x509/v3_prn.cc",
+    "src/crypto/x509/v3_purp.cc",
+    "src/crypto/x509/v3_skey.cc",
+    "src/crypto/x509/v3_utl.cc",
+    "src/crypto/x509/x509.cc",
+    "src/crypto/x509/x509_att.cc",
+    "src/crypto/x509/x509_cmp.cc",
+    "src/crypto/x509/x509_d2.cc",
+    "src/crypto/x509/x509_def.cc",
+    "src/crypto/x509/x509_ext.cc",
+    "src/crypto/x509/x509_lu.cc",
+    "src/crypto/x509/x509_obj.cc",
+    "src/crypto/x509/x509_req.cc",
+    "src/crypto/x509/x509_set.cc",
+    "src/crypto/x509/x509_trs.cc",
+    "src/crypto/x509/x509_txt.cc",
+    "src/crypto/x509/x509_v3.cc",
+    "src/crypto/x509/x509_vfy.cc",
+    "src/crypto/x509/x509_vpm.cc",
+    "src/crypto/x509/x509cset.cc",
+    "src/crypto/x509/x509name.cc",
+    "src/crypto/x509/x509rset.cc",
+    "src/crypto/x509/x509spki.cc",
+    "src/crypto/x509/x_algor.cc",
+    "src/crypto/x509/x_all.cc",
+    "src/crypto/x509/x_attrib.cc",
+    "src/crypto/x509/x_crl.cc",
+    "src/crypto/x509/x_exten.cc",
+    "src/crypto/x509/x_name.cc",
+    "src/crypto/x509/x_pubkey.cc",
+    "src/crypto/x509/x_req.cc",
+    "src/crypto/x509/x_sig.cc",
+    "src/crypto/x509/x_spki.cc",
+    "src/crypto/x509/x_val.cc",
+    "src/crypto/x509/x_x509.cc",
+    "src/crypto/x509/x_x509a.cc",
     "src/gen/crypto/err_data.cc"
-  ], 
+  ],
   "crypto_asm": [
-    "src/crypto/curve25519/asm/x25519-asm-arm.S", 
-    "src/crypto/hrss/asm/poly_rq_mul.S", 
-    "src/crypto/poly1305/poly1305_arm_asm.S", 
-    "src/gen/bcm/aes-gcm-avx10-x86_64-apple.S", 
-    "src/gen/bcm/aes-gcm-avx10-x86_64-linux.S", 
-    "src/gen/bcm/aes-gcm-avx2-x86_64-apple.S", 
-    "src/gen/bcm/aes-gcm-avx2-x86_64-linux.S", 
-    "src/gen/bcm/aesni-gcm-x86_64-apple.S", 
-    "src/gen/bcm/aesni-gcm-x86_64-linux.S", 
-    "src/gen/bcm/aesni-x86-apple.S", 
-    "src/gen/bcm/aesni-x86-linux.S", 
-    "src/gen/bcm/aesni-x86_64-apple.S", 
-    "src/gen/bcm/aesni-x86_64-linux.S", 
-    "src/gen/bcm/aesv8-armv7-linux.S", 
-    "src/gen/bcm/aesv8-armv8-apple.S", 
-    "src/gen/bcm/aesv8-armv8-linux.S", 
-    "src/gen/bcm/aesv8-armv8-win.S", 
-    "src/gen/bcm/aesv8-gcm-armv8-apple.S", 
-    "src/gen/bcm/aesv8-gcm-armv8-linux.S", 
-    "src/gen/bcm/aesv8-gcm-armv8-win.S", 
-    "src/gen/bcm/armv4-mont-linux.S", 
-    "src/gen/bcm/armv8-mont-apple.S", 
-    "src/gen/bcm/armv8-mont-linux.S", 
-    "src/gen/bcm/armv8-mont-win.S", 
-    "src/gen/bcm/bn-586-apple.S", 
-    "src/gen/bcm/bn-586-linux.S", 
-    "src/gen/bcm/bn-armv8-apple.S", 
-    "src/gen/bcm/bn-armv8-linux.S", 
-    "src/gen/bcm/bn-armv8-win.S", 
-    "src/gen/bcm/bsaes-armv7-linux.S", 
-    "src/gen/bcm/co-586-apple.S", 
-    "src/gen/bcm/co-586-linux.S", 
-    "src/gen/bcm/ghash-armv4-linux.S", 
-    "src/gen/bcm/ghash-neon-armv8-apple.S", 
-    "src/gen/bcm/ghash-neon-armv8-linux.S", 
-    "src/gen/bcm/ghash-neon-armv8-win.S", 
-    "src/gen/bcm/ghash-ssse3-x86-apple.S", 
-    "src/gen/bcm/ghash-ssse3-x86-linux.S", 
-    "src/gen/bcm/ghash-ssse3-x86_64-apple.S", 
-    "src/gen/bcm/ghash-ssse3-x86_64-linux.S", 
-    "src/gen/bcm/ghash-x86-apple.S", 
-    "src/gen/bcm/ghash-x86-linux.S", 
-    "src/gen/bcm/ghash-x86_64-apple.S", 
-    "src/gen/bcm/ghash-x86_64-linux.S", 
-    "src/gen/bcm/ghashv8-armv7-linux.S", 
-    "src/gen/bcm/ghashv8-armv8-apple.S", 
-    "src/gen/bcm/ghashv8-armv8-linux.S", 
-    "src/gen/bcm/ghashv8-armv8-win.S", 
-    "src/gen/bcm/p256-armv8-asm-apple.S", 
-    "src/gen/bcm/p256-armv8-asm-linux.S", 
-    "src/gen/bcm/p256-armv8-asm-win.S", 
-    "src/gen/bcm/p256-x86_64-asm-apple.S", 
-    "src/gen/bcm/p256-x86_64-asm-linux.S", 
-    "src/gen/bcm/p256_beeu-armv8-asm-apple.S", 
-    "src/gen/bcm/p256_beeu-armv8-asm-linux.S", 
-    "src/gen/bcm/p256_beeu-armv8-asm-win.S", 
-    "src/gen/bcm/p256_beeu-x86_64-asm-apple.S", 
-    "src/gen/bcm/p256_beeu-x86_64-asm-linux.S", 
-    "src/gen/bcm/rdrand-x86_64-apple.S", 
-    "src/gen/bcm/rdrand-x86_64-linux.S", 
-    "src/gen/bcm/rsaz-avx2-apple.S", 
-    "src/gen/bcm/rsaz-avx2-linux.S", 
-    "src/gen/bcm/sha1-586-apple.S", 
-    "src/gen/bcm/sha1-586-linux.S", 
-    "src/gen/bcm/sha1-armv4-large-linux.S", 
-    "src/gen/bcm/sha1-armv8-apple.S", 
-    "src/gen/bcm/sha1-armv8-linux.S", 
-    "src/gen/bcm/sha1-armv8-win.S", 
-    "src/gen/bcm/sha1-x86_64-apple.S", 
-    "src/gen/bcm/sha1-x86_64-linux.S", 
-    "src/gen/bcm/sha256-586-apple.S", 
-    "src/gen/bcm/sha256-586-linux.S", 
-    "src/gen/bcm/sha256-armv4-linux.S", 
-    "src/gen/bcm/sha256-armv8-apple.S", 
-    "src/gen/bcm/sha256-armv8-linux.S", 
-    "src/gen/bcm/sha256-armv8-win.S", 
-    "src/gen/bcm/sha256-x86_64-apple.S", 
-    "src/gen/bcm/sha256-x86_64-linux.S", 
-    "src/gen/bcm/sha512-586-apple.S", 
-    "src/gen/bcm/sha512-586-linux.S", 
-    "src/gen/bcm/sha512-armv4-linux.S", 
-    "src/gen/bcm/sha512-armv8-apple.S", 
-    "src/gen/bcm/sha512-armv8-linux.S", 
-    "src/gen/bcm/sha512-armv8-win.S", 
-    "src/gen/bcm/sha512-x86_64-apple.S", 
-    "src/gen/bcm/sha512-x86_64-linux.S", 
-    "src/gen/bcm/vpaes-armv7-linux.S", 
-    "src/gen/bcm/vpaes-armv8-apple.S", 
-    "src/gen/bcm/vpaes-armv8-linux.S", 
-    "src/gen/bcm/vpaes-armv8-win.S", 
-    "src/gen/bcm/vpaes-x86-apple.S", 
-    "src/gen/bcm/vpaes-x86-linux.S", 
-    "src/gen/bcm/vpaes-x86_64-apple.S", 
-    "src/gen/bcm/vpaes-x86_64-linux.S", 
-    "src/gen/bcm/x86-mont-apple.S", 
-    "src/gen/bcm/x86-mont-linux.S", 
-    "src/gen/bcm/x86_64-mont-apple.S", 
-    "src/gen/bcm/x86_64-mont-linux.S", 
-    "src/gen/bcm/x86_64-mont5-apple.S", 
-    "src/gen/bcm/x86_64-mont5-linux.S", 
-    "src/gen/crypto/aes128gcmsiv-x86_64-apple.S", 
-    "src/gen/crypto/aes128gcmsiv-x86_64-linux.S", 
-    "src/gen/crypto/chacha-armv4-linux.S", 
-    "src/gen/crypto/chacha-armv8-apple.S", 
-    "src/gen/crypto/chacha-armv8-linux.S", 
-    "src/gen/crypto/chacha-armv8-win.S", 
-    "src/gen/crypto/chacha-x86-apple.S", 
-    "src/gen/crypto/chacha-x86-linux.S", 
-    "src/gen/crypto/chacha-x86_64-apple.S", 
-    "src/gen/crypto/chacha-x86_64-linux.S", 
-    "src/gen/crypto/chacha20_poly1305_armv8-apple.S", 
-    "src/gen/crypto/chacha20_poly1305_armv8-linux.S", 
-    "src/gen/crypto/chacha20_poly1305_armv8-win.S", 
-    "src/gen/crypto/chacha20_poly1305_x86_64-apple.S", 
-    "src/gen/crypto/chacha20_poly1305_x86_64-linux.S", 
-    "src/gen/crypto/md5-586-apple.S", 
-    "src/gen/crypto/md5-586-linux.S", 
-    "src/gen/crypto/md5-x86_64-apple.S", 
-    "src/gen/crypto/md5-x86_64-linux.S", 
-    "src/gen/test_support/trampoline-armv4-linux.S", 
-    "src/gen/test_support/trampoline-armv8-apple.S", 
-    "src/gen/test_support/trampoline-armv8-linux.S", 
-    "src/gen/test_support/trampoline-armv8-win.S", 
-    "src/gen/test_support/trampoline-x86-apple.S", 
-    "src/gen/test_support/trampoline-x86-linux.S", 
-    "src/gen/test_support/trampoline-x86_64-apple.S", 
-    "src/gen/test_support/trampoline-x86_64-linux.S", 
-    "src/third_party/fiat/asm/fiat_curve25519_adx_mul.S", 
-    "src/third_party/fiat/asm/fiat_curve25519_adx_square.S", 
-    "src/third_party/fiat/asm/fiat_p256_adx_mul.S", 
+    "src/crypto/curve25519/asm/x25519-asm-arm.S",
+    "src/crypto/hrss/asm/poly_rq_mul.S",
+    "src/crypto/poly1305/poly1305_arm_asm.S",
+    "src/gen/bcm/aes-gcm-avx2-x86_64-apple.S",
+    "src/gen/bcm/aes-gcm-avx2-x86_64-linux.S",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-apple.S",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-linux.S",
+    "src/gen/bcm/aesni-gcm-x86_64-apple.S",
+    "src/gen/bcm/aesni-gcm-x86_64-linux.S",
+    "src/gen/bcm/aesni-x86-apple.S",
+    "src/gen/bcm/aesni-x86-linux.S",
+    "src/gen/bcm/aesni-x86_64-apple.S",
+    "src/gen/bcm/aesni-x86_64-linux.S",
+    "src/gen/bcm/aesv8-armv7-linux.S",
+    "src/gen/bcm/aesv8-armv8-apple.S",
+    "src/gen/bcm/aesv8-armv8-linux.S",
+    "src/gen/bcm/aesv8-armv8-win.S",
+    "src/gen/bcm/aesv8-gcm-armv8-apple.S",
+    "src/gen/bcm/aesv8-gcm-armv8-linux.S",
+    "src/gen/bcm/aesv8-gcm-armv8-win.S",
+    "src/gen/bcm/armv4-mont-linux.S",
+    "src/gen/bcm/armv8-mont-apple.S",
+    "src/gen/bcm/armv8-mont-linux.S",
+    "src/gen/bcm/armv8-mont-win.S",
+    "src/gen/bcm/bn-586-apple.S",
+    "src/gen/bcm/bn-586-linux.S",
+    "src/gen/bcm/bn-armv8-apple.S",
+    "src/gen/bcm/bn-armv8-linux.S",
+    "src/gen/bcm/bn-armv8-win.S",
+    "src/gen/bcm/bsaes-armv7-linux.S",
+    "src/gen/bcm/co-586-apple.S",
+    "src/gen/bcm/co-586-linux.S",
+    "src/gen/bcm/ghash-armv4-linux.S",
+    "src/gen/bcm/ghash-neon-armv8-apple.S",
+    "src/gen/bcm/ghash-neon-armv8-linux.S",
+    "src/gen/bcm/ghash-neon-armv8-win.S",
+    "src/gen/bcm/ghash-ssse3-x86-apple.S",
+    "src/gen/bcm/ghash-ssse3-x86-linux.S",
+    "src/gen/bcm/ghash-ssse3-x86_64-apple.S",
+    "src/gen/bcm/ghash-ssse3-x86_64-linux.S",
+    "src/gen/bcm/ghash-x86-apple.S",
+    "src/gen/bcm/ghash-x86-linux.S",
+    "src/gen/bcm/ghash-x86_64-apple.S",
+    "src/gen/bcm/ghash-x86_64-linux.S",
+    "src/gen/bcm/ghashv8-armv7-linux.S",
+    "src/gen/bcm/ghashv8-armv8-apple.S",
+    "src/gen/bcm/ghashv8-armv8-linux.S",
+    "src/gen/bcm/ghashv8-armv8-win.S",
+    "src/gen/bcm/p256-armv8-asm-apple.S",
+    "src/gen/bcm/p256-armv8-asm-linux.S",
+    "src/gen/bcm/p256-armv8-asm-win.S",
+    "src/gen/bcm/p256-x86_64-asm-apple.S",
+    "src/gen/bcm/p256-x86_64-asm-linux.S",
+    "src/gen/bcm/p256_beeu-armv8-asm-apple.S",
+    "src/gen/bcm/p256_beeu-armv8-asm-linux.S",
+    "src/gen/bcm/p256_beeu-armv8-asm-win.S",
+    "src/gen/bcm/p256_beeu-x86_64-asm-apple.S",
+    "src/gen/bcm/p256_beeu-x86_64-asm-linux.S",
+    "src/gen/bcm/rdrand-x86_64-apple.S",
+    "src/gen/bcm/rdrand-x86_64-linux.S",
+    "src/gen/bcm/rsaz-avx2-apple.S",
+    "src/gen/bcm/rsaz-avx2-linux.S",
+    "src/gen/bcm/sha1-586-apple.S",
+    "src/gen/bcm/sha1-586-linux.S",
+    "src/gen/bcm/sha1-armv4-large-linux.S",
+    "src/gen/bcm/sha1-armv8-apple.S",
+    "src/gen/bcm/sha1-armv8-linux.S",
+    "src/gen/bcm/sha1-armv8-win.S",
+    "src/gen/bcm/sha1-x86_64-apple.S",
+    "src/gen/bcm/sha1-x86_64-linux.S",
+    "src/gen/bcm/sha256-586-apple.S",
+    "src/gen/bcm/sha256-586-linux.S",
+    "src/gen/bcm/sha256-armv4-linux.S",
+    "src/gen/bcm/sha256-armv8-apple.S",
+    "src/gen/bcm/sha256-armv8-linux.S",
+    "src/gen/bcm/sha256-armv8-win.S",
+    "src/gen/bcm/sha256-x86_64-apple.S",
+    "src/gen/bcm/sha256-x86_64-linux.S",
+    "src/gen/bcm/sha512-586-apple.S",
+    "src/gen/bcm/sha512-586-linux.S",
+    "src/gen/bcm/sha512-armv4-linux.S",
+    "src/gen/bcm/sha512-armv8-apple.S",
+    "src/gen/bcm/sha512-armv8-linux.S",
+    "src/gen/bcm/sha512-armv8-win.S",
+    "src/gen/bcm/sha512-x86_64-apple.S",
+    "src/gen/bcm/sha512-x86_64-linux.S",
+    "src/gen/bcm/vpaes-armv7-linux.S",
+    "src/gen/bcm/vpaes-armv8-apple.S",
+    "src/gen/bcm/vpaes-armv8-linux.S",
+    "src/gen/bcm/vpaes-armv8-win.S",
+    "src/gen/bcm/vpaes-x86-apple.S",
+    "src/gen/bcm/vpaes-x86-linux.S",
+    "src/gen/bcm/vpaes-x86_64-apple.S",
+    "src/gen/bcm/vpaes-x86_64-linux.S",
+    "src/gen/bcm/x86-mont-apple.S",
+    "src/gen/bcm/x86-mont-linux.S",
+    "src/gen/bcm/x86_64-mont-apple.S",
+    "src/gen/bcm/x86_64-mont-linux.S",
+    "src/gen/bcm/x86_64-mont5-apple.S",
+    "src/gen/bcm/x86_64-mont5-linux.S",
+    "src/gen/crypto/aes128gcmsiv-x86_64-apple.S",
+    "src/gen/crypto/aes128gcmsiv-x86_64-linux.S",
+    "src/gen/crypto/chacha-armv4-linux.S",
+    "src/gen/crypto/chacha-armv8-apple.S",
+    "src/gen/crypto/chacha-armv8-linux.S",
+    "src/gen/crypto/chacha-armv8-win.S",
+    "src/gen/crypto/chacha-x86-apple.S",
+    "src/gen/crypto/chacha-x86-linux.S",
+    "src/gen/crypto/chacha-x86_64-apple.S",
+    "src/gen/crypto/chacha-x86_64-linux.S",
+    "src/gen/crypto/chacha20_poly1305_armv8-apple.S",
+    "src/gen/crypto/chacha20_poly1305_armv8-linux.S",
+    "src/gen/crypto/chacha20_poly1305_armv8-win.S",
+    "src/gen/crypto/chacha20_poly1305_x86_64-apple.S",
+    "src/gen/crypto/chacha20_poly1305_x86_64-linux.S",
+    "src/gen/crypto/md5-586-apple.S",
+    "src/gen/crypto/md5-586-linux.S",
+    "src/gen/crypto/md5-x86_64-apple.S",
+    "src/gen/crypto/md5-x86_64-linux.S",
+    "src/gen/test_support/trampoline-armv4-linux.S",
+    "src/gen/test_support/trampoline-armv8-apple.S",
+    "src/gen/test_support/trampoline-armv8-linux.S",
+    "src/gen/test_support/trampoline-armv8-win.S",
+    "src/gen/test_support/trampoline-x86-apple.S",
+    "src/gen/test_support/trampoline-x86-linux.S",
+    "src/gen/test_support/trampoline-x86_64-apple.S",
+    "src/gen/test_support/trampoline-x86_64-linux.S",
+    "src/third_party/fiat/asm/fiat_curve25519_adx_mul.S",
+    "src/third_party/fiat/asm/fiat_curve25519_adx_square.S",
+    "src/third_party/fiat/asm/fiat_p256_adx_mul.S",
     "src/third_party/fiat/asm/fiat_p256_adx_sqr.S"
-  ], 
+  ],
   "crypto_headers": [
-    "src/include/openssl/aead.h", 
-    "src/include/openssl/aes.h", 
-    "src/include/openssl/arm_arch.h", 
-    "src/include/openssl/asm_base.h", 
-    "src/include/openssl/asn1.h", 
-    "src/include/openssl/asn1_mac.h", 
-    "src/include/openssl/asn1t.h", 
-    "src/include/openssl/base.h", 
-    "src/include/openssl/base64.h", 
-    "src/include/openssl/bcm_public.h", 
-    "src/include/openssl/bio.h", 
-    "src/include/openssl/blake2.h", 
-    "src/include/openssl/blowfish.h", 
-    "src/include/openssl/bn.h", 
-    "src/include/openssl/buf.h", 
-    "src/include/openssl/buffer.h", 
-    "src/include/openssl/bytestring.h", 
-    "src/include/openssl/cast.h", 
-    "src/include/openssl/chacha.h", 
-    "src/include/openssl/cipher.h", 
-    "src/include/openssl/cmac.h", 
-    "src/include/openssl/conf.h", 
-    "src/include/openssl/cpu.h", 
-    "src/include/openssl/crypto.h", 
-    "src/include/openssl/ctrdrbg.h", 
-    "src/include/openssl/curve25519.h", 
-    "src/include/openssl/des.h", 
-    "src/include/openssl/dh.h", 
-    "src/include/openssl/digest.h", 
-    "src/include/openssl/dsa.h", 
-    "src/include/openssl/e_os2.h", 
-    "src/include/openssl/ec.h", 
-    "src/include/openssl/ec_key.h", 
-    "src/include/openssl/ecdh.h", 
-    "src/include/openssl/ecdsa.h", 
-    "src/include/openssl/engine.h", 
-    "src/include/openssl/err.h", 
-    "src/include/openssl/evp.h", 
-    "src/include/openssl/evp_errors.h", 
-    "src/include/openssl/ex_data.h", 
-    "src/include/openssl/experimental/kyber.h", 
-    "src/include/openssl/hkdf.h", 
-    "src/include/openssl/hmac.h", 
-    "src/include/openssl/hpke.h", 
-    "src/include/openssl/hrss.h", 
-    "src/include/openssl/is_boringssl.h", 
-    "src/include/openssl/kdf.h", 
-    "src/include/openssl/lhash.h", 
-    "src/include/openssl/md4.h", 
-    "src/include/openssl/md5.h", 
-    "src/include/openssl/mem.h", 
-    "src/include/openssl/mldsa.h", 
-    "src/include/openssl/mlkem.h", 
-    "src/include/openssl/nid.h", 
-    "src/include/openssl/obj.h", 
-    "src/include/openssl/obj_mac.h", 
-    "src/include/openssl/objects.h", 
-    "src/include/openssl/opensslconf.h", 
-    "src/include/openssl/opensslv.h", 
-    "src/include/openssl/ossl_typ.h", 
-    "src/include/openssl/pem.h", 
-    "src/include/openssl/pkcs12.h", 
-    "src/include/openssl/pkcs7.h", 
-    "src/include/openssl/pkcs8.h", 
-    "src/include/openssl/poly1305.h", 
-    "src/include/openssl/pool.h", 
-    "src/include/openssl/posix_time.h", 
-    "src/include/openssl/rand.h", 
-    "src/include/openssl/rc4.h", 
-    "src/include/openssl/ripemd.h", 
-    "src/include/openssl/rsa.h", 
-    "src/include/openssl/safestack.h", 
-    "src/include/openssl/service_indicator.h", 
-    "src/include/openssl/sha.h", 
-    "src/include/openssl/siphash.h", 
-    "src/include/openssl/slhdsa.h", 
-    "src/include/openssl/span.h", 
-    "src/include/openssl/stack.h", 
-    "src/include/openssl/target.h", 
-    "src/include/openssl/thread.h", 
-    "src/include/openssl/time.h", 
-    "src/include/openssl/trust_token.h", 
-    "src/include/openssl/type_check.h", 
-    "src/include/openssl/x509.h", 
-    "src/include/openssl/x509_vfy.h", 
-    "src/include/openssl/x509v3.h", 
+    "src/include/openssl/aead.h",
+    "src/include/openssl/aes.h",
+    "src/include/openssl/arm_arch.h",
+    "src/include/openssl/asm_base.h",
+    "src/include/openssl/asn1.h",
+    "src/include/openssl/asn1_mac.h",
+    "src/include/openssl/asn1t.h",
+    "src/include/openssl/base.h",
+    "src/include/openssl/base64.h",
+    "src/include/openssl/bcm_public.h",
+    "src/include/openssl/bio.h",
+    "src/include/openssl/blake2.h",
+    "src/include/openssl/blowfish.h",
+    "src/include/openssl/bn.h",
+    "src/include/openssl/buf.h",
+    "src/include/openssl/buffer.h",
+    "src/include/openssl/bytestring.h",
+    "src/include/openssl/cast.h",
+    "src/include/openssl/chacha.h",
+    "src/include/openssl/cipher.h",
+    "src/include/openssl/cmac.h",
+    "src/include/openssl/cms.h",
+    "src/include/openssl/conf.h",
+    "src/include/openssl/cpu.h",
+    "src/include/openssl/crypto.h",
+    "src/include/openssl/ctrdrbg.h",
+    "src/include/openssl/curve25519.h",
+    "src/include/openssl/des.h",
+    "src/include/openssl/dh.h",
+    "src/include/openssl/digest.h",
+    "src/include/openssl/dsa.h",
+    "src/include/openssl/e_os2.h",
+    "src/include/openssl/ec.h",
+    "src/include/openssl/ec_key.h",
+    "src/include/openssl/ecdh.h",
+    "src/include/openssl/ecdsa.h",
+    "src/include/openssl/engine.h",
+    "src/include/openssl/err.h",
+    "src/include/openssl/evp.h",
+    "src/include/openssl/evp_errors.h",
+    "src/include/openssl/ex_data.h",
+    "src/include/openssl/experimental/kyber.h",
+    "src/include/openssl/hkdf.h",
+    "src/include/openssl/hmac.h",
+    "src/include/openssl/hpke.h",
+    "src/include/openssl/hrss.h",
+    "src/include/openssl/is_boringssl.h",
+    "src/include/openssl/kdf.h",
+    "src/include/openssl/lhash.h",
+    "src/include/openssl/md4.h",
+    "src/include/openssl/md5.h",
+    "src/include/openssl/mem.h",
+    "src/include/openssl/mldsa.h",
+    "src/include/openssl/mlkem.h",
+    "src/include/openssl/nid.h",
+    "src/include/openssl/obj.h",
+    "src/include/openssl/obj_mac.h",
+    "src/include/openssl/objects.h",
+    "src/include/openssl/opensslconf.h",
+    "src/include/openssl/opensslv.h",
+    "src/include/openssl/ossl_typ.h",
+    "src/include/openssl/pem.h",
+    "src/include/openssl/pkcs12.h",
+    "src/include/openssl/pkcs7.h",
+    "src/include/openssl/pkcs8.h",
+    "src/include/openssl/poly1305.h",
+    "src/include/openssl/pool.h",
+    "src/include/openssl/posix_time.h",
+    "src/include/openssl/rand.h",
+    "src/include/openssl/rc4.h",
+    "src/include/openssl/ripemd.h",
+    "src/include/openssl/rsa.h",
+    "src/include/openssl/safestack.h",
+    "src/include/openssl/service_indicator.h",
+    "src/include/openssl/sha.h",
+    "src/include/openssl/siphash.h",
+    "src/include/openssl/slhdsa.h",
+    "src/include/openssl/span.h",
+    "src/include/openssl/stack.h",
+    "src/include/openssl/target.h",
+    "src/include/openssl/thread.h",
+    "src/include/openssl/time.h",
+    "src/include/openssl/trust_token.h",
+    "src/include/openssl/type_check.h",
+    "src/include/openssl/x509.h",
+    "src/include/openssl/x509_vfy.h",
+    "src/include/openssl/x509v3.h",
     "src/include/openssl/x509v3_errors.h"
-  ], 
+  ],
   "crypto_internal_headers": [
-    "src/crypto/asn1/internal.h", 
-    "src/crypto/bcm_support.h", 
-    "src/crypto/bio/internal.h", 
-    "src/crypto/bytestring/internal.h", 
-    "src/crypto/chacha/internal.h", 
-    "src/crypto/cipher/internal.h", 
-    "src/crypto/conf/internal.h", 
-    "src/crypto/cpu_arm_linux.h", 
-    "src/crypto/curve25519/curve25519_tables.h", 
-    "src/crypto/curve25519/internal.h", 
-    "src/crypto/des/internal.h", 
-    "src/crypto/dsa/internal.h", 
-    "src/crypto/ec/internal.h", 
-    "src/crypto/err/internal.h", 
-    "src/crypto/evp/internal.h", 
-    "src/crypto/fipsmodule/aes/internal.h", 
-    "src/crypto/fipsmodule/bcm_interface.h", 
-    "src/crypto/fipsmodule/bn/internal.h", 
-    "src/crypto/fipsmodule/bn/rsaz_exp.h", 
-    "src/crypto/fipsmodule/cipher/internal.h", 
-    "src/crypto/fipsmodule/delocate.h", 
-    "src/crypto/fipsmodule/dh/internal.h", 
-    "src/crypto/fipsmodule/digest/internal.h", 
-    "src/crypto/fipsmodule/digest/md32_common.h", 
-    "src/crypto/fipsmodule/ec/builtin_curves.h", 
-    "src/crypto/fipsmodule/ec/internal.h", 
-    "src/crypto/fipsmodule/ec/p256-nistz-table.h", 
-    "src/crypto/fipsmodule/ec/p256-nistz.h", 
-    "src/crypto/fipsmodule/ec/p256_table.h", 
-    "src/crypto/fipsmodule/ecdsa/internal.h", 
-    "src/crypto/fipsmodule/keccak/internal.h", 
-    "src/crypto/fipsmodule/rand/internal.h", 
-    "src/crypto/fipsmodule/rsa/internal.h", 
-    "src/crypto/fipsmodule/service_indicator/internal.h", 
-    "src/crypto/fipsmodule/sha/internal.h", 
-    "src/crypto/fipsmodule/slhdsa/address.h", 
-    "src/crypto/fipsmodule/slhdsa/fors.h", 
-    "src/crypto/fipsmodule/slhdsa/merkle.h", 
-    "src/crypto/fipsmodule/slhdsa/params.h", 
-    "src/crypto/fipsmodule/slhdsa/thash.h", 
-    "src/crypto/fipsmodule/slhdsa/wots.h", 
-    "src/crypto/fipsmodule/tls/internal.h", 
-    "src/crypto/hrss/internal.h", 
-    "src/crypto/internal.h", 
-    "src/crypto/kyber/internal.h", 
-    "src/crypto/lhash/internal.h", 
-    "src/crypto/md5/internal.h", 
-    "src/crypto/obj/obj_dat.h", 
-    "src/crypto/pem/internal.h", 
-    "src/crypto/pkcs7/internal.h", 
-    "src/crypto/pkcs8/internal.h", 
-    "src/crypto/poly1305/internal.h", 
-    "src/crypto/pool/internal.h", 
-    "src/crypto/rand/getrandom_fillin.h", 
-    "src/crypto/rand/sysrand_internal.h", 
-    "src/crypto/rsa/internal.h", 
-    "src/crypto/spake2plus/internal.h", 
-    "src/crypto/trust_token/internal.h", 
-    "src/crypto/x509/ext_dat.h", 
-    "src/crypto/x509/internal.h", 
-    "src/third_party/fiat/curve25519_32.h", 
-    "src/third_party/fiat/curve25519_64.h", 
-    "src/third_party/fiat/curve25519_64_adx.h", 
-    "src/third_party/fiat/curve25519_64_msvc.h", 
-    "src/third_party/fiat/p256_32.h", 
-    "src/third_party/fiat/p256_64.h", 
+    "src/crypto/asn1/internal.h",
+    "src/crypto/bcm_support.h",
+    "src/crypto/bio/internal.h",
+    "src/crypto/bytestring/internal.h",
+    "src/crypto/chacha/internal.h",
+    "src/crypto/cipher/internal.h",
+    "src/crypto/conf/internal.h",
+    "src/crypto/cpu_arm_linux.h",
+    "src/crypto/curve25519/curve25519_tables.h",
+    "src/crypto/curve25519/internal.h",
+    "src/crypto/des/internal.h",
+    "src/crypto/dsa/internal.h",
+    "src/crypto/ec/internal.h",
+    "src/crypto/err/internal.h",
+    "src/crypto/evp/internal.h",
+    "src/crypto/fipsmodule/aes/internal.h",
+    "src/crypto/fipsmodule/bcm_interface.h",
+    "src/crypto/fipsmodule/bn/internal.h",
+    "src/crypto/fipsmodule/bn/rsaz_exp.h",
+    "src/crypto/fipsmodule/cipher/internal.h",
+    "src/crypto/fipsmodule/delocate.h",
+    "src/crypto/fipsmodule/dh/internal.h",
+    "src/crypto/fipsmodule/digest/internal.h",
+    "src/crypto/fipsmodule/digest/md32_common.h",
+    "src/crypto/fipsmodule/ec/builtin_curves.h",
+    "src/crypto/fipsmodule/ec/internal.h",
+    "src/crypto/fipsmodule/ec/p256-nistz-table.h",
+    "src/crypto/fipsmodule/ec/p256-nistz.h",
+    "src/crypto/fipsmodule/ec/p256_table.h",
+    "src/crypto/fipsmodule/ecdsa/internal.h",
+    "src/crypto/fipsmodule/keccak/internal.h",
+    "src/crypto/fipsmodule/rand/internal.h",
+    "src/crypto/fipsmodule/rsa/internal.h",
+    "src/crypto/fipsmodule/service_indicator/internal.h",
+    "src/crypto/fipsmodule/sha/internal.h",
+    "src/crypto/fipsmodule/slhdsa/address.h",
+    "src/crypto/fipsmodule/slhdsa/fors.h",
+    "src/crypto/fipsmodule/slhdsa/merkle.h",
+    "src/crypto/fipsmodule/slhdsa/params.h",
+    "src/crypto/fipsmodule/slhdsa/thash.h",
+    "src/crypto/fipsmodule/slhdsa/wots.h",
+    "src/crypto/fipsmodule/tls/internal.h",
+    "src/crypto/hrss/internal.h",
+    "src/crypto/internal.h",
+    "src/crypto/kyber/internal.h",
+    "src/crypto/lhash/internal.h",
+    "src/crypto/md5/internal.h",
+    "src/crypto/obj/obj_dat.h",
+    "src/crypto/pem/internal.h",
+    "src/crypto/pkcs7/internal.h",
+    "src/crypto/pkcs8/internal.h",
+    "src/crypto/poly1305/internal.h",
+    "src/crypto/pool/internal.h",
+    "src/crypto/rand/getrandom_fillin.h",
+    "src/crypto/rand/internal.h",
+    "src/crypto/rsa/internal.h",
+    "src/crypto/spake2plus/internal.h",
+    "src/crypto/trust_token/internal.h",
+    "src/crypto/x509/ext_dat.h",
+    "src/crypto/x509/internal.h",
+    "src/third_party/fiat/curve25519_32.h",
+    "src/third_party/fiat/curve25519_64.h",
+    "src/third_party/fiat/curve25519_64_adx.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_nasm": [
-    "src/gen/bcm/aes-gcm-avx10-x86_64-win.asm", 
-    "src/gen/bcm/aes-gcm-avx2-x86_64-win.asm", 
-    "src/gen/bcm/aesni-gcm-x86_64-win.asm", 
-    "src/gen/bcm/aesni-x86-win.asm", 
-    "src/gen/bcm/aesni-x86_64-win.asm", 
-    "src/gen/bcm/bn-586-win.asm", 
-    "src/gen/bcm/co-586-win.asm", 
-    "src/gen/bcm/ghash-ssse3-x86-win.asm", 
-    "src/gen/bcm/ghash-ssse3-x86_64-win.asm", 
-    "src/gen/bcm/ghash-x86-win.asm", 
-    "src/gen/bcm/ghash-x86_64-win.asm", 
-    "src/gen/bcm/p256-x86_64-asm-win.asm", 
-    "src/gen/bcm/p256_beeu-x86_64-asm-win.asm", 
-    "src/gen/bcm/rdrand-x86_64-win.asm", 
-    "src/gen/bcm/rsaz-avx2-win.asm", 
-    "src/gen/bcm/sha1-586-win.asm", 
-    "src/gen/bcm/sha1-x86_64-win.asm", 
-    "src/gen/bcm/sha256-586-win.asm", 
-    "src/gen/bcm/sha256-x86_64-win.asm", 
-    "src/gen/bcm/sha512-586-win.asm", 
-    "src/gen/bcm/sha512-x86_64-win.asm", 
-    "src/gen/bcm/vpaes-x86-win.asm", 
-    "src/gen/bcm/vpaes-x86_64-win.asm", 
-    "src/gen/bcm/x86-mont-win.asm", 
-    "src/gen/bcm/x86_64-mont-win.asm", 
-    "src/gen/bcm/x86_64-mont5-win.asm", 
-    "src/gen/crypto/aes128gcmsiv-x86_64-win.asm", 
-    "src/gen/crypto/chacha-x86-win.asm", 
-    "src/gen/crypto/chacha-x86_64-win.asm", 
-    "src/gen/crypto/chacha20_poly1305_x86_64-win.asm", 
-    "src/gen/crypto/md5-586-win.asm", 
-    "src/gen/crypto/md5-x86_64-win.asm", 
-    "src/gen/test_support/trampoline-x86-win.asm", 
+    "src/gen/bcm/aes-gcm-avx2-x86_64-win.asm",
+    "src/gen/bcm/aes-gcm-avx512-x86_64-win.asm",
+    "src/gen/bcm/aesni-gcm-x86_64-win.asm",
+    "src/gen/bcm/aesni-x86-win.asm",
+    "src/gen/bcm/aesni-x86_64-win.asm",
+    "src/gen/bcm/bn-586-win.asm",
+    "src/gen/bcm/co-586-win.asm",
+    "src/gen/bcm/ghash-ssse3-x86-win.asm",
+    "src/gen/bcm/ghash-ssse3-x86_64-win.asm",
+    "src/gen/bcm/ghash-x86-win.asm",
+    "src/gen/bcm/ghash-x86_64-win.asm",
+    "src/gen/bcm/p256-x86_64-asm-win.asm",
+    "src/gen/bcm/p256_beeu-x86_64-asm-win.asm",
+    "src/gen/bcm/rdrand-x86_64-win.asm",
+    "src/gen/bcm/rsaz-avx2-win.asm",
+    "src/gen/bcm/sha1-586-win.asm",
+    "src/gen/bcm/sha1-x86_64-win.asm",
+    "src/gen/bcm/sha256-586-win.asm",
+    "src/gen/bcm/sha256-x86_64-win.asm",
+    "src/gen/bcm/sha512-586-win.asm",
+    "src/gen/bcm/sha512-x86_64-win.asm",
+    "src/gen/bcm/vpaes-x86-win.asm",
+    "src/gen/bcm/vpaes-x86_64-win.asm",
+    "src/gen/bcm/x86-mont-win.asm",
+    "src/gen/bcm/x86_64-mont-win.asm",
+    "src/gen/bcm/x86_64-mont5-win.asm",
+    "src/gen/crypto/aes128gcmsiv-x86_64-win.asm",
+    "src/gen/crypto/chacha-x86-win.asm",
+    "src/gen/crypto/chacha-x86_64-win.asm",
+    "src/gen/crypto/chacha20_poly1305_x86_64-win.asm",
+    "src/gen/crypto/md5-586-win.asm",
+    "src/gen/crypto/md5-x86_64-win.asm",
+    "src/gen/test_support/trampoline-x86-win.asm",
     "src/gen/test_support/trampoline-x86_64-win.asm"
-  ], 
+  ],
   "crypto_test": [
-    "src/crypto/abi_self_test.cc", 
-    "src/crypto/asn1/asn1_test.cc", 
-    "src/crypto/base64/base64_test.cc", 
-    "src/crypto/bio/bio_test.cc", 
-    "src/crypto/blake2/blake2_test.cc", 
-    "src/crypto/buf/buf_test.cc", 
-    "src/crypto/bytestring/bytestring_test.cc", 
-    "src/crypto/chacha/chacha_test.cc", 
-    "src/crypto/cipher/aead_test.cc", 
-    "src/crypto/cipher/cipher_test.cc", 
-    "src/crypto/compiler_test.cc", 
-    "src/crypto/conf/conf_test.cc", 
-    "src/crypto/constant_time_test.cc", 
-    "src/crypto/cpu_arm_linux_test.cc", 
-    "src/crypto/crypto_test.cc", 
-    "src/crypto/curve25519/ed25519_test.cc", 
-    "src/crypto/curve25519/spake25519_test.cc", 
-    "src/crypto/curve25519/x25519_test.cc", 
-    "src/crypto/dh/dh_test.cc", 
-    "src/crypto/digest/digest_test.cc", 
-    "src/crypto/dsa/dsa_test.cc", 
-    "src/crypto/ecdh/ecdh_test.cc", 
-    "src/crypto/err/err_test.cc", 
-    "src/crypto/evp/evp_extra_test.cc", 
-    "src/crypto/evp/evp_test.cc", 
-    "src/crypto/evp/pbkdf_test.cc", 
-    "src/crypto/evp/scrypt_test.cc", 
-    "src/crypto/fipsmodule/aes/aes_test.cc", 
-    "src/crypto/fipsmodule/aes/gcm_test.cc", 
-    "src/crypto/fipsmodule/bn/bn_test.cc", 
-    "src/crypto/fipsmodule/cmac/cmac_test.cc", 
-    "src/crypto/fipsmodule/ec/ec_test.cc", 
-    "src/crypto/fipsmodule/ec/p256-nistz_test.cc", 
-    "src/crypto/fipsmodule/ec/p256_test.cc", 
-    "src/crypto/fipsmodule/ecdsa/ecdsa_test.cc", 
-    "src/crypto/fipsmodule/hkdf/hkdf_test.cc", 
-    "src/crypto/fipsmodule/keccak/keccak_test.cc", 
-    "src/crypto/fipsmodule/rand/ctrdrbg_test.cc", 
-    "src/crypto/fipsmodule/service_indicator/service_indicator_test.cc", 
-    "src/crypto/fipsmodule/sha/sha_test.cc", 
-    "src/crypto/hmac/hmac_test.cc", 
-    "src/crypto/hpke/hpke_test.cc", 
-    "src/crypto/hrss/hrss_test.cc", 
-    "src/crypto/impl_dispatch_test.cc", 
-    "src/crypto/kyber/kyber_test.cc", 
-    "src/crypto/lhash/lhash_test.cc", 
-    "src/crypto/md5/md5_test.cc", 
-    "src/crypto/mldsa/mldsa_test.cc", 
-    "src/crypto/mlkem/mlkem_test.cc", 
-    "src/crypto/obj/obj_test.cc", 
-    "src/crypto/pem/pem_test.cc", 
-    "src/crypto/pkcs7/pkcs7_test.cc", 
-    "src/crypto/pkcs8/pkcs12_test.cc", 
-    "src/crypto/pkcs8/pkcs8_test.cc", 
-    "src/crypto/poly1305/poly1305_test.cc", 
-    "src/crypto/pool/pool_test.cc", 
-    "src/crypto/rand/fork_detect_test.cc", 
-    "src/crypto/rand/getentropy_test.cc", 
-    "src/crypto/rand/rand_test.cc", 
-    "src/crypto/refcount_test.cc", 
-    "src/crypto/rsa/rsa_test.cc", 
-    "src/crypto/self_test.cc", 
-    "src/crypto/siphash/siphash_test.cc", 
-    "src/crypto/slhdsa/slhdsa_test.cc", 
-    "src/crypto/spake2plus/spake2plus_test.cc", 
-    "src/crypto/stack/stack_test.cc", 
-    "src/crypto/test/gtest_main.cc", 
-    "src/crypto/thread_test.cc", 
-    "src/crypto/trust_token/trust_token_test.cc", 
-    "src/crypto/x509/tab_test.cc", 
-    "src/crypto/x509/x509_test.cc", 
+    "src/crypto/abi_self_test.cc",
+    "src/crypto/asn1/asn1_test.cc",
+    "src/crypto/base64/base64_test.cc",
+    "src/crypto/bio/bio_test.cc",
+    "src/crypto/blake2/blake2_test.cc",
+    "src/crypto/buf/buf_test.cc",
+    "src/crypto/bytestring/bytestring_test.cc",
+    "src/crypto/chacha/chacha_test.cc",
+    "src/crypto/cipher/aead_test.cc",
+    "src/crypto/cipher/cipher_test.cc",
+    "src/crypto/cms/cms_test.cc",
+    "src/crypto/compiler_test.cc",
+    "src/crypto/conf/conf_test.cc",
+    "src/crypto/constant_time_test.cc",
+    "src/crypto/cpu_arm_linux_test.cc",
+    "src/crypto/crypto_test.cc",
+    "src/crypto/curve25519/ed25519_test.cc",
+    "src/crypto/curve25519/spake25519_test.cc",
+    "src/crypto/curve25519/x25519_test.cc",
+    "src/crypto/dh/dh_test.cc",
+    "src/crypto/digest/digest_test.cc",
+    "src/crypto/dsa/dsa_test.cc",
+    "src/crypto/ecdh/ecdh_test.cc",
+    "src/crypto/err/err_test.cc",
+    "src/crypto/evp/evp_extra_test.cc",
+    "src/crypto/evp/evp_test.cc",
+    "src/crypto/evp/pbkdf_test.cc",
+    "src/crypto/evp/scrypt_test.cc",
+    "src/crypto/fipsmodule/aes/aes_test.cc",
+    "src/crypto/fipsmodule/aes/gcm_test.cc",
+    "src/crypto/fipsmodule/bn/bn_test.cc",
+    "src/crypto/fipsmodule/cmac/cmac_test.cc",
+    "src/crypto/fipsmodule/ec/ec_test.cc",
+    "src/crypto/fipsmodule/ec/p256-nistz_test.cc",
+    "src/crypto/fipsmodule/ec/p256_test.cc",
+    "src/crypto/fipsmodule/ecdsa/ecdsa_test.cc",
+    "src/crypto/fipsmodule/hkdf/hkdf_test.cc",
+    "src/crypto/fipsmodule/keccak/keccak_test.cc",
+    "src/crypto/fipsmodule/rand/ctrdrbg_test.cc",
+    "src/crypto/fipsmodule/service_indicator/service_indicator_test.cc",
+    "src/crypto/fipsmodule/sha/sha_test.cc",
+    "src/crypto/hmac/hmac_test.cc",
+    "src/crypto/hpke/hpke_test.cc",
+    "src/crypto/hrss/hrss_test.cc",
+    "src/crypto/impl_dispatch_test.cc",
+    "src/crypto/kyber/kyber_test.cc",
+    "src/crypto/lhash/lhash_test.cc",
+    "src/crypto/md5/md5_test.cc",
+    "src/crypto/mldsa/mldsa_test.cc",
+    "src/crypto/mlkem/mlkem_test.cc",
+    "src/crypto/obj/obj_test.cc",
+    "src/crypto/pem/pem_test.cc",
+    "src/crypto/pkcs7/pkcs7_test.cc",
+    "src/crypto/pkcs8/pkcs12_test.cc",
+    "src/crypto/pkcs8/pkcs8_test.cc",
+    "src/crypto/poly1305/poly1305_test.cc",
+    "src/crypto/pool/pool_test.cc",
+    "src/crypto/rand/fork_detect_test.cc",
+    "src/crypto/rand/getentropy_test.cc",
+    "src/crypto/rand/rand_test.cc",
+    "src/crypto/refcount_test.cc",
+    "src/crypto/rsa/rsa_test.cc",
+    "src/crypto/self_test.cc",
+    "src/crypto/siphash/siphash_test.cc",
+    "src/crypto/slhdsa/slhdsa_test.cc",
+    "src/crypto/spake2plus/spake2plus_test.cc",
+    "src/crypto/stack/stack_test.cc",
+    "src/crypto/test/gtest_main.cc",
+    "src/crypto/thread_test.cc",
+    "src/crypto/trust_token/trust_token_test.cc",
+    "src/crypto/x509/tab_test.cc",
+    "src/crypto/x509/x509_test.cc",
     "src/crypto/x509/x509_time_test.cc"
-  ], 
+  ],
   "crypto_test_data": [
-    "src/crypto/blake2/blake2b256_tests.txt", 
-    "src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt", 
-    "src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt", 
-    "src/crypto/cipher/test/aes_128_ccm_bluetooth_8_tests.txt", 
-    "src/crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt", 
-    "src/crypto/cipher/test/aes_128_ccm_matter_tests.txt", 
-    "src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt", 
-    "src/crypto/cipher/test/aes_128_gcm_randnonce_tests.txt", 
-    "src/crypto/cipher/test/aes_128_gcm_siv_tests.txt", 
-    "src/crypto/cipher/test/aes_128_gcm_tests.txt", 
-    "src/crypto/cipher/test/aes_192_gcm_tests.txt", 
-    "src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt", 
-    "src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt", 
-    "src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt", 
-    "src/crypto/cipher/test/aes_256_gcm_randnonce_tests.txt", 
-    "src/crypto/cipher/test/aes_256_gcm_siv_tests.txt", 
-    "src/crypto/cipher/test/aes_256_gcm_tests.txt", 
-    "src/crypto/cipher/test/chacha20_poly1305_tests.txt", 
-    "src/crypto/cipher/test/cipher_tests.txt", 
-    "src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", 
-    "src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_128_cbc.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_128_ctr.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_128_gcm.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_192_cbc.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_192_ctr.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_256_cbc.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_256_ctr.txt", 
-    "src/crypto/cipher/test/nist_cavp/aes_256_gcm.txt", 
-    "src/crypto/cipher/test/nist_cavp/tdes_cbc.txt", 
-    "src/crypto/cipher/test/nist_cavp/tdes_ecb.txt", 
-    "src/crypto/cipher/test/xchacha20_poly1305_tests.txt", 
-    "src/crypto/curve25519/ed25519_tests.txt", 
-    "src/crypto/ecdh/ecdh_tests.txt", 
-    "src/crypto/evp/evp_tests.txt", 
-    "src/crypto/evp/scrypt_tests.txt", 
-    "src/crypto/fipsmodule/aes/aes_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/exp_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/gcd_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/miller_rabin_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/mod_exp_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/mod_inv_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/mod_mul_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/mod_sqrt_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/product_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/quotient_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/shift_tests.txt", 
-    "src/crypto/fipsmodule/bn/test/sum_tests.txt", 
-    "src/crypto/fipsmodule/cmac/cavp_3des_cmac_tests.txt", 
-    "src/crypto/fipsmodule/cmac/cavp_aes128_cmac_tests.txt", 
-    "src/crypto/fipsmodule/cmac/cavp_aes192_cmac_tests.txt", 
-    "src/crypto/fipsmodule/cmac/cavp_aes256_cmac_tests.txt", 
-    "src/crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt", 
-    "src/crypto/fipsmodule/ec/p256-nistz_tests.txt", 
-    "src/crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt", 
-    "src/crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt", 
-    "src/crypto/fipsmodule/keccak/keccak_tests.txt", 
-    "src/crypto/fipsmodule/rand/ctrdrbg_vectors.txt", 
-    "src/crypto/hmac/hmac_tests.txt", 
-    "src/crypto/hpke/hpke_test_vectors.txt", 
-    "src/crypto/kyber/kyber_tests.txt", 
-    "src/crypto/mldsa/mldsa_nist_keygen_65_tests.txt", 
-    "src/crypto/mldsa/mldsa_nist_keygen_87_tests.txt", 
-    "src/crypto/mldsa/mldsa_nist_siggen_65_tests.txt", 
-    "src/crypto/mldsa/mldsa_nist_siggen_87_tests.txt", 
-    "src/crypto/mlkem/mlkem1024_decap_tests.txt", 
-    "src/crypto/mlkem/mlkem1024_encap_tests.txt", 
-    "src/crypto/mlkem/mlkem1024_keygen_tests.txt", 
-    "src/crypto/mlkem/mlkem1024_nist_decap_tests.txt", 
-    "src/crypto/mlkem/mlkem1024_nist_keygen_tests.txt", 
-    "src/crypto/mlkem/mlkem768_decap_tests.txt", 
-    "src/crypto/mlkem/mlkem768_encap_tests.txt", 
-    "src/crypto/mlkem/mlkem768_keygen_tests.txt", 
-    "src/crypto/mlkem/mlkem768_nist_decap_tests.txt", 
-    "src/crypto/mlkem/mlkem768_nist_keygen_tests.txt", 
-    "src/crypto/pkcs8/test/bad1.p12", 
-    "src/crypto/pkcs8/test/bad2.p12", 
-    "src/crypto/pkcs8/test/bad3.p12", 
-    "src/crypto/pkcs8/test/empty_password.p12", 
-    "src/crypto/pkcs8/test/empty_password_ber.p12", 
-    "src/crypto/pkcs8/test/empty_password_ber_nested.p12", 
-    "src/crypto/pkcs8/test/no_encryption.p12", 
-    "src/crypto/pkcs8/test/nss.p12", 
-    "src/crypto/pkcs8/test/null_password.p12", 
-    "src/crypto/pkcs8/test/openssl.p12", 
-    "src/crypto/pkcs8/test/pbes2_sha1.p12", 
-    "src/crypto/pkcs8/test/pbes2_sha256.p12", 
-    "src/crypto/pkcs8/test/unicode_password.p12", 
-    "src/crypto/pkcs8/test/windows.p12", 
-    "src/crypto/poly1305/poly1305_tests.txt", 
-    "src/crypto/siphash/siphash_tests.txt", 
-    "src/crypto/slhdsa/slhdsa_keygen.txt", 
-    "src/crypto/slhdsa/slhdsa_prehash.txt", 
-    "src/crypto/slhdsa/slhdsa_siggen.txt", 
-    "src/crypto/slhdsa/slhdsa_sigver.txt", 
-    "src/crypto/x509/test/basic_constraints_ca.pem", 
-    "src/crypto/x509/test/basic_constraints_ca_pathlen_0.pem", 
-    "src/crypto/x509/test/basic_constraints_ca_pathlen_1.pem", 
-    "src/crypto/x509/test/basic_constraints_ca_pathlen_10.pem", 
-    "src/crypto/x509/test/basic_constraints_leaf.pem", 
-    "src/crypto/x509/test/basic_constraints_none.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_authority_key_identifier.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_basic_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_ext_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_name_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_subject_alt_name.pem", 
-    "src/crypto/x509/test/invalid_extension_intermediate_subject_key_identifier.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_authority_key_identifier.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_basic_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_ext_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_name_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_subject_alt_name.pem", 
-    "src/crypto/x509/test/invalid_extension_leaf_subject_key_identifier.pem", 
-    "src/crypto/x509/test/invalid_extension_root.pem", 
-    "src/crypto/x509/test/invalid_extension_root_authority_key_identifier.pem", 
-    "src/crypto/x509/test/invalid_extension_root_basic_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_root_ext_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_root_key_usage.pem", 
-    "src/crypto/x509/test/invalid_extension_root_name_constraints.pem", 
-    "src/crypto/x509/test/invalid_extension_root_subject_alt_name.pem", 
-    "src/crypto/x509/test/invalid_extension_root_subject_key_identifier.pem", 
-    "src/crypto/x509/test/many_constraints.pem", 
-    "src/crypto/x509/test/many_names1.pem", 
-    "src/crypto/x509/test/many_names2.pem", 
-    "src/crypto/x509/test/many_names3.pem", 
-    "src/crypto/x509/test/policy_intermediate.pem", 
-    "src/crypto/x509/test/policy_intermediate_any.pem", 
-    "src/crypto/x509/test/policy_intermediate_duplicate.pem", 
-    "src/crypto/x509/test/policy_intermediate_invalid.pem", 
-    "src/crypto/x509/test/policy_intermediate_mapped.pem", 
-    "src/crypto/x509/test/policy_intermediate_mapped_any.pem", 
-    "src/crypto/x509/test/policy_intermediate_mapped_oid3.pem", 
-    "src/crypto/x509/test/policy_intermediate_require.pem", 
-    "src/crypto/x509/test/policy_intermediate_require1.pem", 
-    "src/crypto/x509/test/policy_intermediate_require2.pem", 
-    "src/crypto/x509/test/policy_intermediate_require_duplicate.pem", 
-    "src/crypto/x509/test/policy_intermediate_require_no_policies.pem", 
-    "src/crypto/x509/test/policy_leaf.pem", 
-    "src/crypto/x509/test/policy_leaf_any.pem", 
-    "src/crypto/x509/test/policy_leaf_duplicate.pem", 
-    "src/crypto/x509/test/policy_leaf_invalid.pem", 
-    "src/crypto/x509/test/policy_leaf_none.pem", 
-    "src/crypto/x509/test/policy_leaf_oid1.pem", 
-    "src/crypto/x509/test/policy_leaf_oid2.pem", 
-    "src/crypto/x509/test/policy_leaf_oid3.pem", 
-    "src/crypto/x509/test/policy_leaf_oid4.pem", 
-    "src/crypto/x509/test/policy_leaf_oid5.pem", 
-    "src/crypto/x509/test/policy_leaf_require.pem", 
-    "src/crypto/x509/test/policy_leaf_require1.pem", 
-    "src/crypto/x509/test/policy_root.pem", 
-    "src/crypto/x509/test/policy_root2.pem", 
-    "src/crypto/x509/test/policy_root_cross_inhibit_mapping.pem", 
-    "src/crypto/x509/test/pss_sha1.pem", 
-    "src/crypto/x509/test/pss_sha1_explicit.pem", 
-    "src/crypto/x509/test/pss_sha1_mgf1_syntax_error.pem", 
-    "src/crypto/x509/test/pss_sha224.pem", 
-    "src/crypto/x509/test/pss_sha256.pem", 
-    "src/crypto/x509/test/pss_sha256_explicit_trailer.pem", 
-    "src/crypto/x509/test/pss_sha256_mgf1_sha384.pem", 
-    "src/crypto/x509/test/pss_sha256_mgf1_syntax_error.pem", 
-    "src/crypto/x509/test/pss_sha256_omit_nulls.pem", 
-    "src/crypto/x509/test/pss_sha256_salt31.pem", 
-    "src/crypto/x509/test/pss_sha256_salt_overflow.pem", 
-    "src/crypto/x509/test/pss_sha256_unknown_mgf.pem", 
-    "src/crypto/x509/test/pss_sha256_wrong_trailer.pem", 
-    "src/crypto/x509/test/pss_sha384.pem", 
-    "src/crypto/x509/test/pss_sha512.pem", 
-    "src/crypto/x509/test/some_names1.pem", 
-    "src/crypto/x509/test/some_names2.pem", 
-    "src/crypto/x509/test/some_names3.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_basic_constraints.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_ext_key_usage.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_key_usage.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_name_constraints.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_subject_alt_name.pem", 
-    "src/crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem", 
-    "src/third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt", 
-    "src/third_party/wycheproof_testvectors/aes_cmac_test.txt", 
-    "src/third_party/wycheproof_testvectors/aes_gcm_siv_test.txt", 
-    "src/third_party/wycheproof_testvectors/aes_gcm_test.txt", 
-    "src/third_party/wycheproof_testvectors/chacha20_poly1305_test.txt", 
-    "src/third_party/wycheproof_testvectors/dsa_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdh_secp224r1_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdh_secp256r1_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdh_secp384r1_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdh_secp521r1_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/eddsa_test.txt", 
-    "src/third_party/wycheproof_testvectors/hkdf_sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/hkdf_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/hkdf_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/hkdf_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/hmac_sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/hmac_sha224_test.txt", 
-    "src/third_party/wycheproof_testvectors/hmac_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/hmac_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/hmac_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/kw_test.txt", 
-    "src/third_party/wycheproof_testvectors/kwp_test.txt", 
-    "src/third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt", 
-    "src/third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt", 
-    "src/third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt", 
-    "src/third_party/wycheproof_testvectors/mldsa_87_standard_verify_test.txt", 
-    "src/third_party/wycheproof_testvectors/primality_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha1_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha224_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha1_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_32_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_3072_sha256_mgf1_32_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_4096_sha256_mgf1_32_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_4096_sha512_mgf1_32_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_pss_misc_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt", 
-    "src/third_party/wycheproof_testvectors/rsa_signature_test.txt", 
-    "src/third_party/wycheproof_testvectors/x25519_test.txt", 
+    "src/crypto/blake2/blake2b256_tests.txt",
+    "src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt",
+    "src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt",
+    "src/crypto/cipher/test/aes_128_ccm_bluetooth_8_tests.txt",
+    "src/crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt",
+    "src/crypto/cipher/test/aes_128_ccm_matter_tests.txt",
+    "src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt",
+    "src/crypto/cipher/test/aes_128_eax_test.txt",
+    "src/crypto/cipher/test/aes_128_gcm_randnonce_tests.txt",
+    "src/crypto/cipher/test/aes_128_gcm_siv_tests.txt",
+    "src/crypto/cipher/test/aes_128_gcm_tests.txt",
+    "src/crypto/cipher/test/aes_192_gcm_tests.txt",
+    "src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt",
+    "src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt",
+    "src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt",
+    "src/crypto/cipher/test/aes_256_eax_test.txt",
+    "src/crypto/cipher/test/aes_256_gcm_randnonce_tests.txt",
+    "src/crypto/cipher/test/aes_256_gcm_siv_tests.txt",
+    "src/crypto/cipher/test/aes_256_gcm_tests.txt",
+    "src/crypto/cipher/test/chacha20_poly1305_tests.txt",
+    "src/crypto/cipher/test/cipher_tests.txt",
+    "src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt",
+    "src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_128_cbc.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_128_ctr.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_128_gcm.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_192_cbc.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_192_ctr.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_256_cbc.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_256_ctr.txt",
+    "src/crypto/cipher/test/nist_cavp/aes_256_gcm.txt",
+    "src/crypto/cipher/test/nist_cavp/tdes_cbc.txt",
+    "src/crypto/cipher/test/nist_cavp/tdes_ecb.txt",
+    "src/crypto/cipher/test/xchacha20_poly1305_tests.txt",
+    "src/crypto/curve25519/ed25519_tests.txt",
+    "src/crypto/ecdh/ecdh_tests.txt",
+    "src/crypto/evp/evp_tests.txt",
+    "src/crypto/evp/scrypt_tests.txt",
+    "src/crypto/fipsmodule/aes/aes_tests.txt",
+    "src/crypto/fipsmodule/bn/test/exp_tests.txt",
+    "src/crypto/fipsmodule/bn/test/gcd_tests.txt",
+    "src/crypto/fipsmodule/bn/test/miller_rabin_tests.txt",
+    "src/crypto/fipsmodule/bn/test/mod_exp_tests.txt",
+    "src/crypto/fipsmodule/bn/test/mod_inv_tests.txt",
+    "src/crypto/fipsmodule/bn/test/mod_mul_tests.txt",
+    "src/crypto/fipsmodule/bn/test/mod_sqrt_tests.txt",
+    "src/crypto/fipsmodule/bn/test/product_tests.txt",
+    "src/crypto/fipsmodule/bn/test/quotient_tests.txt",
+    "src/crypto/fipsmodule/bn/test/shift_tests.txt",
+    "src/crypto/fipsmodule/bn/test/sum_tests.txt",
+    "src/crypto/fipsmodule/cmac/cavp_3des_cmac_tests.txt",
+    "src/crypto/fipsmodule/cmac/cavp_aes128_cmac_tests.txt",
+    "src/crypto/fipsmodule/cmac/cavp_aes192_cmac_tests.txt",
+    "src/crypto/fipsmodule/cmac/cavp_aes256_cmac_tests.txt",
+    "src/crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
+    "src/crypto/fipsmodule/ec/p256-nistz_tests.txt",
+    "src/crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt",
+    "src/crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt",
+    "src/crypto/fipsmodule/keccak/keccak_tests.txt",
+    "src/crypto/fipsmodule/rand/ctrdrbg_vectors.txt",
+    "src/crypto/hmac/hmac_tests.txt",
+    "src/crypto/hpke/hpke_test_vectors.txt",
+    "src/crypto/kyber/kyber_tests.txt",
+    "src/crypto/mldsa/mldsa_nist_keygen_65_tests.txt",
+    "src/crypto/mldsa/mldsa_nist_keygen_87_tests.txt",
+    "src/crypto/mldsa/mldsa_nist_siggen_65_tests.txt",
+    "src/crypto/mldsa/mldsa_nist_siggen_87_tests.txt",
+    "src/crypto/mlkem/mlkem1024_decap_tests.txt",
+    "src/crypto/mlkem/mlkem1024_encap_tests.txt",
+    "src/crypto/mlkem/mlkem1024_keygen_tests.txt",
+    "src/crypto/mlkem/mlkem1024_nist_decap_tests.txt",
+    "src/crypto/mlkem/mlkem1024_nist_keygen_tests.txt",
+    "src/crypto/mlkem/mlkem768_decap_tests.txt",
+    "src/crypto/mlkem/mlkem768_encap_tests.txt",
+    "src/crypto/mlkem/mlkem768_keygen_tests.txt",
+    "src/crypto/mlkem/mlkem768_nist_decap_tests.txt",
+    "src/crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+    "src/crypto/pkcs7/test/nss.p7c",
+    "src/crypto/pkcs7/test/openssl_crl.p7c",
+    "src/crypto/pkcs7/test/sign_cert.pem",
+    "src/crypto/pkcs7/test/sign_key.pem",
+    "src/crypto/pkcs7/test/sign_sha1.p7s",
+    "src/crypto/pkcs7/test/sign_sha1_key_id.p7s",
+    "src/crypto/pkcs7/test/sign_sha256.p7s",
+    "src/crypto/pkcs7/test/sign_sha256_key_id.p7s",
+    "src/crypto/pkcs7/test/windows.p7c",
+    "src/crypto/pkcs8/test/bad1.p12",
+    "src/crypto/pkcs8/test/bad2.p12",
+    "src/crypto/pkcs8/test/bad3.p12",
+    "src/crypto/pkcs8/test/empty_password.p12",
+    "src/crypto/pkcs8/test/empty_password_ber.p12",
+    "src/crypto/pkcs8/test/empty_password_ber_nested.p12",
+    "src/crypto/pkcs8/test/no_encryption.p12",
+    "src/crypto/pkcs8/test/nss.p12",
+    "src/crypto/pkcs8/test/null_password.p12",
+    "src/crypto/pkcs8/test/openssl.p12",
+    "src/crypto/pkcs8/test/pbes2_sha1.p12",
+    "src/crypto/pkcs8/test/pbes2_sha256.p12",
+    "src/crypto/pkcs8/test/unicode_password.p12",
+    "src/crypto/pkcs8/test/windows.p12",
+    "src/crypto/poly1305/poly1305_tests.txt",
+    "src/crypto/siphash/siphash_tests.txt",
+    "src/crypto/slhdsa/slhdsa_keygen.txt",
+    "src/crypto/slhdsa/slhdsa_prehash.txt",
+    "src/crypto/slhdsa/slhdsa_siggen.txt",
+    "src/crypto/slhdsa/slhdsa_sigver.txt",
+    "src/crypto/x509/test/basic_constraints_ca.pem",
+    "src/crypto/x509/test/basic_constraints_ca_pathlen_0.pem",
+    "src/crypto/x509/test/basic_constraints_ca_pathlen_1.pem",
+    "src/crypto/x509/test/basic_constraints_ca_pathlen_10.pem",
+    "src/crypto/x509/test/basic_constraints_leaf.pem",
+    "src/crypto/x509/test/basic_constraints_none.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_authority_key_identifier.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_basic_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_ext_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_name_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_subject_alt_name.pem",
+    "src/crypto/x509/test/invalid_extension_intermediate_subject_key_identifier.pem",
+    "src/crypto/x509/test/invalid_extension_leaf.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_authority_key_identifier.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_basic_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_ext_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_name_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_subject_alt_name.pem",
+    "src/crypto/x509/test/invalid_extension_leaf_subject_key_identifier.pem",
+    "src/crypto/x509/test/invalid_extension_root.pem",
+    "src/crypto/x509/test/invalid_extension_root_authority_key_identifier.pem",
+    "src/crypto/x509/test/invalid_extension_root_basic_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_root_ext_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_root_key_usage.pem",
+    "src/crypto/x509/test/invalid_extension_root_name_constraints.pem",
+    "src/crypto/x509/test/invalid_extension_root_subject_alt_name.pem",
+    "src/crypto/x509/test/invalid_extension_root_subject_key_identifier.pem",
+    "src/crypto/x509/test/many_constraints.pem",
+    "src/crypto/x509/test/many_names1.pem",
+    "src/crypto/x509/test/many_names2.pem",
+    "src/crypto/x509/test/many_names3.pem",
+    "src/crypto/x509/test/policy_intermediate.pem",
+    "src/crypto/x509/test/policy_intermediate_any.pem",
+    "src/crypto/x509/test/policy_intermediate_duplicate.pem",
+    "src/crypto/x509/test/policy_intermediate_invalid.pem",
+    "src/crypto/x509/test/policy_intermediate_mapped.pem",
+    "src/crypto/x509/test/policy_intermediate_mapped_any.pem",
+    "src/crypto/x509/test/policy_intermediate_mapped_oid3.pem",
+    "src/crypto/x509/test/policy_intermediate_require.pem",
+    "src/crypto/x509/test/policy_intermediate_require1.pem",
+    "src/crypto/x509/test/policy_intermediate_require2.pem",
+    "src/crypto/x509/test/policy_intermediate_require_duplicate.pem",
+    "src/crypto/x509/test/policy_intermediate_require_no_policies.pem",
+    "src/crypto/x509/test/policy_leaf.pem",
+    "src/crypto/x509/test/policy_leaf_any.pem",
+    "src/crypto/x509/test/policy_leaf_duplicate.pem",
+    "src/crypto/x509/test/policy_leaf_invalid.pem",
+    "src/crypto/x509/test/policy_leaf_none.pem",
+    "src/crypto/x509/test/policy_leaf_oid1.pem",
+    "src/crypto/x509/test/policy_leaf_oid2.pem",
+    "src/crypto/x509/test/policy_leaf_oid3.pem",
+    "src/crypto/x509/test/policy_leaf_oid4.pem",
+    "src/crypto/x509/test/policy_leaf_oid5.pem",
+    "src/crypto/x509/test/policy_leaf_require.pem",
+    "src/crypto/x509/test/policy_leaf_require1.pem",
+    "src/crypto/x509/test/policy_root.pem",
+    "src/crypto/x509/test/policy_root2.pem",
+    "src/crypto/x509/test/policy_root_cross_inhibit_mapping.pem",
+    "src/crypto/x509/test/pss_sha1.pem",
+    "src/crypto/x509/test/pss_sha1_explicit.pem",
+    "src/crypto/x509/test/pss_sha1_mgf1_syntax_error.pem",
+    "src/crypto/x509/test/pss_sha224.pem",
+    "src/crypto/x509/test/pss_sha256.pem",
+    "src/crypto/x509/test/pss_sha256_explicit_trailer.pem",
+    "src/crypto/x509/test/pss_sha256_mgf1_sha384.pem",
+    "src/crypto/x509/test/pss_sha256_mgf1_syntax_error.pem",
+    "src/crypto/x509/test/pss_sha256_omit_nulls.pem",
+    "src/crypto/x509/test/pss_sha256_salt31.pem",
+    "src/crypto/x509/test/pss_sha256_salt_overflow.pem",
+    "src/crypto/x509/test/pss_sha256_unknown_mgf.pem",
+    "src/crypto/x509/test/pss_sha256_wrong_trailer.pem",
+    "src/crypto/x509/test/pss_sha384.pem",
+    "src/crypto/x509/test/pss_sha512.pem",
+    "src/crypto/x509/test/some_names1.pem",
+    "src/crypto/x509/test/some_names2.pem",
+    "src/crypto/x509/test/some_names3.pem",
+    "src/crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem",
+    "src/crypto/x509/test/trailing_data_leaf_basic_constraints.pem",
+    "src/crypto/x509/test/trailing_data_leaf_ext_key_usage.pem",
+    "src/crypto/x509/test/trailing_data_leaf_key_usage.pem",
+    "src/crypto/x509/test/trailing_data_leaf_name_constraints.pem",
+    "src/crypto/x509/test/trailing_data_leaf_subject_alt_name.pem",
+    "src/crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
+    "src/third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
+    "src/third_party/wycheproof_testvectors/aes_cmac_test.txt",
+    "src/third_party/wycheproof_testvectors/aes_eax_test.txt",
+    "src/third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
+    "src/third_party/wycheproof_testvectors/aes_gcm_test.txt",
+    "src/third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
+    "src/third_party/wycheproof_testvectors/dsa_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdh_secp224r1_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdh_secp256r1_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdh_secp384r1_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdh_secp521r1_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/eddsa_test.txt",
+    "src/third_party/wycheproof_testvectors/hkdf_sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/hkdf_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/hkdf_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/hkdf_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/hmac_sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/hmac_sha224_test.txt",
+    "src/third_party/wycheproof_testvectors/hmac_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/hmac_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/hmac_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/kw_test.txt",
+    "src/third_party/wycheproof_testvectors/kwp_test.txt",
+    "src/third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt",
+    "src/third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt",
+    "src/third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt",
+    "src/third_party/wycheproof_testvectors/mldsa_87_standard_verify_test.txt",
+    "src/third_party/wycheproof_testvectors/primality_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha1_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha224_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha1_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_32_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_3072_sha256_mgf1_32_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_4096_sha256_mgf1_32_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_4096_sha512_mgf1_32_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_pss_misc_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt",
+    "src/third_party/wycheproof_testvectors/rsa_signature_test.txt",
+    "src/third_party/wycheproof_testvectors/x25519_test.txt",
     "src/third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt"
-  ], 
+  ],
   "fips_fragments": [
-    "src/crypto/fipsmodule/aes/aes.cc.inc", 
-    "src/crypto/fipsmodule/aes/aes_nohw.cc.inc", 
-    "src/crypto/fipsmodule/aes/cbc.cc.inc", 
-    "src/crypto/fipsmodule/aes/cfb.cc.inc", 
-    "src/crypto/fipsmodule/aes/ctr.cc.inc", 
-    "src/crypto/fipsmodule/aes/gcm.cc.inc", 
-    "src/crypto/fipsmodule/aes/gcm_nohw.cc.inc", 
-    "src/crypto/fipsmodule/aes/key_wrap.cc.inc", 
-    "src/crypto/fipsmodule/aes/mode_wrappers.cc.inc", 
-    "src/crypto/fipsmodule/aes/ofb.cc.inc", 
-    "src/crypto/fipsmodule/aes/polyval.cc.inc", 
-    "src/crypto/fipsmodule/bn/add.cc.inc", 
-    "src/crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc", 
-    "src/crypto/fipsmodule/bn/bn.cc.inc", 
-    "src/crypto/fipsmodule/bn/bytes.cc.inc", 
-    "src/crypto/fipsmodule/bn/cmp.cc.inc", 
-    "src/crypto/fipsmodule/bn/ctx.cc.inc", 
-    "src/crypto/fipsmodule/bn/div.cc.inc", 
-    "src/crypto/fipsmodule/bn/div_extra.cc.inc", 
-    "src/crypto/fipsmodule/bn/exponentiation.cc.inc", 
-    "src/crypto/fipsmodule/bn/gcd.cc.inc", 
-    "src/crypto/fipsmodule/bn/gcd_extra.cc.inc", 
-    "src/crypto/fipsmodule/bn/generic.cc.inc", 
-    "src/crypto/fipsmodule/bn/jacobi.cc.inc", 
-    "src/crypto/fipsmodule/bn/montgomery.cc.inc", 
-    "src/crypto/fipsmodule/bn/montgomery_inv.cc.inc", 
-    "src/crypto/fipsmodule/bn/mul.cc.inc", 
-    "src/crypto/fipsmodule/bn/prime.cc.inc", 
-    "src/crypto/fipsmodule/bn/random.cc.inc", 
-    "src/crypto/fipsmodule/bn/rsaz_exp.cc.inc", 
-    "src/crypto/fipsmodule/bn/shift.cc.inc", 
-    "src/crypto/fipsmodule/bn/sqrt.cc.inc", 
-    "src/crypto/fipsmodule/cipher/aead.cc.inc", 
-    "src/crypto/fipsmodule/cipher/cipher.cc.inc", 
-    "src/crypto/fipsmodule/cipher/e_aes.cc.inc", 
-    "src/crypto/fipsmodule/cipher/e_aesccm.cc.inc", 
-    "src/crypto/fipsmodule/cmac/cmac.cc.inc", 
-    "src/crypto/fipsmodule/dh/check.cc.inc", 
-    "src/crypto/fipsmodule/dh/dh.cc.inc", 
-    "src/crypto/fipsmodule/digest/digest.cc.inc", 
-    "src/crypto/fipsmodule/digest/digests.cc.inc", 
-    "src/crypto/fipsmodule/digestsign/digestsign.cc.inc", 
-    "src/crypto/fipsmodule/ec/ec.cc.inc", 
-    "src/crypto/fipsmodule/ec/ec_key.cc.inc", 
-    "src/crypto/fipsmodule/ec/ec_montgomery.cc.inc", 
-    "src/crypto/fipsmodule/ec/felem.cc.inc", 
-    "src/crypto/fipsmodule/ec/oct.cc.inc", 
-    "src/crypto/fipsmodule/ec/p224-64.cc.inc", 
-    "src/crypto/fipsmodule/ec/p256-nistz.cc.inc", 
-    "src/crypto/fipsmodule/ec/p256.cc.inc", 
-    "src/crypto/fipsmodule/ec/scalar.cc.inc", 
-    "src/crypto/fipsmodule/ec/simple.cc.inc", 
-    "src/crypto/fipsmodule/ec/simple_mul.cc.inc", 
-    "src/crypto/fipsmodule/ec/util.cc.inc", 
-    "src/crypto/fipsmodule/ec/wnaf.cc.inc", 
-    "src/crypto/fipsmodule/ecdh/ecdh.cc.inc", 
-    "src/crypto/fipsmodule/ecdsa/ecdsa.cc.inc", 
-    "src/crypto/fipsmodule/hkdf/hkdf.cc.inc", 
-    "src/crypto/fipsmodule/hmac/hmac.cc.inc", 
-    "src/crypto/fipsmodule/keccak/keccak.cc.inc", 
-    "src/crypto/fipsmodule/mldsa/mldsa.cc.inc", 
-    "src/crypto/fipsmodule/mlkem/mlkem.cc.inc", 
-    "src/crypto/fipsmodule/rand/ctrdrbg.cc.inc", 
-    "src/crypto/fipsmodule/rand/rand.cc.inc", 
-    "src/crypto/fipsmodule/rsa/blinding.cc.inc", 
-    "src/crypto/fipsmodule/rsa/padding.cc.inc", 
-    "src/crypto/fipsmodule/rsa/rsa.cc.inc", 
-    "src/crypto/fipsmodule/rsa/rsa_impl.cc.inc", 
-    "src/crypto/fipsmodule/self_check/fips.cc.inc", 
-    "src/crypto/fipsmodule/self_check/self_check.cc.inc", 
-    "src/crypto/fipsmodule/service_indicator/service_indicator.cc.inc", 
-    "src/crypto/fipsmodule/sha/sha1.cc.inc", 
-    "src/crypto/fipsmodule/sha/sha256.cc.inc", 
-    "src/crypto/fipsmodule/sha/sha512.cc.inc", 
-    "src/crypto/fipsmodule/slhdsa/fors.cc.inc", 
-    "src/crypto/fipsmodule/slhdsa/merkle.cc.inc", 
-    "src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc", 
-    "src/crypto/fipsmodule/slhdsa/thash.cc.inc", 
-    "src/crypto/fipsmodule/slhdsa/wots.cc.inc", 
+    "src/crypto/fipsmodule/aes/aes.cc.inc",
+    "src/crypto/fipsmodule/aes/aes_nohw.cc.inc",
+    "src/crypto/fipsmodule/aes/cbc.cc.inc",
+    "src/crypto/fipsmodule/aes/cfb.cc.inc",
+    "src/crypto/fipsmodule/aes/ctr.cc.inc",
+    "src/crypto/fipsmodule/aes/gcm.cc.inc",
+    "src/crypto/fipsmodule/aes/gcm_nohw.cc.inc",
+    "src/crypto/fipsmodule/aes/key_wrap.cc.inc",
+    "src/crypto/fipsmodule/aes/mode_wrappers.cc.inc",
+    "src/crypto/fipsmodule/aes/ofb.cc.inc",
+    "src/crypto/fipsmodule/bn/add.cc.inc",
+    "src/crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
+    "src/crypto/fipsmodule/bn/bn.cc.inc",
+    "src/crypto/fipsmodule/bn/bytes.cc.inc",
+    "src/crypto/fipsmodule/bn/cmp.cc.inc",
+    "src/crypto/fipsmodule/bn/ctx.cc.inc",
+    "src/crypto/fipsmodule/bn/div.cc.inc",
+    "src/crypto/fipsmodule/bn/div_extra.cc.inc",
+    "src/crypto/fipsmodule/bn/exponentiation.cc.inc",
+    "src/crypto/fipsmodule/bn/gcd.cc.inc",
+    "src/crypto/fipsmodule/bn/gcd_extra.cc.inc",
+    "src/crypto/fipsmodule/bn/generic.cc.inc",
+    "src/crypto/fipsmodule/bn/jacobi.cc.inc",
+    "src/crypto/fipsmodule/bn/montgomery.cc.inc",
+    "src/crypto/fipsmodule/bn/montgomery_inv.cc.inc",
+    "src/crypto/fipsmodule/bn/mul.cc.inc",
+    "src/crypto/fipsmodule/bn/prime.cc.inc",
+    "src/crypto/fipsmodule/bn/random.cc.inc",
+    "src/crypto/fipsmodule/bn/rsaz_exp.cc.inc",
+    "src/crypto/fipsmodule/bn/shift.cc.inc",
+    "src/crypto/fipsmodule/bn/sqrt.cc.inc",
+    "src/crypto/fipsmodule/cipher/aead.cc.inc",
+    "src/crypto/fipsmodule/cipher/cipher.cc.inc",
+    "src/crypto/fipsmodule/cipher/e_aes.cc.inc",
+    "src/crypto/fipsmodule/cipher/e_aesccm.cc.inc",
+    "src/crypto/fipsmodule/cmac/cmac.cc.inc",
+    "src/crypto/fipsmodule/dh/check.cc.inc",
+    "src/crypto/fipsmodule/dh/dh.cc.inc",
+    "src/crypto/fipsmodule/digest/digest.cc.inc",
+    "src/crypto/fipsmodule/digest/digests.cc.inc",
+    "src/crypto/fipsmodule/digestsign/digestsign.cc.inc",
+    "src/crypto/fipsmodule/ec/ec.cc.inc",
+    "src/crypto/fipsmodule/ec/ec_key.cc.inc",
+    "src/crypto/fipsmodule/ec/ec_montgomery.cc.inc",
+    "src/crypto/fipsmodule/ec/felem.cc.inc",
+    "src/crypto/fipsmodule/ec/oct.cc.inc",
+    "src/crypto/fipsmodule/ec/p224-64.cc.inc",
+    "src/crypto/fipsmodule/ec/p256-nistz.cc.inc",
+    "src/crypto/fipsmodule/ec/p256.cc.inc",
+    "src/crypto/fipsmodule/ec/scalar.cc.inc",
+    "src/crypto/fipsmodule/ec/simple.cc.inc",
+    "src/crypto/fipsmodule/ec/simple_mul.cc.inc",
+    "src/crypto/fipsmodule/ec/util.cc.inc",
+    "src/crypto/fipsmodule/ec/wnaf.cc.inc",
+    "src/crypto/fipsmodule/ecdh/ecdh.cc.inc",
+    "src/crypto/fipsmodule/ecdsa/ecdsa.cc.inc",
+    "src/crypto/fipsmodule/hkdf/hkdf.cc.inc",
+    "src/crypto/fipsmodule/hmac/hmac.cc.inc",
+    "src/crypto/fipsmodule/keccak/keccak.cc.inc",
+    "src/crypto/fipsmodule/mldsa/fips_known_values.inc",
+    "src/crypto/fipsmodule/mldsa/mldsa.cc.inc",
+    "src/crypto/fipsmodule/mlkem/fips_known_values.inc",
+    "src/crypto/fipsmodule/mlkem/mlkem.cc.inc",
+    "src/crypto/fipsmodule/rand/ctrdrbg.cc.inc",
+    "src/crypto/fipsmodule/rand/rand.cc.inc",
+    "src/crypto/fipsmodule/rsa/blinding.cc.inc",
+    "src/crypto/fipsmodule/rsa/padding.cc.inc",
+    "src/crypto/fipsmodule/rsa/rsa.cc.inc",
+    "src/crypto/fipsmodule/rsa/rsa_impl.cc.inc",
+    "src/crypto/fipsmodule/self_check/fips.cc.inc",
+    "src/crypto/fipsmodule/self_check/self_check.cc.inc",
+    "src/crypto/fipsmodule/service_indicator/service_indicator.cc.inc",
+    "src/crypto/fipsmodule/sha/sha1.cc.inc",
+    "src/crypto/fipsmodule/sha/sha256.cc.inc",
+    "src/crypto/fipsmodule/sha/sha512.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/fips_known_values.inc",
+    "src/crypto/fipsmodule/slhdsa/fors.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/merkle.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/thash.cc.inc",
+    "src/crypto/fipsmodule/slhdsa/wots.cc.inc",
     "src/crypto/fipsmodule/tls/kdf.cc.inc"
-  ], 
+  ],
   "fuzz": [
-    "src/fuzz/arm_cpuinfo.cc", 
-    "src/fuzz/bn_div.cc", 
-    "src/fuzz/bn_mod_exp.cc", 
-    "src/fuzz/cert.cc", 
-    "src/fuzz/client.cc", 
-    "src/fuzz/conf.cc", 
-    "src/fuzz/crl_getcrlstatusforcert_fuzzer.cc", 
-    "src/fuzz/crl_parse_crl_certificatelist_fuzzer.cc", 
-    "src/fuzz/crl_parse_crl_tbscertlist_fuzzer.cc", 
-    "src/fuzz/crl_parse_issuing_distribution_point_fuzzer.cc", 
-    "src/fuzz/decode_client_hello_inner.cc", 
-    "src/fuzz/der_roundtrip.cc", 
-    "src/fuzz/dtls_client.cc", 
-    "src/fuzz/dtls_server.cc", 
-    "src/fuzz/ocsp_parse_ocsp_cert_id_fuzzer.cc", 
-    "src/fuzz/ocsp_parse_ocsp_response_data_fuzzer.cc", 
-    "src/fuzz/ocsp_parse_ocsp_response_fuzzer.cc", 
-    "src/fuzz/ocsp_parse_ocsp_single_response_fuzzer.cc", 
-    "src/fuzz/parse_authority_key_identifier_fuzzer.cc", 
-    "src/fuzz/parse_certificate_fuzzer.cc", 
-    "src/fuzz/parse_crldp_fuzzer.cc", 
-    "src/fuzz/pkcs12.cc", 
-    "src/fuzz/pkcs8.cc", 
-    "src/fuzz/privkey.cc", 
-    "src/fuzz/read_pem.cc", 
-    "src/fuzz/server.cc", 
-    "src/fuzz/session.cc", 
-    "src/fuzz/spki.cc", 
-    "src/fuzz/ssl_ctx_api.cc", 
-    "src/fuzz/verify_name_match_fuzzer.cc", 
-    "src/fuzz/verify_name_match_normalizename_fuzzer.cc", 
+    "src/fuzz/arm_cpuinfo.cc",
+    "src/fuzz/bn_div.cc",
+    "src/fuzz/bn_mod_exp.cc",
+    "src/fuzz/cert.cc",
+    "src/fuzz/client.cc",
+    "src/fuzz/client_no_fuzzer_mode.cc",
+    "src/fuzz/conf.cc",
+    "src/fuzz/crl_getcrlstatusforcert_fuzzer.cc",
+    "src/fuzz/crl_parse_crl_certificatelist_fuzzer.cc",
+    "src/fuzz/crl_parse_crl_tbscertlist_fuzzer.cc",
+    "src/fuzz/crl_parse_issuing_distribution_point_fuzzer.cc",
+    "src/fuzz/decode_client_hello_inner.cc",
+    "src/fuzz/der_roundtrip.cc",
+    "src/fuzz/dtls_client.cc",
+    "src/fuzz/dtls_server.cc",
+    "src/fuzz/ocsp_parse_ocsp_cert_id_fuzzer.cc",
+    "src/fuzz/ocsp_parse_ocsp_response_data_fuzzer.cc",
+    "src/fuzz/ocsp_parse_ocsp_response_fuzzer.cc",
+    "src/fuzz/ocsp_parse_ocsp_single_response_fuzzer.cc",
+    "src/fuzz/parse_authority_key_identifier_fuzzer.cc",
+    "src/fuzz/parse_certificate_fuzzer.cc",
+    "src/fuzz/parse_crldp_fuzzer.cc",
+    "src/fuzz/pkcs12.cc",
+    "src/fuzz/pkcs8.cc",
+    "src/fuzz/privkey.cc",
+    "src/fuzz/read_pem.cc",
+    "src/fuzz/server.cc",
+    "src/fuzz/server_no_fuzzer_mode.cc",
+    "src/fuzz/session.cc",
+    "src/fuzz/spki.cc",
+    "src/fuzz/ssl_ctx_api.cc",
+    "src/fuzz/verify_name_match_fuzzer.cc",
+    "src/fuzz/verify_name_match_normalizename_fuzzer.cc",
     "src/fuzz/verify_name_match_verifynameinsubtree_fuzzer.cc"
-  ], 
+  ],
   "pki": [
-    "src/pki/cert_error_id.cc", 
-    "src/pki/cert_error_params.cc", 
-    "src/pki/cert_errors.cc", 
-    "src/pki/cert_issuer_source_static.cc", 
-    "src/pki/certificate.cc", 
-    "src/pki/certificate_policies.cc", 
-    "src/pki/common_cert_errors.cc", 
-    "src/pki/crl.cc", 
-    "src/pki/encode_values.cc", 
-    "src/pki/extended_key_usage.cc", 
-    "src/pki/general_names.cc", 
-    "src/pki/input.cc", 
-    "src/pki/ip_util.cc", 
-    "src/pki/name_constraints.cc", 
-    "src/pki/ocsp.cc", 
-    "src/pki/parse_certificate.cc", 
-    "src/pki/parse_name.cc", 
-    "src/pki/parse_values.cc", 
-    "src/pki/parsed_certificate.cc", 
-    "src/pki/parser.cc", 
-    "src/pki/path_builder.cc", 
-    "src/pki/pem.cc", 
-    "src/pki/revocation_util.cc", 
-    "src/pki/signature_algorithm.cc", 
-    "src/pki/simple_path_builder_delegate.cc", 
-    "src/pki/string_util.cc", 
-    "src/pki/trust_store.cc", 
-    "src/pki/trust_store_collection.cc", 
-    "src/pki/trust_store_in_memory.cc", 
-    "src/pki/verify.cc", 
-    "src/pki/verify_certificate_chain.cc", 
-    "src/pki/verify_error.cc", 
-    "src/pki/verify_name_match.cc", 
+    "src/pki/cert_error_id.cc",
+    "src/pki/cert_error_params.cc",
+    "src/pki/cert_errors.cc",
+    "src/pki/cert_issuer_source_static.cc",
+    "src/pki/certificate.cc",
+    "src/pki/certificate_policies.cc",
+    "src/pki/common_cert_errors.cc",
+    "src/pki/crl.cc",
+    "src/pki/encode_values.cc",
+    "src/pki/extended_key_usage.cc",
+    "src/pki/general_names.cc",
+    "src/pki/input.cc",
+    "src/pki/ip_util.cc",
+    "src/pki/name_constraints.cc",
+    "src/pki/ocsp.cc",
+    "src/pki/parse_certificate.cc",
+    "src/pki/parse_name.cc",
+    "src/pki/parse_values.cc",
+    "src/pki/parsed_certificate.cc",
+    "src/pki/parser.cc",
+    "src/pki/path_builder.cc",
+    "src/pki/pem.cc",
+    "src/pki/revocation_util.cc",
+    "src/pki/signature_algorithm.cc",
+    "src/pki/simple_path_builder_delegate.cc",
+    "src/pki/string_util.cc",
+    "src/pki/trust_store.cc",
+    "src/pki/trust_store_collection.cc",
+    "src/pki/trust_store_in_memory.cc",
+    "src/pki/verify.cc",
+    "src/pki/verify_certificate_chain.cc",
+    "src/pki/verify_error.cc",
+    "src/pki/verify_name_match.cc",
     "src/pki/verify_signed_data.cc"
-  ], 
+  ],
   "pki_headers": [
-    "src/include/openssl/pki/certificate.h", 
-    "src/include/openssl/pki/ocsp.h", 
-    "src/include/openssl/pki/signature_verify_cache.h", 
-    "src/include/openssl/pki/verify.h", 
+    "src/include/openssl/pki/certificate.h",
+    "src/include/openssl/pki/ocsp.h",
+    "src/include/openssl/pki/signature_verify_cache.h",
+    "src/include/openssl/pki/verify.h",
     "src/include/openssl/pki/verify_error.h"
-  ], 
+  ],
   "pki_internal_headers": [
-    "src/pki/cert_error_id.h", 
-    "src/pki/cert_error_params.h", 
-    "src/pki/cert_errors.h", 
-    "src/pki/cert_issuer_source.h", 
-    "src/pki/cert_issuer_source_static.h", 
-    "src/pki/cert_issuer_source_sync_unittest.h", 
-    "src/pki/certificate_policies.h", 
-    "src/pki/common_cert_errors.h", 
-    "src/pki/crl.h", 
-    "src/pki/encode_values.h", 
-    "src/pki/extended_key_usage.h", 
-    "src/pki/general_names.h", 
-    "src/pki/input.h", 
-    "src/pki/ip_util.h", 
-    "src/pki/mock_signature_verify_cache.h", 
-    "src/pki/name_constraints.h", 
-    "src/pki/nist_pkits_unittest.h", 
-    "src/pki/ocsp.h", 
-    "src/pki/parse_certificate.h", 
-    "src/pki/parse_name.h", 
-    "src/pki/parse_values.h", 
-    "src/pki/parsed_certificate.h", 
-    "src/pki/parser.h", 
-    "src/pki/path_builder.h", 
-    "src/pki/pem.h", 
-    "src/pki/revocation_util.h", 
-    "src/pki/signature_algorithm.h", 
-    "src/pki/simple_path_builder_delegate.h", 
-    "src/pki/string_util.h", 
-    "src/pki/test_helpers.h", 
-    "src/pki/testdata/nist-pkits/pkits_testcases-inl.h", 
-    "src/pki/trust_store.h", 
-    "src/pki/trust_store_collection.h", 
-    "src/pki/trust_store_in_memory.h", 
-    "src/pki/verify_certificate_chain.h", 
-    "src/pki/verify_certificate_chain_typed_unittest.h", 
-    "src/pki/verify_name_match.h", 
+    "src/pki/cert_error_id.h",
+    "src/pki/cert_error_params.h",
+    "src/pki/cert_errors.h",
+    "src/pki/cert_issuer_source.h",
+    "src/pki/cert_issuer_source_static.h",
+    "src/pki/cert_issuer_source_sync_unittest.h",
+    "src/pki/certificate_policies.h",
+    "src/pki/common_cert_errors.h",
+    "src/pki/crl.h",
+    "src/pki/encode_values.h",
+    "src/pki/extended_key_usage.h",
+    "src/pki/general_names.h",
+    "src/pki/input.h",
+    "src/pki/ip_util.h",
+    "src/pki/mock_signature_verify_cache.h",
+    "src/pki/name_constraints.h",
+    "src/pki/nist_pkits_unittest.h",
+    "src/pki/ocsp.h",
+    "src/pki/parse_certificate.h",
+    "src/pki/parse_name.h",
+    "src/pki/parse_values.h",
+    "src/pki/parsed_certificate.h",
+    "src/pki/parser.h",
+    "src/pki/path_builder.h",
+    "src/pki/pem.h",
+    "src/pki/revocation_util.h",
+    "src/pki/signature_algorithm.h",
+    "src/pki/simple_path_builder_delegate.h",
+    "src/pki/string_util.h",
+    "src/pki/test_helpers.h",
+    "src/pki/testdata/nist-pkits/pkits_testcases-inl.h",
+    "src/pki/trust_store.h",
+    "src/pki/trust_store_collection.h",
+    "src/pki/trust_store_in_memory.h",
+    "src/pki/verify_certificate_chain.h",
+    "src/pki/verify_certificate_chain_typed_unittest.h",
+    "src/pki/verify_name_match.h",
     "src/pki/verify_signed_data.h"
-  ], 
+  ],
   "pki_test": [
-    "src/crypto/test/gtest_main.cc", 
-    "src/pki/cert_issuer_source_static_unittest.cc", 
-    "src/pki/certificate_policies_unittest.cc", 
-    "src/pki/certificate_unittest.cc", 
-    "src/pki/crl_unittest.cc", 
-    "src/pki/encode_values_unittest.cc", 
-    "src/pki/extended_key_usage_unittest.cc", 
-    "src/pki/general_names_unittest.cc", 
-    "src/pki/input_unittest.cc", 
-    "src/pki/ip_util_unittest.cc", 
-    "src/pki/mock_signature_verify_cache.cc", 
-    "src/pki/name_constraints_unittest.cc", 
-    "src/pki/nist_pkits_unittest.cc", 
-    "src/pki/ocsp_unittest.cc", 
-    "src/pki/parse_certificate_unittest.cc", 
-    "src/pki/parse_name_unittest.cc", 
-    "src/pki/parse_values_unittest.cc", 
-    "src/pki/parsed_certificate_unittest.cc", 
-    "src/pki/parser_unittest.cc", 
-    "src/pki/path_builder_pkits_unittest.cc", 
-    "src/pki/path_builder_unittest.cc", 
-    "src/pki/path_builder_verify_certificate_chain_unittest.cc", 
-    "src/pki/pem_unittest.cc", 
-    "src/pki/signature_algorithm_unittest.cc", 
-    "src/pki/simple_path_builder_delegate_unittest.cc", 
-    "src/pki/string_util_unittest.cc", 
-    "src/pki/test_helpers.cc", 
-    "src/pki/trust_store_collection_unittest.cc", 
-    "src/pki/trust_store_in_memory_unittest.cc", 
-    "src/pki/verify_certificate_chain_pkits_unittest.cc", 
-    "src/pki/verify_certificate_chain_unittest.cc", 
-    "src/pki/verify_name_match_unittest.cc", 
-    "src/pki/verify_signed_data_unittest.cc", 
+    "src/crypto/test/gtest_main.cc",
+    "src/pki/cert_issuer_source_static_unittest.cc",
+    "src/pki/certificate_policies_unittest.cc",
+    "src/pki/certificate_unittest.cc",
+    "src/pki/crl_unittest.cc",
+    "src/pki/encode_values_unittest.cc",
+    "src/pki/extended_key_usage_unittest.cc",
+    "src/pki/general_names_unittest.cc",
+    "src/pki/input_unittest.cc",
+    "src/pki/ip_util_unittest.cc",
+    "src/pki/mock_signature_verify_cache.cc",
+    "src/pki/name_constraints_unittest.cc",
+    "src/pki/nist_pkits_unittest.cc",
+    "src/pki/ocsp_unittest.cc",
+    "src/pki/parse_certificate_unittest.cc",
+    "src/pki/parse_name_unittest.cc",
+    "src/pki/parse_values_unittest.cc",
+    "src/pki/parsed_certificate_unittest.cc",
+    "src/pki/parser_unittest.cc",
+    "src/pki/path_builder_pkits_unittest.cc",
+    "src/pki/path_builder_unittest.cc",
+    "src/pki/path_builder_verify_certificate_chain_unittest.cc",
+    "src/pki/pem_unittest.cc",
+    "src/pki/signature_algorithm_unittest.cc",
+    "src/pki/simple_path_builder_delegate_unittest.cc",
+    "src/pki/string_util_unittest.cc",
+    "src/pki/test_helpers.cc",
+    "src/pki/trust_store_collection_unittest.cc",
+    "src/pki/trust_store_in_memory_unittest.cc",
+    "src/pki/verify_certificate_chain_pkits_unittest.cc",
+    "src/pki/verify_certificate_chain_unittest.cc",
+    "src/pki/verify_name_match_unittest.cc",
+    "src/pki/verify_signed_data_unittest.cc",
     "src/pki/verify_unittest.cc"
-  ], 
+  ],
   "pki_test_data": [
-    "src/pki/testdata/cert_issuer_source_static_unittest/c1.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/c2.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/d.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/e1.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/e2.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/i1_1.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/i1_2.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/i2.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/i3_1.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/i3_2.pem", 
-    "src/pki/testdata/cert_issuer_source_static_unittest/root.pem", 
-    "src/pki/testdata/certificate_policies_unittest/anypolicy.pem", 
-    "src/pki/testdata/certificate_policies_unittest/anypolicy_with_qualifier.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-anypolicy_with_custom_qualifier.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-empty.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_dupe.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyinformation_unconsumed_data.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem", 
-    "src/pki/testdata/certificate_policies_unittest/invalid-policy_identifier_not_oid.pem", 
-    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3.pem", 
-    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4.pem", 
-    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4_with_qualifiers.pem", 
-    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_with_custom_qualifier.pem", 
-    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_with_qualifier.pem", 
-    "src/pki/testdata/crl_unittest/bad_crldp_has_crlissuer.pem", 
-    "src/pki/testdata/crl_unittest/bad_fake_critical_crlentryextension.pem", 
-    "src/pki/testdata/crl_unittest/bad_fake_critical_extension.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_contains_wrong_uri.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_indirectcrl.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_onlycontainscacerts.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_onlycontainscacerts_no_basic_constraints.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_onlycontainsusercerts.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainscacerts.pem", 
-    "src/pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainsusercerts.pem", 
-    "src/pki/testdata/crl_unittest/bad_key_rollover_signature.pem", 
-    "src/pki/testdata/crl_unittest/bad_nextupdate_too_old.pem", 
-    "src/pki/testdata/crl_unittest/bad_signature.pem", 
-    "src/pki/testdata/crl_unittest/bad_thisupdate_in_future.pem", 
-    "src/pki/testdata/crl_unittest/bad_thisupdate_too_old.pem", 
-    "src/pki/testdata/crl_unittest/bad_wrong_issuer.pem", 
-    "src/pki/testdata/crl_unittest/good.pem", 
-    "src/pki/testdata/crl_unittest/good_fake_extension.pem", 
-    "src/pki/testdata/crl_unittest/good_fake_extension_no_nextupdate.pem", 
-    "src/pki/testdata/crl_unittest/good_generalizedtime.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_contains_uri.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_onlycontainscacerts.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_onlycontainsusercerts.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_onlycontainsusercerts_no_basic_constraints.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_uri_and_onlycontainscacerts.pem", 
-    "src/pki/testdata/crl_unittest/good_idp_uri_and_onlycontainsusercerts.pem", 
-    "src/pki/testdata/crl_unittest/good_issuer_name_normalization.pem", 
-    "src/pki/testdata/crl_unittest/good_issuer_no_keyusage.pem", 
-    "src/pki/testdata/crl_unittest/good_key_rollover.pem", 
-    "src/pki/testdata/crl_unittest/good_no_crldp.pem", 
-    "src/pki/testdata/crl_unittest/good_no_nextupdate.pem", 
-    "src/pki/testdata/crl_unittest/good_no_version.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_crlentryextensions.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_extensions.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_nextupdate.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_revocationdate.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_revokedcerts.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_signaturevalue.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_after_thisupdate.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_crlentry.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_issuer_name.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_revocationdate.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_revoked_serial_number.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_signaturealgorithm.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_signaturevalue.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_tbs_signature_algorithm.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_tbscertlist.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_thisupdate.pem", 
-    "src/pki/testdata/crl_unittest/invalid_garbage_version.pem", 
-    "src/pki/testdata/crl_unittest/invalid_idp_dpname_choice_extra_data.pem", 
-    "src/pki/testdata/crl_unittest/invalid_idp_empty_sequence.pem", 
-    "src/pki/testdata/crl_unittest/invalid_idp_onlycontains_user_and_ca_certs.pem", 
-    "src/pki/testdata/crl_unittest/invalid_idp_onlycontainsusercerts_v1_leaf.pem", 
-    "src/pki/testdata/crl_unittest/invalid_issuer_keyusage_no_crlsign.pem", 
-    "src/pki/testdata/crl_unittest/invalid_key_rollover_issuer_keyusage_no_crlsign.pem", 
-    "src/pki/testdata/crl_unittest/invalid_mismatched_signature_algorithm.pem", 
-    "src/pki/testdata/crl_unittest/invalid_revoked_empty_sequence.pem", 
-    "src/pki/testdata/crl_unittest/invalid_v1_explicit.pem", 
-    "src/pki/testdata/crl_unittest/invalid_v1_with_crlentryextension.pem", 
-    "src/pki/testdata/crl_unittest/invalid_v1_with_extension.pem", 
-    "src/pki/testdata/crl_unittest/invalid_v3.pem", 
-    "src/pki/testdata/crl_unittest/revoked.pem", 
-    "src/pki/testdata/crl_unittest/revoked_fake_crlentryextension.pem", 
-    "src/pki/testdata/crl_unittest/revoked_generalized_revocationdate.pem", 
-    "src/pki/testdata/crl_unittest/revoked_key_rollover.pem", 
-    "src/pki/testdata/crl_unittest/revoked_no_nextupdate.pem", 
-    "src/pki/testdata/name_constraints_unittest/directoryname-excludeall.pem", 
-    "src/pki/testdata/name_constraints_unittest/directoryname-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/directoryname.pem", 
-    "src/pki/testdata/name_constraints_unittest/directoryname_and_dnsname.pem", 
-    "src/pki/testdata/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-exclude_dot.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-excludeall.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-permitted_two_dot.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-with_max.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_0.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_0_and_max.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_1.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_1_and_max.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname.pem", 
-    "src/pki/testdata/name_constraints_unittest/dnsname2.pem", 
-    "src/pki/testdata/name_constraints_unittest/edipartyname-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/edipartyname-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/invalid-empty_excluded_subtree.pem", 
-    "src/pki/testdata/name_constraints_unittest/invalid-empty_permitted_subtree.pem", 
-    "src/pki/testdata/name_constraints_unittest/invalid-no_subtrees.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-excludeall.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_addr.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_1.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_2.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_3.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_4.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-mapped_addrs.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_all.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_prefix1.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_prefix31.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_singlehost.pem", 
-    "src/pki/testdata/name_constraints_unittest/ipaddress.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-ca.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-de.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-empty.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-jp-tokyo.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-jp.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-1.1.1.1.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-192.168.1.1.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-invalidstring.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-localpartcase.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-multiple.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-foo.com.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-ipv6.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona-permitted.example.com.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-arizona.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-california-192.168.1.1.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-california-mountain_view.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-california-permitted.example.com.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us-california.pem", 
-    "src/pki/testdata/name_constraints_unittest/name-us.pem", 
-    "src/pki/testdata/name_constraints_unittest/othername-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/othername-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/registeredid-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/registeredid-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-empty.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-hostname.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-hostnamewithat.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-ipv4.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-quoted.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-subdomains.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-empty.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-hostname.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-hostnamewithat.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-ipv4.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-quoted.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-subdomains.pem", 
-    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-directoryname.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-dnsname.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-edipartyname.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-excluded-directoryname.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-excluded-dnsname.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-excluded-ipaddress.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-invalid-empty.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-invalid-ipaddress.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-ipaddress4.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-ipaddress6.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-othername.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-registeredid.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-domaincase.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-empty-localpart.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-empty.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-ipv4.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-localpartcase.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-multiple.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-no-at.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-quoted.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-no-at.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-two-ats.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomaincase.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name-two-ats.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-rfc822name.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-uri.pem", 
-    "src/pki/testdata/name_constraints_unittest/san-x400address.pem", 
-    "src/pki/testdata/name_constraints_unittest/uri-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/uri-permitted.pem", 
-    "src/pki/testdata/name_constraints_unittest/x400address-excluded.pem", 
-    "src/pki/testdata/name_constraints_unittest/x400address-permitted.pem", 
-    "src/pki/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BadSignedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DSACACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/GoodCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/GoodsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/LongSerialNumberCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/Mapping1to2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/NameOrderingCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/NoCRLCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/NoPoliciesCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP1234CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP123CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP12CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP2subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/PoliciesP3CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/RevokedsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt", 
-    "src/pki/testdata/nist-pkits/certs/TwoCRLsCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UIDCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/WrongCRLCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/anyPolicyCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/distributionPoint1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/distributionPoint2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt", 
-    "src/pki/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt", 
-    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt", 
-    "src/pki/testdata/nist-pkits/crls/BadCRLIssuerNameCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BadCRLSignatureCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BadSignedCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BadnotAfterDateCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BadnotBeforeDateCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/DSACACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/DSAParametersInheritedCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/GoodCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/GoodsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/LongSerialNumberCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/Mapping1to2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/MappingFromanyPolicyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/MappingToanyPolicyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/MissingbasicConstraintsCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/NameOrderCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/NegativeSerialNumberCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/NoPoliciesCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/NoissuingDistributionPointCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/OldCRLnextUpdateCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P1Mapping1to234CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P1Mapping1to234subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP1234CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP123CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP123subCAP12CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP12CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP12subCAP1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP2subCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP2subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/PoliciesP3CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/RevokedsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/TrustAnchorRootCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/TwoCRLsCABadCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/TwoCRLsCAGoodCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/UIDCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/UnknownCRLExtensionCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/WrongCRLCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/anyPolicyCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA1deltaCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA2deltaCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA3CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLCA3deltaCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/distributionPoint1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/distributionPoint2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/indirectCRLCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/indirectCRLCA3CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/indirectCRLCA5CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN4CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN5CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDNS1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsDNS2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsURI1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/nameConstraintsURI2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlyContainsCACertsCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlyContainsUserCertsCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint1CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint1subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy2CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7CACRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl", 
-    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl", 
-    "src/pki/testdata/ocsp_unittest/bad_ocsp_type.pem", 
-    "src/pki/testdata/ocsp_unittest/bad_signature.pem", 
-    "src/pki/testdata/ocsp_unittest/bad_status.pem", 
-    "src/pki/testdata/ocsp_unittest/good_response.pem", 
-    "src/pki/testdata/ocsp_unittest/good_response_next_update.pem", 
-    "src/pki/testdata/ocsp_unittest/good_response_sha256.pem", 
-    "src/pki/testdata/ocsp_unittest/has_critical_ct_extension.pem", 
-    "src/pki/testdata/ocsp_unittest/has_critical_response_extension.pem", 
-    "src/pki/testdata/ocsp_unittest/has_critical_single_extension.pem", 
-    "src/pki/testdata/ocsp_unittest/has_extension.pem", 
-    "src/pki/testdata/ocsp_unittest/has_single_extension.pem", 
-    "src/pki/testdata/ocsp_unittest/has_version.pem", 
-    "src/pki/testdata/ocsp_unittest/malformed_request.pem", 
-    "src/pki/testdata/ocsp_unittest/missing_response.pem", 
-    "src/pki/testdata/ocsp_unittest/multiple_response.pem", 
-    "src/pki/testdata/ocsp_unittest/no_response.pem", 
-    "src/pki/testdata/ocsp_unittest/ocsp_extra_certs.pem", 
-    "src/pki/testdata/ocsp_unittest/ocsp_sign_bad_indirect.pem", 
-    "src/pki/testdata/ocsp_unittest/ocsp_sign_direct.pem", 
-    "src/pki/testdata/ocsp_unittest/ocsp_sign_indirect.pem", 
-    "src/pki/testdata/ocsp_unittest/ocsp_sign_indirect_missing.pem", 
-    "src/pki/testdata/ocsp_unittest/other_response.pem", 
-    "src/pki/testdata/ocsp_unittest/responder_id.pem", 
-    "src/pki/testdata/ocsp_unittest/responder_name.pem", 
-    "src/pki/testdata/ocsp_unittest/revoke_response.pem", 
-    "src/pki/testdata/ocsp_unittest/revoke_response_reason.pem", 
-    "src/pki/testdata/ocsp_unittest/unknown_response.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/empty_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_extension_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_issuer_and_serial.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_contents.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_issuer.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_key_identifier.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_serial.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_and_serial.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_only.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier_and_issuer_and_serial.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/serial_only.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/url_issuer_and_serial.pem", 
-    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier_not_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/bad_key_usage.pem", 
-    "src/pki/testdata/parse_certificate_unittest/bad_policy_qualifiers.pem", 
-    "src/pki/testdata/parse_certificate_unittest/bad_signature_algorithm_oid.pem", 
-    "src/pki/testdata/parse_certificate_unittest/bad_validity.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_false.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_no_path.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_path_9.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_negative_path.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_not_ca.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_path_too_large.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_255.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_256.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem", 
-    "src/pki/testdata/parse_certificate_unittest/basic_constraints_unconsumed_data.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_algorithm_not_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_data_after_signature.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_empty_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_missing_signature.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_not_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_signature_not_bit_string.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_skeleton.pem", 
-    "src/pki/testdata/parse_certificate_unittest/cert_version3.pem", 
-    "src/pki/testdata/parse_certificate_unittest/crldp_1uri_noissuer.pem", 
-    "src/pki/testdata/parse_certificate_unittest/crldp_3uri_noissuer.pem", 
-    "src/pki/testdata/parse_certificate_unittest/crldp_full_name_as_dirname.pem", 
-    "src/pki/testdata/parse_certificate_unittest/crldp_issuer_as_dirname.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extended_key_usage.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extension_critical.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extension_critical_0.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extension_critical_3.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extension_not_critical.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extensions_data_after_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extensions_duplicate_key_usage.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extensions_empty_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extensions_not_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/extensions_real.pem", 
-    "src/pki/testdata/parse_certificate_unittest/failed_signature_algorithm.pem", 
-    "src/pki/testdata/parse_certificate_unittest/inhibit_any_policy.pem", 
-    "src/pki/testdata/parse_certificate_unittest/issuer_bad_printable_string.pem", 
-    "src/pki/testdata/parse_certificate_unittest/key_usage.pem", 
-    "src/pki/testdata/parse_certificate_unittest/name_constraints_bad_ip.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policies.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policy_constraints_empty.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policy_constraints_inhibit.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policy_constraints_inhibit_require.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policy_constraints_require.pem", 
-    "src/pki/testdata/parse_certificate_unittest/policy_qualifiers_empty_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_37_bytes.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_negative.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_not_minimal.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_not_number.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_zero.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_zero_padded.pem", 
-    "src/pki/testdata/parse_certificate_unittest/serial_zero_padded_21_bytes.pem", 
-    "src/pki/testdata/parse_certificate_unittest/signature_algorithm_null.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_alt_name.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_blank_subjectaltname_not_critical.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_key_identifier_not_octet_string.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_not_ascii.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_not_printable_string.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_printable_string_containing_utf8_client_cert.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_t61string.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_t61string_1-32.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_t61string_126-160.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subject_t61string_actual.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subjectaltname_bad_ip.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subjectaltname_dns_not_ascii.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subjectaltname_general_names_empty_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/subjectaltname_trailing_data.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_explicit_v1.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v1.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v1_extensions.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v2_extensions.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v2_no_optionals.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_all_optionals.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_data_after_extensions.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_extensions.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_no_optionals.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v3_real.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_v4.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_validity_both_generalized_time.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_validity_both_utc_time.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_validity_relaxed.pem", 
-    "src/pki/testdata/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem", 
-    "src/pki/testdata/parse_certificate_unittest/v1_explicit_version.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_match_name_only.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_matching.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_mismatch.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root2.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/target.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_a.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_b.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_c.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_a.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_b.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_c.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_a.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_b.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_c.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/root.pem", 
-    "src/pki/testdata/path_builder_unittest/key_id_prioritization/target.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-B-by-F.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-C-by-D.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-C-by-E.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-D-by-D.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-E-by-E.pem", 
-    "src/pki/testdata/path_builder_unittest/multi-root-F-by-E.pem", 
-    "src/pki/testdata/path_builder_unittest/precertificate/precertificate.pem", 
-    "src/pki/testdata/path_builder_unittest/precertificate/root.pem", 
-    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root1.pem", 
-    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root1_cross.pem", 
-    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root2.pem", 
-    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/target.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_ac.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_ad.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_bc.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_bd.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/root.pem", 
-    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/target.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-after.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-before.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration-and-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-before-ta-with-expiration.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-before.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/not-after.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/not-before.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.4.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.10.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.13.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.4.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.7.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.10.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.11.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.9.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.10.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.4.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.10.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.12.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.13.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.15.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.16.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.17.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.20.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.21.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.22.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.23.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.24.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.25.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.26.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.27.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.28.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.29.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.31.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.33.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.34.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.35.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.36.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.37.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.38.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.7.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.9.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.16.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.7.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.10.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.11.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.12.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.16.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.9.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.1.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.12.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.14.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.2.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.4.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.6.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.7.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.9.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.3.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.5.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.7.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.8.txt", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration-and-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints-require-basic-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-require-basic-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-constraints.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-expiration.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-and-trust_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-root.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/unspecified-trust-root.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/any.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf-strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict-leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-and-trust_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-not_after.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-wrong_eku.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf_require_self_signed.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf-and-trust_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf_require_self_signed.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-and-trust_anchor.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-not_after.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-wrong_eku.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf_require_self_signed.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only-trusted_leaf.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/chain.pem", 
-    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/main.test", 
-    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/ta-with-constraints.test", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_1.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_2.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-dupe_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_attr.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_rdn.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_1.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_2.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/custom-custom-normalized.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-badAttributeType.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-empty.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-extradata.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-onlyOneElement.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-setNotSequence.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-Name-setInsteadOfSequence.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-RDN-empty.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/invalid-RDN-sequenceInsteadOfSet.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode-mixed-normalized.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode-mixed-unnormalized.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-BMPSTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-UNIVERSALSTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-UTF8-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UNIVERSALSTRING-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UTF8-unmangled.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/valid-Name-empty.pem", 
-    "src/pki/testdata/verify_name_match_unittest/names/valid-minimal.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/ecdsa-using-rsa-key.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-using-pss-key-with-params.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-wrong-salt.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem", 
-    "src/pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem", 
-    "src/pki/testdata/verify_unittest/google-intermediate1.der", 
-    "src/pki/testdata/verify_unittest/google-intermediate2.der", 
-    "src/pki/testdata/verify_unittest/google-leaf.der", 
-    "src/pki/testdata/verify_unittest/lencr-intermediate-r3.der", 
-    "src/pki/testdata/verify_unittest/lencr-leaf.der", 
-    "src/pki/testdata/verify_unittest/lencr-root-dst-x3.der", 
-    "src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der", 
-    "src/pki/testdata/verify_unittest/lencr-root-x1.der", 
-    "src/pki/testdata/verify_unittest/mozilla_roots.der", 
+    "src/pki/testdata/cert_issuer_source_static_unittest/c1.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/c2.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/d.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/e1.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/e2.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/i1_1.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/i1_2.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/i2.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/i3_1.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/i3_2.pem",
+    "src/pki/testdata/cert_issuer_source_static_unittest/root.pem",
+    "src/pki/testdata/certificate_policies_unittest/anypolicy.pem",
+    "src/pki/testdata/certificate_policies_unittest/anypolicy_with_qualifier.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-anypolicy_with_custom_qualifier.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-empty.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_dupe.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyinformation_unconsumed_data.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem",
+    "src/pki/testdata/certificate_policies_unittest/invalid-policy_identifier_not_oid.pem",
+    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3.pem",
+    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4.pem",
+    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4_with_qualifiers.pem",
+    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_with_custom_qualifier.pem",
+    "src/pki/testdata/certificate_policies_unittest/policy_1_2_3_with_qualifier.pem",
+    "src/pki/testdata/crl_unittest/bad_crldp_has_crlissuer.pem",
+    "src/pki/testdata/crl_unittest/bad_fake_critical_crlentryextension.pem",
+    "src/pki/testdata/crl_unittest/bad_fake_critical_extension.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_contains_wrong_uri.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_indirectcrl.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_onlycontainscacerts.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_onlycontainscacerts_no_basic_constraints.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_onlycontainsusercerts.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainscacerts.pem",
+    "src/pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainsusercerts.pem",
+    "src/pki/testdata/crl_unittest/bad_key_rollover_signature.pem",
+    "src/pki/testdata/crl_unittest/bad_nextupdate_too_old.pem",
+    "src/pki/testdata/crl_unittest/bad_signature.pem",
+    "src/pki/testdata/crl_unittest/bad_thisupdate_in_future.pem",
+    "src/pki/testdata/crl_unittest/bad_thisupdate_too_old.pem",
+    "src/pki/testdata/crl_unittest/bad_wrong_issuer.pem",
+    "src/pki/testdata/crl_unittest/good.pem",
+    "src/pki/testdata/crl_unittest/good_fake_extension.pem",
+    "src/pki/testdata/crl_unittest/good_fake_extension_no_nextupdate.pem",
+    "src/pki/testdata/crl_unittest/good_generalizedtime.pem",
+    "src/pki/testdata/crl_unittest/good_idp_contains_uri.pem",
+    "src/pki/testdata/crl_unittest/good_idp_onlycontainscacerts.pem",
+    "src/pki/testdata/crl_unittest/good_idp_onlycontainsusercerts.pem",
+    "src/pki/testdata/crl_unittest/good_idp_onlycontainsusercerts_no_basic_constraints.pem",
+    "src/pki/testdata/crl_unittest/good_idp_uri_and_onlycontainscacerts.pem",
+    "src/pki/testdata/crl_unittest/good_idp_uri_and_onlycontainsusercerts.pem",
+    "src/pki/testdata/crl_unittest/good_issuer_name_normalization.pem",
+    "src/pki/testdata/crl_unittest/good_issuer_no_keyusage.pem",
+    "src/pki/testdata/crl_unittest/good_key_rollover.pem",
+    "src/pki/testdata/crl_unittest/good_no_crldp.pem",
+    "src/pki/testdata/crl_unittest/good_no_nextupdate.pem",
+    "src/pki/testdata/crl_unittest/good_no_version.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_crlentryextensions.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_extensions.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_nextupdate.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_revocationdate.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_revokedcerts.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_signaturevalue.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_after_thisupdate.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_crlentry.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_issuer_name.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_revocationdate.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_revoked_serial_number.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_signaturealgorithm.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_signaturevalue.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_tbs_signature_algorithm.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_tbscertlist.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_thisupdate.pem",
+    "src/pki/testdata/crl_unittest/invalid_garbage_version.pem",
+    "src/pki/testdata/crl_unittest/invalid_idp_dpname_choice_extra_data.pem",
+    "src/pki/testdata/crl_unittest/invalid_idp_empty_sequence.pem",
+    "src/pki/testdata/crl_unittest/invalid_idp_onlycontains_user_and_ca_certs.pem",
+    "src/pki/testdata/crl_unittest/invalid_idp_onlycontainsusercerts_v1_leaf.pem",
+    "src/pki/testdata/crl_unittest/invalid_issuer_keyusage_no_crlsign.pem",
+    "src/pki/testdata/crl_unittest/invalid_key_rollover_issuer_keyusage_no_crlsign.pem",
+    "src/pki/testdata/crl_unittest/invalid_mismatched_signature_algorithm.pem",
+    "src/pki/testdata/crl_unittest/invalid_revoked_empty_sequence.pem",
+    "src/pki/testdata/crl_unittest/invalid_v1_explicit.pem",
+    "src/pki/testdata/crl_unittest/invalid_v1_with_crlentryextension.pem",
+    "src/pki/testdata/crl_unittest/invalid_v1_with_extension.pem",
+    "src/pki/testdata/crl_unittest/invalid_v3.pem",
+    "src/pki/testdata/crl_unittest/revoked.pem",
+    "src/pki/testdata/crl_unittest/revoked_fake_crlentryextension.pem",
+    "src/pki/testdata/crl_unittest/revoked_generalized_revocationdate.pem",
+    "src/pki/testdata/crl_unittest/revoked_key_rollover.pem",
+    "src/pki/testdata/crl_unittest/revoked_no_nextupdate.pem",
+    "src/pki/testdata/name_constraints_unittest/directoryname-excludeall.pem",
+    "src/pki/testdata/name_constraints_unittest/directoryname-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/directoryname.pem",
+    "src/pki/testdata/name_constraints_unittest/directoryname_and_dnsname.pem",
+    "src/pki/testdata/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-exclude_dot.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-excludeall.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-permitted_two_dot.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-with_max.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_0.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_0_and_max.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_1.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname-with_min_1_and_max.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname.pem",
+    "src/pki/testdata/name_constraints_unittest/dnsname2.pem",
+    "src/pki/testdata/name_constraints_unittest/edipartyname-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/edipartyname-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/invalid-empty_excluded_subtree.pem",
+    "src/pki/testdata/name_constraints_unittest/invalid-empty_permitted_subtree.pem",
+    "src/pki/testdata/name_constraints_unittest/invalid-no_subtrees.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-excludeall.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_addr.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_1.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_2.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_3.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_4.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-mapped_addrs.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_all.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_prefix1.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_prefix31.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress-permit_singlehost.pem",
+    "src/pki/testdata/name_constraints_unittest/ipaddress.pem",
+    "src/pki/testdata/name_constraints_unittest/name-ca.pem",
+    "src/pki/testdata/name_constraints_unittest/name-de.pem",
+    "src/pki/testdata/name_constraints_unittest/name-empty.pem",
+    "src/pki/testdata/name_constraints_unittest/name-jp-tokyo.pem",
+    "src/pki/testdata/name_constraints_unittest/name-jp.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-1.1.1.1.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-192.168.1.1.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-invalidstring.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-localpartcase.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email-multiple.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-email.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-foo.com.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-ipv6.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona-permitted.example.com.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-arizona.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-california-192.168.1.1.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-california-mountain_view.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-california-permitted.example.com.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us-california.pem",
+    "src/pki/testdata/name_constraints_unittest/name-us.pem",
+    "src/pki/testdata/name_constraints_unittest/othername-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/othername-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/registeredid-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/registeredid-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-empty.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-hostname.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-hostnamewithat.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-ipv4.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-quoted.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded-subdomains.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-empty.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-hostname.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-hostnamewithat.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-ipv4.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-quoted.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted-subdomains.pem",
+    "src/pki/testdata/name_constraints_unittest/rfc822name-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/san-directoryname.pem",
+    "src/pki/testdata/name_constraints_unittest/san-dnsname.pem",
+    "src/pki/testdata/name_constraints_unittest/san-edipartyname.pem",
+    "src/pki/testdata/name_constraints_unittest/san-excluded-directoryname.pem",
+    "src/pki/testdata/name_constraints_unittest/san-excluded-dnsname.pem",
+    "src/pki/testdata/name_constraints_unittest/san-excluded-ipaddress.pem",
+    "src/pki/testdata/name_constraints_unittest/san-invalid-empty.pem",
+    "src/pki/testdata/name_constraints_unittest/san-invalid-ipaddress.pem",
+    "src/pki/testdata/name_constraints_unittest/san-ipaddress4.pem",
+    "src/pki/testdata/name_constraints_unittest/san-ipaddress6.pem",
+    "src/pki/testdata/name_constraints_unittest/san-othername.pem",
+    "src/pki/testdata/name_constraints_unittest/san-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/san-registeredid.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-domaincase.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-empty-localpart.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-empty.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-ipv4.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-localpartcase.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-multiple.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-no-at.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-quoted.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-no-at.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-two-ats.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomain.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-subdomaincase.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name-two-ats.pem",
+    "src/pki/testdata/name_constraints_unittest/san-rfc822name.pem",
+    "src/pki/testdata/name_constraints_unittest/san-uri.pem",
+    "src/pki/testdata/name_constraints_unittest/san-x400address.pem",
+    "src/pki/testdata/name_constraints_unittest/uri-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/uri-permitted.pem",
+    "src/pki/testdata/name_constraints_unittest/x400address-excluded.pem",
+    "src/pki/testdata/name_constraints_unittest/x400address-permitted.pem",
+    "src/pki/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BadSignedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DSACACert.crt",
+    "src/pki/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/GoodCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/GoodsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/LongSerialNumberCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/Mapping1to2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/NameOrderingCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/NoCRLCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/NoPoliciesCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP1234CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP123CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP12CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP2subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/PoliciesP3CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/RevokedsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt",
+    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt",
+    "src/pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt",
+    "src/pki/testdata/nist-pkits/certs/TwoCRLsCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UIDCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt",
+    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt",
+    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt",
+    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt",
+    "src/pki/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt",
+    "src/pki/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt",
+    "src/pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt",
+    "src/pki/testdata/nist-pkits/certs/WrongCRLCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/anyPolicyCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/distributionPoint1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/distributionPoint2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt",
+    "src/pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt",
+    "src/pki/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt",
+    "src/pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt",
+    "src/pki/testdata/nist-pkits/crls/BadCRLIssuerNameCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BadCRLSignatureCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BadSignedCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BadnotAfterDateCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BadnotBeforeDateCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/DSACACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/DSAParametersInheritedCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/GoodCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/GoodsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/LongSerialNumberCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/Mapping1to2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/MappingFromanyPolicyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/MappingToanyPolicyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/MissingbasicConstraintsCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/NameOrderCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/NegativeSerialNumberCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/NoPoliciesCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/NoissuingDistributionPointCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/OldCRLnextUpdateCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P1Mapping1to234CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P1Mapping1to234subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP1234CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP123CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP123subCAP12CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP12CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP12subCAP1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP2subCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP2subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/PoliciesP3CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/RevokedsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/TrustAnchorRootCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/TwoCRLsCABadCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/TwoCRLsCAGoodCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/UIDCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/UnknownCRLExtensionCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/WrongCRLCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/anyPolicyCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA1deltaCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA2deltaCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA3CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLCA3deltaCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/distributionPoint1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/distributionPoint2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/indirectCRLCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/indirectCRLCA3CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/indirectCRLCA5CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN4CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDN5CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDNS1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsDNS2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsURI1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/nameConstraintsURI2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlyContainsCACertsCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlyContainsUserCertsCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint0subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint1CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint1subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl",
+    "src/pki/testdata/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy2CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7CACRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl",
+    "src/pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl",
+    "src/pki/testdata/ocsp_unittest/bad_ocsp_type.pem",
+    "src/pki/testdata/ocsp_unittest/bad_signature.pem",
+    "src/pki/testdata/ocsp_unittest/bad_status.pem",
+    "src/pki/testdata/ocsp_unittest/good_response.pem",
+    "src/pki/testdata/ocsp_unittest/good_response_next_update.pem",
+    "src/pki/testdata/ocsp_unittest/good_response_sha256.pem",
+    "src/pki/testdata/ocsp_unittest/has_critical_ct_extension.pem",
+    "src/pki/testdata/ocsp_unittest/has_critical_response_extension.pem",
+    "src/pki/testdata/ocsp_unittest/has_critical_single_extension.pem",
+    "src/pki/testdata/ocsp_unittest/has_extension.pem",
+    "src/pki/testdata/ocsp_unittest/has_single_extension.pem",
+    "src/pki/testdata/ocsp_unittest/has_version.pem",
+    "src/pki/testdata/ocsp_unittest/malformed_request.pem",
+    "src/pki/testdata/ocsp_unittest/missing_response.pem",
+    "src/pki/testdata/ocsp_unittest/multiple_response.pem",
+    "src/pki/testdata/ocsp_unittest/no_response.pem",
+    "src/pki/testdata/ocsp_unittest/ocsp_extra_certs.pem",
+    "src/pki/testdata/ocsp_unittest/ocsp_sign_bad_indirect.pem",
+    "src/pki/testdata/ocsp_unittest/ocsp_sign_direct.pem",
+    "src/pki/testdata/ocsp_unittest/ocsp_sign_indirect.pem",
+    "src/pki/testdata/ocsp_unittest/ocsp_sign_indirect_missing.pem",
+    "src/pki/testdata/ocsp_unittest/other_response.pem",
+    "src/pki/testdata/ocsp_unittest/responder_id.pem",
+    "src/pki/testdata/ocsp_unittest/responder_name.pem",
+    "src/pki/testdata/ocsp_unittest/revoke_response.pem",
+    "src/pki/testdata/ocsp_unittest/revoke_response_reason.pem",
+    "src/pki/testdata/ocsp_unittest/unknown_response.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/empty_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_extension_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_issuer_and_serial.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_contents.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_issuer.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_key_identifier.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_serial.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_and_serial.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_only.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier_and_issuer_and_serial.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/serial_only.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier/url_issuer_and_serial.pem",
+    "src/pki/testdata/parse_certificate_unittest/authority_key_identifier_not_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/bad_key_usage.pem",
+    "src/pki/testdata/parse_certificate_unittest/bad_policy_qualifiers.pem",
+    "src/pki/testdata/parse_certificate_unittest/bad_signature_algorithm_oid.pem",
+    "src/pki/testdata/parse_certificate_unittest/bad_validity.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_false.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_no_path.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_ca_path_9.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_negative_path.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_not_ca.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_path_too_large.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_255.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_256.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem",
+    "src/pki/testdata/parse_certificate_unittest/basic_constraints_unconsumed_data.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_algorithm_not_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_data_after_signature.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_empty_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_missing_signature.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_not_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_signature_not_bit_string.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_skeleton.pem",
+    "src/pki/testdata/parse_certificate_unittest/cert_version3.pem",
+    "src/pki/testdata/parse_certificate_unittest/crldp_1uri_noissuer.pem",
+    "src/pki/testdata/parse_certificate_unittest/crldp_3uri_noissuer.pem",
+    "src/pki/testdata/parse_certificate_unittest/crldp_full_name_as_dirname.pem",
+    "src/pki/testdata/parse_certificate_unittest/crldp_issuer_as_dirname.pem",
+    "src/pki/testdata/parse_certificate_unittest/extended_key_usage.pem",
+    "src/pki/testdata/parse_certificate_unittest/extension_critical.pem",
+    "src/pki/testdata/parse_certificate_unittest/extension_critical_0.pem",
+    "src/pki/testdata/parse_certificate_unittest/extension_critical_3.pem",
+    "src/pki/testdata/parse_certificate_unittest/extension_not_critical.pem",
+    "src/pki/testdata/parse_certificate_unittest/extensions_data_after_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/extensions_duplicate_key_usage.pem",
+    "src/pki/testdata/parse_certificate_unittest/extensions_empty_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/extensions_not_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/extensions_real.pem",
+    "src/pki/testdata/parse_certificate_unittest/failed_signature_algorithm.pem",
+    "src/pki/testdata/parse_certificate_unittest/inhibit_any_policy.pem",
+    "src/pki/testdata/parse_certificate_unittest/issuer_bad_printable_string.pem",
+    "src/pki/testdata/parse_certificate_unittest/key_usage.pem",
+    "src/pki/testdata/parse_certificate_unittest/name_constraints_bad_ip.pem",
+    "src/pki/testdata/parse_certificate_unittest/policies.pem",
+    "src/pki/testdata/parse_certificate_unittest/policy_constraints_empty.pem",
+    "src/pki/testdata/parse_certificate_unittest/policy_constraints_inhibit.pem",
+    "src/pki/testdata/parse_certificate_unittest/policy_constraints_inhibit_require.pem",
+    "src/pki/testdata/parse_certificate_unittest/policy_constraints_require.pem",
+    "src/pki/testdata/parse_certificate_unittest/policy_qualifiers_empty_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_37_bytes.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_negative.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_not_minimal.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_not_number.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_zero.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_zero_padded.pem",
+    "src/pki/testdata/parse_certificate_unittest/serial_zero_padded_21_bytes.pem",
+    "src/pki/testdata/parse_certificate_unittest/signature_algorithm_null.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_alt_name.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_blank_subjectaltname_not_critical.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_key_identifier_not_octet_string.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_not_ascii.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_not_printable_string.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_printable_string_containing_utf8_client_cert.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_t61string.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_t61string_1-32.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_t61string_126-160.pem",
+    "src/pki/testdata/parse_certificate_unittest/subject_t61string_actual.pem",
+    "src/pki/testdata/parse_certificate_unittest/subjectaltname_bad_ip.pem",
+    "src/pki/testdata/parse_certificate_unittest/subjectaltname_dns_not_ascii.pem",
+    "src/pki/testdata/parse_certificate_unittest/subjectaltname_general_names_empty_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/subjectaltname_trailing_data.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_explicit_v1.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v1.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v1_extensions.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v2_extensions.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v2_no_optionals.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_all_optionals.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_data_after_extensions.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_extensions.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_no_optionals.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v3_real.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_v4.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_validity_both_generalized_time.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_validity_both_utc_time.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_validity_relaxed.pem",
+    "src/pki/testdata/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem",
+    "src/pki/testdata/parse_certificate_unittest/v1_explicit_version.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_match_name_only.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_matching.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_mismatch.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root2.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/target.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_a.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_b.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_c.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_a.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_b.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_c.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_a.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_b.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_c.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/root.pem",
+    "src/pki/testdata/path_builder_unittest/key_id_prioritization/target.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-A-by-B.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-B-by-C.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-B-by-F.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-C-by-D.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-C-by-E.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-D-by-D.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-E-by-E.pem",
+    "src/pki/testdata/path_builder_unittest/multi-root-F-by-E.pem",
+    "src/pki/testdata/path_builder_unittest/precertificate/precertificate.pem",
+    "src/pki/testdata/path_builder_unittest/precertificate/root.pem",
+    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root1.pem",
+    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root1_cross.pem",
+    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/root2.pem",
+    "src/pki/testdata/path_builder_unittest/self_issued_prioritization/target.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_ac.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_ad.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_bc.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/int_bd.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/root.pem",
+    "src/pki/testdata/path_builder_unittest/validity_date_prioritization/target.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-after.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-before.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration-and-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-after.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-before-ta-with-expiration.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-root/not-before.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/not-after.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/expired-target/not-before.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.4.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.10.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.13.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.4.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.7.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.10.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.11.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.9.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.10.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.4.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.10.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.12.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.13.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.15.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.16.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.17.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.20.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.21.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.22.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.23.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.24.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.25.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.26.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.27.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.28.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.29.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.31.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.33.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.34.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.35.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.36.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.37.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.38.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.7.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.9.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.16.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.7.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.10.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.11.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.12.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.16.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.9.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.1.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.12.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.14.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.2.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.4.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.6.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.7.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.9.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.3.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.5.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.7.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.8.txt",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration-and-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints-require-basic-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-require-basic-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-constraints.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-expiration.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-and-trust_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-root.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/unspecified-trust-root.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/any.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf-strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict-leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-and-trust_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-not_after.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-wrong_eku.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf_require_self_signed.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf-and-trust_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf_require_self_signed.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-and-trust_anchor.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-not_after.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-wrong_eku.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf_require_self_signed.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only-trusted_leaf.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/chain.pem",
+    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/main.test",
+    "src/pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/ta-with-constraints.test",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_1.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_2.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-dupe_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_attr.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_rdn.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_1.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_2.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/custom-custom-normalized.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-badAttributeType.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-empty.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-extradata.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-onlyOneElement.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-setNotSequence.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-Name-setInsteadOfSequence.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-RDN-empty.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/invalid-RDN-sequenceInsteadOfSet.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode-mixed-normalized.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode-mixed-unnormalized.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-BMPSTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-UNIVERSALSTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode_bmp-UTF8-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UNIVERSALSTRING-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UTF8-unmangled.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/valid-Name-empty.pem",
+    "src/pki/testdata/verify_name_match_unittest/names/valid-minimal.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem",
+    "src/pki/testdata/verify_signed_data_unittest/ecdsa-using-rsa-key.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-using-pss-key-with-params.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-wrong-salt.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem",
+    "src/pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem",
+    "src/pki/testdata/verify_unittest/google-intermediate1.der",
+    "src/pki/testdata/verify_unittest/google-intermediate2.der",
+    "src/pki/testdata/verify_unittest/google-leaf.der",
+    "src/pki/testdata/verify_unittest/lencr-intermediate-r3.der",
+    "src/pki/testdata/verify_unittest/lencr-leaf.der",
+    "src/pki/testdata/verify_unittest/lencr-root-dst-x3.der",
+    "src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der",
+    "src/pki/testdata/verify_unittest/lencr-root-x1.der",
+    "src/pki/testdata/verify_unittest/mozilla_roots.der",
     "src/pki/testdata/verify_unittest/self-issued.pem"
-  ], 
+  ],
   "rust_bssl_crypto": [
-    "src/rust/bssl-crypto/src/aead.rs", 
-    "src/rust/bssl-crypto/src/aes.rs", 
-    "src/rust/bssl-crypto/src/cipher/aes_cbc.rs", 
-    "src/rust/bssl-crypto/src/cipher/aes_ctr.rs", 
-    "src/rust/bssl-crypto/src/cipher/mod.rs", 
-    "src/rust/bssl-crypto/src/digest.rs", 
-    "src/rust/bssl-crypto/src/ec.rs", 
-    "src/rust/bssl-crypto/src/ecdh.rs", 
-    "src/rust/bssl-crypto/src/ecdsa.rs", 
-    "src/rust/bssl-crypto/src/ed25519.rs", 
-    "src/rust/bssl-crypto/src/hkdf.rs", 
-    "src/rust/bssl-crypto/src/hmac.rs", 
-    "src/rust/bssl-crypto/src/hpke.rs", 
-    "src/rust/bssl-crypto/src/lib.rs", 
-    "src/rust/bssl-crypto/src/macros.rs", 
-    "src/rust/bssl-crypto/src/mem.rs", 
-    "src/rust/bssl-crypto/src/mldsa.rs", 
-    "src/rust/bssl-crypto/src/mlkem.rs", 
-    "src/rust/bssl-crypto/src/rand.rs", 
-    "src/rust/bssl-crypto/src/rsa.rs", 
-    "src/rust/bssl-crypto/src/scoped.rs", 
-    "src/rust/bssl-crypto/src/slhdsa.rs", 
-    "src/rust/bssl-crypto/src/test_helpers.rs", 
+    "src/rust/bssl-crypto/src/aead.rs",
+    "src/rust/bssl-crypto/src/aes.rs",
+    "src/rust/bssl-crypto/src/cipher/aes_cbc.rs",
+    "src/rust/bssl-crypto/src/cipher/aes_ctr.rs",
+    "src/rust/bssl-crypto/src/cipher/mod.rs",
+    "src/rust/bssl-crypto/src/digest.rs",
+    "src/rust/bssl-crypto/src/ec.rs",
+    "src/rust/bssl-crypto/src/ecdh.rs",
+    "src/rust/bssl-crypto/src/ecdsa.rs",
+    "src/rust/bssl-crypto/src/ed25519.rs",
+    "src/rust/bssl-crypto/src/hkdf.rs",
+    "src/rust/bssl-crypto/src/hmac.rs",
+    "src/rust/bssl-crypto/src/hpke.rs",
+    "src/rust/bssl-crypto/src/lib.rs",
+    "src/rust/bssl-crypto/src/macros.rs",
+    "src/rust/bssl-crypto/src/mem.rs",
+    "src/rust/bssl-crypto/src/mldsa.rs",
+    "src/rust/bssl-crypto/src/mlkem.rs",
+    "src/rust/bssl-crypto/src/rand.rs",
+    "src/rust/bssl-crypto/src/rsa.rs",
+    "src/rust/bssl-crypto/src/scoped.rs",
+    "src/rust/bssl-crypto/src/slhdsa.rs",
+    "src/rust/bssl-crypto/src/test_helpers.rs",
     "src/rust/bssl-crypto/src/x25519.rs"
-  ], 
+  ],
   "rust_bssl_sys": [
     "src/rust/bssl-sys/src/lib.rs"
-  ], 
+  ],
   "ssl": [
-    "src/ssl/bio_ssl.cc", 
-    "src/ssl/d1_both.cc", 
-    "src/ssl/d1_lib.cc", 
-    "src/ssl/d1_pkt.cc", 
-    "src/ssl/d1_srtp.cc", 
-    "src/ssl/dtls_method.cc", 
-    "src/ssl/dtls_record.cc", 
-    "src/ssl/encrypted_client_hello.cc", 
-    "src/ssl/extensions.cc", 
-    "src/ssl/handoff.cc", 
-    "src/ssl/handshake.cc", 
-    "src/ssl/handshake_client.cc", 
-    "src/ssl/handshake_server.cc", 
-    "src/ssl/s3_both.cc", 
-    "src/ssl/s3_lib.cc", 
-    "src/ssl/s3_pkt.cc", 
-    "src/ssl/ssl_aead_ctx.cc", 
-    "src/ssl/ssl_asn1.cc", 
-    "src/ssl/ssl_buffer.cc", 
-    "src/ssl/ssl_cert.cc", 
-    "src/ssl/ssl_cipher.cc", 
-    "src/ssl/ssl_credential.cc", 
-    "src/ssl/ssl_file.cc", 
-    "src/ssl/ssl_key_share.cc", 
-    "src/ssl/ssl_lib.cc", 
-    "src/ssl/ssl_privkey.cc", 
-    "src/ssl/ssl_session.cc", 
-    "src/ssl/ssl_stat.cc", 
-    "src/ssl/ssl_transcript.cc", 
-    "src/ssl/ssl_versions.cc", 
-    "src/ssl/ssl_x509.cc", 
-    "src/ssl/t1_enc.cc", 
-    "src/ssl/tls13_both.cc", 
-    "src/ssl/tls13_client.cc", 
-    "src/ssl/tls13_enc.cc", 
-    "src/ssl/tls13_server.cc", 
-    "src/ssl/tls_method.cc", 
+    "src/ssl/bio_ssl.cc",
+    "src/ssl/d1_both.cc",
+    "src/ssl/d1_lib.cc",
+    "src/ssl/d1_pkt.cc",
+    "src/ssl/d1_srtp.cc",
+    "src/ssl/dtls_method.cc",
+    "src/ssl/dtls_record.cc",
+    "src/ssl/encrypted_client_hello.cc",
+    "src/ssl/extensions.cc",
+    "src/ssl/handoff.cc",
+    "src/ssl/handshake.cc",
+    "src/ssl/handshake_client.cc",
+    "src/ssl/handshake_server.cc",
+    "src/ssl/s3_both.cc",
+    "src/ssl/s3_lib.cc",
+    "src/ssl/s3_pkt.cc",
+    "src/ssl/ssl_aead_ctx.cc",
+    "src/ssl/ssl_asn1.cc",
+    "src/ssl/ssl_buffer.cc",
+    "src/ssl/ssl_cert.cc",
+    "src/ssl/ssl_cipher.cc",
+    "src/ssl/ssl_credential.cc",
+    "src/ssl/ssl_file.cc",
+    "src/ssl/ssl_key_share.cc",
+    "src/ssl/ssl_lib.cc",
+    "src/ssl/ssl_privkey.cc",
+    "src/ssl/ssl_session.cc",
+    "src/ssl/ssl_stat.cc",
+    "src/ssl/ssl_transcript.cc",
+    "src/ssl/ssl_versions.cc",
+    "src/ssl/ssl_x509.cc",
+    "src/ssl/t1_enc.cc",
+    "src/ssl/tls13_both.cc",
+    "src/ssl/tls13_client.cc",
+    "src/ssl/tls13_enc.cc",
+    "src/ssl/tls13_server.cc",
+    "src/ssl/tls_method.cc",
     "src/ssl/tls_record.cc"
-  ], 
+  ],
   "ssl_headers": [
-    "src/include/openssl/dtls1.h", 
-    "src/include/openssl/srtp.h", 
-    "src/include/openssl/ssl.h", 
-    "src/include/openssl/ssl3.h", 
+    "src/include/openssl/dtls1.h",
+    "src/include/openssl/srtp.h",
+    "src/include/openssl/ssl.h",
+    "src/include/openssl/ssl3.h",
     "src/include/openssl/tls1.h"
-  ], 
+  ],
   "ssl_internal_headers": [
     "src/ssl/internal.h"
-  ], 
+  ],
   "ssl_test": [
-    "src/crypto/test/gtest_main.cc", 
-    "src/ssl/span_test.cc", 
-    "src/ssl/ssl_c_test.c", 
-    "src/ssl/ssl_internal_test.cc", 
+    "src/crypto/test/gtest_main.cc",
+    "src/ssl/span_test.cc",
+    "src/ssl/ssl_c_test.c",
+    "src/ssl/ssl_internal_test.cc",
     "src/ssl/ssl_test.cc"
-  ], 
+  ],
   "test_support": [
-    "src/crypto/test/abi_test.cc", 
-    "src/crypto/test/file_test.cc", 
-    "src/crypto/test/file_test_gtest.cc", 
-    "src/crypto/test/file_util.cc", 
-    "src/crypto/test/test_data.cc", 
-    "src/crypto/test/test_util.cc", 
+    "src/crypto/test/abi_test.cc",
+    "src/crypto/test/file_test.cc",
+    "src/crypto/test/file_test_gtest.cc",
+    "src/crypto/test/file_util.cc",
+    "src/crypto/test/test_data.cc",
+    "src/crypto/test/test_util.cc",
     "src/crypto/test/wycheproof_util.cc"
-  ], 
+  ],
   "test_support_headers": [
-    "src/crypto/test/abi_test.h", 
-    "src/crypto/test/file_test.h", 
-    "src/crypto/test/file_util.h", 
-    "src/crypto/test/gtest_main.h", 
-    "src/crypto/test/test_data.h", 
-    "src/crypto/test/test_util.h", 
-    "src/crypto/test/wycheproof_util.h", 
-    "src/ssl/test/async_bio.h", 
-    "src/ssl/test/fuzzer.h", 
-    "src/ssl/test/fuzzer_tags.h", 
-    "src/ssl/test/handshake_util.h", 
-    "src/ssl/test/mock_quic_transport.h", 
-    "src/ssl/test/packeted_bio.h", 
-    "src/ssl/test/settings_writer.h", 
-    "src/ssl/test/test_config.h", 
+    "src/crypto/test/abi_test.h",
+    "src/crypto/test/file_test.h",
+    "src/crypto/test/file_util.h",
+    "src/crypto/test/gtest_main.h",
+    "src/crypto/test/test_data.h",
+    "src/crypto/test/test_util.h",
+    "src/crypto/test/wycheproof_util.h",
+    "src/ssl/test/async_bio.h",
+    "src/ssl/test/fuzzer.h",
+    "src/ssl/test/fuzzer_tags.h",
+    "src/ssl/test/handshake_util.h",
+    "src/ssl/test/mock_quic_transport.h",
+    "src/ssl/test/packeted_bio.h",
+    "src/ssl/test/settings_writer.h",
+    "src/ssl/test/test_config.h",
     "src/ssl/test/test_state.h"
-  ], 
+  ],
   "tool": [
-    "src/tool/args.cc", 
-    "src/tool/ciphers.cc", 
-    "src/tool/client.cc", 
-    "src/tool/const.cc", 
-    "src/tool/digest.cc", 
-    "src/tool/fd.cc", 
-    "src/tool/file.cc", 
-    "src/tool/generate_ech.cc", 
-    "src/tool/generate_ed25519.cc", 
-    "src/tool/genrsa.cc", 
-    "src/tool/pkcs12.cc", 
-    "src/tool/rand.cc", 
-    "src/tool/server.cc", 
-    "src/tool/sign.cc", 
-    "src/tool/speed.cc", 
-    "src/tool/tool.cc", 
+    "src/tool/args.cc",
+    "src/tool/ciphers.cc",
+    "src/tool/client.cc",
+    "src/tool/const.cc",
+    "src/tool/digest.cc",
+    "src/tool/fd.cc",
+    "src/tool/file.cc",
+    "src/tool/generate_ech.cc",
+    "src/tool/generate_ed25519.cc",
+    "src/tool/genrsa.cc",
+    "src/tool/pkcs12.cc",
+    "src/tool/rand.cc",
+    "src/tool/server.cc",
+    "src/tool/sign.cc",
+    "src/tool/speed.cc",
+    "src/tool/tool.cc",
     "src/tool/transport_common.cc"
-  ], 
+  ],
   "tool_headers": [
-    "src/tool/internal.h", 
+    "src/tool/internal.h",
     "src/tool/transport_common.h"
-  ], 
+  ],
   "urandom_test": [
     "src/crypto/rand/urandom_test.cc"
   ]
diff --git a/src/.bcr/metadata.template.json b/src/.bcr/metadata.template.json
index 6d8f767..ed376c9 100644
--- a/src/.bcr/metadata.template.json
+++ b/src/.bcr/metadata.template.json
@@ -7,14 +7,14 @@
       "name": "Adam Langley"
     },
     {
-      "email": "bbe@google.com",
-      "github": "bob-beck",
-      "name": "Bob Beck"
-    },
-    {
       "email": "davidben@google.com",
       "github": "davidben",
       "name": "David Benjamin"
+    },
+    {
+      "email": "dadrian@google.com",
+      "github": "dadrian",
+      "name": "David Adrian"
     }
   ],
   "repository": [
diff --git a/src/.gitignore b/src/.gitignore
index f19d1c8..8c3524b 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -34,8 +34,7 @@
 /util/bot/sde-win32
 /util/bot/sde-win32.tar.xz
 /util/bot/tools
-/util/bot/win_toolchain
-/util/bot/win_toolchain.json
+/util/bot/windows_sdk
 
 # Ignore target under any directory.
 target/
diff --git a/src/BUILD.bazel b/src/BUILD.bazel
index 5c68e63..b7dc359 100644
--- a/src/BUILD.bazel
+++ b/src/BUILD.bazel
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@rules_license//rules:license.bzl", "license")
 load(
     ":gen/sources.bzl",
     "bcm_internal_headers",
@@ -43,7 +44,6 @@
     "urandom_test_sources",
 )
 load(":util/util.bzl", "bssl_cc_binary", "bssl_cc_library", "bssl_cc_test")
-load("@rules_license//rules:license.bzl", "license")
 
 package(
     default_applicable_licenses = [":license"],
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 50f5e37..4211db0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -36,6 +36,9 @@
 enable_language(C)
 enable_language(CXX)
 
+# TODO(crbug,com/389897612): Register tests with CTest. For now, we include this
+# only to pick up the standard |BUILD_TESTING| option.
+include(CTest)
 include(GNUInstallDirs)
 
 set(INSTALL_ENABLED 1)
@@ -241,13 +244,8 @@
     message(FATAL_ERROR "You need Clang ≥ 6.0.0")
   endif()
 
-  add_definitions(-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-  set(RUNNER_ARGS "-deterministic")
-
-  if(NOT NO_FUZZER_MODE)
-    add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
-    set(RUNNER_ARGS ${RUNNER_ARGS} "-fuzzer" "-shim-config" "fuzzer_mode.json")
-  endif()
+  add_definitions(-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+  set(RUNNER_ARGS "-deterministic" "-fuzzer" "-shim-config" "fuzzer_mode.json")
 
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,fuzzer-no-link -fsanitize-coverage=edge,indirect-calls")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,fuzzer-no-link -fsanitize-coverage=edge,indirect-calls")
@@ -481,33 +479,33 @@
   target_link_libraries(libcxx libcxxabi)
 endif()
 
-# Add minimal googletest targets. The provided one has many side-effects, and
-# googletest has a very straightforward build.
-add_library(
-  boringssl_gtest
-  third_party/googletest/googlemock/src/gmock-all.cc
-  third_party/googletest/googletest/src/gtest-all.cc
-)
-if(USE_CUSTOM_LIBCXX)
-  target_link_libraries(boringssl_gtest libcxx)
-endif()
-target_include_directories(
+if(BUILD_TESTING)
+  # Add minimal googletest targets. The provided one has many side-effects, and
+  # googletest has a very straightforward build.
+  add_library(
     boringssl_gtest
-    PUBLIC
-    third_party/googletest/googlemock/include
-    third_party/googletest/googletest/include
-    PRIVATE
-    third_party/googletest/googlemock
-    third_party/googletest/googletest
-)
+    third_party/googletest/googlemock/src/gmock-all.cc
+    third_party/googletest/googletest/src/gtest-all.cc
+  )
+  if(USE_CUSTOM_LIBCXX)
+    target_link_libraries(boringssl_gtest libcxx)
+  endif()
+  target_include_directories(
+      boringssl_gtest
+      PUBLIC
+      third_party/googletest/googlemock/include
+      third_party/googletest/googletest/include
+      PRIVATE
+      third_party/googletest/googlemock
+      third_party/googletest/googletest
+  )
 
-# Declare a dummy target to build all unit tests. Test targets should inject
-# themselves as dependencies next to the target definition.
-add_custom_target(all_tests)
+  # Declare a dummy target to build all unit tests. Test targets should inject
+  # themselves as dependencies next to the target definition.
+  add_custom_target(all_tests)
 
-add_subdirectory(ssl/test)
-add_subdirectory(util/fipstools)
-add_subdirectory(util/fipstools/acvp/modulewrapper)
+  add_subdirectory(ssl/test)
+endif()
 
 if(OPENSSL_ASM)
   set(CRYPTO_SOURCES_ASM_USED ${CRYPTO_SOURCES_ASM})
@@ -661,66 +659,64 @@
 target_link_libraries(ssl crypto)
 
 add_library(decrepit ${DECREPIT_SOURCES})
-target_link_libraries(decrepit crypto ssl)
-
-add_library(test_support_lib STATIC
-            ${TEST_SUPPORT_SOURCES} ${TEST_SUPPORT_SOURCES_ASM_USED})
-if(LIBUNWIND_FOUND)
-  target_compile_options(test_support_lib PRIVATE ${LIBUNWIND_CFLAGS_OTHER})
-  target_include_directories(test_support_lib PRIVATE ${LIBUNWIND_INCLUDE_DIRS})
-  target_link_libraries(test_support_lib ${LIBUNWIND_LDFLAGS})
-endif()
-if(WIN32)
-  target_link_libraries(test_support_lib dbghelp)
-endif()
-target_link_libraries(test_support_lib boringssl_gtest crypto)
-
-# urandom_test is a separate binary because it needs to be able to observe the
-# PRNG initialisation, which means that it can't have other tests running before
-# it does.
-add_executable(urandom_test ${URANDOM_TEST_SOURCES})
-target_link_libraries(urandom_test test_support_lib boringssl_gtest crypto)
-add_dependencies(all_tests urandom_test)
-
-add_executable(crypto_test ${CRYPTO_TEST_SOURCES})
-target_link_libraries(crypto_test test_support_lib boringssl_gtest crypto)
-add_dependencies(all_tests crypto_test)
-
-add_executable(ssl_test ${SSL_TEST_SOURCES})
-target_link_libraries(ssl_test test_support_lib boringssl_gtest ssl crypto)
-add_dependencies(all_tests ssl_test)
-add_executable(decrepit_test ${DECREPIT_TEST_SOURCES})
-target_link_libraries(decrepit_test test_support_lib boringssl_gtest
-                      decrepit crypto)
-add_dependencies(all_tests decrepit_test)
+target_link_libraries(decrepit ssl crypto)
 
 if(APPLE)
   set(PKI_CXX_FLAGS "-fno-aligned-new")
 endif()
-
 add_library(pki ${PKI_SOURCES})
 target_link_libraries(pki crypto)
+target_compile_options(pki PRIVATE ${PKI_CXX_FLAGS})
 
-add_executable(pki_test ${PKI_TEST_SOURCES})
-target_link_libraries(pki_test test_support_lib boringssl_gtest pki crypto)
-add_dependencies(all_tests pki_test)
+if(BUILD_TESTING)
+  add_library(test_support_lib STATIC
+              ${TEST_SUPPORT_SOURCES} ${TEST_SUPPORT_SOURCES_ASM_USED})
+  if(LIBUNWIND_FOUND)
+    target_compile_options(test_support_lib PRIVATE ${LIBUNWIND_CFLAGS_OTHER})
+    target_include_directories(test_support_lib PRIVATE ${LIBUNWIND_INCLUDE_DIRS})
+    target_link_libraries(test_support_lib ${LIBUNWIND_LDFLAGS})
+  endif()
+  if(WIN32)
+    target_link_libraries(test_support_lib dbghelp)
+  endif()
+  target_link_libraries(test_support_lib boringssl_gtest crypto)
 
-set_target_properties(
-  pki pki_test
-  PROPERTIES
-  COMPILE_FLAGS "${PKI_CXX_FLAGS}")
+  # urandom_test is a separate binary because it needs to be able to observe the
+  # PRNG initialisation, which means that it can't have other tests running before
+  # it does.
+  add_executable(urandom_test ${URANDOM_TEST_SOURCES})
+  target_link_libraries(urandom_test test_support_lib boringssl_gtest crypto)
+  add_dependencies(all_tests urandom_test)
+
+  add_executable(crypto_test ${CRYPTO_TEST_SOURCES})
+  target_link_libraries(crypto_test test_support_lib boringssl_gtest crypto)
+  add_dependencies(all_tests crypto_test)
+
+  add_executable(ssl_test ${SSL_TEST_SOURCES})
+  target_link_libraries(ssl_test test_support_lib boringssl_gtest ssl crypto)
+  add_dependencies(all_tests ssl_test)
+  add_executable(decrepit_test ${DECREPIT_TEST_SOURCES})
+  target_link_libraries(decrepit_test test_support_lib boringssl_gtest
+                        decrepit ssl crypto)
+  add_dependencies(all_tests decrepit_test)
+
+  add_executable(pki_test ${PKI_TEST_SOURCES})
+  target_link_libraries(pki_test test_support_lib boringssl_gtest pki crypto)
+  target_compile_options(pki_test PRIVATE ${PKI_CXX_FLAGS})
+  add_dependencies(all_tests pki_test)
+
+  add_executable(test_fips util/fipstools/test_fips.cc)
+  target_link_libraries(test_fips crypto)
+endif()
+
+if(FIPS)
+  add_executable(modulewrapper ${MODULEWRAPPER_SOURCES})
+  target_link_libraries(modulewrapper crypto)
+endif()
 
 add_executable(bssl ${BSSL_SOURCES})
 target_link_libraries(bssl ssl crypto)
 
-# Historically, targets were built in subdirectories. For compatibility with
-# existing tools, we, for now, copy the targets into the subdirectories. This
-# will be removed sometime in 2024.
-copy_post_build(crypto crypto crypto_test urandom_test)
-copy_post_build(ssl ssl ssl_test)
-copy_post_build(decrepit decrepit decrepit_test)
-copy_post_build(tool bssl)
-
 if(FUZZ)
   if(LIBFUZZER_FROM_DEPS)
     file(GLOB LIBFUZZER_SOURCES "util/bot/libFuzzer/*.cpp")
@@ -749,56 +745,58 @@
   set(HANDSHAKER_ARGS "-handshaker-path" $<TARGET_FILE:handshaker>)
 endif()
 
-if(FIPS)
-  add_custom_target(
-    acvp_tests
-    COMMAND ${GO_EXECUTABLE} build -o ${CMAKE_CURRENT_BINARY_DIR}/acvptool
-            boringssl.googlesource.com/boringssl.git/util/fipstools/acvp/acvptool
-    COMMAND ${GO_EXECUTABLE} build -o ${CMAKE_CURRENT_BINARY_DIR}/testmodulewrapper
-            boringssl.googlesource.com/boringssl.git/util/fipstools/acvp/acvptool/testmodulewrapper
-    COMMAND cd util/fipstools/acvp/acvptool/test &&
-            ${GO_EXECUTABLE} run check_expected.go
-            -tool ${CMAKE_CURRENT_BINARY_DIR}/acvptool
-            -module-wrappers modulewrapper:$<TARGET_FILE:modulewrapper>,testmodulewrapper:${CMAKE_CURRENT_BINARY_DIR}/testmodulewrapper
-            -tests tests.json
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    DEPENDS modulewrapper
-    USES_TERMINAL)
-
-  add_custom_target(
-    fips_specific_tests_if_any
-    DEPENDS acvp_tests
-  )
-else()
-  add_custom_target(fips_specific_tests_if_any)
-endif()
-
-file(STRINGS util/go_tests.txt GO_TESTS)
-set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
-             util/go_tests.txt)
-
-if(GO_EXECUTABLE)
-  add_custom_target(
-      run_tests
-      COMMAND ${CMAKE_COMMAND} -E echo "Running Go tests"
-      COMMAND ${GO_EXECUTABLE} test ${GO_TESTS}
-      COMMAND ${CMAKE_COMMAND} -E echo
-      COMMAND ${CMAKE_COMMAND} -E echo "Running unit tests"
-      COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
-              ${CMAKE_CURRENT_BINARY_DIR}
-      COMMAND ${CMAKE_COMMAND} -E echo
-      COMMAND ${CMAKE_COMMAND} -E echo "Running SSL tests"
-      COMMAND cd ssl/test/runner &&
-              ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
-                ${HANDSHAKER_ARGS} ${RUNNER_ARGS}
+if(BUILD_TESTING)
+  if(FIPS)
+    add_custom_target(
+      acvp_tests
+      COMMAND ${GO_EXECUTABLE} build -o ${CMAKE_CURRENT_BINARY_DIR}/acvptool
+              boringssl.googlesource.com/boringssl.git/util/fipstools/acvp/acvptool
+      COMMAND ${GO_EXECUTABLE} build -o ${CMAKE_CURRENT_BINARY_DIR}/testmodulewrapper
+              boringssl.googlesource.com/boringssl.git/util/fipstools/acvp/acvptool/testmodulewrapper
+      COMMAND cd util/fipstools/acvp/acvptool/test &&
+              ${GO_EXECUTABLE} run check_expected.go
+              -tool ${CMAKE_CURRENT_BINARY_DIR}/acvptool
+              -module-wrappers modulewrapper:$<TARGET_FILE:modulewrapper>,testmodulewrapper:${CMAKE_CURRENT_BINARY_DIR}/testmodulewrapper
+              -tests tests.json
       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-      DEPENDS all_tests bssl_shim handshaker fips_specific_tests_if_any
+      DEPENDS modulewrapper
       USES_TERMINAL)
-else()
-  add_custom_target(
-      run_tests
-      COMMAND ${CMAKE_COMMAND} -E echo "Running tests requires Go"
-      COMMAND ${CMAKE_COMMAND} -E false)
+
+    add_custom_target(
+      fips_specific_tests_if_any
+      DEPENDS acvp_tests
+    )
+  else()
+    add_custom_target(fips_specific_tests_if_any)
+  endif()
+
+  file(STRINGS util/go_tests.txt GO_TESTS)
+  set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
+              util/go_tests.txt)
+
+  if(GO_EXECUTABLE)
+    add_custom_target(
+        run_tests
+        COMMAND ${CMAKE_COMMAND} -E echo "Running Go tests"
+        COMMAND ${GO_EXECUTABLE} test ${GO_TESTS}
+        COMMAND ${CMAKE_COMMAND} -E echo
+        COMMAND ${CMAKE_COMMAND} -E echo "Running unit tests"
+        COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
+                ${CMAKE_CURRENT_BINARY_DIR}
+        COMMAND ${CMAKE_COMMAND} -E echo
+        COMMAND ${CMAKE_COMMAND} -E echo "Running SSL tests"
+        COMMAND cd ssl/test/runner &&
+                ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
+                  ${HANDSHAKER_ARGS} ${RUNNER_ARGS}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DEPENDS all_tests bssl_shim handshaker fips_specific_tests_if_any
+        USES_TERMINAL)
+  else()
+    add_custom_target(
+        run_tests
+        COMMAND ${CMAKE_COMMAND} -E echo "Running tests requires Go"
+        COMMAND ${CMAKE_COMMAND} -E false)
+  endif()
 endif()
 
 if(INSTALL_ENABLED)
diff --git a/src/CONTRIBUTING.md b/src/CONTRIBUTING.md
index ef70b89..4d9279a 100644
--- a/src/CONTRIBUTING.md
+++ b/src/CONTRIBUTING.md
@@ -22,10 +22,13 @@
 If you have not done so on this machine, you will need to set up a password for
 Gerrit. Sign in with a Google account, visit
 [this link](https://boringssl.googlesource.com/), and click the "Generate
-Password" link in the top right. You must also have a Gerrit account associated with
+Password" link in the top right.
+
+You must also have a Gerrit account associated with
 your Google account.  To do this visit the [Gerrit review server](https://boringssl-review.googlesource.com)
 and click "Sign in" (top right).
-You will also need to prepare your checkout to
+
+Finally, you will need to prepare your checkout to
 [add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html)
 on commit. Run:
 
@@ -38,7 +41,7 @@
     git push origin HEAD:refs/for/main
 
 The output will then give you a link to the change. Add `agl@google.com`,
-`davidben@google.com`, and `bbe@google.com` as reviewers.
+`davidben@google.com` as reviewers.
 
 Pushing a commit with the same Change-Id as an existing change will upload a new
 version of it. (Use the `git rebase` or `git commit --amend` commands.)
@@ -62,6 +65,23 @@
 all past contributors. If you previously made a contribution, you are likewise
 welcome to send us a patch to be added, or request that we add you.
 
+After the copyright lines, files should include the license notice described in
+the Apache 2.0 appendix. Thus new files should begin with the following header:
+
+    // Copyright YEAR The BoringSSL Authors
+    //
+    // Licensed under the Apache License, Version 2.0 (the "License");
+    // you may not use this file except in compliance with the License.
+    // You may obtain a copy of the License at
+    //
+    //     https://www.apache.org/licenses/LICENSE-2.0
+    //
+    // Unless required by applicable law or agreed to in writing, software
+    // distributed under the License is distributed on an "AS IS" BASIS,
+    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    // See the License for the specific language governing permissions and
+    // limitations under the License.
+
 ### The small print
 Contributions made by corporations are covered by a different agreement than
 the one above, the
diff --git a/src/FUZZING.md b/src/FUZZING.md
index 89cf5e9..3689ad0 100644
--- a/src/FUZZING.md
+++ b/src/FUZZING.md
@@ -48,13 +48,11 @@
 
 ## Fuzzer mode
 
-When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` and `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. This modifies the library to be more friendly to fuzzers. If `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` is set, BoringSSL will:
+When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` defined. BoringSSL will then:
 
 * Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state.
 
-* Use a hard-coded time instead of the actual time.
-
-Additionally, if `BORINGSSL_UNSAFE_FUZZER_MODE` is set, BoringSSL will:
+Additionally, if `CRYPTO_set_fuzzer_mode()` is called to enable fuzzer mode, BoringSSL will:
 
 * Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded.
 
@@ -70,7 +68,7 @@
 
 The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. The `run_tests` target will pass appropriate command-line flags.
 
-There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-config` flags.
+There are separate fuzzers, `client_no_fuzzer_mode` and `server_no_fuzzer_mode`, with fuzzer mode disabled. This configuration is run in the same way but without `-fuzzer` and `-shim-config` flags.
 
 If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora.sh`:
 
diff --git a/src/MODULE.bazel b/src/MODULE.bazel
index 1595fbc..6737496 100644
--- a/src/MODULE.bazel
+++ b/src/MODULE.bazel
@@ -16,7 +16,7 @@
 # the revision where we bump the version.
 module(
     name = "boringssl",
-    version = "0.20250212.0",
+    version = "0.20250415.0",
     compatibility_level = 2,
 )
 
@@ -31,7 +31,6 @@
 # https://github.com/bazelbuild/bazel/issues/22187 is ever fixed, we can change
 # this.
 bazel_dep(name = "googletest", version = "1.16.0")
-
 bazel_dep(name = "platforms", version = "0.0.11")
 bazel_dep(name = "rules_cc", version = "0.1.1")
 bazel_dep(name = "rules_license", version = "1.0.0")
diff --git a/src/STYLE.md b/src/STYLE.md
index 98a8159..1b6bd0b 100644
--- a/src/STYLE.md
+++ b/src/STYLE.md
@@ -143,7 +143,7 @@
 Name public headers like `include/openssl/evp.h` with header guards like
 `OPENSSL_HEADER_EVP_H`. Name internal headers like
 `crypto/ec/internal.h` with header guards like
-`OPENSSL_HEADER_EC_INTERNAL_H`.
+`OPENSSL_HEADER_CRYPTO_EC_INTERNAL_H`.
 
 Name enums like `enum unix_hacker_t`. For instance:
 
diff --git a/src/build.json b/src/build.json
index 1ac48f2..67d3992 100644
--- a/src/build.json
+++ b/src/build.json
@@ -26,7 +26,6 @@
             "crypto/fipsmodule/aes/key_wrap.cc.inc",
             "crypto/fipsmodule/aes/mode_wrappers.cc.inc",
             "crypto/fipsmodule/aes/ofb.cc.inc",
-            "crypto/fipsmodule/aes/polyval.cc.inc",
             "crypto/fipsmodule/bn/add.cc.inc",
             "crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
             "crypto/fipsmodule/bn/bn.cc.inc",
@@ -76,7 +75,9 @@
             "crypto/fipsmodule/hkdf/hkdf.cc.inc",
             "crypto/fipsmodule/hmac/hmac.cc.inc",
             "crypto/fipsmodule/keccak/keccak.cc.inc",
+            "crypto/fipsmodule/mldsa/fips_known_values.inc",
             "crypto/fipsmodule/mldsa/mldsa.cc.inc",
+            "crypto/fipsmodule/mlkem/fips_known_values.inc",
             "crypto/fipsmodule/mlkem/mlkem.cc.inc",
             "crypto/fipsmodule/rand/ctrdrbg.cc.inc",
             "crypto/fipsmodule/rand/rand.cc.inc",
@@ -95,6 +96,7 @@
             "crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
             "crypto/fipsmodule/slhdsa/thash.cc.inc",
             "crypto/fipsmodule/slhdsa/wots.cc.inc",
+            "crypto/fipsmodule/slhdsa/fips_known_values.inc",
             "crypto/fipsmodule/tls/kdf.cc.inc"
         ],
         "asm": [
@@ -140,8 +142,8 @@
         ],
         "perlasm_x86_64": [
             {"src": "crypto/fipsmodule/aes/asm/aesni-gcm-x86_64.pl"},
-            {"src": "crypto/fipsmodule/aes/asm/aes-gcm-avx10-x86_64.pl"},
             {"src": "crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl"},
+            {"src": "crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl"},
             {"src": "crypto/fipsmodule/aes/asm/aesni-x86_64.pl"},
             {"src": "crypto/fipsmodule/aes/asm/ghash-ssse3-x86_64.pl"},
             {"src": "crypto/fipsmodule/aes/asm/ghash-x86_64.pl"},
@@ -158,7 +160,8 @@
         ]
     },
     "crypto": {
-        "srcs": [
+      "srcs": [
+            "crypto/aes/aes.cc",
             "crypto/asn1/a_bitstr.cc",
             "crypto/asn1/a_bool.cc",
             "crypto/asn1/a_d2i_fp.cc",
@@ -201,6 +204,9 @@
             "crypto/blake2/blake2.cc",
             "crypto/bn/bn_asn1.cc",
             "crypto/bn/convert.cc",
+            "crypto/bn/div.cc",
+            "crypto/bn/exponentiation.cc",
+            "crypto/bn/sqrt.cc",
             "crypto/buf/buf.cc",
             "crypto/bytestring/asn1_compat.cc",
             "crypto/bytestring/ber.cc",
@@ -211,6 +217,7 @@
             "crypto/cipher/derive_key.cc",
             "crypto/cipher/get_cipher.cc",
             "crypto/cipher/e_aesctrhmac.cc",
+            "crypto/cipher/e_aeseax.cc",
             "crypto/cipher/e_aesgcmsiv.cc",
             "crypto/cipher/e_chacha20poly1305.cc",
             "crypto/cipher/e_des.cc",
@@ -219,6 +226,7 @@
             "crypto/cipher/e_rc4.cc",
             "crypto/cipher/e_tls.cc",
             "crypto/cipher/tls_cbc.cc",
+            "crypto/cms/cms.cc",
             "crypto/conf/conf.cc",
             "crypto/cpu_aarch64_apple.cc",
             "crypto/cpu_aarch64_fuchsia.cc",
@@ -267,6 +275,7 @@
             "crypto/evp/sign.cc",
             "crypto/ex_data.cc",
             "crypto/fipsmodule/fips_shared_support.cc",
+            "crypto/fuzzer_mode.cc",
             "crypto/hpke/hpke.cc",
             "crypto/hrss/hrss.cc",
             "crypto/kyber/kyber.cc",
@@ -418,6 +427,7 @@
             "include/openssl/chacha.h",
             "include/openssl/cipher.h",
             "include/openssl/cmac.h",
+            "include/openssl/cms.h",
             "include/openssl/conf.h",
             "include/openssl/cpu.h",
             "include/openssl/crypto.h",
@@ -540,7 +550,7 @@
             "crypto/poly1305/internal.h",
             "crypto/pool/internal.h",
             "crypto/rand/getrandom_fillin.h",
-            "crypto/rand/sysrand_internal.h",
+            "crypto/rand/internal.h",
             "crypto/rsa/internal.h",
             "crypto/spake2plus/internal.h",
             "crypto/trust_token/internal.h",
@@ -804,6 +814,7 @@
             "crypto/chacha/chacha_test.cc",
             "crypto/cipher/aead_test.cc",
             "crypto/cipher/cipher_test.cc",
+            "crypto/cms/cms_test.cc",
             "crypto/compiler_test.cc",
             "crypto/conf/conf_test.cc",
             "crypto/constant_time_test.cc",
@@ -904,6 +915,9 @@
             "crypto/mlkem/mlkem768_keygen_tests.txt",
             "crypto/mlkem/mlkem768_nist_decap_tests.txt",
             "crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+            "crypto/pkcs7/test/*.p7c",
+            "crypto/pkcs7/test/*.p7s",
+            "crypto/pkcs7/test/*.pem",
             "crypto/pkcs8/test/*.p12",
             "crypto/poly1305/poly1305_tests.txt",
             "crypto/siphash/siphash_tests.txt",
@@ -1042,5 +1056,14 @@
             "rust/bssl-crypto/src/*.rs",
             "rust/bssl-crypto/src/*/*.rs"
         ]
+    },
+    "modulewrapper": {
+        "srcs": [
+            "util/fipstools/acvp/modulewrapper/main.cc",
+            "util/fipstools/acvp/modulewrapper/modulewrapper.cc"
+        ],
+        "internal_hdrs": [
+            "util/fipstools/acvp/modulewrapper/modulewrapper.h"
+        ]
     }
 }
diff --git a/src/crypto/aes/aes.cc b/src/crypto/aes/aes.cc
new file mode 100644
index 0000000..fc9b67d
--- /dev/null
+++ b/src/crypto/aes/aes.cc
@@ -0,0 +1,41 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <assert.h>
+
+#include <openssl/aes.h>
+
+#include "../fipsmodule/bcm_interface.h"
+
+void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+  BCM_aes_encrypt(in, out, key);
+}
+
+void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+  BCM_aes_decrypt(in, out, key);
+}
+
+int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+  if (bits != 128 && bits != 192 && bits != 256) {
+    return -2;
+  }
+  return bcm_success(BCM_aes_set_encrypt_key(key, bits, aeskey)) ? 0 : -1;
+}
+
+int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+  if (bits != 128 && bits != 192 && bits != 256) {
+    return -2;
+  }
+  return bcm_success(BCM_aes_set_decrypt_key(key, bits, aeskey)) ? 0 : -1;
+}
diff --git a/src/crypto/asn1/a_bitstr.cc b/src/crypto/asn1/a_bitstr.cc
index 82df5c8..6bdd726 100644
--- a/src/crypto/asn1/a_bitstr.cc
+++ b/src/crypto/asn1/a_bitstr.cc
@@ -17,6 +17,7 @@
 #include <limits.h>
 #include <string.h>
 
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
@@ -94,6 +95,21 @@
   return ret;
 }
 
+int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in,
+                            CBS_ASN1_TAG tag) {
+  int len = i2c_ASN1_BIT_STRING(in, nullptr);
+  if (len <= 0) {
+    return 0;
+  }
+  tag = tag == 0 ? CBS_ASN1_BITSTRING : tag;
+  CBB child;
+  uint8_t *ptr;
+  return CBB_add_asn1(out, &child, tag) &&                         //
+         CBB_add_space(&child, &ptr, static_cast<size_t>(len)) &&  //
+         i2c_ASN1_BIT_STRING(in, &ptr) == len &&                   //
+         CBB_flush(out);
+}
+
 ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
                                      const unsigned char **pp, long len) {
   ASN1_BIT_STRING *ret = NULL;
diff --git a/src/crypto/asn1/a_int.cc b/src/crypto/asn1/a_int.cc
index 7b0e28b..e641705 100644
--- a/src/crypto/asn1/a_int.cc
+++ b/src/crypto/asn1/a_int.cc
@@ -23,6 +23,7 @@
 #include <openssl/mem.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 
 ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) {
@@ -72,6 +73,20 @@
   return 1;
 }
 
+int asn1_marshal_integer(CBB *out, const ASN1_INTEGER *in, CBS_ASN1_TAG tag) {
+  int len = i2c_ASN1_INTEGER(in, nullptr);
+  if (len <= 0) {
+    return 0;
+  }
+  tag = tag == 0 ? CBS_ASN1_INTEGER : tag;
+  CBB child;
+  uint8_t *ptr;
+  return CBB_add_asn1(out, &child, tag) &&     //
+         CBB_add_space(&child, &ptr, static_cast<size_t>(len)) &&   //
+         i2c_ASN1_INTEGER(in, &ptr) == len &&  //
+         CBB_flush(out);
+}
+
 int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
   if (in == NULL) {
     return 0;
diff --git a/src/crypto/asn1/asn1_test.cc b/src/crypto/asn1/asn1_test.cc
index c4d6f0e..36ef5d6 100644
--- a/src/crypto/asn1/asn1_test.cc
+++ b/src/crypto/asn1/asn1_test.cc
@@ -106,22 +106,6 @@
                                   obj->value.asn1_string->length));
   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 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;
-  obj->value.asn1_string = ASN1_STRING_type_new(128);
-  ASSERT_TRUE(obj->value.asn1_string);
-  const uint8_t zero = 0;
-  ASSERT_TRUE(ASN1_STRING_set(obj->value.asn1_string, &zero, sizeof(zero)));
-  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|.
   static const uint8_t kConstructedOctetString[] = {0x24, 0x00};
@@ -1963,18 +1947,6 @@
 }
 #endif  // OPENSSL_THREADS
 
-// Test that multi-string types correctly encode negative ENUMERATED.
-// Multi-string types cannot contain INTEGER, so we only test ENUMERATED.
-TEST(ASN1Test, NegativeEnumeratedMultistring) {
-  static const uint8_t kMinusOne[] = {0x0a, 0x01, 0xff};  // ENUMERATED { -1 }
-  // |ASN1_PRINTABLE| is a multi-string type that allows ENUMERATED.
-  const uint8_t *p = kMinusOne;
-  bssl::UniquePtr<ASN1_STRING> str(
-      d2i_ASN1_PRINTABLE(nullptr, &p, sizeof(kMinusOne)));
-  ASSERT_TRUE(str);
-  TestSerialize(str.get(), i2d_ASN1_PRINTABLE, kMinusOne);
-}
-
 // Encoding a CHOICE type with an invalid selector should fail.
 TEST(ASN1Test, InvalidChoice) {
   bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
@@ -2009,6 +1981,16 @@
   ASSERT_TRUE(obj);
   EXPECT_EQ(-1, obj->type);
   EXPECT_EQ(-1, i2d_ASN1_TYPE(obj.get(), nullptr));
+
+  // The historical in-memory representation of [UNIVERSAL 128] was for both
+  // |obj->type| and |obj->value.asn1_string->type| to be 128. This is no longer
+  // used and should be rejected by the encoder.
+  obj.reset(ASN1_TYPE_new());
+  ASSERT_TRUE(obj);
+  obj->type = 128;
+  obj->value.asn1_string = ASN1_STRING_type_new(128);
+  ASSERT_TRUE(obj->value.asn1_string);
+  EXPECT_EQ(-1, i2d_ASN1_TYPE(obj.get(), nullptr));
 }
 
 // Encoding invalid MSTRING types should fail. An MSTRING is a CHOICE of
@@ -3020,9 +3002,8 @@
   // Test only the first field present.
   bssl::ScopedCBB cbb;
   ASSERT_TRUE(CBB_init(cbb.get(), 64));
-  CBB seq;
-  ASSERT_TRUE(CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE));
-  ASSERT_TRUE(CBB_add_bytes(&seq, inp.data(), inp.size()));
+  ASSERT_TRUE(CBB_add_asn1_element(cbb.get(), CBS_ASN1_SEQUENCE, inp.data(),
+                                   inp.size()));
   ASSERT_TRUE(CBB_flush(cbb.get()));
   const uint8_t *ptr = CBB_data(cbb.get());
   obj.reset(d2i_embed(nullptr, &ptr, CBB_len(cbb.get())));
@@ -3038,6 +3019,7 @@
   // Test all fields present.
   cbb.Reset();
   ASSERT_TRUE(CBB_init(cbb.get(), 64));
+  CBB seq;
   ASSERT_TRUE(CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE));
   ASSERT_TRUE(CBB_add_bytes(&seq, inp.data(), inp.size()));
   CBB child;
diff --git a/src/crypto/asn1/internal.h b/src/crypto/asn1/internal.h
index 302dd71..2baeb12 100644
--- a/src/crypto/asn1/internal.h
+++ b/src/crypto/asn1/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_ASN1_INTERNAL_H
-#define OPENSSL_HEADER_ASN1_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_ASN1_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_ASN1_INTERNAL_H
 
 #include <time.h>
 
@@ -180,6 +180,17 @@
 int asn1_bit_string_length(const ASN1_BIT_STRING *str,
                            uint8_t *out_padding_bits);
 
+// asn1_marshal_bit_string marshals |in| as a DER-encoded, ASN.1 BIT STRING and
+// writes the result to |out|. It returns one on success and zero on error. If
+// |tag| is non-zero, the tag is replaced with |tag|.
+int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in,
+                            CBS_ASN1_TAG tag);
+
+// asn1_marshal_integer marshals |in| as a DER-encoded, ASN.1 INTEGER and writes
+// the result to |out|. It returns one on success and zero on error. If |tag| is
+// non-zero, the tag is replaced with |tag|.
+int asn1_marshal_integer(CBB *out, const ASN1_INTEGER *in, CBS_ASN1_TAG tag);
+
 typedef struct {
   int nid;
   long minsize;
@@ -214,9 +225,14 @@
   ASN1_ex_i2d *asn1_ex_i2d;
 } ASN1_EXTERN_FUNCS;
 
+// ASN1_ANY_AS_STRING is an |ASN1_ITEM| with ASN.1 type ANY and C type
+// |ASN1_STRING*|. Types which are not represented with |ASN1_STRING|, such as
+// |ASN1_OBJECT|, are represented with type |V_ASN1_OTHER|.
+DECLARE_ASN1_ITEM(ASN1_ANY_AS_STRING)
+
 
 #if defined(__cplusplus)
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_ASN1_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_ASN1_INTERNAL_H
diff --git a/src/crypto/asn1/tasn_dec.cc b/src/crypto/asn1/tasn_dec.cc
index bf5e030..627c135 100644
--- a/src/crypto/asn1/tasn_dec.cc
+++ b/src/crypto/asn1/tasn_dec.cc
@@ -52,46 +52,43 @@
                             long len, const ASN1_ITEM *it, int tag, int aclass,
                             char opt, CRYPTO_BUFFER *buf, int depth);
 
-// Table to convert tags to bit values, used for MSTRING type
-static const unsigned long tag2bit[31] = {
-    0,  // (reserved)
-    0,  // BOOLEAN
-    0,  // INTEGER
-    B_ASN1_BIT_STRING,
-    B_ASN1_OCTET_STRING,
-    0,               // NULL
-    0,               // OBJECT IDENTIFIER
-    B_ASN1_UNKNOWN,  // ObjectDescriptor
-    B_ASN1_UNKNOWN,  // EXTERNAL
-    B_ASN1_UNKNOWN,  // REAL
-    B_ASN1_UNKNOWN,  // ENUMERATED
-    B_ASN1_UNKNOWN,  // EMBEDDED PDV
-    B_ASN1_UTF8STRING,
-    B_ASN1_UNKNOWN,  // RELATIVE-OID
-    B_ASN1_UNKNOWN,  // TIME
-    B_ASN1_UNKNOWN,  // (reserved)
-    B_ASN1_SEQUENCE,
-    0,  // SET
-    B_ASN1_NUMERICSTRING,
-    B_ASN1_PRINTABLESTRING,
-    B_ASN1_T61STRING,
-    B_ASN1_VIDEOTEXSTRING,
-    B_ASN1_IA5STRING,
-    B_ASN1_UTCTIME,
-    B_ASN1_GENERALIZEDTIME,
-    B_ASN1_GRAPHICSTRING,
-    B_ASN1_ISO64STRING,
-    B_ASN1_GENERALSTRING,
-    B_ASN1_UNIVERSALSTRING,
-    B_ASN1_UNKNOWN,  // CHARACTER STRING
-    B_ASN1_BMPSTRING,
-};
-
 unsigned long ASN1_tag2bit(int tag) {
-  if (tag < 0 || tag > 30) {
-    return 0;
+  switch (tag) {
+    case V_ASN1_BIT_STRING:
+      return B_ASN1_BIT_STRING;
+    case V_ASN1_OCTET_STRING:
+      return B_ASN1_OCTET_STRING;
+    case V_ASN1_UTF8STRING:
+      return B_ASN1_UTF8STRING;
+    case V_ASN1_SEQUENCE:
+      return B_ASN1_SEQUENCE;
+    case V_ASN1_NUMERICSTRING:
+      return B_ASN1_NUMERICSTRING;
+    case V_ASN1_PRINTABLESTRING:
+      return B_ASN1_PRINTABLESTRING;
+    case V_ASN1_T61STRING:
+      return B_ASN1_T61STRING;
+    case V_ASN1_VIDEOTEXSTRING:
+      return B_ASN1_VIDEOTEXSTRING;
+    case V_ASN1_IA5STRING:
+      return B_ASN1_IA5STRING;
+    case V_ASN1_UTCTIME:
+      return B_ASN1_UTCTIME;
+    case V_ASN1_GENERALIZEDTIME:
+      return B_ASN1_GENERALIZEDTIME;
+    case V_ASN1_GRAPHICSTRING:
+      return B_ASN1_GRAPHICSTRING;
+    case V_ASN1_ISO64STRING:
+      return B_ASN1_ISO64STRING;
+    case V_ASN1_GENERALSTRING:
+      return B_ASN1_GENERALSTRING;
+    case V_ASN1_UNIVERSALSTRING:
+      return B_ASN1_UNIVERSALSTRING;
+    case V_ASN1_BMPSTRING:
+      return B_ASN1_BMPSTRING;
+    default:
+      return 0;
   }
-  return tag2bit[tag];
 }
 
 static int is_supported_universal_type(int tag, int aclass) {
@@ -629,6 +626,7 @@
     return 0;  // Should never happen
   }
 
+  assert(it->itype == ASN1_ITYPE_PRIMITIVE || it->itype == ASN1_ITYPE_MSTRING);
   if (it->itype == ASN1_ITYPE_MSTRING) {
     utype = tag;
     tag = -1;
@@ -636,7 +634,7 @@
     utype = it->utype;
   }
 
-  if (utype == V_ASN1_ANY) {
+  if (utype == V_ASN1_ANY || utype == V_ASN1_ANY_AS_STRING) {
     // If type is ANY need to figure out type from tag
     unsigned char oclass;
     if (tag >= 0) {
@@ -647,8 +645,9 @@
       OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
       return 0;
     }
+    const int is_string = utype == V_ASN1_ANY_AS_STRING;
     p = *in;
-    ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, &p, inlen, -1, 0, 0);
+    ret = asn1_check_tlen(&plen, &utype, &oclass, &cst, &p, inlen, -1, 0, 0);
     if (!ret) {
       OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
       return 0;
@@ -656,6 +655,37 @@
     if (!is_supported_universal_type(utype, oclass)) {
       utype = V_ASN1_OTHER;
     }
+    // These three types are not represented as |ASN1_STRING|, so they must be
+    // parsed separately and then treated as an opaque |V_ASN1_OTHER|.
+    if (is_string && (utype == V_ASN1_OBJECT || utype == V_ASN1_NULL ||
+                      utype == V_ASN1_BOOLEAN)) {
+      if (cst) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
+        return 0;
+      }
+      CBS cbs;
+      CBS_init(&cbs, p, plen);
+      if (utype == V_ASN1_OBJECT && !CBS_is_valid_asn1_oid(&cbs)) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
+        return 0;
+      }
+      if (utype == V_ASN1_NULL && CBS_len(&cbs) != 0) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
+        return 0;
+      }
+      if (utype == V_ASN1_BOOLEAN) {
+        if (CBS_len(&cbs) != 1) {
+          OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+          return 0;
+        }
+        uint8_t v = CBS_data(&cbs)[0];
+        if (v != 0 && v != 0xff) {
+          OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
+          return 0;
+        }
+      }
+      utype = V_ASN1_OTHER;
+    }
   }
   if (tag == -1) {
     tag = utype;
@@ -738,6 +768,10 @@
     opval = pval;
     pval = &typ->value.asn1_value;
   }
+
+  // If implementing a type that is not represented in |ASN1_STRING|, the
+  // |V_ASN1_ANY_AS_STRING| logic must be modified to redirect it to
+  // |V_ASN1_OTHER|.
   switch (utype) {
     case V_ASN1_OBJECT:
       if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) {
@@ -796,14 +830,7 @@
     case V_ASN1_UTF8STRING:
     case V_ASN1_OTHER:
     case V_ASN1_SET:
-    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: {
+    case V_ASN1_SEQUENCE: {
       CBS cbs;
       CBS_init(&cbs, cont, (size_t)len);
       if (utype == V_ASN1_BMPSTRING) {
@@ -866,6 +893,10 @@
       }
       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.cc b/src/crypto/asn1/tasn_enc.cc
index 9156e16..9aa2039 100644
--- a/src/crypto/asn1/tasn_enc.cc
+++ b/src/crypto/asn1/tasn_enc.cc
@@ -527,21 +527,23 @@
   unsigned char c;
   int len;
 
+  assert(it->itype == ASN1_ITYPE_PRIMITIVE || it->itype == ASN1_ITYPE_MSTRING);
   // Historically, |it->funcs| for primitive types contained an
   // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
   assert(it->funcs == NULL);
 
   *out_omit = 0;
 
-  // Should type be omitted?
-  if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
+  // Handle omitted optional values for all but BOOLEAN, which uses a
+  // non-pointer representation.
+  if (it->itype != ASN1_ITYPE_PRIMITIVE || it->utype != V_ASN1_BOOLEAN) {
     if (!*pval) {
       *out_omit = 1;
       return 0;
     }
   }
 
-  if (it->itype == ASN1_ITYPE_MSTRING) {
+  if (it->itype == ASN1_ITYPE_MSTRING || it->utype == V_ASN1_ANY_AS_STRING) {
     // If MSTRING type set the underlying type
     strtmp = (ASN1_STRING *)*pval;
     utype = strtmp->type;
@@ -550,15 +552,8 @@
       OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
       return -1;
     }
-    // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
-    // that do not match their corresponding utype values. INTEGERs cannot
-    // participate in MSTRING types, but ENUMERATEDs can.
-    //
-    // TODO(davidben): Is this a bug? Although arguably one of the MSTRING
-    // types should contain more values, rather than less. See
-    // https://crbug.com/boringssl/412. But it is not possible to fit all
-    // possible ANY values into an |ASN1_STRING|, so matching the spec here
-    // is somewhat hopeless.
+    // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values that
+    // do not match their corresponding utype values.
     if (utype == V_ASN1_NEG_INTEGER) {
       utype = V_ASN1_INTEGER;
     } else if (utype == V_ASN1_NEG_ENUMERATED) {
@@ -649,18 +644,15 @@
     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/asn1/tasn_typ.cc b/src/crypto/asn1/tasn_typ.cc
index 97d0e44..1d11ae8 100644
--- a/src/crypto/asn1/tasn_typ.cc
+++ b/src/crypto/asn1/tasn_typ.cc
@@ -16,7 +16,8 @@
 
 #include <openssl/asn1t.h>
 
-// Declarations for string types
+#include "internal.h"
+
 
 #define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname)                         \
   IMPLEMENT_ASN1_TYPE(sname)                                           \
@@ -45,18 +46,13 @@
 IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
 
 IMPLEMENT_ASN1_TYPE(ASN1_ANY)
+IMPLEMENT_ASN1_TYPE(ASN1_ANY_AS_STRING)
 
 // Just swallow an ASN1_SEQUENCE in an ASN1_STRING
 IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
 
 IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
 
-// Multistring types
-
-IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
-IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, ASN1_PRINTABLE,
-                                     ASN1_PRINTABLE)
-
 IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
 IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, DISPLAYTEXT, DISPLAYTEXT)
 
diff --git a/src/crypto/bcm_support.h b/src/crypto/bcm_support.h
index 903c85c..faea2bb 100644
--- a/src/crypto/bcm_support.h
+++ b/src/crypto/bcm_support.h
@@ -25,41 +25,6 @@
 extern "C" {
 #endif
 
-#if defined(OPENSSL_LINUX)
-// On linux we use MADVISE instead of pthread_atfork(), due
-// to concerns about clone() being used for address space
-// duplication.
-#define OPENSSL_FORK_DETECTION
-#define OPENSSL_FORK_DETECTION_MADVISE
-#elif defined(OPENSSL_MACOS) || defined(OPENSSL_IOS) || \
-    defined(OPENSSL_OPENBSD) || defined(OPENSSL_FREEBSD)
-// These platforms may detect address space duplication with pthread_atfork.
-// iOS doesn't normally allow fork in apps, but it's there.
-#define OPENSSL_FORK_DETECTION
-#define OPENSSL_FORK_DETECTION_PTHREAD_ATFORK
-#elif defined(OPENSSL_WINDOWS) || defined(OPENSSL_TRUSTY) || \
-    defined(__ZEPHYR__) || defined(CROS_EC)
-// These platforms do not fork.
-#define OPENSSL_DOES_NOT_FORK
-#endif
-
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-#define OPENSSL_RAND_DETERMINISTIC
-#elif defined(OPENSSL_TRUSTY)
-#define OPENSSL_RAND_TRUSTY
-#elif defined(OPENSSL_WINDOWS)
-#define OPENSSL_RAND_WINDOWS
-#elif defined(OPENSSL_LINUX)
-#define OPENSSL_RAND_URANDOM
-#elif defined(OPENSSL_APPLE) && !defined(OPENSSL_MACOS)
-// Unlike macOS, iOS and similar hide away getentropy().
-#define OPENSSL_RAND_IOS
-#else
-// By default if you are integrating BoringSSL we expect you to
-// provide getentropy from the <unistd.h> header file.
-#define OPENSSL_RAND_GETENTROPY
-#endif
-
 // Provided by libcrypto, called from BCM
 
 // CRYPTO_init_sysrand initializes long-lived resources needed to draw entropy
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 4dfcbf5..faeccd8 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -39,10 +39,8 @@
 #else
 #include <fcntl.h>
 #include <io.h>
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 namespace {
diff --git a/src/crypto/bio/connect.cc b/src/crypto/bio/connect.cc
index 8175b9d..21f09b9 100644
--- a/src/crypto/bio/connect.cc
+++ b/src/crypto/bio/connect.cc
@@ -26,10 +26,8 @@
 #include <sys/socket.h>
 #include <unistd.h>
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/err.h>
diff --git a/src/crypto/bio/internal.h b/src/crypto/bio/internal.h
index 8c44d2d..d06be4d 100644
--- a/src/crypto/bio/internal.h
+++ b/src/crypto/bio/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_BIO_INTERNAL_H
-#define OPENSSL_HEADER_BIO_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_BIO_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_BIO_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -26,9 +26,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 typedef int socklen_t;
 #endif
 #endif  // !OPENSSL_NO_SOCK
@@ -76,4 +74,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_BIO_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_BIO_INTERNAL_H
diff --git a/src/crypto/bio/socket.cc b/src/crypto/bio/socket.cc
index 22ef4f7..672c9b5 100644
--- a/src/crypto/bio/socket.cc
+++ b/src/crypto/bio/socket.cc
@@ -22,10 +22,7 @@
 #if !defined(OPENSSL_WINDOWS)
 #include <unistd.h>
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
-
 OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
diff --git a/src/crypto/bio/socket_helper.cc b/src/crypto/bio/socket_helper.cc
index 4b88020..7d1e2a3 100644
--- a/src/crypto/bio/socket_helper.cc
+++ b/src/crypto/bio/socket_helper.cc
@@ -30,10 +30,8 @@
 #include <netdb.h>
 #include <unistd.h>
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include "internal.h"
diff --git a/src/crypto/bn/convert.cc b/src/crypto/bn/convert.cc
index 6f4d4fa..59ea6d4 100644
--- a/src/crypto/bn/convert.cc
+++ b/src/crypto/bn/convert.cc
@@ -19,6 +19,8 @@
 #include <limits.h>
 #include <stdio.h>
 
+#include <algorithm>
+
 #include <openssl/bio.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
@@ -196,33 +198,32 @@
 char *BN_bn2dec(const BIGNUM *a) {
   // It is easier to print strings little-endian, so we assemble it in reverse
   // and fix at the end.
-  BIGNUM *copy = NULL;
-  CBB cbb;
-  if (!CBB_init(&cbb, 16) || //
-      !CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
-    goto err;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 16) || //
+      !CBB_add_u8(cbb.get(), 0 /* trailing NUL */)) {
+    return nullptr;
   }
 
   if (BN_is_zero(a)) {
-    if (!CBB_add_u8(&cbb, '0')) {
-      goto err;
+    if (!CBB_add_u8(cbb.get(), '0')) {
+      return nullptr;
     }
   } else {
-    copy = BN_dup(a);
-    if (copy == NULL) {
-      goto err;
+    bssl::UniquePtr<BIGNUM> copy(BN_dup(a));
+    if (copy == nullptr) {
+      return nullptr;
     }
 
-    while (!BN_is_zero(copy)) {
-      BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
+    while (!BN_is_zero(copy.get())) {
+      BN_ULONG word = BN_div_word(copy.get(), BN_DEC_CONV);
       if (word == (BN_ULONG)-1) {
-        goto err;
+        return nullptr;
       }
 
-      const int add_leading_zeros = !BN_is_zero(copy);
+      const int add_leading_zeros = !BN_is_zero(copy.get());
       for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
-        if (!CBB_add_u8(&cbb, '0' + word % 10)) {
-          goto err;
+        if (!CBB_add_u8(cbb.get(), '0' + word % 10)) {
+          return nullptr;
         }
         word /= 10;
       }
@@ -231,30 +232,18 @@
   }
 
   if (BN_is_negative(a) && //
-      !CBB_add_u8(&cbb, '-')) {
-    goto err;
+      !CBB_add_u8(cbb.get(), '-')) {
+    return nullptr;
   }
 
   uint8_t *data;
   size_t len;
-  if (!CBB_finish(&cbb, &data, &len)) {
-    goto err;
+  if (!CBB_finish(cbb.get(), &data, &len)) {
+    return nullptr;
   }
 
-  // Reverse the buffer.
-  for (size_t i = 0; i < len / 2; i++) {
-    uint8_t tmp = data[i];
-    data[i] = data[len - 1 - i];
-    data[len - 1 - i] = tmp;
-  }
-
-  BN_free(copy);
-  return (char *)data;
-
-err:
-  BN_free(copy);
-  CBB_cleanup(&cbb);
-  return NULL;
+  std::reverse(data, data + len);
+  return reinterpret_cast<char *>(data);
 }
 
 int BN_dec2bn(BIGNUM **outp, const char *in) {
@@ -285,33 +274,28 @@
 }
 
 int BN_print(BIO *bp, const BIGNUM *a) {
-  int i, j, v, z = 0;
-  int ret = 0;
-
   if (a->neg && BIO_write(bp, "-", 1) != 1) {
-    goto end;
+    return 0;
   }
 
   if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
-    goto end;
+    return 0;
   }
 
-  for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
-    for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
+  int z = 0;
+  for (int i = bn_minimal_width(a) - 1; i >= 0; i--) {
+    for (int j = BN_BITS2 - 4; j >= 0; j -= 4) {
       // strip leading zeros
-      v = ((int)(a->d[i] >> (long)j)) & 0x0f;
+      int v = ((int)(a->d[i] >> (long)j)) & 0x0f;
       if (z || v != 0) {
         if (BIO_write(bp, &hextable[v], 1) != 1) {
-          goto end;
+          return 0;
         }
         z = 1;
       }
     }
   }
-  ret = 1;
-
-end:
-  return ret;
+  return 1;
 }
 
 int BN_print_fp(FILE *fp, const BIGNUM *a) {
diff --git a/src/crypto/bn/div.cc b/src/crypto/bn/div.cc
new file mode 100644
index 0000000..868a2a3
--- /dev/null
+++ b/src/crypto/bn/div.cc
@@ -0,0 +1,100 @@
+// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/bn.h>
+
+#include <openssl/err.h>
+
+#include "../fipsmodule/bn/internal.h"
+#include "../internal.h"
+
+
+int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+  if (e == 0 || a->width == 0) {
+    BN_zero(r);
+    return 1;
+  }
+
+  size_t num_words = 1 + ((e - 1) / BN_BITS2);
+
+  // If |a| definitely has less than |e| bits, just BN_copy.
+  if ((size_t)a->width < num_words) {
+    return BN_copy(r, a) != NULL;
+  }
+
+  // Otherwise, first make sure we have enough space in |r|.
+  // Note that this will fail if num_words > INT_MAX.
+  if (!bn_wexpand(r, num_words)) {
+    return 0;
+  }
+
+  // Copy the content of |a| into |r|.
+  OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
+
+  // If |e| isn't word-aligned, we have to mask off some of our bits.
+  size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
+  if (top_word_exponent != 0) {
+    r->d[num_words - 1] &= (((BN_ULONG)1) << top_word_exponent) - 1;
+  }
+
+  // Fill in the remaining fields of |r|.
+  r->neg = a->neg;
+  r->width = (int)num_words;
+  bn_set_minimal_width(r);
+  return 1;
+}
+
+int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+  if (!BN_mod_pow2(r, a, e)) {
+    return 0;
+  }
+
+  // If the returned value was non-negative, we're done.
+  if (BN_is_zero(r) || !r->neg) {
+    return 1;
+  }
+
+  size_t num_words = 1 + (e - 1) / BN_BITS2;
+
+  // Expand |r| to the size of our modulus.
+  if (!bn_wexpand(r, num_words)) {
+    return 0;
+  }
+
+  // Clear the upper words of |r|.
+  OPENSSL_memset(&r->d[r->width], 0, (num_words - r->width) * BN_BYTES);
+
+  // Set parameters of |r|.
+  r->neg = 0;
+  r->width = (int)num_words;
+
+  // Now, invert every word. The idea here is that we want to compute 2^e-|x|,
+  // which is actually equivalent to the twos-complement representation of |x|
+  // in |e| bits, which is -x = ~x + 1.
+  for (int i = 0; i < r->width; i++) {
+    r->d[i] = ~r->d[i];
+  }
+
+  // If our exponent doesn't span the top word, we have to mask the rest.
+  size_t top_word_exponent = e % BN_BITS2;
+  if (top_word_exponent != 0) {
+    r->d[r->width - 1] &= (((BN_ULONG)1) << top_word_exponent) - 1;
+  }
+
+  // Keep the minimal-width invariant for |BIGNUM|.
+  bn_set_minimal_width(r);
+
+  // Finally, add one, for the reason described above.
+  return BN_add(r, r, BN_value_one());
+}
diff --git a/src/crypto/bn/exponentiation.cc b/src/crypto/bn/exponentiation.cc
new file mode 100644
index 0000000..07f9ec6
--- /dev/null
+++ b/src/crypto/bn/exponentiation.cc
@@ -0,0 +1,166 @@
+// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/bn.h>
+
+#include <assert.h>
+
+#include <openssl/err.h>
+
+#include "../fipsmodule/bn/internal.h"
+
+
+int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *rr;
+  if (r == a || r == p) {
+    rr = BN_CTX_get(ctx);
+  } else {
+    rr = r;
+  }
+
+  BIGNUM *v = BN_CTX_get(ctx);
+  if (rr == NULL || v == NULL) {
+    return 0;
+  }
+
+  if (BN_copy(v, a) == NULL) {
+    return 0;
+  }
+  int bits = BN_num_bits(p);
+
+  if (BN_is_odd(p)) {
+    if (BN_copy(rr, a) == NULL) {
+      return 0;
+    }
+  } else {
+    if (!BN_one(rr)) {
+      return 0;
+    }
+  }
+
+  for (int i = 1; i < bits; i++) {
+    if (!BN_sqr(v, v, ctx)) {
+      return 0;
+    }
+    if (BN_is_bit_set(p, i)) {
+      if (!BN_mul(rr, rr, v, ctx)) {
+        return 0;
+      }
+    }
+  }
+
+  if (r != rr && !BN_copy(r, rr)) {
+    return 0;
+  }
+  return 1;
+}
+
+static int mod_exp_even(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                        const BIGNUM *m, BN_CTX *ctx) {
+  // No cryptographic operations require modular exponentiation with an even
+  // modulus. We support it for backwards compatibility with any applications
+  // that may have relied on the operation, but optimize for simplicity over
+  // performance with straightforward square-and-multiply routine.
+  int bits = BN_num_bits(p);
+  if (bits == 0) {
+    return BN_one(r);
+  }
+
+  // Make a copy of |a|, in case it aliases |r|.
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *tmp = BN_CTX_get(ctx);
+  if (tmp == nullptr || !BN_copy(tmp, a)) {
+    return 0;
+  }
+
+  assert(BN_is_bit_set(p, bits - 1));
+  if (!BN_copy(r, tmp)) {
+    return 0;
+  }
+
+  for (int i = bits - 2; i >= 0; i--) {
+    if (!BN_mod_sqr(r, r, m, ctx) ||
+        (BN_is_bit_set(p, i) && !BN_mod_mul(r, r, tmp, m, ctx))) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+               BN_CTX *ctx) {
+  if (m->neg) {
+    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+    return 0;
+  }
+  if (a->neg || BN_ucmp(a, m) >= 0) {
+    if (!BN_nnmod(r, a, m, ctx)) {
+      return 0;
+    }
+    a = r;
+  }
+
+  if (BN_is_odd(m)) {
+    return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
+  }
+
+  return mod_exp_even(r, a, p, m, ctx);
+}
+
+int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
+                         const BIGNUM *m, BN_CTX *ctx,
+                         const BN_MONT_CTX *mont) {
+  // BN_mod_exp_mont requires reduced inputs.
+  if (bn_minimal_width(m) == 1) {
+    a %= m->d[0];
+  }
+
+  bssl::UniquePtr<BIGNUM> a_bignum(BN_new());
+  if (a_bignum == nullptr || !BN_set_word(a_bignum.get(), a)) {
+    OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  return BN_mod_exp_mont(rr, a_bignum.get(), p, m, ctx, mont);
+}
+
+int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
+                     const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
+                     BN_CTX *ctx, const BN_MONT_CTX *mont) {
+  // Allocate a montgomery context if it was not supplied by the caller.
+  bssl::UniquePtr<BN_MONT_CTX> new_mont;
+  if (mont == nullptr) {
+    new_mont.reset(BN_MONT_CTX_new_for_modulus(m, ctx));
+    if (new_mont == nullptr) {
+      return 0;
+    }
+    mont = new_mont.get();
+  }
+
+  // BN_mod_mul_montgomery removes one Montgomery factor, so passing one
+  // Montgomery-encoded and one non-Montgomery-encoded value gives a
+  // non-Montgomery-encoded result.
+  bssl::UniquePtr<BIGNUM> tmp(BN_new());
+  if (tmp == nullptr ||  //
+      !BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) ||
+      !BN_mod_exp_mont(tmp.get(), a2, p2, m, ctx, mont) ||
+      !BN_to_montgomery(rr, rr, mont, ctx) ||
+      !BN_mod_mul_montgomery(rr, rr, tmp.get(), mont, ctx)) {
+    return 0;
+  }
+
+  return 1;
+}
diff --git a/src/crypto/bn/sqrt.cc b/src/crypto/bn/sqrt.cc
new file mode 100644
index 0000000..e23f1a3
--- /dev/null
+++ b/src/crypto/bn/sqrt.cc
@@ -0,0 +1,93 @@
+// Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/bn.h>
+
+#include <openssl/err.h>
+
+
+int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) {
+  BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2;
+  int ok = 0, last_delta_valid = 0;
+
+  if (in->neg) {
+    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+    return 0;
+  }
+  if (BN_is_zero(in)) {
+    BN_zero(out_sqrt);
+    return 1;
+  }
+
+  bssl::BN_CTXScope scope(ctx);
+  if (out_sqrt == in) {
+    estimate = BN_CTX_get(ctx);
+  } else {
+    estimate = out_sqrt;
+  }
+  tmp = BN_CTX_get(ctx);
+  last_delta = BN_CTX_get(ctx);
+  delta = BN_CTX_get(ctx);
+  if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) {
+    goto err;
+  }
+
+  // We estimate that the square root of an n-bit number is 2^{n/2}.
+  if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
+    goto err;
+  }
+
+  // This is Newton's method for finding a root of the equation |estimate|^2 -
+  // |in| = 0.
+  for (;;) {
+    // |estimate| = 1/2 * (|estimate| + |in|/|estimate|)
+    if (!BN_div(tmp, NULL, in, estimate, ctx) ||
+        !BN_add(tmp, tmp, estimate) ||
+        !BN_rshift1(estimate, tmp) ||
+        // |tmp| = |estimate|^2
+        !BN_sqr(tmp, estimate, ctx) ||
+        // |delta| = |in| - |tmp|
+        !BN_sub(delta, in, tmp)) {
+      OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB);
+      goto err;
+    }
+
+    delta->neg = 0;
+    // The difference between |in| and |estimate| squared is required to always
+    // decrease. This ensures that the loop always terminates, but I don't have
+    // a proof that it always finds the square root for a given square.
+    if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) {
+      break;
+    }
+
+    last_delta_valid = 1;
+
+    tmp2 = last_delta;
+    last_delta = delta;
+    delta = tmp2;
+  }
+
+  if (BN_cmp(tmp, in) != 0) {
+    OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
+    goto err;
+  }
+
+  ok = 1;
+
+err:
+  if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) {
+    ok = 0;
+  }
+  return ok;
+}
diff --git a/src/crypto/bytestring/bytestring_test.cc b/src/crypto/bytestring/bytestring_test.cc
index 23133e0..c5fff11 100644
--- a/src/crypto/bytestring/bytestring_test.cc
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -257,6 +257,18 @@
   EXPECT_EQ(CBS_ASN1_SEQUENCE, tag);
   EXPECT_EQ(Bytes("\x01\x02"), Bytes(CBS_data(&contents), CBS_len(&contents)));
 
+  CBS_init(&data, kData1, sizeof(kData1));
+  // We should be able to ignore the contents and get the tag.
+  ASSERT_TRUE(CBS_get_any_asn1(&data, NULL, &tag));
+  EXPECT_EQ(CBS_ASN1_SEQUENCE, tag);
+  // We should be able to ignore the tag and get the contents.
+  CBS_init(&data, kData1, sizeof(kData1));
+  ASSERT_TRUE(CBS_get_any_asn1(&data, &contents, NULL));
+  EXPECT_EQ(Bytes("\x01\x02"), Bytes(CBS_data(&contents), CBS_len(&contents)));
+  // We should be able to ignore both the tag and contents.
+  CBS_init(&data, kData1, sizeof(kData1));
+  ASSERT_TRUE(CBS_get_any_asn1(&data, NULL, NULL));
+
   size_t header_len;
   CBS_init(&data, kData1, sizeof(kData1));
   ASSERT_TRUE(CBS_get_any_asn1_element(&data, &contents, &tag, &header_len));
diff --git a/src/crypto/bytestring/cbb.cc b/src/crypto/bytestring/cbb.cc
index 316ac4a..b847331 100644
--- a/src/crypto/bytestring/cbb.cc
+++ b/src/crypto/bytestring/cbb.cc
@@ -481,6 +481,19 @@
   cbb->child = NULL;
 }
 
+int CBB_add_asn1_element(CBB *cbb, CBS_ASN1_TAG tag, const uint8_t *data,
+                         size_t data_len) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, tag) ||
+      !CBB_add_bytes(&child, data, data_len) ||  //
+      !CBB_flush(cbb)) {
+    cbb_on_error(cbb);
+    return 0;
+  }
+
+  return 1;
+}
+
 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
   return CBB_add_asn1_uint64_with_tag(cbb, value, CBS_ASN1_INTEGER);
 }
@@ -557,14 +570,7 @@
 }
 
 int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
-  CBB child;
-  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&child, data, data_len) || !CBB_flush(cbb)) {
-    cbb_on_error(cbb);
-    return 0;
-  }
-
-  return 1;
+  return CBB_add_asn1_element(cbb, CBS_ASN1_OCTETSTRING, data, data_len);
 }
 
 int CBB_add_asn1_bool(CBB *cbb, int value) {
diff --git a/src/crypto/bytestring/cbs.cc b/src/crypto/bytestring/cbs.cc
index 73a9d63..fd11c5a 100644
--- a/src/crypto/bytestring/cbs.cc
+++ b/src/crypto/bytestring/cbs.cc
@@ -410,7 +410,7 @@
     return 0;
   }
 
-  if (!CBS_skip(out, header_len)) {
+  if (out && !CBS_skip(out, header_len)) {
     assert(0);
     return 0;
   }
diff --git a/src/crypto/bytestring/internal.h b/src/crypto/bytestring/internal.h
index f2ea91a..110fb95 100644
--- a/src/crypto/bytestring/internal.h
+++ b/src/crypto/bytestring/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_BYTESTRING_INTERNAL_H
-#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -71,4 +71,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_BYTESTRING_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H
diff --git a/src/crypto/chacha/internal.h b/src/crypto/chacha/internal.h
index 828621b..ec0c79f 100644
--- a/src/crypto/chacha/internal.h
+++ b/src/crypto/chacha/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CHACHA_INTERNAL
-#define OPENSSL_HEADER_CHACHA_INTERNAL
+#ifndef OPENSSL_HEADER_CRYPTO_CHACHA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_CHACHA_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -37,7 +37,7 @@
 inline int ChaCha20_ctr32_ssse3_capable(size_t len) {
   // Unlike the x86_64 version, the x86 SSSE3 routine runs for all non-zero
   // lengths.
-  return len > 0 && CRYPTO_is_SSSE3_capable() && CRYPTO_is_FXSR_capable();
+  return len > 0 && CRYPTO_is_SSSE3_capable();
 }
 void ChaCha20_ctr32_ssse3(uint8_t *out, const uint8_t *in, size_t in_len,
                           const uint32_t key[8], const uint32_t counter[4]);
@@ -99,4 +99,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CHACHA_INTERNAL
+#endif  // OPENSSL_HEADER_CRYPTO_CHACHA_INTERNAL_H
diff --git a/src/crypto/cipher/aead_test.cc b/src/crypto/cipher/aead_test.cc
index 6e708e0..5eb0c39 100644
--- a/src/crypto/cipher/aead_test.cc
+++ b/src/crypto/cipher/aead_test.cc
@@ -152,6 +152,12 @@
 
     {"AES_128_CCM_Matter", EVP_aead_aes_128_ccm_matter,
      "aes_128_ccm_matter_tests.txt", 0},
+
+    {"AES_128_EAX", EVP_aead_aes_128_eax, "aes_128_eax_test.txt",
+     kVariableNonce},
+
+    {"AES_256_EAX", EVP_aead_aes_256_eax, "aes_256_eax_test.txt",
+     kVariableNonce},
 };
 
 class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
@@ -1025,6 +1031,36 @@
       });
 }
 
+TEST(AEADTest, WycheproofAESEAX) {
+  FileTestGTest(
+      "third_party/wycheproof_testvectors/aes_eax_test.txt", [](FileTest *t) {
+        std::string key_size_str;
+        ASSERT_TRUE(t->GetInstruction(&key_size_str, "keySize"));
+        const EVP_AEAD *aead;
+        switch (atoi(key_size_str.c_str())) {
+          case 128:
+            aead = EVP_aead_aes_128_eax();
+            break;
+          case 256:
+            aead = EVP_aead_aes_256_eax();
+            break;
+          default:
+            t->SkipCurrent();
+            GTEST_SKIP() << "Unsupported key size: " << key_size_str;
+        }
+
+        std::string nonce_size_str;
+        ASSERT_TRUE(t->GetInstruction(&nonce_size_str, "ivSize"));
+        // Skip tests with invalid nonce size.
+        if (nonce_size_str != "96" && nonce_size_str != "128") {
+          t->SkipCurrent();
+          GTEST_SKIP() << "Unsupported nonce size: " << nonce_size_str;
+        }
+
+        RunWycheproofTestCase(t, aead);
+      });
+}
+
 TEST(AEADTest, FreeNull) { EVP_AEAD_CTX_free(nullptr); }
 
 }  // namespace
diff --git a/src/crypto/cipher/derive_key.cc b/src/crypto/cipher/derive_key.cc
index d8aecdd..ac0f284 100644
--- a/src/crypto/cipher/derive_key.cc
+++ b/src/crypto/cipher/derive_key.cc
@@ -25,7 +25,6 @@
 int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
                    const uint8_t *salt, const uint8_t *data, size_t data_len,
                    unsigned count, uint8_t *key, uint8_t *iv) {
-  EVP_MD_CTX c;
   uint8_t md_buf[EVP_MAX_MD_SIZE];
   unsigned addmd = 0;
   unsigned mds = 0, i;
@@ -37,36 +36,36 @@
   assert(nkey <= EVP_MAX_KEY_LENGTH);
   assert(niv <= EVP_MAX_IV_LENGTH);
 
-  if (data == NULL) {
+  if (data == nullptr) {
     return nkey;
   }
 
-  EVP_MD_CTX_init(&c);
+  bssl::ScopedEVP_MD_CTX c;
   for (;;) {
-    if (!EVP_DigestInit_ex(&c, md, NULL)) {
+    if (!EVP_DigestInit_ex(c.get(), md, nullptr)) {
       goto err;
     }
     if (addmd++) {
-      if (!EVP_DigestUpdate(&c, md_buf, mds)) {
+      if (!EVP_DigestUpdate(c.get(), md_buf, mds)) {
         goto err;
       }
     }
-    if (!EVP_DigestUpdate(&c, data, data_len)) {
+    if (!EVP_DigestUpdate(c.get(), data, data_len)) {
       goto err;
     }
-    if (salt != NULL) {
-      if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN)) {
+    if (salt != nullptr) {
+      if (!EVP_DigestUpdate(c.get(), salt, PKCS5_SALT_LEN)) {
         goto err;
       }
     }
-    if (!EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+    if (!EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
       goto err;
     }
 
     for (i = 1; i < count; i++) {
-      if (!EVP_DigestInit_ex(&c, md, NULL) ||
-          !EVP_DigestUpdate(&c, md_buf, mds) ||
-          !EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+      if (!EVP_DigestInit_ex(c.get(), md, nullptr) ||
+          !EVP_DigestUpdate(c.get(), md_buf, mds) ||
+          !EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
         goto err;
       }
     }
@@ -77,7 +76,7 @@
         if (nkey == 0 || i == mds) {
           break;
         }
-        if (key != NULL) {
+        if (key != nullptr) {
           *(key++) = md_buf[i];
         }
         nkey--;
@@ -90,7 +89,7 @@
         if (niv == 0 || i == mds) {
           break;
         }
-        if (iv != NULL) {
+        if (iv != nullptr) {
           *(iv++) = md_buf[i];
         }
         niv--;
@@ -104,7 +103,6 @@
   rv = EVP_CIPHER_key_length(type);
 
 err:
-  EVP_MD_CTX_cleanup(&c);
   OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE);
   return rv;
 }
diff --git a/src/crypto/cipher/e_aeseax.cc b/src/crypto/cipher/e_aeseax.cc
new file mode 100644
index 0000000..e4c8781
--- /dev/null
+++ b/src/crypto/cipher/e_aeseax.cc
@@ -0,0 +1,289 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/aead.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <openssl/aes.h>
+#include <openssl/base.h>
+#include <openssl/cipher.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "../fipsmodule/cipher/internal.h"
+#include "../internal.h"
+
+// Implementation of AES-EAX defined in
+// https://www.iacr.org/archive/fse2004/30170391/30170391.pdf.
+
+#define EVP_AEAD_AES_EAX_TAG_LEN AES_BLOCK_SIZE
+
+struct aead_aes_eax_ctx {
+  union {
+    double align;
+    AES_KEY ks;
+  } ks;
+  uint8_t b[AES_BLOCK_SIZE];
+  uint8_t p[AES_BLOCK_SIZE];
+};
+
+static void mult_by_X(uint8_t out[AES_BLOCK_SIZE],
+                      const uint8_t in[AES_BLOCK_SIZE]) {
+  const crypto_word_t in_hi = CRYPTO_load_word_be(in);
+  for (size_t i = 0; i < AES_BLOCK_SIZE - 1; ++i) {
+    out[i] = (in[i] << 1) | (in[i + 1] >> 7);
+  }
+  // Carry over 0x87 if msb is 1, 0x00 if msb is 0.
+  out[AES_BLOCK_SIZE - 1] = in[AES_BLOCK_SIZE - 1] << 1;
+  const uint8_t p = 0x87;
+  constant_time_conditional_memxor(out + AES_BLOCK_SIZE - 1, &p, /*n=*/1,
+                                   constant_time_msb_w(in_hi));
+}
+
+static int aead_aes_eax_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+                             size_t key_len, size_t tag_len) {
+  struct aead_aes_eax_ctx *aes_ctx = (struct aead_aes_eax_ctx *)&ctx->state;
+
+  if (key_len != 16 && key_len != 32) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
+    return 0;
+  }
+
+  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+    tag_len = EVP_AEAD_AES_EAX_TAG_LEN;
+  }
+
+  if (tag_len != EVP_AEAD_AES_EAX_TAG_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
+    return 0;
+  }
+
+  if (AES_set_encrypt_key(key, /*bits=*/key_len * 8, &aes_ctx->ks.ks) != 0) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
+    return 0;
+  }
+  ctx->tag_len = tag_len;
+
+  // L <- Ek(0^n).
+  OPENSSL_memset(aes_ctx->b, 0, sizeof(aes_ctx->b));
+  AES_encrypt(aes_ctx->b, aes_ctx->b, &aes_ctx->ks.ks);
+  // B <- 2L.
+  mult_by_X(aes_ctx->b, aes_ctx->b);
+  // P <- 4L = 2B.
+  mult_by_X(aes_ctx->p, aes_ctx->b);
+  return 1;
+}
+
+static void aead_aes_eax_cleanup(EVP_AEAD_CTX *ctx) {}
+
+// Implements the CBK function in the paper.
+static void cbk_block(const struct aead_aes_eax_ctx *aes_ctx,
+                      const uint8_t in[AES_BLOCK_SIZE],
+                      uint8_t out[AES_BLOCK_SIZE]) {
+  CRYPTO_xor16(out, in, out);
+  AES_encrypt(out, out, &aes_ctx->ks.ks);
+}
+
+// Precondition: in_len <= AES_BLOCK_SIZE.
+static void pad(const struct aead_aes_eax_ctx *aes_ctx,
+                uint8_t out[AES_BLOCK_SIZE], const uint8_t *in, size_t in_len) {
+  assert(in_len <= AES_BLOCK_SIZE);
+  if (in_len == AES_BLOCK_SIZE) {
+    CRYPTO_xor16(out, aes_ctx->b, in);
+    return;
+  }
+  OPENSSL_memset(out, 0, AES_BLOCK_SIZE);
+  OPENSSL_memcpy(out, in, in_len);
+  out[in_len] = 0x80;
+  CRYPTO_xor16(out, aes_ctx->p, out);
+}
+
+static void omac(const struct aead_aes_eax_ctx *aes_ctx,
+                 uint8_t out[AES_BLOCK_SIZE], const uint8_t *in,
+                 size_t in_len) {
+  if (in_len == 0) {
+    // CBK(pad(M;B,P)) = CBK(B). Avoiding padding to skip a copy.
+    cbk_block(aes_ctx, aes_ctx->b, out);
+    return;
+  }
+  // CBK(M1) = Ek(M1 ^ 0^n)
+  AES_encrypt(out, out, &aes_ctx->ks.ks);
+  while (in_len > AES_BLOCK_SIZE) {
+    // Full blocks, no padding needed.
+    cbk_block(aes_ctx, in, out);
+    in += AES_BLOCK_SIZE;
+    in_len -= AES_BLOCK_SIZE;
+  }
+  // Last block to be padded.
+  uint8_t padded_block[AES_BLOCK_SIZE];
+  pad(aes_ctx, padded_block, in, in_len);
+  cbk_block(aes_ctx, padded_block, out);
+}
+
+static void omac_with_tag(const struct aead_aes_eax_ctx *aes_ctx,
+                          uint8_t out[AES_BLOCK_SIZE], const uint8_t *in,
+                          size_t in_len, int tag) {
+  OPENSSL_memset(out, 0, AES_BLOCK_SIZE);
+  out[AES_BLOCK_SIZE - 1] = tag;
+  omac(aes_ctx, out, in, in_len);
+}
+
+// Encrypts/decrypts |in_len| bytes from |in| to |out| using AES-CTR with |n| as
+// the IV.
+static void aes_ctr(const struct aead_aes_eax_ctx *aes_ctx, uint8_t *out,
+                    const uint8_t n[AES_BLOCK_SIZE], const uint8_t *in,
+                    size_t in_len) {
+  uint8_t ivec[AES_BLOCK_SIZE];
+  OPENSSL_memcpy(ivec, n, AES_BLOCK_SIZE);
+
+  uint8_t unused_ecount_buf[AES_BLOCK_SIZE];
+  unsigned int unused_num = 0;
+  AES_ctr128_encrypt(in, out, in_len, &aes_ctx->ks.ks, ivec, unused_ecount_buf,
+                     &unused_num);
+}
+
+static int aead_aes_eax_seal_scatter(
+    const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
+    size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
+    size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+    size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
+  assert(extra_in_len == 0);
+  // We use the full 128 bits of the nonce as counter, so no need to check the
+  // plaintext size.
+
+  if (max_out_tag_len < ctx->tag_len) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  if (nonce_len != 12 && nonce_len != 16) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
+  const struct aead_aes_eax_ctx *aes_ctx =
+      (struct aead_aes_eax_ctx *)&ctx->state;
+
+  // N <- OMAC(0 || nonce)
+  uint8_t n[AES_BLOCK_SIZE];
+  omac_with_tag(aes_ctx, n, nonce, nonce_len, /*tag=*/0);
+  // H <- OMAC(1 || ad)
+  uint8_t h[AES_BLOCK_SIZE];
+  omac_with_tag(aes_ctx, h, ad, ad_len, /*tag=*/1);
+
+  // C <- CTR^{N}_{K}(M)
+  aes_ctr(aes_ctx, out, n, in, in_len);
+
+  // MAC <- OMAC(2 || C)
+  omac_with_tag(aes_ctx, out_tag, out, in_len, /*tag=*/2);
+  // MAC <- N ^ C ^ H
+  CRYPTO_xor16(out_tag, n, out_tag);
+  CRYPTO_xor16(out_tag, h, out_tag);
+
+  *out_tag_len = ctx->tag_len;
+  return 1;
+}
+
+static int aead_aes_eax_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                    const uint8_t *nonce, size_t nonce_len,
+                                    const uint8_t *in, size_t in_len,
+                                    const uint8_t *in_tag, size_t in_tag_len,
+                                    const uint8_t *ad, size_t ad_len) {
+  const uint64_t ad_len_64 = ad_len;
+  if (ad_len_64 >= (UINT64_C(1) << 61)) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+    return 0;
+  }
+
+  const uint64_t in_len_64 = in_len;
+  if (in_tag_len != EVP_AEAD_AES_EAX_TAG_LEN ||
+      in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+    return 0;
+  }
+
+  if (nonce_len != 12 && nonce_len != 16) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
+  const struct aead_aes_eax_ctx *aes_ctx =
+      (struct aead_aes_eax_ctx *)&ctx->state;
+
+  // N <- OMAC(0 || nonce)
+  uint8_t n[AES_BLOCK_SIZE];
+  omac_with_tag(aes_ctx, n, nonce, nonce_len, /*tag=*/0);
+  // H <- OMAC(1 || ad)
+  uint8_t h[AES_BLOCK_SIZE];
+  omac_with_tag(aes_ctx, h, ad, ad_len, /*tag=*/1);
+
+  // MAC <- OMAC(2 || C)
+  uint8_t mac[AES_BLOCK_SIZE];
+  omac_with_tag(aes_ctx, mac, in, in_len, /*tag=*/2);
+  // MAC <- N ^ C ^ H
+  CRYPTO_xor16(mac, n, mac);
+  CRYPTO_xor16(mac, h, mac);
+
+  if (CRYPTO_memcmp(mac, in_tag, in_tag_len) != 0) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+    return 0;
+  }
+
+  // M <- CTR^{N}_{K}(C)
+  aes_ctr(aes_ctx, out, n, in, in_len);
+  return 1;
+}
+
+static const EVP_AEAD aead_aes_128_eax = {
+    16,                        // AES key size
+    16,                        // nonce length
+    EVP_AEAD_AES_EAX_TAG_LEN,  // overhead
+    EVP_AEAD_AES_EAX_TAG_LEN,  // max tag length
+    0,                         // seal_scatter_supports_extra_in
+
+    aead_aes_eax_init,
+    NULL,  // init_with_direction
+    aead_aes_eax_cleanup,
+    NULL,  // open
+    aead_aes_eax_seal_scatter,
+    aead_aes_eax_open_gather,
+    NULL,  // get_iv
+    NULL,  // tag_len
+};
+
+static const EVP_AEAD aead_aes_256_eax = {
+    32,                        // AES key size
+    16,                        // nonce length
+    EVP_AEAD_AES_EAX_TAG_LEN,  // overhead
+    EVP_AEAD_AES_EAX_TAG_LEN,  // max tag length
+    0,                         // seal_scatter_supports_extra_in
+
+    aead_aes_eax_init,
+    NULL,  // init_with_direction
+    aead_aes_eax_cleanup,
+    NULL,  // open
+    aead_aes_eax_seal_scatter,
+    aead_aes_eax_open_gather,
+    NULL,  // get_iv
+    NULL,  // tag_len
+};
+
+const EVP_AEAD *EVP_aead_aes_128_eax(void) { return &aead_aes_128_eax; }
+
+const EVP_AEAD *EVP_aead_aes_256_eax(void) { return &aead_aes_256_eax; }
diff --git a/src/crypto/cipher/e_aesgcmsiv.cc b/src/crypto/cipher/e_aesgcmsiv.cc
index b429dc5..a7b38c6 100644
--- a/src/crypto/cipher/e_aesgcmsiv.cc
+++ b/src/crypto/cipher/e_aesgcmsiv.cc
@@ -28,6 +28,7 @@
 #define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
 #define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
 
+namespace {
 // TODO(davidben): AES-GCM-SIV assembly is not correct for Windows. It must save
 // and restore xmm6 through xmm15.
 #if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
@@ -36,12 +37,10 @@
 
 // Optimised AES-GCM-SIV
 
-namespace {
 struct aead_aes_gcm_siv_asm_ctx {
   alignas(16) uint8_t key[16 * 15];
   int is_128_bit;
 };
-}  // namespace
 
 // The assembly code assumes 8-byte alignment of the EVP_AEAD_CTX's state, and
 // aligns to 16 bytes itself.
@@ -51,15 +50,6 @@
 static_assert(alignof(union evp_aead_ctx_st_state) >= 8,
               "AEAD state has insufficient alignment");
 
-// asm_ctx_from_ctx returns a 16-byte aligned context pointer from |ctx|.
-static struct aead_aes_gcm_siv_asm_ctx *asm_ctx_from_ctx(
-    const EVP_AEAD_CTX *ctx) {
-  // ctx->state must already be 8-byte aligned. Thus, at most, we may need to
-  // add eight to align it to 16 bytes.
-  const uintptr_t offset = ((uintptr_t)&ctx->state) & 8;
-  return (struct aead_aes_gcm_siv_asm_ctx *)(&ctx->state.opaque[offset]);
-}
-
 extern "C" {
 // aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
 // |out_expanded_key|.
@@ -70,45 +60,7 @@
 // |out_expanded_key|.
 extern void aes256gcmsiv_aes_ks(const uint8_t key[32],
                                 uint8_t out_expanded_key[16 * 15]);
-}
 
-static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                     size_t key_len, size_t tag_len) {
-  const size_t key_bits = key_len * 8;
-
-  if (key_bits != 128 && key_bits != 256) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
-    return 0;  // EVP_AEAD_CTX_init should catch this.
-  }
-
-  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
-    tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
-  }
-
-  if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
-    return 0;
-  }
-
-  struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
-  assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);
-
-  if (key_bits == 128) {
-    aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
-    gcm_siv_ctx->is_128_bit = 1;
-  } else {
-    aes256gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
-    gcm_siv_ctx->is_128_bit = 0;
-  }
-
-  ctx->tag_len = tag_len;
-
-  return 1;
-}
-
-static void aead_aes_gcm_siv_asm_cleanup(EVP_AEAD_CTX *ctx) {}
-
-extern "C" {
 // aesgcmsiv_polyval_horner updates the POLYVAL value in |in_out_poly| to
 // include a number (|in_blocks|) of 16-byte blocks of data from |in|, given
 // the POLYVAL key in |key|.
@@ -225,12 +177,55 @@
                                     size_t in_len);
 }
 
+// asm_ctx_from_ctx returns a 16-byte aligned context pointer from |ctx|.
+struct aead_aes_gcm_siv_asm_ctx *asm_ctx_from_ctx(const EVP_AEAD_CTX *ctx) {
+  // ctx->state must already be 8-byte aligned. Thus, at most, we may need to
+  // add eight to align it to 16 bytes.
+  const uintptr_t offset = ((uintptr_t)&ctx->state) & 8;
+  return (struct aead_aes_gcm_siv_asm_ctx *)(&ctx->state.opaque[offset]);
+}
+
+int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+                              size_t key_len, size_t tag_len) {
+  const size_t key_bits = key_len * 8;
+
+  if (key_bits != 128 && key_bits != 256) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
+    return 0;  // EVP_AEAD_CTX_init should catch this.
+  }
+
+  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+    tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+  }
+
+  if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
+    return 0;
+  }
+
+  struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
+  assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);
+
+  if (key_bits == 128) {
+    aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
+    gcm_siv_ctx->is_128_bit = 1;
+  } else {
+    aes256gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
+    gcm_siv_ctx->is_128_bit = 0;
+  }
+
+  ctx->tag_len = tag_len;
+
+  return 1;
+}
+
+void aead_aes_gcm_siv_asm_cleanup(EVP_AEAD_CTX *ctx) {}
+
 // gcm_siv_asm_polyval evaluates POLYVAL at |auth_key| on the given plaintext
 // and AD. The result is written to |out_tag|.
-static void gcm_siv_asm_polyval(uint8_t out_tag[16], const uint8_t *in,
-                                size_t in_len, const uint8_t *ad, size_t ad_len,
-                                const uint8_t auth_key[16],
-                                const uint8_t nonce[12]) {
+void gcm_siv_asm_polyval(uint8_t out_tag[16], const uint8_t *in, size_t in_len,
+                         const uint8_t *ad, size_t ad_len,
+                         const uint8_t auth_key[16], const uint8_t nonce[12]) {
   OPENSSL_memset(out_tag, 0, 16);
   const size_t ad_blocks = ad_len / 16;
   const size_t in_blocks = in_len / 16;
@@ -283,7 +278,7 @@
 // (same thing in CTR mode) of the final block of a plaintext/ciphertext. It
 // writes |in_len| & 15 bytes to |out| + |in_len|, based on an initial counter
 // derived from |tag|.
-static void aead_aes_gcm_siv_asm_crypt_last_block(
+void aead_aes_gcm_siv_asm_crypt_last_block(
     int is_128_bit, uint8_t *out, const uint8_t *in, size_t in_len,
     const uint8_t tag[16],
     const struct aead_aes_gcm_siv_asm_ctx *enc_key_expanded) {
@@ -309,10 +304,11 @@
 
 // aead_aes_gcm_siv_kdf calculates the record encryption and authentication
 // keys given the |nonce|.
-static void aead_aes_gcm_siv_kdf(
-    int is_128_bit, const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx,
-    uint64_t out_record_auth_key[2], uint64_t out_record_enc_key[4],
-    const uint8_t nonce[12]) {
+void aead_aes_gcm_siv_kdf(int is_128_bit,
+                          const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx,
+                          uint64_t out_record_auth_key[2],
+                          uint64_t out_record_enc_key[4],
+                          const uint8_t nonce[12]) {
   alignas(16) uint8_t padded_nonce[16];
   OPENSSL_memcpy(padded_nonce, nonce, 12);
 
@@ -333,7 +329,7 @@
   out_record_auth_key[1] = key_material[2];
 }
 
-static int aead_aes_gcm_siv_asm_seal_scatter(
+int aead_aes_gcm_siv_asm_seal_scatter(
     const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
     size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
     size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
@@ -399,10 +395,11 @@
   return 1;
 }
 
-static int aead_aes_gcm_siv_asm_open_gather(
-    const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
-    size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
-    size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
+int aead_aes_gcm_siv_asm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                     const uint8_t *nonce, size_t nonce_len,
+                                     const uint8_t *in, size_t in_len,
+                                     const uint8_t *in_tag, size_t in_tag_len,
+                                     const uint8_t *ad, size_t ad_len) {
   const uint64_t ad_len_64 = ad_len;
   if (ad_len_64 >= (UINT64_C(1) << 61)) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
@@ -499,7 +496,7 @@
   return 1;
 }
 
-static const EVP_AEAD aead_aes_128_gcm_siv_asm = {
+const EVP_AEAD aead_aes_128_gcm_siv_asm = {
     16,                              // key length
     EVP_AEAD_AES_GCM_SIV_NONCE_LEN,  // nonce length
     EVP_AEAD_AES_GCM_SIV_TAG_LEN,    // overhead
@@ -516,7 +513,7 @@
     NULL /* tag_len */,
 };
 
-static const EVP_AEAD aead_aes_256_gcm_siv_asm = {
+const EVP_AEAD aead_aes_256_gcm_siv_asm = {
     32,                              // key length
     EVP_AEAD_AES_GCM_SIV_NONCE_LEN,  // nonce length
     EVP_AEAD_AES_GCM_SIV_TAG_LEN,    // overhead
@@ -535,7 +532,7 @@
 
 #endif  // X86_64 && !NO_ASM && !WINDOWS
 
-namespace {
+
 struct aead_aes_gcm_siv_ctx {
   union {
     double align;
@@ -544,7 +541,6 @@
   block128_f kgk_block;
   unsigned is_256 : 1;
 };
-}  // namespace
 
 static_assert(sizeof(((EVP_AEAD_CTX *)NULL)->state) >=
                   sizeof(struct aead_aes_gcm_siv_ctx),
@@ -553,8 +549,8 @@
                   alignof(struct aead_aes_gcm_siv_ctx),
               "AEAD state has insufficient alignment");
 
-static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                 size_t key_len, size_t tag_len) {
+int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
+                          size_t tag_len) {
   const size_t key_bits = key_len * 8;
 
   if (key_bits != 128 && key_bits != 256) {
@@ -582,7 +578,7 @@
   return 1;
 }
 
-static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {}
+void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {}
 
 // gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
 // |in| to |out|, using the block function |enc_block| with |key| in counter
@@ -591,9 +587,9 @@
 // first four bytes are used and the GCM-SIV tweak to the final byte is
 // applied. The |in| and |out| pointers may be equal but otherwise must not
 // alias.
-static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
-                          const uint8_t initial_counter[AES_BLOCK_SIZE],
-                          block128_f enc_block, const AES_KEY *key) {
+void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
+                   const uint8_t initial_counter[AES_BLOCK_SIZE],
+                   block128_f enc_block, const AES_KEY *key) {
   uint8_t counter[16];
 
   OPENSSL_memcpy(counter, initial_counter, AES_BLOCK_SIZE);
@@ -617,45 +613,125 @@
   }
 }
 
+
+// POLYVAL.
+//
+// POLYVAL is a polynomial authenticator that operates over a field very
+// similar to the one that GHASH uses. See
+// https://www.rfc-editor.org/rfc/rfc8452.html#section-3.
+
+// POLYVAL(H, X_1, ..., X_n) =
+// ByteReverse(GHASH(mulX_GHASH(ByteReverse(H)), ByteReverse(X_1), ...,
+// ByteReverse(X_n))).
+//
+// See https://www.rfc-editor.org/rfc/rfc8452.html#appendix-A.
+
+struct polyval_ctx {
+  uint8_t S[16];
+  u128 Htable[16];
+  gmult_func gmult;
+  ghash_func ghash;
+};
+
+// byte_reverse reverses the order of the bytes in |b->c|.
+void byte_reverse(uint8_t b[16]) {
+  uint64_t hi = CRYPTO_load_u64_le(b);
+  uint64_t lo = CRYPTO_load_u64_le(b + 8);
+  CRYPTO_store_u64_le(b, CRYPTO_bswap8(lo));
+  CRYPTO_store_u64_le(b + 8, CRYPTO_bswap8(hi));
+}
+
+// reverse_and_mulX_ghash interprets |b| as a reversed element of the GHASH
+// field, multiplies that by 'x' and serialises the result back into |b|, but
+// with GHASH's backwards bit ordering.
+void reverse_and_mulX_ghash(uint8_t b[16]) {
+  uint64_t hi = CRYPTO_load_u64_le(b);
+  uint64_t lo = CRYPTO_load_u64_le(b + 8);
+  const crypto_word_t carry = constant_time_eq_w(hi & 1, 1);
+  hi >>= 1;
+  hi |= lo << 63;
+  lo >>= 1;
+  lo ^= ((uint64_t)constant_time_select_w(carry, 0xe1, 0)) << 56;
+
+  CRYPTO_store_u64_le(b, CRYPTO_bswap8(lo));
+  CRYPTO_store_u64_le(b + 8, CRYPTO_bswap8(hi));
+}
+
+void crypto_polyval_init(struct polyval_ctx *ctx, const uint8_t key[16]) {
+  alignas(8) uint8_t H[16];
+  OPENSSL_memcpy(H, key, 16);
+  reverse_and_mulX_ghash(H);
+
+  CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, ctx->Htable, H);
+  OPENSSL_memset(&ctx->S, 0, sizeof(ctx->S));
+}
+
+void crypto_polyval_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+                                  size_t in_len) {
+  assert((in_len & 15) == 0);
+  alignas(8) uint8_t buf[32 * 16];
+
+  while (in_len > 0) {
+    size_t todo = in_len;
+    if (todo > sizeof(buf)) {
+      todo = sizeof(buf);
+    }
+    OPENSSL_memcpy(buf, in, todo);
+    in += todo;
+    in_len -= todo;
+
+    size_t blocks = todo / 16;
+    for (size_t i = 0; i < blocks; i++) {
+      byte_reverse(buf + 16 * i);
+    }
+
+    ctx->ghash(ctx->S, ctx->Htable, buf, todo);
+  }
+}
+
+void crypto_polyval_finish(const struct polyval_ctx *ctx, uint8_t out[16]) {
+  OPENSSL_memcpy(out, &ctx->S, 16);
+  byte_reverse(out);
+}
+
 // gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
 // AD. The result is written to |out_tag|.
-static void gcm_siv_polyval(
-    uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
-    size_t ad_len, const uint8_t auth_key[16],
-    const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
+void gcm_siv_polyval(uint8_t out_tag[16], const uint8_t *in, size_t in_len,
+                     const uint8_t *ad, size_t ad_len,
+                     const uint8_t auth_key[16],
+                     const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
   struct polyval_ctx polyval_ctx;
-  CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
+  crypto_polyval_init(&polyval_ctx, auth_key);
 
-  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
+  crypto_polyval_update_blocks(&polyval_ctx, ad, ad_len & ~15);
 
   uint8_t scratch[16];
   if (ad_len & 15) {
     OPENSSL_memset(scratch, 0, sizeof(scratch));
     OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
-    CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+    crypto_polyval_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
   }
 
-  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
+  crypto_polyval_update_blocks(&polyval_ctx, in, in_len & ~15);
   if (in_len & 15) {
     OPENSSL_memset(scratch, 0, sizeof(scratch));
     OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
-    CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+    crypto_polyval_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
   }
 
   uint8_t length_block[16];
   CRYPTO_store_u64_le(length_block, ((uint64_t)ad_len) * 8);
   CRYPTO_store_u64_le(length_block + 8, ((uint64_t)in_len) * 8);
-  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block,
+  crypto_polyval_update_blocks(&polyval_ctx, length_block,
                                sizeof(length_block));
 
-  CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
+  crypto_polyval_finish(&polyval_ctx, out_tag);
   for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
     out_tag[i] ^= nonce[i];
   }
   out_tag[15] &= 0x7f;
 }
 
-namespace {
 // gcm_siv_record_keys contains the keys used for a specific GCM-SIV record.
 struct gcm_siv_record_keys {
   uint8_t auth_key[16];
@@ -665,13 +741,12 @@
   } enc_key;
   block128_f enc_block;
 };
-}  // namespace
 
 // gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
 // given nonce and writes them to |*out_keys|.
-static void gcm_siv_keys(const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
-                         struct gcm_siv_record_keys *out_keys,
-                         const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
+void gcm_siv_keys(const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
+                  struct gcm_siv_record_keys *out_keys,
+                  const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
   const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
   uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
   const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
@@ -701,11 +776,13 @@
                   key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
 }
 
-static int aead_aes_gcm_siv_seal_scatter(
-    const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
-    size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
-    size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
-    size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
+int aead_aes_gcm_siv_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                  uint8_t *out_tag, size_t *out_tag_len,
+                                  size_t max_out_tag_len, const uint8_t *nonce,
+                                  size_t nonce_len, const uint8_t *in,
+                                  size_t in_len, const uint8_t *extra_in,
+                                  size_t extra_in_len, const uint8_t *ad,
+                                  size_t ad_len) {
   const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
       (struct aead_aes_gcm_siv_ctx *)&ctx->state;
   const uint64_t in_len_64 = in_len;
@@ -742,12 +819,11 @@
   return 1;
 }
 
-static int aead_aes_gcm_siv_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                        const uint8_t *nonce, size_t nonce_len,
-                                        const uint8_t *in, size_t in_len,
-                                        const uint8_t *in_tag,
-                                        size_t in_tag_len, const uint8_t *ad,
-                                        size_t ad_len) {
+int aead_aes_gcm_siv_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                 const uint8_t *nonce, size_t nonce_len,
+                                 const uint8_t *in, size_t in_len,
+                                 const uint8_t *in_tag, size_t in_tag_len,
+                                 const uint8_t *ad, size_t ad_len) {
   const uint64_t ad_len_64 = ad_len;
   if (ad_len_64 >= (UINT64_C(1) << 61)) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
@@ -786,7 +862,7 @@
   return 1;
 }
 
-static const EVP_AEAD aead_aes_128_gcm_siv = {
+const EVP_AEAD aead_aes_128_gcm_siv = {
     16,                              // key length
     EVP_AEAD_AES_GCM_SIV_NONCE_LEN,  // nonce length
     EVP_AEAD_AES_GCM_SIV_TAG_LEN,    // overhead
@@ -803,7 +879,7 @@
     NULL /* tag_len */,
 };
 
-static const EVP_AEAD aead_aes_256_gcm_siv = {
+const EVP_AEAD aead_aes_256_gcm_siv = {
     32,                              // key length
     EVP_AEAD_AES_GCM_SIV_NONCE_LEN,  // nonce length
     EVP_AEAD_AES_GCM_SIV_TAG_LEN,    // overhead
@@ -819,6 +895,7 @@
     NULL /* get_iv */,
     NULL /* tag_len */,
 };
+}  // namespace
 
 #if defined(AES_GCM_SIV_ASM)
 
diff --git a/src/crypto/cipher/internal.h b/src/crypto/cipher/internal.h
index c0fb07a..3b0fb7c 100644
--- a/src/crypto/cipher/internal.h
+++ b/src/crypto/cipher/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H
-#define OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_CIPHER_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_CIPHER_INTERNAL_H
 
 #include <assert.h>
 #include <stdlib.h>
@@ -237,4 +237,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_CIPHER_INTERNAL_H
diff --git a/src/crypto/cipher/test/aes_128_eax_test.txt b/src/crypto/cipher/test/aes_128_eax_test.txt
new file mode 100644
index 0000000..84fc4ae
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_eax_test.txt
@@ -0,0 +1,233 @@
+# Test vectors from
+# https://github.com/C2SP/wycheproof/blob/cd27d6419bedd83cbd24611ec54b6d4bfdb0cdca/testvectors/aes_eax_test.json
+
+AD: 6bfb914fd07eae6b
+CT:
+NONCE: 62ec67f9c3a4a407fcb2a8c49031a8b3
+KEY: 233952dee4d5ed5f9b9c6d6ff80ff478
+IN:
+TAG: e037830e8389f27b025a2d6527e79d01
+
+AD: fa3bfd4806eb53fa
+CT: 19dd
+NONCE: becaf043b0a23d843194ba972c66debd
+KEY: 91945d3f4dcbee0bf45ef52255f095a4
+IN: f7fb
+TAG: 5c4c9331049d0bdab0277408f67967e5
+
+AD: 234a3463c1264ac6
+CT: d851d5bae0
+NONCE: 70c3db4f0d26368400a10ed05d2bff5e
+KEY: 01f74ad64077f2e704c0f60ada3dd523
+IN: 1a47cb4933
+TAG: 3a59f238a23e39199dc9266626c40f80
+
+AD: 33cce2eabff5a79d
+CT: 632a9d131a
+NONCE: 8408dfff3c1a2b1292dc199e46b7d617
+KEY: d07cf6cbb7f313bdde66b727afd3c5e8
+IN: 481c9e39b1
+TAG: d4c168a4225d8e1ff755939974a7bede
+
+AD: aeb96eaebe2970e9
+CT: 071dfe16c675
+NONCE: fdb6b06676eedc5c61d74276e1f8e816
+KEY: 35b6d0580005bbc12b0587124557d2c2
+IN: 40d0c07da5e4
+TAG: cb0677e536f73afe6a14b74ee49844dd
+
+AD: d4482d1ca78dce0f
+CT: 835bb4f15d743e350e728414
+NONCE: 6eac5c93072d8e8513f750935e46da1b
+KEY: bd8e6e11475e60b268784c38c62feb22
+IN: 4de3b35c3fc039245bd1fb7d
+TAG: abb8644fd6ccb86947c5e10590210a4f
+
+AD: 65d2017990d62528
+CT: 02083e3979da014812f59f11d52630da30
+NONCE: 1a8c98dcd73d38393b2bf1569deefc19
+KEY: 7c77d6e813bed5ac98baa417477a2e7d
+IN: 8b0a79306c9ce7ed99dae4f87f8dd61636
+TAG: 137327d10649b0aa6e1c181db617d7f2
+
+AD: 54b9f04e6a09189a
+CT: 2ec47b2c4954a489afc7ba4897edcdae8cc3
+NONCE: dde59b97d722156d4d9aff2bc7559826
+KEY: 5fff20cafab119ca2fc73549e20f5b0d
+IN: 1bda122bce8a8dbaf1877d962b8592dd2d56
+TAG: 3b60450599bd02c96382902aef7f832a
+
+AD: 899a175897561d7e
+CT: 0de18fd0fdd91e7af19f1d8ee8733938b1e8
+NONCE: b781fcf2f75fa5a8de97a9ca48e522ec
+KEY: a4a4782bcffd3ec5e7ef6d8c34a56123
+IN: 6cf36720872b8513f6eab1a8a44438d5ef11
+TAG: e7f6d2231618102fdb7fe55ff1991700
+
+AD: 126735fcc320d25a
+CT: cb8920f87a6c75cff39627b56e3ed197c552d295a7
+NONCE: 22e7add93cfc6393c57ec0b3c17d6b44
+KEY: 8395fcf1e95bebd697bd010bc766aac3
+IN: ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7
+TAG: cfc46afc253b4652b1af3795b124ab6e
+
+AD:
+CT: 3c441f32ce07822364d7a2990e50bb13d7b02a26969e4a937e5e9073b0d9c968
+NONCE: 3c8cc2970a008f75cc5beae2847258c2
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: db90bdb3da3d00afd0fc6a83551da95e
+
+AD:
+CT: d19ac59849026a91aa1b9aec29b11a202a4d739fd86c28e3ae3d588ea21d70c6
+NONCE: aef03d00598494e9fb03cd7d8b590866
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: c30f6cd9202074ed6e2a2a360eac8c47
+
+AD:
+CT: 2108558ac4b2c2d5cc66cea51d6210e046177a67631cd2dd8f09469733acb517
+NONCE: 55d12511c696a80d0514d1ffba49cada
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: fc355e87a267be3ae3e44c0bf3f99b2b
+
+AD:
+CT: 4d2c1524ca4baa4eefcce6b91b227ee83abaff8105dcafa2ab191f5df2575035
+NONCE: 79422ddd91c4eee2deaef1f968305304
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: e2c865ce2d7abdac024c6f991a848390
+
+AD:
+CT: 8eb01e62185d782eb9287a341a6862ac5257d6f9adc99ee0a24d9c22b3e9b38a
+NONCE: 0af5aa7a7676e28306306bcd9bf2003a
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: 39c339bc8a74c75e2c65c6119544d61e
+
+AD:
+CT: 94c5d2aca6dbbce8c24513a25e095c0e54a942860d327a222a815cc713b163b4
+NONCE: af5a03ae7edd73471bdcdfac5e194a60
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111
+TAG: f50b30304e45c9d411e8df4508a98612
+
+AD:
+CT: 3bb6173e3772d4b62eef37f9ef0781f360b6c74be3bf6b371067bc1b090d9d6622a1fbec6ac471b3349cd4277a101d40890fbf27dfdcd0b4e3781f9806daabb6
+NONCE: b37087680f0edd5a52228b8c7aaea664
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 00000000000000000000000000000000111111111111111111111111111111112222222222222222222222222222222233333333333333333333333333333333
+TAG: a0498745e59999ddc32d5b140241124e
+
+AD:
+CT: e9b0bb8857818ce3201c3690d21daa7f264fb8ee93cc7a4674ea2fc32bf182fb2a7e8ad51507ad4f31cefc2356fe7936a7f6e19f95e88fdbf17620916d3a6f3d01fc17d358672f777fd4099246e436e1
+NONCE: 4f802da62a384555a19bc2b382eb25af
+KEY: 000102030405060708090a0b0c0d0e0f
+IN: 0000000000000000000000000000000011111111111111111111111111111111222222222222222222222222222222223333333333333333333333333333333344444444444444444444444444444444
+TAG: 67910be744b8315ae0eb6124590c5d8b
+
+AD:
+CT:
+NONCE: fa294b129972f7fc5bbd5b96bba837c9
+KEY: b67b1a6efdd40d37080fbe8f8047aeb9
+IN:
+TAG: b14b64fb589899699570cc9160e39896
+
+AD:
+CT: 1d
+NONCE: 9477849d6ccdfca112d92e53fae4a7ca
+KEY: 209e6dbf2ad26a105445fc0207cd9e9a
+IN: 01
+TAG: 52a5f600fe5338026a7cb09c11640082
+
+AD:
+CT: d7b8a6b43d2e9f98c2b44ce5e3cfdb
+NONCE: 5171524568e81d97e8c4de4ba56c10a0
+KEY: a549442e35154032d07c8666006aa6a2
+IN: 1182e93596cac5608946400bc73f3a
+TAG: 1bdd52fc987daf0ee19234c905ea645f
+
+AD:
+CT: 73e5c6f0e703a52d02f7f7faeb1b77fd4fd0cb421eaf
+NONCE: 0e6ec879b02c6f516976e35898428da7
+KEY: 958bcdb66a3952b53701582a68a0e474
+IN: 140415823ecc8932a058384b738ea6ea6d4dfe3bbeee
+TAG: 6c154a85968edd74776575a4450bd897
+
+AD: df10d0d212242450
+CT: 936b69b6c955adfd15539b9be4989cb6
+NONCE: 2e35901ae7d491eecc8838fedd631405
+KEY: 965b757ba5018a8d66edc78e0ceee86b
+IN: 36e57a763958b02cea9d6a676ebce81f
+TAG: ee15a1454e88faad8e48a8df2983b425
+
+AD: 7c571d2fbb5f62523c0eb338bef9a9
+CT: 67caac35443a3138d2cb811f0ce04dd2
+NONCE: 7f2985296315507aa4c0a93d5c12bd77
+KEY: 88d02033781c7b4164711a05420f256e
+IN: d98adc03d9d582732eb07df23d7b9f74
+TAG: b7968e0b5640e3b236569653208b9deb
+
+AD: 16843c091d43b0a191d0c73d15601be9
+CT: 200ac451fbeb0f6151d61583a43b7343
+NONCE: bf47afdfd492137a24236bc36797a88e
+KEY: 515840cf67d2e40eb65e54a24c72cbf2
+IN: c834588cb6daf9f06dd23519f4be9f56
+TAG: 2ad43e4caa51983a9d4d24481bf4c839
+
+AD: 904d86f133cec15a0c3caf14d7e029c82a07705a23f0d080
+CT: 27c6e9a653c5253ca1c5673f97b9b33e
+NONCE: d02bf0763a9fefbf70c33aee1e9da1d6
+KEY: 2e4492d444e5b6f4cec8c2d3615ac858
+IN: 9e62d6511b0bda7dd7740b614d97bae0
+TAG: 2d581271e1fa9e3686136caa8f4d6c8e
+
+AD:
+CT:
+NONCE: 438a547a94ea88dce46c6c85
+KEY: bedcfb5a011ebc84600fcb296c15af0d
+IN:
+TAG: 9607977cd7556b1dfedf0c73a35a5197
+
+AD:
+CT: 98
+NONCE: b30c084727ad1c592ac21d12
+KEY: 384ea416ac3c2f51a76e7d8226346d4e
+IN: 35
+TAG: f5d7930952e275beecb998d804c241f0
+
+AD:
+CT: 7fd2878318ab0f2b
+NONCE: b5e006ded553110e6dc56529
+KEY: cae31cd9f55526eb038241fc44cac1e5
+IN: d10989f2c52e94ad
+TAG: ab184ffde523565529a9be111b0c2d6d
+
+AD:
+CT: e928622d1e6e798d8665ae732c4c1e5f
+NONCE: 0e1666f2dc652f7708fb8f0d
+KEY: ffdf4228361ea1f8165852136b3480f7
+IN: 25b12e28ac0ef6ead0226a3b2288c800
+TAG: 33ab476757ffa42c0f6c276391a46eac
+
+AD:
+CT: efd299a43b25ce8cc31b80e5489ef9ce7356ececa91bc7bd
+NONCE: fbbc04fd6e025b7193eb57f6
+KEY: a8ee11b26d7ceb7f17eaa1e4b83a2cf6
+IN: c08f085e6a9e0ef3636280c11ecfadf0c1e72919ffc17eaf
+TAG: 3c33fc0bcd256b0a8a34ecc8b01e52a6
+
+AD:
+CT: 356bca9cddd39efd393278e43b4e80266071608036e81d6e924d4e4800fb27
+NONCE: 42b51388f6f9047a2a994575
+KEY: 1655bf662f7ee685615701fd3779d628
+IN: 857b2f6cd608c9cea0246c740caa4ca19c5f1c7d71cb9273f0d8c8bb65b70a
+TAG: 71f02ba7c6cf3a579e56245025420071
+
+AD:
+CT: 9d911b934a68ce7db322410028bd31bd81bcbdadf26f15676be472bc3821fb68e4728db76930bc0958aeed6faf3e333da7af3d48c480b424ff3d6600cc56a507c8ad
+NONCE: 064b3cfbe04d94d4d5c19b30
+KEY: 42e38abef2dd7573248c5aefb3ecca54
+IN: 2c763b9ec84903bcbb8aec15e678a3a955e4870edbf62d9d3c81c4f9ed6154877875779ca33cce8f73a55ca7af1d8d817fc6baac00ef962c5a0da339ce81427a3d59
+TAG: d679eb9e5d744b62d91dcf6fb6284f41
\ No newline at end of file
diff --git a/src/crypto/cipher/test/aes_256_eax_test.txt b/src/crypto/cipher/test/aes_256_eax_test.txt
new file mode 100644
index 0000000..d038ab0
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_eax_test.txt
@@ -0,0 +1,107 @@
+# Test vectors from
+# https://github.com/C2SP/wycheproof/blob/cd27d6419bedd83cbd24611ec54b6d4bfdb0cdca/testvectors/aes_eax_test.json
+
+AD:
+CT:
+NONCE: 4da5bf8dfd5852c1ea12379d
+KEY: 80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0
+IN:
+TAG: 4d293af9a8fe4ac034f14b14334c16ae
+
+AD:
+CT: 8c
+NONCE: 99e23ec48985bccdeeab60f1
+KEY: cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273
+IN: 2a
+TAG: c460d5ff45235c3c2491c7e6a32491d6
+
+AD:
+CT: 6038296421fb5007
+NONCE: 4f07afedfdc3b6c2361823d3
+KEY: 51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152
+IN: be3308f72a2c6aed
+TAG: 0a91c72219c0b9ad716accd910e04e13
+
+AD:
+CT: c4066e265a948f40e05e37fa400fde1b
+NONCE: 2fcb1b38a99e71b84740ad9b
+KEY: 59d4eafb4de0cfc7d3db99a8f54b15d7b39f0acc8da69763b019c1699f87674a
+IN: 549b365af913f3b081131ccb6b825588
+TAG: 611de27128955c54edd7a4d6d23e78ee
+
+AD:
+CT: f64ffe52cd838cea89dd500662a2ee4b4b450eee68218e84
+NONCE: e6b1adf2fd58a8762c65f31b
+KEY: 0212a8de5007ed87b33f1a7090b6114f9e08cefd9607f2c276bdcfdbc5ce9cd7
+IN: 10f1ecf9c60584665d9ae5efe279e7f7377eea6916d2b111
+TAG: ae1e2eda96bed82182240aae08f9fe9c
+
+AD:
+CT: 01f09a6a136909c158e13502ee5488f592ee24059d6da734acba8c11e9815f
+NONCE: 04a9be03508a5f31371a6fd2
+KEY: 2eb51c469aa8eb9e6c54a8349bae50a20f0e382711bba1152c424f03b6671d71
+IN: b053999286a2824f42cc8c203ab24e2c97a685adcc2ad32662558e55a5c729
+TAG: 79e57b518fa6dabe94e0e89cae89976b
+
+AD:
+CT: 72356ce9f1822e30809817a3b91ea13700ab3275b6f3718a845ad0b132bf4bbbb61ee466c1b0a1cb5a26424dbcc8d1b649f22785907a9c0164a2a41a9fc477d6c4dd
+NONCE: ce03bbb56778f25d4528350b
+KEY: 95e87eda64d0dc2d4e851030c3e1b27cca2265b3464c2c572bd8fc8cfb282d1b
+IN: 2e5acc19acb9940bb74d414b45e71386a409b641490b139493d7d632cbf1674fdf2511c3fad6c27359e6137b4cd52efc4bf871e6623451517d6a3c68240f2a79916a
+TAG: 872861d71412e15732f60a83d4b47ee1
+
+AD:
+CT:
+NONCE: 00c49f4ebb07393f07ebc3825f7b0830
+KEY: b4cd11db0b3e0b9b34eafd9fe027746976379155e76116afde1b96d21298e34f
+IN:
+TAG: 80d821cde2d6c523b718597b11dd0fa8
+
+AD:
+CT: 25
+NONCE: 0ad570d8863918fe89124e09d125a271
+KEY: b7797eb0c1a6089ad5452d81fdb14828c040ddc4589c32b565aad8cb4de3e4a0
+IN: ed
+TAG: 4fef9ec45255dbba5631105d00a55767
+
+AD:
+CT: cbfcaa3634d6cff5656bc6bda6ab5f
+NONCE: 2a55caa137c5b0b66cf3809eb8f730c4
+KEY: 4c010d9561c7234c308c01cea3040c925a9f324dc958ff904ae39b37e60e1e03
+IN: 2a093c9ed72b8ff4994201e9f9e010
+TAG: 0144be0643b036a8147e19f4ea9e7af2
+
+AD:
+CT: f531097aa1bb35d9f401d459340afbd27f9bdf72c537
+NONCE: 21cbeff0b123799da74f4daff2e279c5
+KEY: 2f6cfb7a215a7bafb607c273f7e66f9a6d51d57f9c29422ec64699bad0c6f33b
+IN: 39dbc71f6838ed6c6e582137436e1c61bbbfb80531f4
+TAG: e4e18170dce4e1af90b15eae64355331
+
+AD: e9ee894ad5b0781d
+CT: 0b70b24253b2e1c3ef1165925b5c5e57
+NONCE: 42f82085c08afd5b19a9491a79cd8119
+KEY: 7517c973a9de3614431e3198f4ddc0f8dc33862654649e9ff7838635bb278231
+IN: d17fbed25ad5f72477580b9e82a7b883
+TAG: 45009a2a101877ed70e58f2e5910004f
+
+AD: 813399ff1e1ef0b58bb2be130ce5d4
+CT: 65019212ccbbd4cd2f995cc59d46fd27
+NONCE: d4df79c69f73b26a13598af07eed6a77
+KEY: 9f5c60fb5df5cf2b1b39254c3fa80e51d30d64e344b3aba59574305b4d2212ad
+IN: a3ca2ef9bd1fdbaa83db4c7eae6de94e
+TAG: 4026c486430a1ae2a5fc4081cd665468
+
+AD: d1544013b885a7083abece9e31d98ebc
+CT: 91b9f4424b68b4af839ce553d10b7dbc
+NONCE: 7078c9239650b8a1a8cf031d460e51c1
+KEY: 38f3d880ed6cd605f2eab88027c9a1c21d13e3de1af50ac884723bcf2b70f495
+IN: 52609620d7f572aa9267565e459ae419
+TAG: 0541b1a518f4bb585a594f3eab5535c3
+
+AD: d28d5811d4168a08da54b97831b59200041adb0e2891ea91
+CT: e42b53912ce21a3ee7a1fb51194d6fe3
+NONCE: 1ec1d18c96ca6cad66690e60b91cf222
+KEY: ec88cec13d8ebae7d62f60197e5486d61c33ee5a50b19f197c1348fbc9e27e8e
+IN: 658c6c7d8ea64a48375d69d9a405095a
+TAG: 2bc8cc7f42cac1a121fd9ddff4f2073c
diff --git a/src/crypto/cms/cms.cc b/src/crypto/cms/cms.cc
new file mode 100644
index 0000000..b2f1953
--- /dev/null
+++ b/src/crypto/cms/cms.cc
@@ -0,0 +1,172 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/cms.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+#include "../pkcs7/internal.h"
+
+
+// TODO(davidben): Should we move the core PKCS#7 / CMS implementation into
+// crypto/cms instead of crypto/pkcs7? CMS is getting new features while PKCS#7
+// is not.
+OPENSSL_DECLARE_ERROR_REASON(CMS, CERTIFICATE_HAS_NO_KEYID)
+
+struct CMS_SignerInfo_st {
+  X509 *signcert = nullptr;
+  EVP_PKEY *pkey = nullptr;
+  const EVP_MD *md = nullptr;
+  bool use_key_id = false;
+};
+
+struct CMS_ContentInfo_st {
+  bool has_signer_info = false;
+  CMS_SignerInfo signer_info;
+  uint8_t *der = nullptr;
+  size_t der_len = 0;
+};
+
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                          BIO *data, uint32_t flags) {
+  // We only support external signatures and do not support embedding
+  // certificates in SignedData.
+  if ((flags & CMS_DETACHED) == 0 || sk_X509_num(certs) != 0) {
+    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return nullptr;
+  }
+
+  bssl::UniquePtr<CMS_ContentInfo> cms(
+      static_cast<CMS_ContentInfo *>(OPENSSL_zalloc(sizeof(CMS_ContentInfo))));
+  if (cms == nullptr) {
+    return nullptr;
+  }
+
+  if (pkey != nullptr &&
+      !CMS_add1_signer(cms.get(), signcert, pkey, /*md=*/nullptr, flags)) {
+    return nullptr;
+  }
+
+  // We don't actually use streaming mode, but Linux passes |CMS_STREAM| to
+  // |CMS_sign| and OpenSSL interprets it as an alias for |CMS_PARTIAL| in this
+  // context.
+  if ((flags & (CMS_PARTIAL | CMS_STREAM)) == 0 &&
+      !CMS_final(cms.get(), data, NULL, flags)) {
+    return nullptr;
+  }
+
+  return cms.release();
+}
+
+void CMS_ContentInfo_free(CMS_ContentInfo *cms) {
+  if (cms == nullptr) {
+    return;
+  }
+  X509_free(cms->signer_info.signcert);
+  EVP_PKEY_free(cms->signer_info.pkey);
+  OPENSSL_free(cms->der);
+  OPENSSL_free(cms);
+}
+
+CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signcert,
+                                EVP_PKEY *pkey, const EVP_MD *md,
+                                uint32_t flags) {
+  if (  // Already finalized.
+      cms->der_len != 0 ||
+      // We only support one signer.
+      cms->has_signer_info ||
+      // We do not support configuring a signer in multiple steps. (In OpenSSL,
+      // this is used to configure attributes.
+      (flags & CMS_PARTIAL) != 0 ||
+      // We do not support embedding certificates in SignedData.
+      (flags & CMS_NOCERTS) == 0 ||
+      // We do not support attributes in SignedData.
+      (flags & CMS_NOATTR) == 0) {
+    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return nullptr;
+  }
+
+  if (signcert == nullptr || pkey == nullptr) {
+    OPENSSL_PUT_ERROR(CMS, ERR_R_PASSED_NULL_PARAMETER);
+    return nullptr;
+  }
+
+  if (!X509_check_private_key(signcert, pkey)) {
+    OPENSSL_PUT_ERROR(CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+    return nullptr;
+  }
+
+  // Default to SHA-256.
+  if (md == nullptr) {
+    md = EVP_sha256();
+  }
+
+  // Save information for later.
+  cms->has_signer_info = true;
+  cms->signer_info.signcert = bssl::UpRef(signcert).release();
+  cms->signer_info.pkey = bssl::UpRef(pkey).release();
+  cms->signer_info.md = md;
+  cms->signer_info.use_key_id = (flags & CMS_USE_KEYID) != 0;
+  return &cms->signer_info;
+}
+
+int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, uint32_t flags) {
+  if (  // Already finalized.
+      cms->der_len != 0 ||
+      // Require a SignerInfo. We do not support signature-less SignedDatas.
+      !cms->has_signer_info ||
+      // We only support the straightforward passthrough mode, without S/MIME
+      // translations.
+      (flags & CMS_BINARY) == 0 ||
+      // We do not support |dcont|. It is unclear what it does.
+      dcont != nullptr) {
+    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 2048) ||
+      !pkcs7_add_external_signature(cbb.get(), cms->signer_info.signcert,
+                                    cms->signer_info.pkey, cms->signer_info.md,
+                                    data, cms->signer_info.use_key_id) ||
+      !CBB_finish(cbb.get(), &cms->der, &cms->der_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int i2d_CMS_bio(BIO *out, CMS_ContentInfo *cms) {
+  if (cms->der_len == 0) {
+    // Not yet finalized.
+    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  return BIO_write_all(out, cms->der, cms->der_len);
+}
+
+int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags) {
+  // We do not support streaming mode.
+  if ((flags & CMS_STREAM) != 0 || in != nullptr) {
+    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  return i2d_CMS_bio(out, cms);
+}
diff --git a/src/crypto/cms/cms_test.cc b/src/crypto/cms/cms_test.cc
new file mode 100644
index 0000000..f0d8281
--- /dev/null
+++ b/src/crypto/cms/cms_test.cc
@@ -0,0 +1,164 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/cms.h>
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <openssl/bio.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/nid.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+#include "../test/test_data.h"
+#include "../test/test_util.h"
+
+
+static std::vector<uint8_t> BIOMemContents(const BIO *bio) {
+  const uint8_t *data;
+  size_t len;
+  BSSL_CHECK(BIO_mem_contents(bio, &data, &len));
+  return std::vector(data, data + len);
+}
+
+// CMS is (mostly) an extension of PKCS#7, so we reuse the PKCS#7 test data.
+TEST(CMSTest, KernelModuleSigning) {
+  // Sign a message with the same call that the Linux kernel's sign-file.c
+  // makes.
+  std::string cert_pem = GetTestData("crypto/pkcs7/test/sign_cert.pem");
+  std::string key_pem = GetTestData("crypto/pkcs7/test/sign_key.pem");
+  bssl::UniquePtr<BIO> cert_bio(
+      BIO_new_mem_buf(cert_pem.data(), cert_pem.size()));
+  bssl::UniquePtr<X509> cert(
+      PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr));
+
+  bssl::UniquePtr<BIO> key_bio(BIO_new_mem_buf(key_pem.data(), key_pem.size()));
+  bssl::UniquePtr<EVP_PKEY> key(
+      PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr));
+
+  static const char kSignedData[] = "signed data";
+  bssl::UniquePtr<BIO> data_bio(
+      BIO_new_mem_buf(kSignedData, sizeof(kSignedData) - 1));
+
+  // Sign with SHA-256, as the kernel does.
+  bssl::UniquePtr<CMS_ContentInfo> cms(CMS_sign(
+      nullptr, nullptr, nullptr, nullptr,
+      CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(
+      CMS_add1_signer(cms.get(), cert.get(), key.get(), EVP_sha256(),
+                      CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | CMS_NOATTR));
+  ASSERT_TRUE(CMS_final(cms.get(), data_bio.get(), /*dcont=*/nullptr,
+                        CMS_NOCERTS | CMS_BINARY));
+
+  // The kernel uses the streaming API for output, intended to stream the input
+  // to the output, even though it doesn't call it in a streaming mode.
+  bssl::UniquePtr<BIO> out(BIO_new(BIO_s_mem()));
+  ASSERT_TRUE(
+      i2d_CMS_bio_stream(out.get(), cms.get(), /*in=*/nullptr, /*flags=*/0));
+
+  // RSA signatures are deterministic so the output should not change. By
+  // default, |CMS_sign| should sign SHA-256.
+  std::string expected = GetTestData("crypto/pkcs7/test/sign_sha256.p7s");
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // The more straightforward output API works too.
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // The kernel passes unnecessary flags. The minimal set of flags works too.
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(
+      CMS_sign(nullptr, nullptr, nullptr, nullptr, CMS_PARTIAL | CMS_DETACHED));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(CMS_add1_signer(cms.get(), cert.get(), key.get(), EVP_sha256(),
+                              CMS_NOCERTS | CMS_NOATTR));
+  ASSERT_TRUE(
+      CMS_final(cms.get(), data_bio.get(), /*dcont=*/nullptr, CMS_BINARY));
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // SHA-256 is the default hash, so the single-shot API works too, but is less
+  // explicit about the hash chosen.
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(CMS_sign(cert.get(), key.get(), nullptr, data_bio.get(),
+                     CMS_DETACHED | CMS_NOCERTS | CMS_NOATTR | CMS_BINARY));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // The signer can be identified by SKID instead.
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(
+      CMS_sign(nullptr, nullptr, nullptr, nullptr, CMS_PARTIAL | CMS_DETACHED));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(CMS_add1_signer(cms.get(), cert.get(), key.get(), EVP_sha256(),
+                              CMS_NOCERTS | CMS_NOATTR | CMS_USE_KEYID));
+  ASSERT_TRUE(
+      CMS_final(cms.get(), data_bio.get(), /*dcont=*/nullptr, CMS_BINARY));
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  expected = GetTestData("crypto/pkcs7/test/sign_sha256_key_id.p7s");
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // Specify a different hash function.
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(
+      CMS_sign(nullptr, nullptr, nullptr, nullptr, CMS_PARTIAL | CMS_DETACHED));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(CMS_add1_signer(cms.get(), cert.get(), key.get(), EVP_sha1(),
+                              CMS_NOCERTS | CMS_NOATTR));
+  ASSERT_TRUE(
+      CMS_final(cms.get(), data_bio.get(), /*dcont=*/nullptr, CMS_BINARY));
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  expected = GetTestData("crypto/pkcs7/test/sign_sha1.p7s");
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // Ditto, with SKID.
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(
+      CMS_sign(nullptr, nullptr, nullptr, nullptr, CMS_PARTIAL | CMS_DETACHED));
+  ASSERT_TRUE(cms);
+  ASSERT_TRUE(CMS_add1_signer(cms.get(), cert.get(), key.get(), EVP_sha1(),
+                              CMS_NOCERTS | CMS_NOATTR | CMS_USE_KEYID));
+  ASSERT_TRUE(
+      CMS_final(cms.get(), data_bio.get(), /*dcont=*/nullptr, CMS_BINARY));
+  ASSERT_TRUE(BIO_reset(out.get()));
+  ASSERT_TRUE(i2d_CMS_bio(out.get(), cms.get()));
+  expected = GetTestData("crypto/pkcs7/test/sign_sha1_key_id.p7s");
+  EXPECT_EQ(Bytes(BIOMemContents(out.get())), Bytes(expected));
+
+  // If SKID is requested, but there is none, signing should fail.
+  bssl::UniquePtr<X509> cert_no_skid(X509_dup(cert.get()));
+  ASSERT_TRUE(cert_no_skid.get());
+  int loc =
+      X509_get_ext_by_NID(cert_no_skid.get(), NID_subject_key_identifier, -1);
+  ASSERT_GE(loc, 0);
+  X509_EXTENSION_free(X509_delete_ext(cert_no_skid.get(), loc));
+  ASSERT_TRUE(BIO_reset(data_bio.get()));
+  cms.reset(CMS_sign(
+      cert_no_skid.get(), key.get(), nullptr, data_bio.get(),
+      CMS_DETACHED | CMS_NOCERTS | CMS_NOATTR | CMS_BINARY | CMS_USE_KEYID));
+  EXPECT_FALSE(cms);
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_CMS,
+                          CMS_R_CERTIFICATE_HAS_NO_KEYID));
+}
diff --git a/src/crypto/cpu_arm_linux.cc b/src/crypto/cpu_arm_linux.cc
index 42ceecd..90489f7 100644
--- a/src/crypto/cpu_arm_linux.cc
+++ b/src/crypto/cpu_arm_linux.cc
@@ -109,7 +109,11 @@
 
   // Matching OpenSSL, only report other features if NEON is present.
   unsigned long hwcap = getauxval(AT_HWCAP);
-  if (hwcap & HWCAP_NEON) {
+  if (hwcap & CRYPTO_HWCAP_NEON) {
+#if defined(HWCAP_ARM_NEON)
+      static_assert(HWCAP_ARM_NEON == CRYPTO_HWCAP_NEON,
+                    "CRYPTO_HWCAP values must match Linux");
+#endif
     OPENSSL_armcap_P |= ARMV7_NEON;
 
     // Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to
@@ -123,16 +127,35 @@
       g_needs_hwcap2_workaround = hwcap2 != 0;
     }
 
-    if (hwcap2 & HWCAP2_AES) {
+    // HWCAP2_* values, without the "CRYPTO_" prefix, are exposed through
+    // <sys/auxv.h> in some versions of glibc(>= 2.41). Assert that we don't
+    // diverge from those values.
+    if (hwcap2 & CRYPTO_HWCAP2_AES) {
+#if defined(HWCAP2_AES)
+      static_assert(HWCAP2_AES == CRYPTO_HWCAP2_AES,
+                    "CRYPTO_HWCAP2 values must match Linux");
+#endif
       OPENSSL_armcap_P |= ARMV8_AES;
     }
-    if (hwcap2 & HWCAP2_PMULL) {
+    if (hwcap2 & CRYPTO_HWCAP2_PMULL) {
+#if defined(HWCAP2_PMULL)
+      static_assert(HWCAP2_PMULL == CRYPTO_HWCAP2_PMULL,
+                    "CRYPTO_HWCAP2 values must match Linux");
+#endif
       OPENSSL_armcap_P |= ARMV8_PMULL;
     }
-    if (hwcap2 & HWCAP2_SHA1) {
+    if (hwcap2 & CRYPTO_HWCAP2_SHA1) {
+#if defined(HWCAP2_SHA1)
+      static_assert(HWCAP2_SHA1 == CRYPTO_HWCAP2_SHA1,
+                    "CRYPTO_HWCAP2 values must match Linux");
+#endif
       OPENSSL_armcap_P |= ARMV8_SHA1;
     }
-    if (hwcap2 & HWCAP2_SHA2) {
+    if (hwcap2 & CRYPTO_HWCAP2_SHA2) {
+#if defined(HWCAP2_SHA2)
+      static_assert(HWCAP2_SHA2 == CRYPTO_HWCAP2_SHA2,
+                    "CRYPTO_HWCAP2 values must match Linux");
+#endif
       OPENSSL_armcap_P |= ARMV8_SHA256;
     }
   }
diff --git a/src/crypto/cpu_arm_linux.h b/src/crypto/cpu_arm_linux.h
index 81e37cb..196f3dd 100644
--- a/src/crypto/cpu_arm_linux.h
+++ b/src/crypto/cpu_arm_linux.h
@@ -29,14 +29,16 @@
 // The cpuinfo parser lives in a header file so it may be accessible from
 // cross-platform fuzzers without adding code to those platforms normally.
 
-#define HWCAP_NEON (1 << 12)
+#define CRYPTO_HWCAP_NEON (1 << 12)
 
 // See /usr/include/asm/hwcap.h on an ARM installation for the source of
 // these values.
-#define HWCAP2_AES (1 << 0)
-#define HWCAP2_PMULL (1 << 1)
-#define HWCAP2_SHA1 (1 << 2)
-#define HWCAP2_SHA2 (1 << 3)
+// We add the prefix "CRYPTO_" to the definitions so as not to collide with
+// some versions of glibc (>= 2.41) that expose them through <sys/auxv.h>.
+#define CRYPTO_HWCAP2_AES (1 << 0)
+#define CRYPTO_HWCAP2_PMULL (1 << 1)
+#define CRYPTO_HWCAP2_SHA1 (1 << 2)
+#define CRYPTO_HWCAP2_SHA2 (1 << 3)
 
 typedef struct {
   const char *data;
@@ -141,16 +143,16 @@
 
   unsigned long ret = 0;
   if (has_list_item(&features, "aes")) {
-    ret |= HWCAP2_AES;
+    ret |= CRYPTO_HWCAP2_AES;
   }
   if (has_list_item(&features, "pmull")) {
-    ret |= HWCAP2_PMULL;
+    ret |= CRYPTO_HWCAP2_PMULL;
   }
   if (has_list_item(&features, "sha1")) {
-    ret |= HWCAP2_SHA1;
+    ret |= CRYPTO_HWCAP2_SHA1;
   }
   if (has_list_item(&features, "sha2")) {
-    ret |= HWCAP2_SHA2;
+    ret |= CRYPTO_HWCAP2_SHA2;
   }
   return ret;
 }
diff --git a/src/crypto/cpu_arm_linux_test.cc b/src/crypto/cpu_arm_linux_test.cc
index 7c91122..e301ccd 100644
--- a/src/crypto/cpu_arm_linux_test.cc
+++ b/src/crypto/cpu_arm_linux_test.cc
@@ -95,7 +95,8 @@
           // (Extra processors omitted.)
           "\n"
           "Hardware        : Qualcomm Technologies, Inc MSM8998\n",
-          HWCAP2_AES | HWCAP2_PMULL | HWCAP2_SHA1 | HWCAP2_SHA2,
+          CRYPTO_HWCAP2_AES | CRYPTO_HWCAP2_PMULL | CRYPTO_HWCAP2_SHA1 |
+              CRYPTO_HWCAP2_SHA2,
       },
       // Garbage should be tolerated.
       {
@@ -107,23 +108,24 @@
       {
           "Features        : aes pmull sha1 sha2\n"
           "CPU architecture: 8\n",
-          HWCAP2_AES | HWCAP2_PMULL | HWCAP2_SHA1 | HWCAP2_SHA2,
+          CRYPTO_HWCAP2_AES | CRYPTO_HWCAP2_PMULL | CRYPTO_HWCAP2_SHA1 |
+              CRYPTO_HWCAP2_SHA2,
       },
       // Various combinations of ARMv8 flags.
       {
           "Features        : aes sha1 sha2\n"
           "CPU architecture: 8\n",
-          HWCAP2_AES | HWCAP2_SHA1 | HWCAP2_SHA2,
+          CRYPTO_HWCAP2_AES | CRYPTO_HWCAP2_SHA1 | CRYPTO_HWCAP2_SHA2,
       },
       {
           "Features        : pmull sha2\n"
           "CPU architecture: 8\n",
-          HWCAP2_PMULL | HWCAP2_SHA2,
+          CRYPTO_HWCAP2_PMULL | CRYPTO_HWCAP2_SHA2,
       },
       {
           "Features        : aes aes   aes not_aes aes aes \n"
           "CPU architecture: 8\n",
-          HWCAP2_AES,
+          CRYPTO_HWCAP2_AES,
       },
       {
           "Features        : \n"
diff --git a/src/crypto/cpu_intel.cc b/src/crypto/cpu_intel.cc
index 05acad2..722c33f 100644
--- a/src/crypto/cpu_intel.cc
+++ b/src/crypto/cpu_intel.cc
@@ -23,10 +23,8 @@
 #include <string.h>
 
 #if defined(_MSC_VER)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <immintrin.h>
 #include <intrin.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include "internal.h"
@@ -207,10 +205,6 @@
     // 128-bit or 256-bit vectors, and also volume 2a section 2.7.11 ("#UD
     // Equations for EVEX") which says that all EVEX-coded instructions raise an
     // undefined-instruction exception if any of these XCR0 bits is zero.
-    //
-    // AVX10 fixes this by reorganizing the features that used to be part of
-    // "AVX512" and allowing them to be used independently of 512-bit support.
-    // TODO: add AVX10 detection.
     extended_features[0] &= ~(1u << 16);  // AVX512F
     extended_features[0] &= ~(1u << 17);  // AVX512DQ
     extended_features[0] &= ~(1u << 21);  // AVX512IFMA
diff --git a/src/crypto/crypto.cc b/src/crypto/crypto.cc
index 5c31c48..9bc9dc7 100644
--- a/src/crypto/crypto.cc
+++ b/src/crypto/crypto.cc
@@ -54,7 +54,7 @@
 // archive, linking on OS X will fail to resolve common symbols. By
 // initialising it to zero, it becomes a "data symbol", which isn't so
 // affected.
-HIDDEN uint8_t BORINGSSL_function_hit[9] = {0};
+HIDDEN uint8_t BORINGSSL_function_hit[8] = {0};
 #endif
 
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
diff --git a/src/crypto/curve25519/internal.h b/src/crypto/curve25519/internal.h
index c8797d4..17efc95 100644
--- a/src/crypto/curve25519/internal.h
+++ b/src/crypto/curve25519/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H
-#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_CURVE25519_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_CURVE25519_INTERNAL_H
 
 #include <openssl/curve25519.h>
 
@@ -161,4 +161,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CURVE25519_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_CURVE25519_INTERNAL_H
diff --git a/src/crypto/des/internal.h b/src/crypto/des/internal.h
index 78e193a..e51c6e3 100644
--- a/src/crypto/des/internal.h
+++ b/src/crypto/des/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_DES_INTERNAL_H
-#define OPENSSL_HEADER_DES_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_DES_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_DES_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/des.h>
@@ -146,4 +146,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_DES_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_DES_INTERNAL_H
diff --git a/src/crypto/dh/dh_asn1.cc b/src/crypto/dh/dh_asn1.cc
index 13bd4fd..9295e14 100644
--- a/src/crypto/dh/dh_asn1.cc
+++ b/src/crypto/dh/dh_asn1.cc
@@ -44,41 +44,40 @@
 }
 
 DH *DH_parse_parameters(CBS *cbs) {
-  DH *ret = DH_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
       !parse_integer(&child, &ret->p) ||
       !parse_integer(&child, &ret->g)) {
-    goto err;
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
   uint64_t priv_length;
   if (CBS_len(&child) != 0) {
     if (!CBS_get_asn1_uint64(&child, &priv_length) ||
         priv_length > UINT_MAX) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+      return nullptr;
     }
     ret->priv_length = (unsigned)priv_length;
   }
 
   if (CBS_len(&child) != 0) {
-    goto err;
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
-  if (!dh_check_params_fast(ret)) {
-    goto err;
+  if (!dh_check_params_fast(ret.get())) {
+    OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DH_marshal_parameters(CBB *cbb, const DH *dh) {
diff --git a/src/crypto/dh/params.cc b/src/crypto/dh/params.cc
index 18c585e..115505f 100644
--- a/src/crypto/dh/params.cc
+++ b/src/crypto/dh/params.cc
@@ -22,7 +22,8 @@
 #include "../fipsmodule/dh/internal.h"
 
 
-static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, size_t num_words) {
+static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words,
+                          size_t num_words) {
   BIGNUM *alloc = NULL;
   if (ret == NULL) {
     alloc = BN_new();
@@ -304,92 +305,57 @@
     return 0;
   }
 
-  BIGNUM *t1, *t2;
-  int g, ok = 0;
-  BN_CTX *ctx = NULL;
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
-  }
-  BN_CTX_start(ctx);
-  t1 = BN_CTX_get(ctx);
-  t2 = BN_CTX_get(ctx);
-  if (t1 == NULL || t2 == NULL) {
-    goto err;
-  }
-
   // Make sure |dh| has the necessary elements
   if (dh->p == NULL) {
     dh->p = BN_new();
     if (dh->p == NULL) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+      return 0;
     }
   }
   if (dh->g == NULL) {
     dh->g = BN_new();
     if (dh->g == NULL) {
-      goto err;
+      OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+      return 0;
     }
   }
 
+  BN_ULONG t1, t2, g;
   if (generator <= 1) {
     OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR);
-    goto err;
+    return 0;
   }
   if (generator == DH_GENERATOR_2) {
-    if (!BN_set_word(t1, 24)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 11)) {
-      goto err;
-    }
+    t1 = 24;
+    t2 = 11;
     g = 2;
   } else if (generator == DH_GENERATOR_5) {
-    if (!BN_set_word(t1, 10)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 3)) {
-      goto err;
-    }
-    // BN_set_word(t3,7); just have to miss
-    // out on these ones :-(
+    t1 = 10;
+    t2 = 3;
     g = 5;
   } else {
-    // in the general case, don't worry if 'generator' is a
-    // generator or not: since we are using safe primes,
-    // it will generate either an order-q or an order-2q group,
-    // which both is OK
-    if (!BN_set_word(t1, 2)) {
-      goto err;
-    }
-    if (!BN_set_word(t2, 1)) {
-      goto err;
-    }
+    // In the general case, don't worry if 'generator' is a generator or not:
+    // since we are using safe primes, it will generate either an order-q or an
+    // order-2q group, which both is OK.
+    t1 = 2;
+    t2 = 1;
     g = generator;
   }
 
-  if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) {
-    goto err;
-  }
-  if (!BN_GENCB_call(cb, 3, 0)) {
-    goto err;
-  }
-  if (!BN_set_word(dh->g, g)) {
-    goto err;
-  }
-  ok = 1;
-
-err:
-  if (!ok) {
+  bssl::UniquePtr<BIGNUM> t1_bn(BN_new()), t2_bn(BN_new());
+  if (t1_bn == nullptr || t2_bn == nullptr ||
+      !BN_set_word(t1_bn.get(), t1) ||  //
+      !BN_set_word(t2_bn.get(), t2) ||  //
+      !BN_generate_prime_ex(dh->p, prime_bits, 1, t1_bn.get(), t2_bn.get(),
+                            cb) ||
+      !BN_GENCB_call(cb, 3, 0) ||  //
+      !BN_set_word(dh->g, g)) {
     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
+    return 0;
   }
 
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  return ok;
+  return 1;
 }
 
 static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
diff --git a/src/crypto/digest/digest_extra.cc b/src/crypto/digest/digest_extra.cc
index f68ede9..4cbfa1f 100644
--- a/src/crypto/digest/digest_extra.cc
+++ b/src/crypto/digest/digest_extra.cc
@@ -156,21 +156,22 @@
   return ret;
 }
 
-int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md) {
+static int marshal_digest_algorithm(CBB *cbb, const EVP_MD *md,
+                                    bool with_null) {
   CBB algorithm, oid, null;
   if (!CBB_add_asn1(cbb, &algorithm, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
     return 0;
   }
 
-  int found = 0;
+  bool found = false;
   int nid = EVP_MD_type(md);
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
-    if (nid == kMDOIDs[i].nid) {
-      if (!CBB_add_bytes(&oid, kMDOIDs[i].oid, kMDOIDs[i].oid_len)) {
+  for (const auto &mdoid : kMDOIDs) {
+    if (nid == mdoid.nid) {
+      if (!CBB_add_bytes(&oid, mdoid.oid, mdoid.oid_len)) {
         return 0;
       }
-      found = 1;
+      found = true;
       break;
     }
   }
@@ -180,8 +181,7 @@
     return 0;
   }
 
-  // TODO(crbug.com/boringssl/710): Is this correct? See RFC 4055, section 2.1.
-  if (!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||  //
+  if ((with_null && !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL)) ||  //
       !CBB_flush(cbb)) {
     return 0;
   }
@@ -189,6 +189,14 @@
   return 1;
 }
 
+int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md) {
+  return marshal_digest_algorithm(cbb, md, /*with_null=*/true);
+}
+
+int EVP_marshal_digest_algorithm_no_params(CBB *cbb, const EVP_MD *md) {
+  return marshal_digest_algorithm(cbb, md, /*with_null=*/false);
+}
+
 const EVP_MD *EVP_get_digestbyname(const char *name) {
   for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
     const char *short_name = nid_to_digest_mapping[i].short_name;
diff --git a/src/crypto/digest/digest_test.cc b/src/crypto/digest/digest_test.cc
index 8237fb8..8cdc48d 100644
--- a/src/crypto/digest/digest_test.cc
+++ b/src/crypto/digest/digest_test.cc
@@ -282,9 +282,9 @@
   ASSERT_TRUE(CBB_init(cbb.get(), 0));
   EXPECT_FALSE(EVP_marshal_digest_algorithm(cbb.get(), EVP_md5_sha1()));
 
-  static const uint8_t kSHA256[] = {0x30, 0x0d, 0x06, 0x09, 0x60,
-                                    0x86, 0x48, 0x01, 0x65, 0x03,
-                                    0x04, 0x02, 0x01, 0x05, 0x00};
+  static const uint8_t kSHA256NullParam[] = {0x30, 0x0d, 0x06, 0x09, 0x60,
+                                             0x86, 0x48, 0x01, 0x65, 0x03,
+                                             0x04, 0x02, 0x01, 0x05, 0x00};
   static const uint8_t kSHA256NoParam[] = {0x30, 0x0b, 0x06, 0x09, 0x60,
                                            0x86, 0x48, 0x01, 0x65, 0x03,
                                            0x04, 0x02, 0x01};
@@ -292,23 +292,24 @@
       0x30, 0x0e, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
       0x65, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x2a};
 
-  // Serialize SHA-256.
+  // Serialize SHA-256, with and without NULL.
   cbb.Reset();
   ASSERT_TRUE(CBB_init(cbb.get(), 0));
   ASSERT_TRUE(EVP_marshal_digest_algorithm(cbb.get(), EVP_sha256()));
-  uint8_t *der;
-  size_t der_len;
-  ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
-  bssl::UniquePtr<uint8_t> free_der(der);
-  EXPECT_EQ(Bytes(kSHA256), Bytes(der, der_len));
+  EXPECT_EQ(Bytes(kSHA256NullParam),
+            Bytes(CBB_data(cbb.get()), CBB_len(cbb.get())));
+  cbb.Reset();
+  ASSERT_TRUE(CBB_init(cbb.get(), 0));
+  ASSERT_TRUE(EVP_marshal_digest_algorithm_no_params(cbb.get(), EVP_sha256()));
+  EXPECT_EQ(Bytes(kSHA256NoParam),
+            Bytes(CBB_data(cbb.get()), CBB_len(cbb.get())));
 
-  // Parse SHA-256.
+  // Parse SHA-256. Either absent or NULL parameters are tolerated for
+  // compatibility.
   CBS cbs;
-  CBS_init(&cbs, kSHA256, sizeof(kSHA256));
+  CBS_init(&cbs, kSHA256NullParam, sizeof(kSHA256NullParam));
   EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
   EXPECT_EQ(0u, CBS_len(&cbs));
-
-  // Missing parameters are tolerated for compatibility.
   CBS_init(&cbs, kSHA256NoParam, sizeof(kSHA256NoParam));
   EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
   EXPECT_EQ(0u, CBS_len(&cbs));
diff --git a/src/crypto/dsa/dsa.cc b/src/crypto/dsa/dsa.cc
index d1bfdf0..e2125d5 100644
--- a/src/crypto/dsa/dsa.cc
+++ b/src/crypto/dsa/dsa.cc
@@ -33,6 +33,10 @@
 #include "internal.h"
 
 
+static_assert(OPENSSL_DSA_MAX_MODULUS_BITS <=
+                  BN_MONTGOMERY_MAX_WORDS * BN_BITS2,
+              "Max DSA size too big for Montgomery arithmetic");
+
 // Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
 // Miller-Rabin.
 #define DSS_prime_checks 50
@@ -167,17 +171,14 @@
     return 0;
   }
 
-  int ok = 0;
   unsigned char seed[SHA256_DIGEST_LENGTH];
   unsigned char md[SHA256_DIGEST_LENGTH];
   unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
   BIGNUM *r0, *W, *X, *c, *test;
   BIGNUM *g = NULL, *q = NULL, *p = NULL;
-  BN_MONT_CTX *mont = NULL;
   int k, n = 0, m = 0;
   int counter = 0;
   int r = 0;
-  BN_CTX *ctx = NULL;
   unsigned int h = 2;
   const EVP_MD *evpmd;
 
@@ -201,23 +202,23 @@
     OPENSSL_memcpy(seed, seed_in, seed_len);
   }
 
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx.get());
 
-  r0 = BN_CTX_get(ctx);
-  g = BN_CTX_get(ctx);
-  W = BN_CTX_get(ctx);
-  q = BN_CTX_get(ctx);
-  X = BN_CTX_get(ctx);
-  c = BN_CTX_get(ctx);
-  p = BN_CTX_get(ctx);
-  test = BN_CTX_get(ctx);
+  r0 = BN_CTX_get(ctx.get());
+  g = BN_CTX_get(ctx.get());
+  W = BN_CTX_get(ctx.get());
+  q = BN_CTX_get(ctx.get());
+  X = BN_CTX_get(ctx.get());
+  c = BN_CTX_get(ctx.get());
+  p = BN_CTX_get(ctx.get());
+  test = BN_CTX_get(ctx.get());
 
   if (test == NULL || !BN_lshift(test, BN_value_one(), bits - 1)) {
-    goto err;
+    return 0;
   }
 
   for (;;) {
@@ -225,13 +226,13 @@
     for (;;) {
       // step 1
       if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, m++)) {
-        goto err;
+        return 0;
       }
 
       int use_random_seed = (seed_in == NULL);
       if (use_random_seed) {
         if (!RAND_bytes(seed, qsize)) {
-          goto err;
+          return 0;
         }
         // DSA parameters are public.
         CONSTTIME_DECLASSIFY(seed, qsize);
@@ -252,7 +253,7 @@
       // step 2
       if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) ||
           !EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) {
-        goto err;
+        return 0;
       }
       for (size_t i = 0; i < qsize; i++) {
         md[i] ^= buf2[i];
@@ -262,17 +263,17 @@
       md[0] |= 0x80;
       md[qsize - 1] |= 0x01;
       if (!BN_bin2bn(md, qsize, q)) {
-        goto err;
+        return 0;
       }
 
       // step 4
-      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed,
-                                  cb);
+      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx.get(),
+                                  use_random_seed, cb);
       if (r > 0) {
         break;
       }
       if (r != 0) {
-        goto err;
+        return 0;
       }
 
       // do a callback call
@@ -280,7 +281,7 @@
     }
 
     if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) {
-      goto err;
+      return 0;
     }
 
     // step 6
@@ -291,7 +292,7 @@
 
     for (;;) {
       if ((counter != 0) && !BN_GENCB_call(cb, BN_GENCB_GENERATED, counter)) {
-        goto err;
+        return 0;
       }
 
       // step 7
@@ -307,36 +308,36 @@
         }
 
         if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) {
-          goto err;
+          return 0;
         }
 
         // step 8
         if (!BN_bin2bn(md, qsize, r0) || !BN_lshift(r0, r0, (qsize << 3) * k) ||
             !BN_add(W, W, r0)) {
-          goto err;
+          return 0;
         }
       }
 
       // more of step 8
       if (!BN_mask_bits(W, bits - 1) || !BN_copy(X, W) || !BN_add(X, X, test)) {
-        goto err;
+        return 0;
       }
 
       // step 9
-      if (!BN_lshift1(r0, q) || !BN_mod(c, X, r0, ctx) ||
+      if (!BN_lshift1(r0, q) || !BN_mod(c, X, r0, ctx.get()) ||
           !BN_sub(r0, c, BN_value_one()) || !BN_sub(p, X, r0)) {
-        goto err;
+        return 0;
       }
 
       // step 10
       if (BN_cmp(p, test) >= 0) {
         // step 11
-        r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
+        r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx.get(), 1, cb);
         if (r > 0) {
           goto end;  // found it
         }
         if (r != 0) {
-          goto err;
+          return 0;
         }
       }
 
@@ -352,68 +353,56 @@
   }
 end:
   if (!BN_GENCB_call(cb, 2, 1)) {
-    goto err;
+    return 0;
   }
 
   // We now need to generate g
   // Set r0=(p-1)/q
-  if (!BN_sub(test, p, BN_value_one()) || !BN_div(r0, NULL, test, q, ctx)) {
-    goto err;
+  if (!BN_sub(test, p, BN_value_one()) ||
+      !BN_div(r0, NULL, test, q, ctx.get())) {
+    return 0;
   }
 
-  mont = BN_MONT_CTX_new_for_modulus(p, ctx);
-  if (mont == NULL || !BN_set_word(test, h)) {
-    goto err;
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new_for_modulus(p, ctx.get()));
+  if (mont == nullptr || !BN_set_word(test, h)) {
+    return 0;
   }
 
   for (;;) {
     // g=test^r0%p
-    if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) {
-      goto err;
+    if (!BN_mod_exp_mont(g, test, r0, p, ctx.get(), mont.get())) {
+      return 0;
     }
     if (!BN_is_one(g)) {
       break;
     }
     if (!BN_add(test, test, BN_value_one())) {
-      goto err;
+      return 0;
     }
     h++;
   }
 
   if (!BN_GENCB_call(cb, 3, 1)) {
-    goto err;
+    return 0;
   }
 
-  ok = 1;
-
-err:
-  if (ok) {
-    BN_free(dsa->p);
-    BN_free(dsa->q);
-    BN_free(dsa->g);
-    dsa->p = BN_dup(p);
-    dsa->q = BN_dup(q);
-    dsa->g = BN_dup(g);
-    if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
-      ok = 0;
-      goto err;
-    }
-    if (out_counter != NULL) {
-      *out_counter = counter;
-    }
-    if (out_h != NULL) {
-      *out_h = h;
-    }
+  BN_free(dsa->p);
+  BN_free(dsa->q);
+  BN_free(dsa->g);
+  dsa->p = BN_dup(p);
+  dsa->q = BN_dup(q);
+  dsa->g = BN_dup(g);
+  if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+    return 0;
+  }
+  if (out_counter != NULL) {
+    *out_counter = counter;
+  }
+  if (out_h != NULL) {
+    *out_h = h;
   }
 
-  if (ctx) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-
-  BN_MONT_CTX_free(mont);
-
-  return ok;
+  return 1;
 }
 
 DSA *DSAparams_dup(const DSA *dsa) {
@@ -436,17 +425,17 @@
     return 0;
   }
 
-  int ok = 0;
-  BIGNUM *pub_key = NULL, *priv_key = NULL;
-  BN_CTX *ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
 
-  priv_key = dsa->priv_key;
-  if (priv_key == NULL) {
+  int ok = 0;
+  BIGNUM *pub_key = nullptr;
+  BIGNUM *priv_key = dsa->priv_key;
+  if (priv_key == nullptr) {
     priv_key = BN_new();
-    if (priv_key == NULL) {
+    if (priv_key == nullptr) {
       goto err;
     }
   }
@@ -456,16 +445,16 @@
   }
 
   pub_key = dsa->pub_key;
-  if (pub_key == NULL) {
+  if (pub_key == nullptr) {
     pub_key = BN_new();
-    if (pub_key == NULL) {
+    if (pub_key == nullptr) {
       goto err;
     }
   }
 
   if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock,
-                              dsa->p, ctx) ||
-      !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx,
+                              dsa->p, ctx.get()) ||
+      !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx.get(),
                                  dsa->method_mont_p)) {
     goto err;
   }
@@ -478,13 +467,12 @@
   ok = 1;
 
 err:
-  if (dsa->pub_key == NULL) {
+  if (dsa->pub_key == nullptr) {
     BN_free(pub_key);
   }
-  if (dsa->priv_key == NULL) {
+  if (dsa->priv_key == nullptr) {
     BN_free(priv_key);
   }
-  BN_CTX_free(ctx);
 
   return ok;
 }
@@ -529,14 +517,13 @@
 // neither inputs nor outputs are in Montgomery form.
 static int mod_mul_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                              const BN_MONT_CTX *mont, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   // |BN_mod_mul_montgomery| removes a factor of R, so we cancel it with a
   // single |BN_to_montgomery| which adds one factor of R.
-  int ok = tmp != NULL && BN_to_montgomery(tmp, a, mont, ctx) &&
-           BN_mod_mul_montgomery(r, tmp, b, mont, ctx);
-  BN_CTX_end(ctx);
-  return ok;
+  return tmp != nullptr &&  //
+         BN_to_montgomery(tmp, a, mont, ctx) &&
+         BN_mod_mul_montgomery(r, tmp, b, mont, ctx);
 }
 
 DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, const DSA *dsa) {
@@ -691,9 +678,20 @@
       goto err;
     }
 
-    // Calculate W = inv(S) mod Q
-    // save W in u2
-    if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) {
+    if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+                                (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
+                                ctx) ||
+        !BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_q,
+                                (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->q,
+                                ctx)) {
+      goto err;
+    }
+
+    // Calculate W = inv(S) mod Q, in the Montgomery domain. This is slightly
+    // more efficiently computed as FromMont(s)^-1 = (s * R^-1)^-1 = s^-1 * R,
+    // instead of ToMont(s^-1) = s^-1 * R.
+    if (!BN_from_montgomery(&u2, sig->s, dsa->method_mont_q, ctx) ||
+        !BN_mod_inverse(&u2, &u2, dsa->q, ctx)) {
       goto err;
     }
 
@@ -710,19 +708,15 @@
       goto err;
     }
 
-    // u1 = M * w mod q
-    if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx)) {
+    // u1 = M * w mod q. w was stored in the Montgomery domain while M was not,
+    // so the result will already be out of the Montgomery domain.
+    if (!BN_mod_mul_montgomery(&u1, &u1, &u2, dsa->method_mont_q, ctx)) {
       goto err;
     }
 
-    // u2 = r * w mod q
-    if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx)) {
-      goto err;
-    }
-
-    if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
-                                (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
-                                ctx)) {
+    // u2 = r * w mod q. w was stored in the Montgomery domain while r was not,
+    // so the result will already be out of the Montgomery domain.
+    if (!BN_mod_mul_montgomery(&u2, sig->r, &u2, dsa->method_mont_q, ctx)) {
       goto err;
     }
 
@@ -731,7 +725,6 @@
       goto err;
     }
 
-    // BN_copy(&u1,&t1);
     // let u1 = u1 mod q
     if (!BN_mod(&u1, &t1, dsa->q, ctx)) {
       goto err;
@@ -921,31 +914,28 @@
 }
 
 DH *DSA_dup_DH(const DSA *dsa) {
-  if (dsa == NULL) {
-    return NULL;
+  if (dsa == nullptr) {
+    return nullptr;
   }
 
-  DH *ret = DH_new();
-  if (ret == NULL) {
-    goto err;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
-  if (dsa->q != NULL) {
+  if (dsa->q != nullptr) {
     ret->priv_length = BN_num_bits(dsa->q);
-    if ((ret->q = BN_dup(dsa->q)) == NULL) {
-      goto err;
+    if ((ret->q = BN_dup(dsa->q)) == nullptr) {
+      return nullptr;
     }
   }
-  if ((dsa->p != NULL && (ret->p = BN_dup(dsa->p)) == NULL) ||
-      (dsa->g != NULL && (ret->g = BN_dup(dsa->g)) == NULL) ||
-      (dsa->pub_key != NULL && (ret->pub_key = BN_dup(dsa->pub_key)) == NULL) ||
-      (dsa->priv_key != NULL &&
-       (ret->priv_key = BN_dup(dsa->priv_key)) == NULL)) {
-    goto err;
+  if ((dsa->p != nullptr && (ret->p = BN_dup(dsa->p)) == nullptr) ||
+      (dsa->g != nullptr && (ret->g = BN_dup(dsa->g)) == nullptr) ||
+      (dsa->pub_key != nullptr &&
+       (ret->pub_key = BN_dup(dsa->pub_key)) == nullptr) ||
+      (dsa->priv_key != nullptr &&
+       (ret->priv_key = BN_dup(dsa->priv_key)) == nullptr)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/src/crypto/dsa/dsa_asn1.cc b/src/crypto/dsa/dsa_asn1.cc
index a267473..af5ccad 100644
--- a/src/crypto/dsa/dsa_asn1.cc
+++ b/src/crypto/dsa/dsa_asn1.cc
@@ -136,9 +136,9 @@
 }
 
 DSA *DSA_parse_public_key(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
@@ -148,16 +148,12 @@
       !parse_integer(&child, &ret->g) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
@@ -175,9 +171,9 @@
 }
 
 DSA *DSA_parse_parameters(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
@@ -186,16 +182,12 @@
       !parse_integer(&child, &ret->g) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
@@ -212,9 +204,9 @@
 }
 
 DSA *DSA_parse_private_key(CBS *cbs) {
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   CBS child;
@@ -222,12 +214,12 @@
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
       !CBS_get_asn1_uint64(&child, &version)) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
 
   if (version != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
-    goto err;
+    return nullptr;
   }
 
   if (!parse_integer(&child, &ret->p) ||
@@ -237,17 +229,13 @@
       !parse_integer(&child, &ret->priv_key) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
-  if (!dsa_check_key(ret)) {
-    goto err;
+  if (!dsa_check_key(ret.get())) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
 
 int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
diff --git a/src/crypto/dsa/internal.h b/src/crypto/dsa/internal.h
index e987774..537c576 100644
--- a/src/crypto/dsa/internal.h
+++ b/src/crypto/dsa/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
-#define OPENSSL_HEADER_DSA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_DSA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_DSA_INTERNAL_H
 
 #include <openssl/dsa.h>
 
@@ -51,4 +51,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_DSA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_DSA_INTERNAL_H
diff --git a/src/crypto/ec/ec_asn1.cc b/src/crypto/ec/ec_asn1.cc
index 19d6072..ce81580 100644
--- a/src/crypto/ec/ec_asn1.cc
+++ b/src/crypto/ec/ec_asn1.cc
@@ -51,12 +51,10 @@
       version != 1 ||
       !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
   // Parse the optional parameters field.
-  EC_KEY *ret = NULL;
-  BIGNUM *priv_key = NULL;
   if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) {
     // Per SEC 1, as an alternative to omitting it, one is allowed to specify
     // this field and put in a NULL to mean inheriting this value. This was
@@ -65,43 +63,44 @@
     CBS child;
     if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
     const EC_GROUP *inner_group = EC_KEY_parse_parameters(&child);
-    if (inner_group == NULL) {
-      goto err;
+    if (inner_group == nullptr) {
+      return nullptr;
     }
-    if (group == NULL) {
+    if (group == nullptr) {
       group = inner_group;
-    } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
+    } else if (EC_GROUP_cmp(group, inner_group, nullptr) != 0) {
       // If a group was supplied externally, it must match.
       OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
-      goto err;
+      return nullptr;
     }
     if (CBS_len(&child) != 0) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
   }
 
-  if (group == NULL) {
+  if (group == nullptr) {
     OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
-    goto err;
+    return nullptr;
   }
 
-  ret = EC_KEY_new();
-  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
-    goto err;
+  bssl::UniquePtr<EC_KEY> ret(EC_KEY_new());
+  if (ret == nullptr || !EC_KEY_set_group(ret.get(), group)) {
+    return nullptr;
   }
 
   // Although RFC 5915 specifies the length of the key, OpenSSL historically
   // got this wrong, so accept any length. See upstream's
   // 30cd4ff294252c4b6a4b69cbef6a5b4117705d22.
-  priv_key = BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
+  bssl::UniquePtr<BIGNUM> priv_key(
+      BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), nullptr));
   ret->pub_key = EC_POINT_new(group);
-  if (priv_key == NULL || ret->pub_key == NULL ||
-      !EC_KEY_set_private_key(ret, priv_key)) {
-    goto err;
+  if (priv_key == nullptr || ret->pub_key == nullptr ||
+      !EC_KEY_set_private_key(ret.get(), priv_key.get())) {
+    return nullptr;
   }
 
   if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
@@ -117,10 +116,10 @@
         // form later.
         CBS_len(&public_key) == 0 ||
         !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
-                            CBS_len(&public_key), NULL) ||
+                            CBS_len(&public_key), nullptr) ||
         CBS_len(&child) != 0) {
       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-      goto err;
+      return nullptr;
     }
 
     // Save the point conversion form.
@@ -131,7 +130,7 @@
     // Compute the public key instead.
     if (!ec_point_mul_scalar_base(group, &ret->pub_key->raw,
                                   &ret->priv_key->scalar)) {
-      goto err;
+      return nullptr;
     }
     // Remember the original private-key-only encoding.
     // TODO(davidben): Consider removing this.
@@ -140,21 +139,15 @@
 
   if (CBS_len(&ec_private_key) != 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
-    goto err;
+    return nullptr;
   }
 
   // Ensure the resulting key is valid.
-  if (!EC_KEY_check_key(ret)) {
-    goto err;
+  if (!EC_KEY_check_key(ret.get())) {
+    return nullptr;
   }
 
-  BN_free(priv_key);
-  return ret;
-
-err:
-  EC_KEY_free(ret);
-  BN_free(priv_key);
-  return NULL;
+  return ret.release();
 }
 
 int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
@@ -327,10 +320,7 @@
     return 0;
   }
 
-  CBB child;
-  return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
-         CBB_add_bytes(&child, group->oid, group->oid_len) &&  //
-         CBB_flush(cbb);
+  return CBB_add_asn1_element(cbb, CBS_ASN1_OBJECT, group->oid, group->oid_len);
 }
 
 EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
@@ -344,14 +334,17 @@
   // TODO(davidben): Remove support for this.
   struct explicit_prime_curve curve;
   if (!parse_explicit_prime_curve(cbs, &curve)) {
-    return NULL;
+    return nullptr;
   }
 
-  const EC_GROUP *ret = NULL;
-  BIGNUM *p = BN_new(), *a = BN_new(), *b = BN_new(), *x = BN_new(),
-         *y = BN_new();
-  if (p == NULL || a == NULL || b == NULL || x == NULL || y == NULL) {
-    goto err;
+  bssl::UniquePtr<BIGNUM> p(BN_new());
+  bssl::UniquePtr<BIGNUM> a(BN_new());
+  bssl::UniquePtr<BIGNUM> b(BN_new());
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  if (p == nullptr || a == nullptr || b == nullptr || x == nullptr ||
+      y == nullptr) {
+    return nullptr;
   }
 
   for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
@@ -362,36 +355,27 @@
 
     // The order alone uniquely identifies the group, but we check the other
     // parameters to avoid misinterpreting the group.
-    if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
-      goto err;
+    if (!EC_GROUP_get_curve_GFp(group, p.get(), a.get(), b.get(), nullptr)) {
+      return nullptr;
     }
-    if (!integers_equal(&curve.prime, p) || !integers_equal(&curve.a, a) ||
-        !integers_equal(&curve.b, b)) {
+    if (!integers_equal(&curve.prime, p.get()) ||
+        !integers_equal(&curve.a, a.get()) ||
+        !integers_equal(&curve.b, b.get())) {
       break;
     }
     if (!EC_POINT_get_affine_coordinates_GFp(
-            group, EC_GROUP_get0_generator(group), x, y, NULL)) {
-      goto err;
+            group, EC_GROUP_get0_generator(group), x.get(), y.get(), nullptr)) {
+      return nullptr;
     }
-    if (!integers_equal(&curve.base_x, x) ||
-        !integers_equal(&curve.base_y, y)) {
+    if (!integers_equal(&curve.base_x, x.get()) ||
+        !integers_equal(&curve.base_y, y.get())) {
       break;
     }
-    ret = group;
-    break;
+    return const_cast<EC_GROUP *>(group);
   }
 
-  if (ret == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
-  }
-
-err:
-  BN_free(p);
-  BN_free(a);
-  BN_free(b);
-  BN_free(x);
-  BN_free(y);
-  return (EC_GROUP *)ret;
+  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+  return nullptr;
 }
 
 int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
diff --git a/src/crypto/ec/hash_to_curve.cc b/src/crypto/ec/hash_to_curve.cc
index 86c2fc6..b9601fc 100644
--- a/src/crypto/ec/hash_to_curve.cc
+++ b/src/crypto/ec/hash_to_curve.cc
@@ -57,84 +57,76 @@
     return 0;
   }
 
-  int ret = 0;
   const size_t block_size = EVP_MD_block_size(md);
   const size_t md_size = EVP_MD_size(md);
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
 
-  {
-    // Long DSTs are hashed down to size. See section 5.3.3.
-    static_assert(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
-    uint8_t dst_buf[EVP_MAX_MD_SIZE];
-    if (dst_len >= 256) {
-      static const char kPrefix[] = "H2C-OVERSIZE-DST-";
-      if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-          !EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
-          !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-          !EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
-        goto err;
-      }
-      dst = dst_buf;
-      dst_len = md_size;
+  // Long DSTs are hashed down to size. See section 5.3.3.
+  static_assert(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
+  uint8_t dst_buf[EVP_MAX_MD_SIZE];
+  if (dst_len >= 256) {
+    static const char kPrefix[] = "H2C-OVERSIZE-DST-";
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), kPrefix, sizeof(kPrefix) - 1) ||
+        !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+        !EVP_DigestFinal_ex(ctx.get(), dst_buf, nullptr)) {
+      return 0;
     }
-    uint8_t dst_len_u8 = (uint8_t)dst_len;
+    dst = dst_buf;
+    dst_len = md_size;
+  }
+  uint8_t dst_len_u8 = (uint8_t)dst_len;
 
-    // Compute b_0.
-    static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
-    // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
-    // be returned. This depends on the static assert above.
-    uint8_t l_i_b_str_zero[3] = {static_cast<uint8_t>(out_len >> 8),
-                                 static_cast<uint8_t>(out_len), 0};
-    uint8_t b_0[EVP_MAX_MD_SIZE];
-    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-        !EVP_DigestUpdate(&ctx, kZeros, block_size) ||
-        !EVP_DigestUpdate(&ctx, msg, msg_len) ||
-        !EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
-        !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-        !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
-        !EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
-      goto err;
-    }
-
-    uint8_t b_i[EVP_MAX_MD_SIZE];
-    uint8_t i = 1;
-    while (out_len > 0) {
-      if (i == 0) {
-        // Input was too large.
-        OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
-        goto err;
-      }
-      if (i > 1) {
-        for (size_t j = 0; j < md_size; j++) {
-          b_i[j] ^= b_0[j];
-        }
-      } else {
-        OPENSSL_memcpy(b_i, b_0, md_size);
-      }
-
-      if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-          !EVP_DigestUpdate(&ctx, b_i, md_size) ||
-          !EVP_DigestUpdate(&ctx, &i, 1) ||
-          !EVP_DigestUpdate(&ctx, dst, dst_len) ||
-          !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
-          !EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
-        goto err;
-      }
-
-      size_t todo = out_len >= md_size ? md_size : out_len;
-      OPENSSL_memcpy(out, b_i, todo);
-      out += todo;
-      out_len -= todo;
-      i++;
-    }
-
-    ret = 1;
+  // Compute b_0.
+  static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
+  // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
+  // be returned. This depends on the static assert above.
+  uint8_t l_i_b_str_zero[3] = {static_cast<uint8_t>(out_len >> 8),
+                               static_cast<uint8_t>(out_len), 0};
+  uint8_t b_0[EVP_MAX_MD_SIZE];
+  if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+      !EVP_DigestUpdate(ctx.get(), kZeros, block_size) ||
+      !EVP_DigestUpdate(ctx.get(), msg, msg_len) ||
+      !EVP_DigestUpdate(ctx.get(), l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
+      !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+      !EVP_DigestUpdate(ctx.get(), &dst_len_u8, 1) ||
+      !EVP_DigestFinal_ex(ctx.get(), b_0, nullptr)) {
+    return 0;
   }
 
-err:
-  EVP_MD_CTX_cleanup(&ctx);
-  return ret;
+  uint8_t b_i[EVP_MAX_MD_SIZE];
+  uint8_t i = 1;
+  while (out_len > 0) {
+    if (i == 0) {
+      // Input was too large.
+      OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+    if (i > 1) {
+      for (size_t j = 0; j < md_size; j++) {
+        b_i[j] ^= b_0[j];
+      }
+    } else {
+      OPENSSL_memcpy(b_i, b_0, md_size);
+    }
+
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), b_i, md_size) ||
+        !EVP_DigestUpdate(ctx.get(), &i, 1) ||
+        !EVP_DigestUpdate(ctx.get(), dst, dst_len) ||
+        !EVP_DigestUpdate(ctx.get(), &dst_len_u8, 1) ||
+        !EVP_DigestFinal_ex(ctx.get(), b_i, nullptr)) {
+      return 0;
+    }
+
+    size_t todo = out_len >= md_size ? md_size : out_len;
+    OPENSSL_memcpy(out, b_i, todo);
+    out += todo;
+    out_len -= todo;
+    i++;
+  }
+
+  return 1;
 }
 
 // num_bytes_to_derive determines the number of bytes to derive when hashing to
diff --git a/src/crypto/ec/internal.h b/src/crypto/ec/internal.h
index 86e19e2..8dbe4a7 100644
--- a/src/crypto/ec/internal.h
+++ b/src/crypto/ec/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
-#define OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_EC_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_EC_INTERNAL_H
 
 #include <openssl/ec.h>
 
@@ -75,4 +75,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_EC_INTERNAL_H
diff --git a/src/crypto/ecdsa/ecdsa_asn1.cc b/src/crypto/ecdsa/ecdsa_asn1.cc
index 1d86a44..28d5036 100644
--- a/src/crypto/ecdsa/ecdsa_asn1.cc
+++ b/src/crypto/ecdsa/ecdsa_asn1.cc
@@ -88,25 +88,20 @@
 
   // TODO(davidben): We can actually do better and go straight from the DER
   // format to the fixed-width format without a malloc.
-  ECDSA_SIG *s = ecdsa_sig_from_fixed(eckey, fixed, fixed_len);
-  if (s == NULL) {
+  bssl::UniquePtr<ECDSA_SIG> s(ecdsa_sig_from_fixed(eckey, fixed, fixed_len));
+  if (s == nullptr) {
     return 0;
   }
 
-  int ret = 0;
   CBB cbb;
   CBB_init_fixed(&cbb, sig, ECDSA_size(eckey));
   size_t len;
-  if (!ECDSA_SIG_marshal(&cbb, s) || !CBB_finish(&cbb, NULL, &len)) {
+  if (!ECDSA_SIG_marshal(&cbb, s.get()) || !CBB_finish(&cbb, nullptr, &len)) {
     OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
-    goto err;
+    return 0;
   }
-  *out_sig_len = (unsigned)len;
-  ret = 1;
-
-err:
-  ECDSA_SIG_free(s);
-  return ret;
+  *out_sig_len = static_cast<unsigned>(len);
+  return 1;
 }
 
 int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
@@ -116,15 +111,15 @@
   // TODO(davidben): We can actually do better and go straight from the DER
   // format to the fixed-width format without a malloc.
   int ret = 0;
-  uint8_t *der = NULL;
-  ECDSA_SIG *s = ECDSA_SIG_from_bytes(sig, sig_len);
-  if (s == NULL) {
+  uint8_t *der = nullptr;
+  bssl::UniquePtr<ECDSA_SIG> s(ECDSA_SIG_from_bytes(sig, sig_len));
+  if (s == nullptr) {
     goto err;
   }
 
   // Defend against potential laxness in the DER parser.
   size_t der_len;
-  if (!ECDSA_SIG_to_bytes(&der, &der_len, s) || der_len != sig_len ||
+  if (!ECDSA_SIG_to_bytes(&der, &der_len, s.get()) || der_len != sig_len ||
       OPENSSL_memcmp(sig, der, sig_len) != 0) {
     // This should never happen. crypto/bytestring is strictly DER.
     OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR);
@@ -133,12 +128,11 @@
 
   uint8_t fixed[ECDSA_MAX_FIXED_LEN];
   size_t fixed_len;
-  ret = ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), s) &&
+  ret = ecdsa_sig_to_fixed(eckey, fixed, &fixed_len, sizeof(fixed), s.get()) &&
         ecdsa_verify_fixed(digest, digest_len, fixed, fixed_len, eckey);
 
 err:
   OPENSSL_free(der);
-  ECDSA_SIG_free(s);
   return ret;
 }
 
diff --git a/src/crypto/err/cms.errordata b/src/crypto/err/cms.errordata
new file mode 100644
index 0000000..68b6e95
--- /dev/null
+++ b/src/crypto/err/cms.errordata
@@ -0,0 +1,2 @@
+CMS,100,CERTIFICATE_HAS_NO_KEYID
+CMS,101,PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
diff --git a/src/crypto/err/err.cc b/src/crypto/err/err.cc
index 82ba0a6..d84153c 100644
--- a/src/crypto/err/err.cc
+++ b/src/crypto/err/err.cc
@@ -24,9 +24,7 @@
 #include <string.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/mem.h>
diff --git a/src/crypto/err/err_test.cc b/src/crypto/err/err_test.cc
index 5b634d2..d62d07f 100644
--- a/src/crypto/err/err_test.cc
+++ b/src/crypto/err/err_test.cc
@@ -26,9 +26,7 @@
 #include "./internal.h"
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <errno.h>
 #endif
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index d8eb3a4..7d77cfd 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -243,6 +243,8 @@
 SSL,237,UNSUPPORTED_CIPHER
 SSL,238,UNSUPPORTED_COMPRESSION_ALGORITHM
 SSL,327,UNSUPPORTED_CREDENTIAL_LIST
+SSL,328,INVALID_TRUST_ANCHOR_LIST
+SSL,329,INVALID_CERTIFICATE_PROPERTY_LIST
 SSL,312,UNSUPPORTED_ECH_SERVER_CONFIG
 SSL,239,UNSUPPORTED_ELLIPTIC_CURVE
 SSL,240,UNSUPPORTED_PROTOCOL
diff --git a/src/crypto/evp/evp_asn1.cc b/src/crypto/evp/evp_asn1.cc
index eeea963..d77a3d2 100644
--- a/src/crypto/evp/evp_asn1.cc
+++ b/src/crypto/evp/evp_asn1.cc
@@ -435,25 +435,24 @@
 
 EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, long len) {
   if (len < 0) {
-    return NULL;
+    return nullptr;
   }
   CBS cbs;
   CBS_init(&cbs, *inp, (size_t)len);
-  EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
-  if (pkey == NULL) {
-    return NULL;
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+  if (pkey == nullptr) {
+    return nullptr;
   }
-  EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
-  EVP_PKEY_free(pkey);
-  if (ec_key == NULL) {
-    return NULL;
+  bssl::UniquePtr<EC_KEY> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
+  if (ec_key == nullptr) {
+    return nullptr;
   }
-  if (out != NULL) {
+  if (out != nullptr) {
     EC_KEY_free(*out);
-    *out = ec_key;
+    *out = ec_key.get();
   }
   *inp = CBS_data(&cbs);
-  return ec_key;
+  return ec_key.release();
 }
 
 int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) {
diff --git a/src/crypto/evp/evp_ctx.cc b/src/crypto/evp/evp_ctx.cc
index e34dfa0..9a5f97e 100644
--- a/src/crypto/evp/evp_ctx.cc
+++ b/src/crypto/evp/evp_ctx.cc
@@ -108,37 +108,36 @@
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx) {
   if (!ctx->pmeth || !ctx->pmeth->copy) {
-    return NULL;
+    return nullptr;
   }
 
-  EVP_PKEY_CTX *ret =
-      reinterpret_cast<EVP_PKEY_CTX *>(OPENSSL_zalloc(sizeof(EVP_PKEY_CTX)));
+  bssl::UniquePtr<EVP_PKEY_CTX> ret(
+      reinterpret_cast<EVP_PKEY_CTX *>(OPENSSL_zalloc(sizeof(EVP_PKEY_CTX))));
   if (!ret) {
-    return NULL;
+    return nullptr;
   }
 
   ret->pmeth = ctx->pmeth;
   ret->engine = ctx->engine;
   ret->operation = ctx->operation;
 
-  if (ctx->pkey != NULL) {
+  if (ctx->pkey != nullptr) {
     EVP_PKEY_up_ref(ctx->pkey);
     ret->pkey = ctx->pkey;
   }
 
-  if (ctx->peerkey != NULL) {
+  if (ctx->peerkey != nullptr) {
     EVP_PKEY_up_ref(ctx->peerkey);
     ret->peerkey = ctx->peerkey;
   }
 
-  if (ctx->pmeth->copy(ret, ctx) <= 0) {
-    ret->pmeth = NULL;
-    EVP_PKEY_CTX_free(ret);
+  if (ctx->pmeth->copy(ret.get(), ctx) <= 0) {
+    ret->pmeth = nullptr;
     OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
-    return NULL;
+    return nullptr;
   }
 
-  return ret;
+  return ret.release();
 }
 
 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
index 70f6c76..f71bd9f 100644
--- a/src/crypto/evp/evp_test.cc
+++ b/src/crypto/evp/evp_test.cc
@@ -19,16 +19,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-OPENSSL_MSVC_PRAGMA(warning(push))
-OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
-
 #include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
-OPENSSL_MSVC_PRAGMA(warning(pop))
-
 #include <gtest/gtest.h>
 
 #include <openssl/bn.h>
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
index da07c27..8307aa4 100644
--- a/src/crypto/evp/internal.h
+++ b/src/crypto/evp/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_EVP_INTERNAL_H
-#define OPENSSL_HEADER_EVP_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -265,4 +265,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_EVP_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H
diff --git a/src/crypto/evp/p_dsa_asn1.cc b/src/crypto/evp/p_dsa_asn1.cc
index aab3f59..8503d4d 100644
--- a/src/crypto/evp/p_dsa_asn1.cc
+++ b/src/crypto/evp/p_dsa_asn1.cc
@@ -62,11 +62,11 @@
       dsa->p != nullptr && dsa->q != nullptr && dsa->g != nullptr;
 
   // See RFC 5480, section 2.
-  CBB spki, algorithm, oid, key_bitstring;
+  CBB spki, algorithm, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, dsa_asn1_meth.oid,
+                            dsa_asn1_meth.oid_len) ||
       (has_params && !DSA_marshal_parameters(&algorithm, dsa)) ||
       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
@@ -126,12 +126,12 @@
   }
 
   // See PKCS#11, v2.40, section 2.5.
-  CBB pkcs8, algorithm, oid, private_key;
+  CBB pkcs8, algorithm, private_key;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, dsa_asn1_meth.oid,
+                            dsa_asn1_meth.oid_len) ||
       !DSA_marshal_parameters(&algorithm, dsa) ||
       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
       !BN_marshal_asn1(&private_key, dsa->priv_key) || !CBB_flush(out)) {
diff --git a/src/crypto/evp/p_ec_asn1.cc b/src/crypto/evp/p_ec_asn1.cc
index bcf2525..d89c6eb 100644
--- a/src/crypto/evp/p_ec_asn1.cc
+++ b/src/crypto/evp/p_ec_asn1.cc
@@ -30,11 +30,11 @@
   const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
 
   // See RFC 5480, section 2.
-  CBB spki, algorithm, oid, key_bitstring;
+  CBB spki, algorithm, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ec_asn1_meth.oid,
+                            ec_asn1_meth.oid_len) ||
       !EC_KEY_marshal_curve_name(&algorithm, group) ||
       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
@@ -114,12 +114,12 @@
   unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
 
   // See RFC 5915.
-  CBB pkcs8, algorithm, oid, private_key;
+  CBB pkcs8, algorithm, private_key;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ec_asn1_meth.oid,
+                            ec_asn1_meth.oid_len) ||
       !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
       !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
diff --git a/src/crypto/evp/p_ed25519_asn1.cc b/src/crypto/evp/p_ed25519_asn1.cc
index 45947d8..8053422 100644
--- a/src/crypto/evp/p_ed25519_asn1.cc
+++ b/src/crypto/evp/p_ed25519_asn1.cc
@@ -129,11 +129,11 @@
   const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
 
   // See RFC 8410, section 4.
-  CBB spki, algorithm, oid, key_bitstring;
+  CBB spki, algorithm, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, ed25519_asn1_meth.oid, ed25519_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ed25519_asn1_meth.oid,
+                            ed25519_asn1_meth.oid_len) ||
       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
       !CBB_add_bytes(&key_bitstring, key->key + ED25519_PUBLIC_KEY_OFFSET,
@@ -176,12 +176,12 @@
   }
 
   // See RFC 8410, section 7.
-  CBB pkcs8, algorithm, oid, private_key, inner;
+  CBB pkcs8, algorithm, private_key, inner;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, ed25519_asn1_meth.oid, ed25519_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ed25519_asn1_meth.oid,
+                            ed25519_asn1_meth.oid_len) ||
       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
       !CBB_add_asn1(&private_key, &inner, CBS_ASN1_OCTETSTRING) ||
       // The PKCS#8 encoding stores only the 32-byte seed which is the first 32
diff --git a/src/crypto/evp/p_rsa_asn1.cc b/src/crypto/evp/p_rsa_asn1.cc
index cdcb6b4..6c6bfc5 100644
--- a/src/crypto/evp/p_rsa_asn1.cc
+++ b/src/crypto/evp/p_rsa_asn1.cc
@@ -28,11 +28,11 @@
 static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
   // See RFC 3279, section 2.3.1.
   const RSA *rsa = reinterpret_cast<const RSA *>(key->pkey);
-  CBB spki, algorithm, oid, null, key_bitstring;
+  CBB spki, algorithm, null, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, rsa_asn1_meth.oid,
+                            rsa_asn1_meth.oid_len) ||
       !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
@@ -76,12 +76,12 @@
 
 static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
   const RSA *rsa = reinterpret_cast<const RSA *>(key->pkey);
-  CBB pkcs8, algorithm, oid, null, private_key;
+  CBB pkcs8, algorithm, null, private_key;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, rsa_asn1_meth.oid,
+                            rsa_asn1_meth.oid_len) ||
       !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
       !RSA_marshal_private_key(&private_key, rsa) ||  //
diff --git a/src/crypto/evp/p_x25519_asn1.cc b/src/crypto/evp/p_x25519_asn1.cc
index 351b788..c31dcc5 100644
--- a/src/crypto/evp/p_x25519_asn1.cc
+++ b/src/crypto/evp/p_x25519_asn1.cc
@@ -143,11 +143,11 @@
   const X25519_KEY *key = reinterpret_cast<X25519_KEY *>(pkey->pkey);
 
   // See RFC 8410, section 4.
-  CBB spki, algorithm, oid, key_bitstring;
+  CBB spki, algorithm, key_bitstring;
   if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, x25519_asn1_meth.oid, x25519_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, x25519_asn1_meth.oid,
+                            x25519_asn1_meth.oid_len) ||
       !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
       !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
       !CBB_add_bytes(&key_bitstring, key->pub, 32) ||  //
@@ -188,12 +188,12 @@
   }
 
   // See RFC 8410, section 7.
-  CBB pkcs8, algorithm, oid, private_key, inner;
+  CBB pkcs8, algorithm, private_key, inner;
   if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
       !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, x25519_asn1_meth.oid, x25519_asn1_meth.oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, x25519_asn1_meth.oid,
+                            x25519_asn1_meth.oid_len) ||
       !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
       !CBB_add_asn1(&private_key, &inner, CBS_ASN1_OCTETSTRING) ||
       // The PKCS#8 encoding stores only the 32-byte seed which is the first 32
diff --git a/src/crypto/evp/sign.cc b/src/crypto/evp/sign.cc
index 2a7836f..e14acc4 100644
--- a/src/crypto/evp/sign.cc
+++ b/src/crypto/evp/sign.cc
@@ -36,39 +36,30 @@
 
 int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig, unsigned *out_sig_len,
                   EVP_PKEY *pkey) {
-  uint8_t m[EVP_MAX_MD_SIZE];
-  unsigned m_len;
-  int ret = 0;
-  EVP_MD_CTX tmp_ctx;
-  EVP_PKEY_CTX *pkctx = NULL;
-  size_t sig_len = EVP_PKEY_size(pkey);
-
   // Ensure the final result will fit in |unsigned|.
+  size_t sig_len = EVP_PKEY_size(pkey);
   if (sig_len > UINT_MAX) {
     sig_len = UINT_MAX;
   }
 
   *out_sig_len = 0;
-  EVP_MD_CTX_init(&tmp_ctx);
-  if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
-      !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
-    goto out;
+  uint8_t m[EVP_MAX_MD_SIZE];
+  unsigned m_len;
+  bssl::ScopedEVP_MD_CTX tmp_ctx;
+  if (!EVP_MD_CTX_copy_ex(tmp_ctx.get(), ctx) ||
+      !EVP_DigestFinal_ex(tmp_ctx.get(), m, &m_len)) {
+    return 0;
   }
-  EVP_MD_CTX_cleanup(&tmp_ctx);
 
-  pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+  bssl::UniquePtr<EVP_PKEY_CTX> pkctx(EVP_PKEY_CTX_new(pkey, nullptr));
   if (!pkctx ||  //
-      !EVP_PKEY_sign_init(pkctx) ||
-      !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) ||
-      !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) {
-    goto out;
+      !EVP_PKEY_sign_init(pkctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(pkctx.get(), ctx->digest) ||
+      !EVP_PKEY_sign(pkctx.get(), sig, &sig_len, m, m_len)) {
+    return 0;
   }
-  *out_sig_len = (unsigned)sig_len;
-  ret = 1;
-
-out:
-  EVP_PKEY_CTX_free(pkctx);
-  return ret;
+  *out_sig_len = static_cast<unsigned>(sig_len);
+  return 1;
 }
 
 int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
@@ -87,28 +78,18 @@
                     EVP_PKEY *pkey) {
   uint8_t m[EVP_MAX_MD_SIZE];
   unsigned m_len;
-  int ret = 0;
-  EVP_MD_CTX tmp_ctx;
-  EVP_PKEY_CTX *pkctx = NULL;
-
-  EVP_MD_CTX_init(&tmp_ctx);
-  if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
-      !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
-    EVP_MD_CTX_cleanup(&tmp_ctx);
-    goto out;
+  bssl::ScopedEVP_MD_CTX tmp_ctx;
+  if (!EVP_MD_CTX_copy_ex(tmp_ctx.get(), ctx) ||
+      !EVP_DigestFinal_ex(tmp_ctx.get(), m, &m_len)) {
+    return 0;
   }
-  EVP_MD_CTX_cleanup(&tmp_ctx);
 
-  pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+  bssl::UniquePtr<EVP_PKEY_CTX> pkctx(EVP_PKEY_CTX_new(pkey, nullptr));
   if (!pkctx ||
-      !EVP_PKEY_verify_init(pkctx) ||
-      !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) {
-    goto out;
+      !EVP_PKEY_verify_init(pkctx.get()) ||
+      !EVP_PKEY_CTX_set_signature_md(pkctx.get(), ctx->digest)) {
+    return 0;
   }
-  ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len);
-
-out:
-  EVP_PKEY_CTX_free(pkctx);
-  return ret;
+  return EVP_PKEY_verify(pkctx.get(), sig, sig_len, m, m_len);
 }
 
diff --git a/src/crypto/fipsmodule/aes/aes.cc.inc b/src/crypto/fipsmodule/aes/aes.cc.inc
index 26e60e7..6df166b 100644
--- a/src/crypto/fipsmodule/aes/aes.cc.inc
+++ b/src/crypto/fipsmodule/aes/aes.cc.inc
@@ -12,11 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <openssl/aes.h>
-
 #include <assert.h>
 
 #include "internal.h"
+#include "../bcm_interface.h"
 
 
 // Be aware that different sets of AES functions use incompatible key
@@ -24,7 +23,8 @@
 // value, or both. Therefore they cannot mix. Also, on AArch64, the plain-C
 // code, above, is incompatible with the |aes_hw_*| functions.
 
-void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+bcm_infallible BCM_aes_encrypt(const uint8_t *in, uint8_t *out,
+                               const AES_KEY *key) {
   if (hwaes_capable()) {
     aes_hw_encrypt(in, out, key);
   } else if (vpaes_capable()) {
@@ -32,9 +32,11 @@
   } else {
     aes_nohw_encrypt(in, out, key);
   }
+  return bcm_infallible::not_approved;
 }
 
-void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+bcm_infallible BCM_aes_decrypt(const uint8_t *in, uint8_t *out,
+                               const AES_KEY *key) {
   if (hwaes_capable()) {
     aes_hw_decrypt(in, out, key);
   } else if (vpaes_capable()) {
@@ -42,32 +44,41 @@
   } else {
     aes_nohw_decrypt(in, out, key);
   }
+  return bcm_infallible::not_approved;
 }
 
-int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
-  if (bits != 128 && bits != 192 && bits != 256) {
-    return -2;
-  }
+bcm_status BCM_aes_set_encrypt_key(const uint8_t *key, unsigned bits,
+                                   AES_KEY *aeskey) {
+  int ret = -1;
   if (hwaes_capable()) {
-    return aes_hw_set_encrypt_key(key, bits, aeskey);
+    ret = aes_hw_set_encrypt_key(key, bits, aeskey);
   } else if (vpaes_capable()) {
-    return vpaes_set_encrypt_key(key, bits, aeskey);
+    ret = vpaes_set_encrypt_key(key, bits, aeskey);
   } else {
-    return aes_nohw_set_encrypt_key(key, bits, aeskey);
+    ret = aes_nohw_set_encrypt_key(key, bits, aeskey);
   }
+  if (ret < 0) {
+    return bcm_status::failure;
+  }
+  BSSL_CHECK(ret == 0);
+  return bcm_status::not_approved;
 }
 
-int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
-  if (bits != 128 && bits != 192 && bits != 256) {
-    return -2;
-  }
+bcm_status BCM_aes_set_decrypt_key(const uint8_t *key, unsigned bits,
+                                   AES_KEY *aeskey) {
+  int ret = -1;
   if (hwaes_capable()) {
-    return aes_hw_set_decrypt_key(key, bits, aeskey);
+    ret = aes_hw_set_decrypt_key(key, bits, aeskey);
   } else if (vpaes_capable()) {
-    return vpaes_set_decrypt_key(key, bits, aeskey);
+    ret = vpaes_set_decrypt_key(key, bits, aeskey);
   } else {
-    return aes_nohw_set_decrypt_key(key, bits, aeskey);
+    ret = aes_nohw_set_decrypt_key(key, bits, aeskey);
   }
+  if (ret < 0) {
+    return bcm_status::failure;
+  }
+  BSSL_CHECK(ret == 0);
+  return bcm_status::not_approved;
 }
 
 #if defined(HWAES) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
diff --git a/src/crypto/fipsmodule/aes/asm/aes-gcm-avx10-x86_64.pl b/src/crypto/fipsmodule/aes/asm/aes-gcm-avx10-x86_64.pl
deleted file mode 100644
index 8a099d3..0000000
--- a/src/crypto/fipsmodule/aes/asm/aes-gcm-avx10-x86_64.pl
+++ /dev/null
@@ -1,1370 +0,0 @@
-#!/usr/bin/env perl
-# Copyright 2024 The BoringSSL Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-#------------------------------------------------------------------------------
-#
-# VAES and VPCLMULQDQ optimized AES-GCM for x86_64
-#
-# This file is based on aes-gcm-avx10-x86_64.S from the Linux kernel
-# (https://git.kernel.org/linus/b06affb1cb580e13).  The following notable
-# changes have been made:
-#
-# - Relicensed under BoringSSL's preferred license.
-#
-# - Converted from GNU assembler to "perlasm".  This was necessary for
-#   compatibility with BoringSSL's Windows builds which use NASM instead of the
-#   GNU assembler.  It was also necessary for compatibility with the 'delocate'
-#   tool used in BoringSSL's FIPS builds.
-#
-# - Added support for the Windows ABI.
-#
-# - Changed function prototypes to be compatible with what BoringSSL wants.
-#
-# - Removed the optimized finalization function, as BoringSSL doesn't want it.
-#
-# - Added a single-block GHASH multiplication function, as BoringSSL needs this.
-#
-# - Added optimization for large amounts of AAD.
-#
-#------------------------------------------------------------------------------
-#
-# This file implements AES-GCM (Galois/Counter Mode) for x86_64 CPUs that
-# support VAES (vector AES), VPCLMULQDQ (vector carryless multiplication), and
-# either AVX512 or AVX10.  Some of the functions, notably the encryption and
-# decryption update functions which are the most performance-critical, are
-# provided in two variants generated from a macro: one using 256-bit vectors
-# (suffix: vaes_avx10_256) and one using 512-bit vectors (vaes_avx10_512).  The
-# other, "shared" functions (vaes_avx10) use at most 256-bit vectors.
-#
-# The functions that use 512-bit vectors are intended for CPUs that support
-# 512-bit vectors *and* where using them doesn't cause significant
-# downclocking.  They require the following CPU features:
-#
-#       VAES && VPCLMULQDQ && BMI2 && ((AVX512BW && AVX512VL) || AVX10/512)
-#
-# The other functions require the following CPU features:
-#
-#       VAES && VPCLMULQDQ && BMI2 && ((AVX512BW && AVX512VL) || AVX10/256)
-#
-# Note that we use "avx10" in the names of the functions as a shorthand to
-# really mean "AVX10 or a certain set of AVX512 features".  Due to Intel's
-# introduction of AVX512 and then its replacement by AVX10, there doesn't seem
-# to be a simple way to name things that makes sense on all CPUs.
-#
-# Note that the macros that support both 256-bit and 512-bit vectors could
-# fairly easily be changed to support 128-bit too.  However, this would *not*
-# be sufficient to allow the code to run on CPUs without AVX512 or AVX10,
-# because the code heavily uses several features of these extensions other than
-# the vector length: the increase in the number of SIMD registers from 16 to
-# 32, masking support, and new instructions such as vpternlogd (which can do a
-# three-argument XOR).  These features are very useful for AES-GCM.
-
-$flavour = shift;
-$output  = shift;
-if ( $flavour =~ /\./ ) { $output = $flavour; undef $flavour; }
-
-if ( $flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/ ) {
-    $win64   = 1;
-    @argregs = ( "%rcx", "%rdx", "%r8", "%r9" );
-}
-else {
-    $win64   = 0;
-    @argregs = ( "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" );
-}
-
-$0 =~ m/(.*[\/\\])[^\/\\]+$/;
-$dir = $1;
-( $xlate = "${dir}x86_64-xlate.pl" and -f $xlate )
-  or ( $xlate = "${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate )
-  or die "can't locate x86_64-xlate.pl";
-
-open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
-*STDOUT = *OUT;
-
-sub _begin_func {
-    my ( $funcname, $uses_seh ) = @_;
-    $g_cur_func_name          = $funcname;
-    $g_cur_func_uses_seh      = $uses_seh;
-    @g_cur_func_saved_gpregs  = ();
-    @g_cur_func_saved_xmmregs = ();
-    return <<___;
-.globl $funcname
-.type $funcname,\@abi-omnipotent
-.align 32
-$funcname:
-    .cfi_startproc
-    @{[ $uses_seh ? ".seh_startproc" : "" ]}
-    _CET_ENDBR
-___
-}
-
-# Push a list of general purpose registers onto the stack.
-sub _save_gpregs {
-    my @gpregs = @_;
-    my $code   = "";
-    die "_save_gpregs requires uses_seh" unless $g_cur_func_uses_seh;
-    die "_save_gpregs can only be called once per function"
-      if @g_cur_func_saved_gpregs;
-    die "Order must be _save_gpregs, then _save_xmmregs"
-      if @g_cur_func_saved_xmmregs;
-    @g_cur_func_saved_gpregs = @gpregs;
-    for my $reg (@gpregs) {
-        $code .= "push $reg\n";
-        if ($win64) {
-            $code .= ".seh_pushreg $reg\n";
-        }
-        else {
-            $code .= ".cfi_push $reg\n";
-        }
-    }
-    return $code;
-}
-
-# Push a list of xmm registers onto the stack if the target is Windows.
-sub _save_xmmregs {
-    my @xmmregs     = @_;
-    my $num_xmmregs = scalar @xmmregs;
-    my $code        = "";
-    die "_save_xmmregs requires uses_seh" unless $g_cur_func_uses_seh;
-    die "_save_xmmregs can only be called once per function"
-      if @g_cur_func_saved_xmmregs;
-    if ( $win64 and $num_xmmregs > 0 ) {
-        @g_cur_func_saved_xmmregs = @xmmregs;
-        my $is_misaligned = ( scalar @g_cur_func_saved_gpregs ) % 2 == 0;
-        my $alloc_size    = 16 * $num_xmmregs + ( $is_misaligned ? 8 : 0 );
-        $code .= "sub \$$alloc_size, %rsp\n";
-        $code .= ".seh_stackalloc $alloc_size\n";
-        for my $i ( 0 .. $num_xmmregs - 1 ) {
-            my $reg_num = $xmmregs[$i];
-            my $pos     = 16 * $i;
-            $code .= "movdqa %xmm$reg_num, $pos(%rsp)\n";
-            $code .= ".seh_savexmm %xmm$reg_num, $pos\n";
-        }
-    }
-    return $code;
-}
-
-sub _end_func {
-    my $code = "";
-
-    # Restore any xmm registers that were saved earlier.
-    my $num_xmmregs = scalar @g_cur_func_saved_xmmregs;
-    if ( $win64 and $num_xmmregs > 0 ) {
-        my $need_alignment = ( scalar @g_cur_func_saved_gpregs ) % 2 == 0;
-        my $alloc_size     = 16 * $num_xmmregs + ( $need_alignment ? 8 : 0 );
-        for my $i ( 0 .. $num_xmmregs - 1 ) {
-            my $reg_num = $g_cur_func_saved_xmmregs[$i];
-            my $pos     = 16 * $i;
-            $code .= "movdqa $pos(%rsp), %xmm$reg_num\n";
-        }
-        $code .= "add \$$alloc_size, %rsp\n";
-    }
-
-    # Restore any general purpose registers that were saved earlier.
-    for my $reg ( reverse @g_cur_func_saved_gpregs ) {
-        $code .= "pop $reg\n";
-        if ( !$win64 ) {
-            $code .= ".cfi_pop $reg\n";
-        }
-    }
-
-    $code .= <<___;
-    ret
-    @{[ $g_cur_func_uses_seh ? ".seh_endproc" : "" ]}
-    .cfi_endproc
-    .size   $g_cur_func_name, . - $g_cur_func_name
-___
-    return $code;
-}
-
-$code = <<___;
-.section .rodata
-.align 64
-
-    # A shuffle mask that reflects the bytes of 16-byte blocks
-.Lbswap_mask:
-    .quad   0x08090a0b0c0d0e0f, 0x0001020304050607
-
-    # This is the GHASH reducing polynomial without its constant term, i.e.
-    # x^128 + x^7 + x^2 + x, represented using the backwards mapping
-    # between bits and polynomial coefficients.
-    #
-    # Alternatively, it can be interpreted as the naturally-ordered
-    # representation of the polynomial x^127 + x^126 + x^121 + 1, i.e. the
-    # "reversed" GHASH reducing polynomial without its x^128 term.
-.Lgfpoly:
-    .quad   1, 0xc200000000000000
-
-    # Same as above, but with the (1 << 64) bit set.
-.Lgfpoly_and_internal_carrybit:
-    .quad   1, 0xc200000000000001
-
-    # The below constants are used for incrementing the counter blocks.
-    # ctr_pattern points to the four 128-bit values [0, 1, 2, 3].
-    # inc_2blocks and inc_4blocks point to the single 128-bit values 2 and
-    # 4.  Note that the same '2' is reused in ctr_pattern and inc_2blocks.
-.Lctr_pattern:
-    .quad   0, 0
-    .quad   1, 0
-.Linc_2blocks:
-    .quad   2, 0
-    .quad   3, 0
-.Linc_4blocks:
-    .quad   4, 0
-
-.text
-___
-
-# Number of powers of the hash key stored in the key struct.  The powers are
-# stored from highest (H^NUM_H_POWERS) to lowest (H^1).
-$NUM_H_POWERS = 16;
-
-$OFFSETOFEND_H_POWERS = $NUM_H_POWERS * 16;
-
-# Offset to 'rounds' in AES_KEY struct
-$OFFSETOF_AES_ROUNDS = 240;
-
-# The current vector length in bytes
-undef $VL;
-
-# Set the vector length in bytes.  This sets the VL variable and defines
-# register aliases V0-V31 that map to the ymm or zmm registers.
-sub _set_veclen {
-    ($VL) = @_;
-    foreach my $i ( 0 .. 31 ) {
-        if ( $VL == 32 ) {
-            ${"V${i}"} = "%ymm${i}";
-        }
-        elsif ( $VL == 64 ) {
-            ${"V${i}"} = "%zmm${i}";
-        }
-        else {
-            die "Unsupported vector length";
-        }
-    }
-}
-
-# The _ghash_mul_step macro does one step of GHASH multiplication of the
-# 128-bit lanes of \a by the corresponding 128-bit lanes of \b and storing the
-# reduced products in \dst.  \t0, \t1, and \t2 are temporary registers of the
-# same size as \a and \b.  To complete all steps, this must invoked with \i=0
-# through \i=9.  The division into steps allows users of this macro to
-# optionally interleave the computation with other instructions.  Users of this
-# macro must preserve the parameter registers across steps.
-#
-# The multiplications are done in GHASH's representation of the finite field
-# GF(2^128).  Elements of GF(2^128) are represented as binary polynomials
-# (i.e. polynomials whose coefficients are bits) modulo a reducing polynomial
-# G.  The GCM specification uses G = x^128 + x^7 + x^2 + x + 1.  Addition is
-# just XOR, while multiplication is more complex and has two parts: (a) do
-# carryless multiplication of two 128-bit input polynomials to get a 256-bit
-# intermediate product polynomial, and (b) reduce the intermediate product to
-# 128 bits by adding multiples of G that cancel out terms in it.  (Adding
-# multiples of G doesn't change which field element the polynomial represents.)
-#
-# Unfortunately, the GCM specification maps bits to/from polynomial
-# coefficients backwards from the natural order.  In each byte it specifies the
-# highest bit to be the lowest order polynomial coefficient, *not* the highest!
-# This makes it nontrivial to work with the GHASH polynomials.  We could
-# reflect the bits, but x86 doesn't have an instruction that does that.
-#
-# Instead, we operate on the values without bit-reflecting them.  This *mostly*
-# just works, since XOR and carryless multiplication are symmetric with respect
-# to bit order, but it has some consequences.  First, due to GHASH's byte
-# order, by skipping bit reflection, *byte* reflection becomes necessary to
-# give the polynomial terms a consistent order.  E.g., considering an N-bit
-# value interpreted using the G = x^128 + x^7 + x^2 + x + 1 convention, bits 0
-# through N-1 of the byte-reflected value represent the coefficients of x^(N-1)
-# through x^0, whereas bits 0 through N-1 of the non-byte-reflected value
-# represent x^7...x^0, x^15...x^8, ..., x^(N-1)...x^(N-8) which can't be worked
-# with.  Fortunately, x86's vpshufb instruction can do byte reflection.
-#
-# Second, forgoing the bit reflection causes an extra multiple of x (still
-# using the G = x^128 + x^7 + x^2 + x + 1 convention) to be introduced by each
-# multiplication.  This is because an M-bit by N-bit carryless multiplication
-# really produces a (M+N-1)-bit product, but in practice it's zero-extended to
-# M+N bits.  In the G = x^128 + x^7 + x^2 + x + 1 convention, which maps bits
-# to polynomial coefficients backwards, this zero-extension actually changes
-# the product by introducing an extra factor of x.  Therefore, users of this
-# macro must ensure that one of the inputs has an extra factor of x^-1, i.e.
-# the multiplicative inverse of x, to cancel out the extra x.
-#
-# Third, the backwards coefficients convention is just confusing to work with,
-# since it makes "low" and "high" in the polynomial math mean the opposite of
-# their normal meaning in computer programming.  This can be solved by using an
-# alternative interpretation: the polynomial coefficients are understood to be
-# in the natural order, and the multiplication is actually \a * \b * x^-128 mod
-# x^128 + x^127 + x^126 + x^121 + 1.  This doesn't change the inputs, outputs,
-# or the implementation at all; it just changes the mathematical interpretation
-# of what each instruction is doing.  Starting from here, we'll use this
-# alternative interpretation, as it's easier to understand the code that way.
-#
-# Moving onto the implementation, the vpclmulqdq instruction does 64 x 64 =>
-# 128-bit carryless multiplication, so we break the 128 x 128 multiplication
-# into parts as follows (the _L and _H suffixes denote low and high 64 bits):
-#
-#     LO = a_L * b_L
-#     MI = (a_L * b_H) + (a_H * b_L)
-#     HI = a_H * b_H
-#
-# The 256-bit product is x^128*HI + x^64*MI + LO.  LO, MI, and HI are 128-bit.
-# Note that MI "overlaps" with LO and HI.  We don't consolidate MI into LO and
-# HI right away, since the way the reduction works makes that unnecessary.
-#
-# For the reduction, we cancel out the low 128 bits by adding multiples of G =
-# x^128 + x^127 + x^126 + x^121 + 1.  This is done by two iterations, each of
-# which cancels out the next lowest 64 bits.  Consider a value x^64*A + B,
-# where A and B are 128-bit.  Adding B_L*G to that value gives:
-#
-#       x^64*A + B + B_L*G
-#     = x^64*A + x^64*B_H + B_L + B_L*(x^128 + x^127 + x^126 + x^121 + 1)
-#     = x^64*A + x^64*B_H + B_L + x^128*B_L + x^64*B_L*(x^63 + x^62 + x^57) + B_L
-#     = x^64*A + x^64*B_H + x^128*B_L + x^64*B_L*(x^63 + x^62 + x^57) + B_L + B_L
-#     = x^64*(A + B_H + x^64*B_L + B_L*(x^63 + x^62 + x^57))
-#
-# So: if we sum A, B with its halves swapped, and the low half of B times x^63
-# + x^62 + x^57, we get a 128-bit value C where x^64*C is congruent to the
-# original value x^64*A + B.  I.e., the low 64 bits got canceled out.
-#
-# We just need to apply this twice: first to fold LO into MI, and second to
-# fold the updated MI into HI.
-#
-# The needed three-argument XORs are done using the vpternlogd instruction with
-# immediate 0x96, since this is faster than two vpxord instructions.
-#
-# A potential optimization, assuming that b is fixed per-key (if a is fixed
-# per-key it would work the other way around), is to use one iteration of the
-# reduction described above to precompute a value c such that x^64*c = b mod G,
-# and then multiply a_L by c (and implicitly by x^64) instead of by b:
-#
-#     MI = (a_L * c_L) + (a_H * b_L)
-#     HI = (a_L * c_H) + (a_H * b_H)
-#
-# This would eliminate the LO part of the intermediate product, which would
-# eliminate the need to fold LO into MI.  This would save two instructions,
-# including a vpclmulqdq.  However, we currently don't use this optimization
-# because it would require twice as many per-key precomputed values.
-#
-# Using Karatsuba multiplication instead of "schoolbook" multiplication
-# similarly would save a vpclmulqdq but does not seem to be worth it.
-sub _ghash_mul_step {
-    my ( $i, $a, $b, $dst, $gfpoly, $t0, $t1, $t2 ) = @_;
-    if ( $i == 0 ) {
-        return "vpclmulqdq \$0x00, $a, $b, $t0\n" .    # LO = a_L * b_L
-          "vpclmulqdq \$0x01, $a, $b, $t1\n";          # MI_0 = a_L * b_H
-    }
-    elsif ( $i == 1 ) {
-        return "vpclmulqdq \$0x10, $a, $b, $t2\n";     # MI_1 = a_H * b_L
-    }
-    elsif ( $i == 2 ) {
-        return "vpxord $t2, $t1, $t1\n";               # MI = MI_0 + MI_1
-    }
-    elsif ( $i == 3 ) {
-        return
-          "vpclmulqdq \$0x01, $t0, $gfpoly, $t2\n";  # LO_L*(x^63 + x^62 + x^57)
-    }
-    elsif ( $i == 4 ) {
-        return "vpshufd \$0x4e, $t0, $t0\n";         # Swap halves of LO
-    }
-    elsif ( $i == 5 ) {
-        return "vpternlogd \$0x96, $t2, $t0, $t1\n";    # Fold LO into MI
-    }
-    elsif ( $i == 6 ) {
-        return "vpclmulqdq \$0x11, $a, $b, $dst\n";     # HI = a_H * b_H
-    }
-    elsif ( $i == 7 ) {
-        return
-          "vpclmulqdq \$0x01, $t1, $gfpoly, $t0\n";  # MI_L*(x^63 + x^62 + x^57)
-    }
-    elsif ( $i == 8 ) {
-        return "vpshufd \$0x4e, $t1, $t1\n";         # Swap halves of MI
-    }
-    elsif ( $i == 9 ) {
-        return "vpternlogd \$0x96, $t0, $t1, $dst\n";    # Fold MI into HI
-    }
-}
-
-# GHASH-multiply the 128-bit lanes of \a by the 128-bit lanes of \b and store
-# the reduced products in \dst.  See _ghash_mul_step for full explanation.
-sub _ghash_mul {
-    my ( $a, $b, $dst, $gfpoly, $t0, $t1, $t2 ) = @_;
-    my $code = "";
-    for my $i ( 0 .. 9 ) {
-        $code .= _ghash_mul_step $i, $a, $b, $dst, $gfpoly, $t0, $t1, $t2;
-    }
-    return $code;
-}
-
-# GHASH-multiply the 128-bit lanes of \a by the 128-bit lanes of \b and add the
-# *unreduced* products to \lo, \mi, and \hi.
-sub _ghash_mul_noreduce {
-    my ( $a, $b, $lo, $mi, $hi, $t0, $t1, $t2, $t3 ) = @_;
-    return <<___;
-    vpclmulqdq      \$0x00, $a, $b, $t0      # a_L * b_L
-    vpclmulqdq      \$0x01, $a, $b, $t1      # a_L * b_H
-    vpclmulqdq      \$0x10, $a, $b, $t2      # a_H * b_L
-    vpclmulqdq      \$0x11, $a, $b, $t3      # a_H * b_H
-    vpxord          $t0, $lo, $lo
-    vpternlogd      \$0x96, $t2, $t1, $mi
-    vpxord          $t3, $hi, $hi
-___
-}
-
-# Reduce the unreduced products from \lo, \mi, and \hi and store the 128-bit
-# reduced products in \hi.  See _ghash_mul_step for explanation of reduction.
-sub _ghash_reduce {
-    my ( $lo, $mi, $hi, $gfpoly, $t0 ) = @_;
-    return <<___;
-    vpclmulqdq      \$0x01, $lo, $gfpoly, $t0
-    vpshufd         \$0x4e, $lo, $lo
-    vpternlogd      \$0x96, $t0, $lo, $mi
-    vpclmulqdq      \$0x01, $mi, $gfpoly, $t0
-    vpshufd         \$0x4e, $mi, $mi
-    vpternlogd      \$0x96, $t0, $mi, $hi
-___
-}
-
-$g_init_macro_expansion_count = 0;
-
-# void gcm_init_##suffix(u128 Htable[16], const uint64_t H[2]);
-#
-# Initialize |Htable| with powers of the GHASH subkey |H|.
-#
-# The powers are stored in the order H^NUM_H_POWERS to H^1.
-#
-# This macro supports both VL=32 and VL=64.  _set_veclen must have been invoked
-# with the desired length.  In the VL=32 case, the function computes twice as
-# many key powers than are actually used by the VL=32 GCM update functions.
-# This is done to keep the key format the same regardless of vector length.
-sub _aes_gcm_init {
-    my $local_label_suffix = "__func" . ++$g_init_macro_expansion_count;
-
-    # Function arguments
-    my ( $HTABLE, $H_PTR ) = @argregs[ 0 .. 1 ];
-
-    # Additional local variables.  V0-V2 and %rax are used as temporaries.
-    my $POWERS_PTR     = "%r8";
-    my $RNDKEYLAST_PTR = "%r9";
-    my ( $H_CUR, $H_CUR_YMM, $H_CUR_XMM )    = ( "$V3", "%ymm3", "%xmm3" );
-    my ( $H_INC, $H_INC_YMM, $H_INC_XMM )    = ( "$V4", "%ymm4", "%xmm4" );
-    my ( $GFPOLY, $GFPOLY_YMM, $GFPOLY_XMM ) = ( "$V5", "%ymm5", "%xmm5" );
-
-    my $code = <<___;
-    # Get pointer to lowest set of key powers (located at end of array).
-    lea             $OFFSETOFEND_H_POWERS-$VL($HTABLE), $POWERS_PTR
-
-    # Load the byte-reflected hash subkey.  BoringSSL provides it in
-    # byte-reflected form except the two halves are in the wrong order.
-    vpshufd         \$0x4e, ($H_PTR), $H_CUR_XMM
-
-    # Finish preprocessing the first key power, H^1.  Since this GHASH
-    # implementation operates directly on values with the backwards bit
-    # order specified by the GCM standard, it's necessary to preprocess the
-    # raw key as follows.  First, reflect its bytes.  Second, multiply it
-    # by x^-1 mod x^128 + x^7 + x^2 + x + 1 (if using the backwards
-    # interpretation of polynomial coefficients), which can also be
-    # interpreted as multiplication by x mod x^128 + x^127 + x^126 + x^121
-    # + 1 using the alternative, natural interpretation of polynomial
-    # coefficients.  For details, see the comment above _ghash_mul_step.
-    #
-    # Either way, for the multiplication the concrete operation performed
-    # is a left shift of the 128-bit value by 1 bit, then an XOR with (0xc2
-    # << 120) | 1 if a 1 bit was carried out.  However, there's no 128-bit
-    # wide shift instruction, so instead double each of the two 64-bit
-    # halves and incorporate the internal carry bit into the value XOR'd.
-    vpshufd         \$0xd3, $H_CUR_XMM, %xmm0
-    vpsrad          \$31, %xmm0, %xmm0
-    vpaddq          $H_CUR_XMM, $H_CUR_XMM, $H_CUR_XMM
-    # H_CUR_XMM ^= xmm0 & gfpoly_and_internal_carrybit
-    vpternlogd      \$0x78, .Lgfpoly_and_internal_carrybit(%rip), %xmm0, $H_CUR_XMM
-
-    # Load the gfpoly constant.
-    vbroadcasti32x4 .Lgfpoly(%rip), $GFPOLY
-
-    # Square H^1 to get H^2.
-    #
-    # Note that as with H^1, all higher key powers also need an extra
-    # factor of x^-1 (or x using the natural interpretation).  Nothing
-    # special needs to be done to make this happen, though: H^1 * H^1 would
-    # end up with two factors of x^-1, but the multiplication consumes one.
-    # So the product H^2 ends up with the desired one factor of x^-1.
-    @{[ _ghash_mul  $H_CUR_XMM, $H_CUR_XMM, $H_INC_XMM, $GFPOLY_XMM,
-                    "%xmm0", "%xmm1", "%xmm2" ]}
-
-    # Create H_CUR_YMM = [H^2, H^1] and H_INC_YMM = [H^2, H^2].
-    vinserti128     \$1, $H_CUR_XMM, $H_INC_YMM, $H_CUR_YMM
-    vinserti128     \$1, $H_INC_XMM, $H_INC_YMM, $H_INC_YMM
-___
-
-    if ( $VL == 64 ) {
-
-        # Create H_CUR = [H^4, H^3, H^2, H^1] and H_INC = [H^4, H^4, H^4, H^4].
-        $code .= <<___;
-        @{[ _ghash_mul  $H_INC_YMM, $H_CUR_YMM, $H_INC_YMM, $GFPOLY_YMM,
-                        "%ymm0", "%ymm1", "%ymm2" ]}
-        vinserti64x4    \$1, $H_CUR_YMM, $H_INC, $H_CUR
-        vshufi64x2      \$0, $H_INC, $H_INC, $H_INC
-___
-    }
-
-    $code .= <<___;
-    # Store the lowest set of key powers.
-    vmovdqu8        $H_CUR, ($POWERS_PTR)
-
-    # Compute and store the remaining key powers.  With VL=32, repeatedly
-    # multiply [H^(i+1), H^i] by [H^2, H^2] to get [H^(i+3), H^(i+2)].
-    # With VL=64, repeatedly multiply [H^(i+3), H^(i+2), H^(i+1), H^i] by
-    # [H^4, H^4, H^4, H^4] to get [H^(i+7), H^(i+6), H^(i+5), H^(i+4)].
-    mov             \$@{[ $NUM_H_POWERS*16/$VL - 1 ]}, %eax
-.Lprecompute_next$local_label_suffix:
-    sub             \$$VL, $POWERS_PTR
-    @{[ _ghash_mul  $H_INC, $H_CUR, $H_CUR, $GFPOLY, $V0, $V1, $V2 ]}
-    vmovdqu8        $H_CUR, ($POWERS_PTR)
-    dec             %eax
-    jnz             .Lprecompute_next$local_label_suffix
-
-    vzeroupper      # This is needed after using ymm or zmm registers.
-___
-    return $code;
-}
-
-# XOR together the 128-bit lanes of \src (whose low lane is \src_xmm) and store
-# the result in \dst_xmm.  This implicitly zeroizes the other lanes of dst.
-sub _horizontal_xor {
-    my ( $src, $src_xmm, $dst_xmm, $t0_xmm, $t1_xmm, $t2_xmm ) = @_;
-    if ( $VL == 32 ) {
-        return <<___;
-        vextracti32x4   \$1, $src, $t0_xmm
-        vpxord          $t0_xmm, $src_xmm, $dst_xmm
-___
-    }
-    elsif ( $VL == 64 ) {
-        return <<___;
-        vextracti32x4   \$1, $src, $t0_xmm
-        vextracti32x4   \$2, $src, $t1_xmm
-        vextracti32x4   \$3, $src, $t2_xmm
-        vpxord          $t0_xmm, $src_xmm, $dst_xmm
-        vpternlogd      \$0x96, $t1_xmm, $t2_xmm, $dst_xmm
-___
-    }
-    else {
-        die "Unsupported vector length";
-    }
-}
-
-# Do one step of the GHASH update of the data blocks given in the vector
-# registers GHASHDATA[0-3].  \i specifies the step to do, 0 through 9.  The
-# division into steps allows users of this macro to optionally interleave the
-# computation with other instructions.  This macro uses the vector register
-# GHASH_ACC as input/output; GHASHDATA[0-3] as inputs that are clobbered;
-# H_POW[4-1], GFPOLY, and BSWAP_MASK as inputs that aren't clobbered; and
-# GHASHTMP[0-2] as temporaries.  This macro handles the byte-reflection of the
-# data blocks.  The parameter registers must be preserved across steps.
-#
-# The GHASH update does: GHASH_ACC = H_POW4*(GHASHDATA0 + GHASH_ACC) +
-# H_POW3*GHASHDATA1 + H_POW2*GHASHDATA2 + H_POW1*GHASHDATA3, where the
-# operations are vectorized operations on vectors of 16-byte blocks.  E.g.,
-# with VL=32 there are 2 blocks per vector and the vectorized terms correspond
-# to the following non-vectorized terms:
-#
-#       H_POW4*(GHASHDATA0 + GHASH_ACC) => H^8*(blk0 + GHASH_ACC_XMM) and H^7*(blk1 + 0)
-#       H_POW3*GHASHDATA1 => H^6*blk2 and H^5*blk3
-#       H_POW2*GHASHDATA2 => H^4*blk4 and H^3*blk5
-#       H_POW1*GHASHDATA3 => H^2*blk6 and H^1*blk7
-#
-# With VL=64, we use 4 blocks/vector, H^16 through H^1, and blk0 through blk15.
-#
-# More concretely, this code does:
-#   - Do vectorized "schoolbook" multiplications to compute the intermediate
-#     256-bit product of each block and its corresponding hash key power.
-#     There are 4*VL/16 of these intermediate products.
-#   - Sum (XOR) the intermediate 256-bit products across vectors.  This leaves
-#     VL/16 256-bit intermediate values.
-#   - Do a vectorized reduction of these 256-bit intermediate values to
-#     128-bits each.  This leaves VL/16 128-bit intermediate values.
-#   - Sum (XOR) these values and store the 128-bit result in GHASH_ACC_XMM.
-#
-# See _ghash_mul_step for the full explanation of the operations performed for
-# each individual finite field multiplication and reduction.
-sub _ghash_step_4x {
-    my ($i) = @_;
-    if ( $i == 0 ) {
-        return <<___;
-        vpshufb         $BSWAP_MASK, $GHASHDATA0, $GHASHDATA0
-        vpxord          $GHASH_ACC, $GHASHDATA0, $GHASHDATA0
-        vpshufb         $BSWAP_MASK, $GHASHDATA1, $GHASHDATA1
-        vpshufb         $BSWAP_MASK, $GHASHDATA2, $GHASHDATA2
-___
-    }
-    elsif ( $i == 1 ) {
-        return <<___;
-        vpshufb         $BSWAP_MASK, $GHASHDATA3, $GHASHDATA3
-        vpclmulqdq      \$0x00, $H_POW4, $GHASHDATA0, $GHASH_ACC    # LO_0
-        vpclmulqdq      \$0x00, $H_POW3, $GHASHDATA1, $GHASHTMP0    # LO_1
-        vpclmulqdq      \$0x00, $H_POW2, $GHASHDATA2, $GHASHTMP1    # LO_2
-___
-    }
-    elsif ( $i == 2 ) {
-        return <<___;
-        vpxord          $GHASHTMP0, $GHASH_ACC, $GHASH_ACC          # sum(LO_{1,0})
-        vpclmulqdq      \$0x00, $H_POW1, $GHASHDATA3, $GHASHTMP2    # LO_3
-        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASH_ACC  # LO = sum(LO_{3,2,1,0})
-        vpclmulqdq      \$0x01, $H_POW4, $GHASHDATA0, $GHASHTMP0    # MI_0
-___
-    }
-    elsif ( $i == 3 ) {
-        return <<___;
-        vpclmulqdq      \$0x01, $H_POW3, $GHASHDATA1, $GHASHTMP1    # MI_1
-        vpclmulqdq      \$0x01, $H_POW2, $GHASHDATA2, $GHASHTMP2    # MI_2
-        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{2,1,0})
-        vpclmulqdq      \$0x01, $H_POW1, $GHASHDATA3, $GHASHTMP1    # MI_3
-___
-    }
-    elsif ( $i == 4 ) {
-        return <<___;
-        vpclmulqdq      \$0x10, $H_POW4, $GHASHDATA0, $GHASHTMP2    # MI_4
-        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{4,3,2,1,0})
-        vpclmulqdq      \$0x10, $H_POW3, $GHASHDATA1, $GHASHTMP1    # MI_5
-        vpclmulqdq      \$0x10, $H_POW2, $GHASHDATA2, $GHASHTMP2    # MI_6
-___
-    }
-    elsif ( $i == 5 ) {
-        return <<___;
-        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{6,5,4,3,2,1,0})
-        vpclmulqdq      \$0x01, $GHASH_ACC, $GFPOLY, $GHASHTMP2     # LO_L*(x^63 + x^62 + x^57)
-        vpclmulqdq      \$0x10, $H_POW1, $GHASHDATA3, $GHASHTMP1    # MI_7
-        vpxord          $GHASHTMP1, $GHASHTMP0, $GHASHTMP0          # MI = sum(MI_{7,6,5,4,3,2,1,0})
-___
-    }
-    elsif ( $i == 6 ) {
-        return <<___;
-        vpshufd         \$0x4e, $GHASH_ACC, $GHASH_ACC              # Swap halves of LO
-        vpclmulqdq      \$0x11, $H_POW4, $GHASHDATA0, $GHASHDATA0   # HI_0
-        vpclmulqdq      \$0x11, $H_POW3, $GHASHDATA1, $GHASHDATA1   # HI_1
-        vpclmulqdq      \$0x11, $H_POW2, $GHASHDATA2, $GHASHDATA2   # HI_2
-___
-    }
-    elsif ( $i == 7 ) {
-        return <<___;
-        vpternlogd      \$0x96, $GHASHTMP2, $GHASH_ACC, $GHASHTMP0  # Fold LO into MI
-        vpclmulqdq      \$0x11, $H_POW1, $GHASHDATA3, $GHASHDATA3   # HI_3
-        vpternlogd      \$0x96, $GHASHDATA2, $GHASHDATA1, $GHASHDATA0 # sum(HI_{2,1,0})
-        vpclmulqdq      \$0x01, $GHASHTMP0, $GFPOLY, $GHASHTMP1     # MI_L*(x^63 + x^62 + x^57)
-___
-    }
-    elsif ( $i == 8 ) {
-        return <<___;
-        vpxord          $GHASHDATA3, $GHASHDATA0, $GHASH_ACC        # HI = sum(HI_{3,2,1,0})
-        vpshufd         \$0x4e, $GHASHTMP0, $GHASHTMP0              # Swap halves of MI
-        vpternlogd      \$0x96, $GHASHTMP1, $GHASHTMP0, $GHASH_ACC  # Fold MI into HI
-___
-    }
-    elsif ( $i == 9 ) {
-        return _horizontal_xor $GHASH_ACC, $GHASH_ACC_XMM, $GHASH_ACC_XMM,
-          $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM;
-    }
-}
-
-# Update GHASH with the blocks given in GHASHDATA[0-3].
-# See _ghash_step_4x for full explanation.
-sub _ghash_4x {
-    my $code = "";
-    for my $i ( 0 .. 9 ) {
-        $code .= _ghash_step_4x $i;
-    }
-    return $code;
-}
-
-$g_ghash_macro_expansion_count = 0;
-
-# void gcm_ghash_##suffix(uint8_t Xi[16], const u128 Htable[16],
-#                         const uint8_t *in, size_t len);
-#
-# This macro generates the body of a GHASH update function with the above
-# prototype.  This macro supports both VL=32 and VL=64.  _set_veclen must have
-# been invoked with the desired length.
-#
-# The generated function processes the AAD (Additional Authenticated Data) in
-# GCM.  Using the key |Htable|, it updates the GHASH accumulator |Xi| with the
-# data given by |in| and |len|.  On the first call, |Xi| must be all zeroes.
-# |len| must be a multiple of 16.
-#
-# This function handles large amounts of AAD efficiently, while also keeping the
-# overhead low for small amounts of AAD which is the common case.  TLS uses less
-# than one block of AAD, but (uncommonly) other use cases may use much more.
-sub _ghash_update {
-    my $local_label_suffix = "__func" . ++$g_ghash_macro_expansion_count;
-    my $code               = "";
-
-    # Function arguments
-    my ( $GHASH_ACC_PTR, $H_POWERS, $AAD, $AADLEN ) = @argregs[ 0 .. 3 ];
-
-    # Additional local variables
-    ( $GHASHDATA0, $GHASHDATA0_XMM ) = ( $V0, "%xmm0" );
-    ( $GHASHDATA1, $GHASHDATA1_XMM ) = ( $V1, "%xmm1" );
-    ( $GHASHDATA2, $GHASHDATA2_XMM ) = ( $V2, "%xmm2" );
-    ( $GHASHDATA3, $GHASHDATA3_XMM ) = ( $V3, "%xmm3" );
-    ( $BSWAP_MASK, $BSWAP_MASK_XMM ) = ( $V4, "%xmm4" );
-    ( $GHASH_ACC,  $GHASH_ACC_XMM )  = ( $V5, "%xmm5" );
-    ( $H_POW4, $H_POW3, $H_POW2 )          = ( $V6, $V7, $V8 );
-    ( $H_POW1, $H_POW1_XMM )               = ( $V9, "%xmm9" );
-    ( $GFPOLY, $GFPOLY_XMM )               = ( $V10, "%xmm10" );
-    ( $GHASHTMP0, $GHASHTMP1, $GHASHTMP2 ) = ( $V11, $V12, $V13 );
-
-    $code .= <<___;
-    @{[ _save_xmmregs (6 .. 13) ]}
-    .seh_endprologue
-
-    # Load the bswap_mask and gfpoly constants.  Since AADLEN is usually small,
-    # usually only 128-bit vectors will be used.  So as an optimization, don't
-    # broadcast these constants to all 128-bit lanes quite yet.
-    vmovdqu         .Lbswap_mask(%rip), $BSWAP_MASK_XMM
-    vmovdqu         .Lgfpoly(%rip), $GFPOLY_XMM
-
-    # Load the GHASH accumulator.
-    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC_XMM
-    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-
-    # Optimize for AADLEN < VL by checking for AADLEN < VL before AADLEN < 4*VL.
-    cmp             \$$VL, $AADLEN
-    jb              .Laad_blockbyblock$local_label_suffix
-
-    # AADLEN >= VL, so we'll operate on full vectors.  Broadcast bswap_mask and
-    # gfpoly to all 128-bit lanes.
-    vshufi64x2      \$0, $BSWAP_MASK, $BSWAP_MASK, $BSWAP_MASK
-    vshufi64x2      \$0, $GFPOLY, $GFPOLY, $GFPOLY
-
-    # Load the lowest set of key powers.
-    vmovdqu8        $OFFSETOFEND_H_POWERS-1*$VL($H_POWERS), $H_POW1
-
-    cmp             \$4*$VL-1, $AADLEN
-    jbe             .Laad_loop_1x$local_label_suffix
-
-    # AADLEN >= 4*VL.  Load the higher key powers.
-    vmovdqu8        $OFFSETOFEND_H_POWERS-4*$VL($H_POWERS), $H_POW4
-    vmovdqu8        $OFFSETOFEND_H_POWERS-3*$VL($H_POWERS), $H_POW3
-    vmovdqu8        $OFFSETOFEND_H_POWERS-2*$VL($H_POWERS), $H_POW2
-
-    # Update GHASH with 4*VL bytes of AAD at a time.
-.Laad_loop_4x$local_label_suffix:
-    vmovdqu8        0*$VL($AAD), $GHASHDATA0
-    vmovdqu8        1*$VL($AAD), $GHASHDATA1
-    vmovdqu8        2*$VL($AAD), $GHASHDATA2
-    vmovdqu8        3*$VL($AAD), $GHASHDATA3
-    @{[ _ghash_4x ]}
-    sub             \$-4*$VL, $AAD  # shorter than 'add 4*VL' when VL=32
-    add             \$-4*$VL, $AADLEN
-    cmp             \$4*$VL-1, $AADLEN
-    ja              .Laad_loop_4x$local_label_suffix
-
-    # Update GHASH with VL bytes of AAD at a time.
-    cmp             \$$VL, $AADLEN
-    jb              .Laad_large_done$local_label_suffix
-.Laad_loop_1x$local_label_suffix:
-    vmovdqu8        ($AAD), $GHASHDATA0
-    vpshufb         $BSWAP_MASK, $GHASHDATA0, $GHASHDATA0
-    vpxord          $GHASHDATA0, $GHASH_ACC, $GHASH_ACC
-    @{[ _ghash_mul  $H_POW1, $GHASH_ACC, $GHASH_ACC, $GFPOLY,
-                    $GHASHDATA0, $GHASHDATA1, $GHASHDATA2 ]}
-    @{[ _horizontal_xor $GHASH_ACC, $GHASH_ACC_XMM, $GHASH_ACC_XMM,
-                        $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM ]}
-    add             \$$VL, $AAD
-    sub             \$$VL, $AADLEN
-    cmp             \$$VL, $AADLEN
-    jae             .Laad_loop_1x$local_label_suffix
-
-.Laad_large_done$local_label_suffix:
-    # Issue the vzeroupper that is needed after using ymm or zmm registers.
-    # Do it here instead of at the end, to minimize overhead for small AADLEN.
-    vzeroupper
-
-    # GHASH the remaining data 16 bytes at a time, using xmm registers only.
-.Laad_blockbyblock$local_label_suffix:
-    test            $AADLEN, $AADLEN
-    jz              .Laad_done$local_label_suffix
-    vmovdqu         $OFFSETOFEND_H_POWERS-16($H_POWERS), $H_POW1_XMM
-.Laad_loop_blockbyblock$local_label_suffix:
-    vmovdqu         ($AAD), $GHASHDATA0_XMM
-    vpshufb         $BSWAP_MASK_XMM, $GHASHDATA0_XMM, $GHASHDATA0_XMM
-    vpxor           $GHASHDATA0_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-    @{[ _ghash_mul  $H_POW1_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM, $GFPOLY_XMM,
-                    $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM ]}
-    add             \$16, $AAD
-    sub             \$16, $AADLEN
-    jnz             .Laad_loop_blockbyblock$local_label_suffix
-
-.Laad_done$local_label_suffix:
-    # Store the updated GHASH accumulator back to memory.
-    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-    vmovdqu         $GHASH_ACC_XMM, ($GHASH_ACC_PTR)
-___
-    return $code;
-}
-
-# Do one non-last round of AES encryption on the counter blocks in V0-V3 using
-# the round key that has been broadcast to all 128-bit lanes of \round_key.
-sub _vaesenc_4x {
-    my ($round_key) = @_;
-    return <<___;
-    vaesenc         $round_key, $V0, $V0
-    vaesenc         $round_key, $V1, $V1
-    vaesenc         $round_key, $V2, $V2
-    vaesenc         $round_key, $V3, $V3
-___
-}
-
-# Start the AES encryption of four vectors of counter blocks.
-sub _ctr_begin_4x {
-    return <<___;
-    # Increment LE_CTR four times to generate four vectors of little-endian
-    # counter blocks, swap each to big-endian, and store them in V0-V3.
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V0
-    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V1
-    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V2
-    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V3
-    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
-
-    # AES "round zero": XOR in the zero-th round key.
-    vpxord          $RNDKEY0, $V0, $V0
-    vpxord          $RNDKEY0, $V1, $V1
-    vpxord          $RNDKEY0, $V2, $V2
-    vpxord          $RNDKEY0, $V3, $V3
-___
-}
-
-# Do the last AES round for four vectors of counter blocks V0-V3, XOR source
-# data with the resulting keystream, and write the result to DST and
-# GHASHDATA[0-3].  (Implementation differs slightly, but has the same effect.)
-sub _aesenclast_and_xor_4x {
-    return <<___;
-    # XOR the source data with the last round key, saving the result in
-    # GHASHDATA[0-3].  This reduces latency by taking advantage of the
-    # property vaesenclast(key, a) ^ b == vaesenclast(key ^ b, a).
-    vpxord          0*$VL($SRC), $RNDKEYLAST, $GHASHDATA0
-    vpxord          1*$VL($SRC), $RNDKEYLAST, $GHASHDATA1
-    vpxord          2*$VL($SRC), $RNDKEYLAST, $GHASHDATA2
-    vpxord          3*$VL($SRC), $RNDKEYLAST, $GHASHDATA3
-
-    # Do the last AES round.  This handles the XOR with the source data
-    # too, as per the optimization described above.
-    vaesenclast     $GHASHDATA0, $V0, $GHASHDATA0
-    vaesenclast     $GHASHDATA1, $V1, $GHASHDATA1
-    vaesenclast     $GHASHDATA2, $V2, $GHASHDATA2
-    vaesenclast     $GHASHDATA3, $V3, $GHASHDATA3
-
-    # Store the en/decrypted data to DST.
-    vmovdqu8        $GHASHDATA0, 0*$VL($DST)
-    vmovdqu8        $GHASHDATA1, 1*$VL($DST)
-    vmovdqu8        $GHASHDATA2, 2*$VL($DST)
-    vmovdqu8        $GHASHDATA3, 3*$VL($DST)
-___
-}
-
-$g_update_macro_expansion_count = 0;
-
-# void aes_gcm_{enc,dec}_update_##suffix(const uint8_t *in, uint8_t *out,
-#                                        size_t len, const AES_KEY *key,
-#                                        const uint8_t ivec[16],
-#                                        const u128 Htable[16],
-#                                        uint8_t Xi[16]);
-#
-# This macro generates a GCM encryption or decryption update function with the
-# above prototype (with \enc selecting which one).  This macro supports both
-# VL=32 and VL=64.  _set_veclen must have been invoked with the desired length.
-#
-# This function computes the next portion of the CTR keystream, XOR's it with
-# |len| bytes from |in|, and writes the resulting encrypted or decrypted data
-# to |out|.  It also updates the GHASH accumulator |Xi| using the next |len|
-# ciphertext bytes.
-#
-# |len| must be a multiple of 16, except on the last call where it can be any
-# length.  The caller must do any buffering needed to ensure this.  Both
-# in-place and out-of-place en/decryption are supported.
-#
-# |ivec| must give the current counter in big-endian format.  This function
-# loads the counter from |ivec| and increments the loaded counter as needed, but
-# it does *not* store the updated counter back to |ivec|.  The caller must
-# update |ivec| if any more data segments follow.  Internally, only the low
-# 32-bit word of the counter is incremented, following the GCM standard.
-sub _aes_gcm_update {
-    my $local_label_suffix = "__func" . ++$g_update_macro_expansion_count;
-
-    my ($enc) = @_;
-
-    my $code = "";
-
-    # Function arguments
-    ( $SRC, $DST, $DATALEN, $AESKEY, $BE_CTR_PTR, $H_POWERS, $GHASH_ACC_PTR ) =
-      $win64
-      ? ( @argregs[ 0 .. 3 ], "%rsi", "%rdi", "%r12" )
-      : ( @argregs[ 0 .. 5 ], "%r12" );
-
-    # Additional local variables
-
-    # %rax, %k1, and %k2 are used as temporary registers.  BE_CTR_PTR is
-    # also available as a temporary register after the counter is loaded.
-
-    # AES key length in bytes
-    ( $AESKEYLEN, $AESKEYLEN64 ) = ( "%r10d", "%r10" );
-
-    # Pointer to the last AES round key for the chosen AES variant
-    $RNDKEYLAST_PTR = "%r11";
-
-    # In the main loop, V0-V3 are used as AES input and output.  Elsewhere
-    # they are used as temporary registers.
-
-    # GHASHDATA[0-3] hold the ciphertext blocks and GHASH input data.
-    ( $GHASHDATA0, $GHASHDATA0_XMM ) = ( $V4, "%xmm4" );
-    ( $GHASHDATA1, $GHASHDATA1_XMM ) = ( $V5, "%xmm5" );
-    ( $GHASHDATA2, $GHASHDATA2_XMM ) = ( $V6, "%xmm6" );
-    ( $GHASHDATA3, $GHASHDATA3_XMM ) = ( $V7, "%xmm7" );
-
-    # BSWAP_MASK is the shuffle mask for byte-reflecting 128-bit values
-    # using vpshufb, copied to all 128-bit lanes.
-    ( $BSWAP_MASK, $BSWAP_MASK_XMM ) = ( $V8, "%xmm8" );
-
-    # RNDKEY temporarily holds the next AES round key.
-    $RNDKEY = $V9;
-
-    # GHASH_ACC is the accumulator variable for GHASH.  When fully reduced,
-    # only the lowest 128-bit lane can be nonzero.  When not fully reduced,
-    # more than one lane may be used, and they need to be XOR'd together.
-    ( $GHASH_ACC, $GHASH_ACC_XMM ) = ( $V10, "%xmm10" );
-
-    # LE_CTR_INC is the vector of 32-bit words that need to be added to a
-    # vector of little-endian counter blocks to advance it forwards.
-    $LE_CTR_INC = $V11;
-
-    # LE_CTR contains the next set of little-endian counter blocks.
-    $LE_CTR = $V12;
-
-    # RNDKEY0, RNDKEYLAST, and RNDKEY_M[9-1] contain cached AES round keys,
-    # copied to all 128-bit lanes.  RNDKEY0 is the zero-th round key,
-    # RNDKEYLAST the last, and RNDKEY_M\i the one \i-th from the last.
-    (
-        $RNDKEY0,   $RNDKEYLAST, $RNDKEY_M9, $RNDKEY_M8,
-        $RNDKEY_M7, $RNDKEY_M6,  $RNDKEY_M5, $RNDKEY_M4,
-        $RNDKEY_M3, $RNDKEY_M2,  $RNDKEY_M1
-    ) = ( $V13, $V14, $V15, $V16, $V17, $V18, $V19, $V20, $V21, $V22, $V23 );
-
-    # GHASHTMP[0-2] are temporary variables used by _ghash_step_4x.  These
-    # cannot coincide with anything used for AES encryption, since for
-    # performance reasons GHASH and AES encryption are interleaved.
-    ( $GHASHTMP0, $GHASHTMP1, $GHASHTMP2 ) = ( $V24, $V25, $V26 );
-
-    # H_POW[4-1] contain the powers of the hash key H^(4*VL/16)...H^1.  The
-    # descending numbering reflects the order of the key powers.
-    ( $H_POW4, $H_POW3, $H_POW2, $H_POW1 ) = ( $V27, $V28, $V29, $V30 );
-
-    # GFPOLY contains the .Lgfpoly constant, copied to all 128-bit lanes.
-    $GFPOLY = $V31;
-
-    if ($win64) {
-        $code .= <<___;
-        @{[ _save_gpregs $BE_CTR_PTR, $H_POWERS, $GHASH_ACC_PTR ]}
-        mov             64(%rsp), $BE_CTR_PTR     # arg5
-        mov             72(%rsp), $H_POWERS       # arg6
-        mov             80(%rsp), $GHASH_ACC_PTR  # arg7
-        @{[ _save_xmmregs (6 .. 15) ]}
-        .seh_endprologue
-___
-    }
-    else {
-        $code .= <<___;
-        @{[ _save_gpregs $GHASH_ACC_PTR ]}
-        mov             16(%rsp), $GHASH_ACC_PTR  # arg7
-___
-    }
-
-    if ($enc) {
-        $code .= <<___;
-#ifdef BORINGSSL_DISPATCH_TEST
-        .extern BORINGSSL_function_hit
-        movb \$1,BORINGSSL_function_hit+@{[ $VL < 64 ? 6 : 7 ]}(%rip)
-#endif
-___
-    }
-    $code .= <<___;
-    # Load some constants.
-    vbroadcasti32x4 .Lbswap_mask(%rip), $BSWAP_MASK
-    vbroadcasti32x4 .Lgfpoly(%rip), $GFPOLY
-
-    # Load the GHASH accumulator and the starting counter.
-    # BoringSSL passes these values in big endian format.
-    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC_XMM
-    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-    vbroadcasti32x4 ($BE_CTR_PTR), $LE_CTR
-    vpshufb         $BSWAP_MASK, $LE_CTR, $LE_CTR
-
-    # Load the AES key length in bytes.  BoringSSL stores number of rounds
-    # minus 1, so convert using: AESKEYLEN = 4 * aeskey->rounds - 20.
-    movl            $OFFSETOF_AES_ROUNDS($AESKEY), $AESKEYLEN
-    lea             -20(,$AESKEYLEN,4), $AESKEYLEN
-
-    # Make RNDKEYLAST_PTR point to the last AES round key.  This is the
-    # round key with index 10, 12, or 14 for AES-128, AES-192, or AES-256
-    # respectively.  Then load the zero-th and last round keys.
-    lea             6*16($AESKEY,$AESKEYLEN64,4), $RNDKEYLAST_PTR
-    vbroadcasti32x4 ($AESKEY), $RNDKEY0
-    vbroadcasti32x4 ($RNDKEYLAST_PTR), $RNDKEYLAST
-
-    # Finish initializing LE_CTR by adding [0, 1, ...] to its low words.
-    vpaddd          .Lctr_pattern(%rip), $LE_CTR, $LE_CTR
-
-    # Initialize LE_CTR_INC to contain VL/16 in all 128-bit lanes.
-    vbroadcasti32x4 .Linc_@{[ $VL / 16 ]}blocks(%rip), $LE_CTR_INC
-
-    # If there are at least 4*VL bytes of data, then continue into the loop
-    # that processes 4*VL bytes of data at a time.  Otherwise skip it.
-    cmp             \$4*$VL-1, $DATALEN
-    jbe             .Lcrypt_loop_4x_done$local_label_suffix
-
-    # Load powers of the hash key.
-    vmovdqu8        $OFFSETOFEND_H_POWERS-4*$VL($H_POWERS), $H_POW4
-    vmovdqu8        $OFFSETOFEND_H_POWERS-3*$VL($H_POWERS), $H_POW3
-    vmovdqu8        $OFFSETOFEND_H_POWERS-2*$VL($H_POWERS), $H_POW2
-    vmovdqu8        $OFFSETOFEND_H_POWERS-1*$VL($H_POWERS), $H_POW1
-___
-
-    # Main loop: en/decrypt and hash 4 vectors at a time.
-    #
-    # When possible, interleave the AES encryption of the counter blocks
-    # with the GHASH update of the ciphertext blocks.  This improves
-    # performance on many CPUs because the execution ports used by the VAES
-    # instructions often differ from those used by vpclmulqdq and other
-    # instructions used in GHASH.  For example, many Intel CPUs dispatch
-    # vaesenc to ports 0 and 1 and vpclmulqdq to port 5.
-    #
-    # The interleaving is easiest to do during decryption, since during
-    # decryption the ciphertext blocks are immediately available.  For
-    # encryption, instead encrypt the first set of blocks, then hash those
-    # blocks while encrypting the next set of blocks, repeat that as
-    # needed, and finally hash the last set of blocks.
-
-    if ($enc) {
-        $code .= <<___;
-        # Encrypt the first 4 vectors of plaintext blocks.  Leave the resulting
-        # ciphertext in GHASHDATA[0-3] for GHASH.
-        @{[ _ctr_begin_4x ]}
-        lea             16($AESKEY), %rax
-.Lvaesenc_loop_first_4_vecs$local_label_suffix:
-        vbroadcasti32x4 (%rax), $RNDKEY
-        @{[ _vaesenc_4x $RNDKEY ]}
-        add             \$16, %rax
-        cmp             %rax, $RNDKEYLAST_PTR
-        jne             .Lvaesenc_loop_first_4_vecs$local_label_suffix
-        @{[ _aesenclast_and_xor_4x ]}
-        sub             \$-4*$VL, $SRC  # shorter than 'add 4*VL' when VL=32
-        sub             \$-4*$VL, $DST
-        add             \$-4*$VL, $DATALEN
-        cmp             \$4*$VL-1, $DATALEN
-        jbe             .Lghash_last_ciphertext_4x$local_label_suffix
-___
-    }
-
-    # Cache as many additional AES round keys as possible.
-    for my $i ( reverse 1 .. 9 ) {
-        $code .= <<___;
-        vbroadcasti32x4 -$i*16($RNDKEYLAST_PTR), ${"RNDKEY_M$i"}
-___
-    }
-
-    $code .= <<___;
-.Lcrypt_loop_4x$local_label_suffix:
-___
-
-    # If decrypting, load more ciphertext blocks into GHASHDATA[0-3].  If
-    # encrypting, GHASHDATA[0-3] already contain the previous ciphertext.
-    if ( !$enc ) {
-        $code .= <<___;
-        vmovdqu8        0*$VL($SRC), $GHASHDATA0
-        vmovdqu8        1*$VL($SRC), $GHASHDATA1
-        vmovdqu8        2*$VL($SRC), $GHASHDATA2
-        vmovdqu8        3*$VL($SRC), $GHASHDATA3
-___
-    }
-
-    $code .= <<___;
-    # Start the AES encryption of the counter blocks.
-    @{[ _ctr_begin_4x ]}
-    cmp             \$24, $AESKEYLEN
-    jl              .Laes128$local_label_suffix
-    je              .Laes192$local_label_suffix
-    # AES-256
-    vbroadcasti32x4 -13*16($RNDKEYLAST_PTR), $RNDKEY
-    @{[ _vaesenc_4x $RNDKEY ]}
-    vbroadcasti32x4 -12*16($RNDKEYLAST_PTR), $RNDKEY
-    @{[ _vaesenc_4x $RNDKEY ]}
-.Laes192$local_label_suffix:
-    vbroadcasti32x4 -11*16($RNDKEYLAST_PTR), $RNDKEY
-    @{[ _vaesenc_4x $RNDKEY ]}
-    vbroadcasti32x4 -10*16($RNDKEYLAST_PTR), $RNDKEY
-    @{[ _vaesenc_4x $RNDKEY ]}
-.Laes128$local_label_suffix:
-___
-
-    # Prefetch the source data 512 bytes ahead into the L1 data cache, to
-    # improve performance when the hardware prefetcher is disabled.  Assumes the
-    # L1 data cache line size is 64 bytes (de facto standard on x86_64).
-    for ( my $i = 0 ; $i < 4 * $VL ; $i += 64 ) {
-        $code .= "prefetcht0  512+$i($SRC)\n";
-    }
-
-    # Finish the AES encryption of the counter blocks in V0-V3, interleaved
-    # with the GHASH update of the ciphertext blocks in GHASHDATA[0-3].
-    for my $i ( reverse 1 .. 9 ) {
-        $code .= <<___;
-        @{[ _ghash_step_4x  (9 - $i) ]}
-        @{[ _vaesenc_4x     ${"RNDKEY_M$i"} ]}
-___
-    }
-    $code .= <<___;
-    @{[ _ghash_step_4x  9 ]}
-    @{[ _aesenclast_and_xor_4x ]}
-    sub             \$-4*$VL, $SRC  # shorter than 'add 4*VL' when VL=32
-    sub             \$-4*$VL, $DST
-    add             \$-4*$VL, $DATALEN
-    cmp             \$4*$VL-1, $DATALEN
-    ja              .Lcrypt_loop_4x$local_label_suffix
-___
-
-    if ($enc) {
-
-        # Update GHASH with the last set of ciphertext blocks.
-        $code .= <<___;
-.Lghash_last_ciphertext_4x$local_label_suffix:
-        @{[ _ghash_4x ]}
-___
-    }
-
-    my $POWERS_PTR = $BE_CTR_PTR;    # BE_CTR_PTR is free to be reused.
-
-    $code .= <<___;
-.Lcrypt_loop_4x_done$local_label_suffix:
-    # Check whether any data remains.
-    test            $DATALEN, $DATALEN
-    jz              .Ldone$local_label_suffix
-
-    # The data length isn't a multiple of 4*VL.  Process the remaining data
-    # of length 1 <= DATALEN < 4*VL, up to one vector (VL bytes) at a time.
-    # Going one vector at a time may seem inefficient compared to having
-    # separate code paths for each possible number of vectors remaining.
-    # However, using a loop keeps the code size down, and it performs
-    # surprising well; modern CPUs will start executing the next iteration
-    # before the previous one finishes and also predict the number of loop
-    # iterations.  For a similar reason, we roll up the AES rounds.
-    #
-    # On the last iteration, the remaining length may be less than VL.
-    # Handle this using masking.
-    #
-    # Since there are enough key powers available for all remaining data,
-    # there is no need to do a GHASH reduction after each iteration.
-    # Instead, multiply each remaining block by its own key power, and only
-    # do a GHASH reduction at the very end.
-
-    # Make POWERS_PTR point to the key powers [H^N, H^(N-1), ...] where N
-    # is the number of blocks that remain.
-    mov             $DATALEN, %rax
-    neg             %rax
-    and             \$-16, %rax  # -round_up(DATALEN, 16)
-    lea             $OFFSETOFEND_H_POWERS($H_POWERS,%rax), $POWERS_PTR
-___
-
-    # Start collecting the unreduced GHASH intermediate value LO, MI, HI.
-    my ( $LO, $LO_XMM ) = ( $GHASHDATA0, $GHASHDATA0_XMM );
-    my ( $MI, $MI_XMM ) = ( $GHASHDATA1, $GHASHDATA1_XMM );
-    my ( $HI, $HI_XMM ) = ( $GHASHDATA2, $GHASHDATA2_XMM );
-    $code .= <<___;
-    vpxor           $LO_XMM, $LO_XMM, $LO_XMM
-    vpxor           $MI_XMM, $MI_XMM, $MI_XMM
-    vpxor           $HI_XMM, $HI_XMM, $HI_XMM
-
-    cmp             \$$VL, $DATALEN
-    jb              .Lpartial_vec$local_label_suffix
-
-.Lcrypt_loop_1x$local_label_suffix:
-    # Process a full vector of length VL.
-
-    # Encrypt a vector of counter blocks.
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V0
-    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
-    vpxord          $RNDKEY0, $V0, $V0
-    lea             16($AESKEY), %rax
-.Lvaesenc_loop_tail_full_vec$local_label_suffix:
-    vbroadcasti32x4 (%rax), $RNDKEY
-    vaesenc         $RNDKEY, $V0, $V0
-    add             \$16, %rax
-    cmp             %rax, $RNDKEYLAST_PTR
-    jne             .Lvaesenc_loop_tail_full_vec$local_label_suffix
-    vaesenclast     $RNDKEYLAST, $V0, $V0
-
-    # XOR the data with the vector of keystream blocks.
-    vmovdqu8        ($SRC), $V1
-    vpxord          $V1, $V0, $V0
-    vmovdqu8        $V0, ($DST)
-
-    # Update GHASH with the ciphertext blocks, without reducing.
-    vmovdqu8        ($POWERS_PTR), $H_POW1
-    vpshufb         $BSWAP_MASK, @{[ $enc ? $V0 : $V1 ]}, $V0
-    vpxord          $GHASH_ACC, $V0, $V0
-    @{[ _ghash_mul_noreduce $H_POW1, $V0, $LO, $MI, $HI, $GHASHDATA3,
-                            $V1, $V2, $V3 ]}
-    vpxor           $GHASH_ACC_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-
-    add             \$$VL, $POWERS_PTR
-    add             \$$VL, $SRC
-    add             \$$VL, $DST
-    sub             \$$VL, $DATALEN
-    cmp             \$$VL, $DATALEN
-    jae             .Lcrypt_loop_1x$local_label_suffix
-
-    test            $DATALEN, $DATALEN
-    jz              .Lreduce$local_label_suffix
-
-.Lpartial_vec$local_label_suffix:
-    # Process a partial vector of length 1 <= DATALEN < VL.
-
-    # Set the data mask %k1 to DATALEN 1's.
-    # Set the key powers mask %k2 to round_up(DATALEN, 16) 1's.
-    mov             \$-1, %rax
-    bzhi            $DATALEN, %rax, %rax
-    @{[ $VL < 64 ? "kmovd %eax, %k1" : "kmovq %rax, %k1" ]}
-    add             \$15, $DATALEN
-    and             \$-16, $DATALEN
-    mov             \$-1, %rax
-    bzhi            $DATALEN, %rax, %rax
-    @{[ $VL < 64 ? "kmovd %eax, %k2" : "kmovq %rax, %k2" ]}
-
-    # Encrypt one last vector of counter blocks.  This does not need to be
-    # masked.  The counter does not need to be incremented here.
-    vpshufb         $BSWAP_MASK, $LE_CTR, $V0
-    vpxord          $RNDKEY0, $V0, $V0
-    lea             16($AESKEY), %rax
-.Lvaesenc_loop_tail_partialvec$local_label_suffix:
-    vbroadcasti32x4 (%rax), $RNDKEY
-    vaesenc         $RNDKEY, $V0, $V0
-    add             \$16, %rax
-    cmp             %rax, $RNDKEYLAST_PTR
-    jne             .Lvaesenc_loop_tail_partialvec$local_label_suffix
-    vaesenclast     $RNDKEYLAST, $V0, $V0
-
-    # XOR the data with the appropriate number of keystream bytes.
-    vmovdqu8        ($SRC), $V1\{%k1}{z}
-    vpxord          $V1, $V0, $V0
-    vmovdqu8        $V0, ($DST){%k1}
-
-    # Update GHASH with the ciphertext block(s), without reducing.
-    #
-    # In the case of DATALEN < VL, the ciphertext is zero-padded to VL.
-    # (If decrypting, it's done by the above masked load.  If encrypting,
-    # it's done by the below masked register-to-register move.)  Note that
-    # if DATALEN <= VL - 16, there will be additional padding beyond the
-    # padding of the last block specified by GHASH itself; i.e., there may
-    # be whole block(s) that get processed by the GHASH multiplication and
-    # reduction instructions but should not actually be included in the
-    # GHASH.  However, any such blocks are all-zeroes, and the values that
-    # they're multiplied with are also all-zeroes.  Therefore they just add
-    # 0 * 0 = 0 to the final GHASH result, which makes no difference.
-    vmovdqu8        ($POWERS_PTR), $H_POW1\{%k2}{z}
-    @{[ $enc ? "vmovdqu8 $V0, $V1\{%k1}{z}" : "" ]}
-    vpshufb         $BSWAP_MASK, $V1, $V0
-    vpxord          $GHASH_ACC, $V0, $V0
-    @{[ _ghash_mul_noreduce $H_POW1, $V0, $LO, $MI, $HI, $GHASHDATA3,
-                            $V1, $V2, $V3 ]}
-
-.Lreduce$local_label_suffix:
-    # Finally, do the GHASH reduction.
-    @{[ _ghash_reduce   $LO, $MI, $HI, $GFPOLY, $V0 ]}
-    @{[ _horizontal_xor $HI, $HI_XMM, $GHASH_ACC_XMM,
-                        "%xmm0", "%xmm1", "%xmm2" ]}
-
-.Ldone$local_label_suffix:
-    # Store the updated GHASH accumulator back to memory.
-    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-    vmovdqu         $GHASH_ACC_XMM, ($GHASH_ACC_PTR)
-
-    vzeroupper      # This is needed after using ymm or zmm registers.
-___
-    return $code;
-}
-
-# void gcm_gmult_vpclmulqdq_avx10(uint8_t Xi[16], const u128 Htable[16]);
-$code .= _begin_func "gcm_gmult_vpclmulqdq_avx10", 1;
-{
-    my ( $GHASH_ACC_PTR, $H_POWERS ) = @argregs[ 0 .. 1 ];
-    my ( $GHASH_ACC, $BSWAP_MASK, $H_POW1, $GFPOLY, $T0, $T1, $T2 ) =
-      map( "%xmm$_", ( 0 .. 6 ) );
-
-    $code .= <<___;
-    @{[ _save_xmmregs (6) ]}
-    .seh_endprologue
-
-    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC
-    vmovdqu         .Lbswap_mask(%rip), $BSWAP_MASK
-    vmovdqu         $OFFSETOFEND_H_POWERS-16($H_POWERS), $H_POW1
-    vmovdqu         .Lgfpoly(%rip), $GFPOLY
-    vpshufb         $BSWAP_MASK, $GHASH_ACC, $GHASH_ACC
-
-    @{[ _ghash_mul  $H_POW1, $GHASH_ACC, $GHASH_ACC, $GFPOLY, $T0, $T1, $T2 ]}
-
-    vpshufb         $BSWAP_MASK, $GHASH_ACC, $GHASH_ACC
-    vmovdqu         $GHASH_ACC, ($GHASH_ACC_PTR)
-___
-}
-$code .= _end_func;
-
-# Disabled until significant deployment of AVX10/256 is seen.  The separate
-# *_vaes_avx2 implementation provides the only 256-bit support for now.
-#
-# $code .= _begin_func "gcm_init_vpclmulqdq_avx10_256", 0;
-# $code .= _aes_gcm_init;
-# $code .= _end_func;
-#
-# $code .= _begin_func "gcm_ghash_vpclmulqdq_avx10_256", 1;
-# $code .= _ghash_update;
-# $code .= _end_func;
-#
-# $code .= _begin_func "aes_gcm_enc_update_vaes_avx10_256", 1;
-# $code .= _aes_gcm_update 1;
-# $code .= _end_func;
-#
-# $code .= _begin_func "aes_gcm_dec_update_vaes_avx10_256", 1;
-# $code .= _aes_gcm_update 0;
-# $code .= _end_func;
-
-_set_veclen 64;
-
-$code .= _begin_func "gcm_init_vpclmulqdq_avx10_512", 0;
-$code .= _aes_gcm_init;
-$code .= _end_func;
-
-$code .= _begin_func "gcm_ghash_vpclmulqdq_avx10_512", 1;
-$code .= _ghash_update;
-$code .= _end_func;
-
-$code .= _begin_func "aes_gcm_enc_update_vaes_avx10_512", 1;
-$code .= _aes_gcm_update 1;
-$code .= _end_func;
-
-$code .= _begin_func "aes_gcm_dec_update_vaes_avx10_512", 1;
-$code .= _aes_gcm_update 0;
-$code .= _end_func;
-
-print $code;
-close STDOUT or die "error closing STDOUT: $!";
-exit 0;
diff --git a/src/crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl b/src/crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl
index ebbd0dd..23ec5da 100644
--- a/src/crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl
+++ b/src/crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl
@@ -15,14 +15,15 @@
 #
 #------------------------------------------------------------------------------
 #
-# VAES and VPCLMULQDQ optimized AES-GCM for x86_64 (AVX2 version)
+# This is an AES-GCM implementation for x86_64 CPUs that support the following
+# CPU features: VAES && VPCLMULQDQ && AVX2.
 #
-# This is similar to aes-gcm-avx10-x86_64.pl, but it uses AVX2 instead of AVX512
-# / AVX10.  This means it can only use 16 vector registers instead of 32, the
+# This is similar to aes-gcm-avx512-x86_64.pl, but it uses AVX2 instead of
+# AVX512.  This means it can only use 16 vector registers instead of 32, the
 # maximum vector length is 32 bytes, and some instructions such as vpternlogd
 # and masked loads/stores are unavailable.  However, it is able to run on CPUs
-# that have VAES without AVX512 / AVX10, namely AMD Zen 3 (including "Milan"
-# server processors) and some Intel client CPUs such as Alder Lake.
+# that have VAES without AVX512, namely AMD Zen 3 (including "Milan" server
+# processors) and some Intel client CPUs such as Alder Lake.
 #
 # This implementation also uses Karatsuba multiplication instead of schoolbook
 # multiplication for GHASH in its main loop.  This does not help much on Intel,
@@ -121,7 +122,7 @@
         for my $i ( 0 .. $num_xmmregs - 1 ) {
             my $reg_num = $xmmregs[$i];
             my $pos     = 16 * $i;
-            $code .= "movdqa %xmm$reg_num, $pos(%rsp)\n";
+            $code .= "vmovdqa %xmm$reg_num, $pos(%rsp)\n";
             $code .= ".seh_savexmm %xmm$reg_num, $pos\n";
         }
     }
@@ -139,7 +140,7 @@
         for my $i ( 0 .. $num_xmmregs - 1 ) {
             my $reg_num = $g_cur_func_saved_xmmregs[$i];
             my $pos     = 16 * $i;
-            $code .= "movdqa $pos(%rsp), %xmm$reg_num\n";
+            $code .= "vmovdqa $pos(%rsp), %xmm$reg_num\n";
         }
         $code .= "add \$$alloc_size, %rsp\n";
     }
@@ -226,6 +227,23 @@
 ___
 }
 
+# This is a specialized version of _ghash_mul that computes \a * \a, i.e. it
+# squares \a.  It skips computing MI = (a_L * a_H) + (a_H * a_L) = 0.
+sub _ghash_square {
+    my ( $a, $dst, $gfpoly, $t0, $t1 ) = @_;
+    return <<___;
+    vpclmulqdq      \$0x00, $a, $a, $t0        # LO = a_L * a_L
+    vpclmulqdq      \$0x11, $a, $a, $dst       # HI = a_H * a_H
+    vpclmulqdq      \$0x01, $t0, $gfpoly, $t1  # LO_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t0, $t0           # Swap halves of LO
+    vpxor           $t0, $t1, $t1              # Fold LO into MI
+    vpclmulqdq      \$0x01, $t1, $gfpoly, $t0  # MI_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t1, $t1           # Swap halves of MI
+    vpxor           $t1, $dst, $dst            # Fold MI into HI (part 1)
+    vpxor           $t0, $dst, $dst            # Fold MI into HI (part 2)
+___
+}
+
 # void gcm_init_vpclmulqdq_avx2(u128 Htable[16], const uint64_t H[2]);
 #
 # Initialize |Htable| with powers of the GHASH subkey |H|.
@@ -265,8 +283,8 @@
     vbroadcasti128  .Lgfpoly(%rip), $GFPOLY
 
     # Square H^1 to get H^2.
-    @{[ _ghash_mul  $H_CUR_XMM, $H_CUR_XMM, $H_INC_XMM, $GFPOLY_XMM,
-                    $TMP0_XMM, $TMP1_XMM, $TMP2_XMM ]}
+    @{[ _ghash_square  $H_CUR_XMM, $H_INC_XMM, $GFPOLY_XMM,
+                       $TMP0_XMM, $TMP1_XMM ]}
 
     # Create H_CUR = [H^2, H^1] and H_INC = [H^2, H^2].
     vinserti128     \$1, $H_CUR_XMM, $H_INC, $H_CUR
@@ -456,6 +474,8 @@
 
     vpshufb         $BSWAP_MASK, $GHASH_ACC, $GHASH_ACC
     vmovdqu         $GHASH_ACC, ($GHASH_ACC_PTR)
+
+    # No need for vzeroupper, since only xmm registers were used.
 ___
 }
 $code .= _end_func;
@@ -490,15 +510,25 @@
     @{[ _save_xmmregs (6 .. 9) ]}
     .seh_endprologue
 
-    vbroadcasti128  .Lbswap_mask(%rip), $BSWAP_MASK
+    # Load the bswap_mask and gfpoly constants.  Since AADLEN is usually small,
+    # usually only 128-bit vectors will be used.  So as an optimization, don't
+    # broadcast these constants to both 128-bit lanes quite yet.
+    vmovdqu         .Lbswap_mask(%rip), $BSWAP_MASK_XMM
+    vmovdqu         .Lgfpoly(%rip), $GFPOLY_XMM
+
+    # Load the GHASH accumulator.
     vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC_XMM
     vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
-    vbroadcasti128  .Lgfpoly(%rip), $GFPOLY
 
     # Optimize for AADLEN < 32 by checking for AADLEN < 32 before AADLEN < 128.
     cmp             \$32, $AADLEN
     jb              .Lghash_lastblock
 
+    # AADLEN >= 32, so we'll operate on full vectors.  Broadcast bswap_mask and
+    # gfpoly to both 128-bit lanes.
+    vinserti128     \$1, $BSWAP_MASK_XMM, $BSWAP_MASK, $BSWAP_MASK
+    vinserti128     \$1, $GFPOLY_XMM, $GFPOLY, $GFPOLY
+
     cmp             \$127, $AADLEN
     jbe             .Lghash_loop_1x
 
@@ -530,9 +560,6 @@
     cmp             \$32, $AADLEN
     jae             .Lghash_loop_1x
 .Lghash_loop_1x_done:
-    # Issue the vzeroupper that is needed after using ymm registers.  Do it here
-    # instead of at the end, to minimize overhead for small AADLEN.
-    vzeroupper
 
     # Update GHASH with the remaining 16-byte block if any.
 .Lghash_lastblock:
@@ -549,6 +576,8 @@
     # Store the updated GHASH accumulator back to memory.
     vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
     vmovdqu         $GHASH_ACC_XMM, ($GHASH_ACC_PTR)
+
+    vzeroupper
 ___
 }
 $code .= _end_func;
@@ -723,7 +752,7 @@
         $code .= <<___;
 #ifdef BORINGSSL_DISPATCH_TEST
         .extern BORINGSSL_function_hit
-        movb \$1,BORINGSSL_function_hit+8(%rip)
+        movb \$1,BORINGSSL_function_hit+6(%rip)
 #endif
 ___
     }
diff --git a/src/crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl b/src/crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl
new file mode 100644
index 0000000..36b79c3
--- /dev/null
+++ b/src/crypto/fipsmodule/aes/asm/aes-gcm-avx512-x86_64.pl
@@ -0,0 +1,1289 @@
+#!/usr/bin/env perl
+# Copyright 2024 The BoringSSL Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#------------------------------------------------------------------------------
+#
+# This is an AES-GCM implementation for x86_64 CPUs that support the following
+# CPU features: VAES && VPCLMULQDQ && AVX512BW && AVX512VL && BMI2.
+#
+# This file is based on aes-gcm-avx10-x86_64.S from the Linux kernel
+# (https://git.kernel.org/linus/b06affb1cb580e13).  The following notable
+# changes have been made:
+#
+# - Relicensed under BoringSSL's preferred license.
+#
+# - Converted from GNU assembler to "perlasm".  This was necessary for
+#   compatibility with BoringSSL's Windows builds which use NASM instead of the
+#   GNU assembler.  It was also necessary for compatibility with the 'delocate'
+#   tool used in BoringSSL's FIPS builds.
+#
+# - Added support for the Windows ABI.
+#
+# - Changed function prototypes to be compatible with what BoringSSL wants.
+#
+# - Removed the optimized finalization function, as BoringSSL doesn't want it.
+#
+# - Added a single-block GHASH multiplication function, as BoringSSL needs this.
+#
+# - Added optimization for large amounts of AAD.
+#
+# - Removed support for maximum vector lengths other than 512 bits.
+
+use strict;
+
+my $flavour = shift;
+my $output  = shift;
+if ( $flavour =~ /\./ ) { $output = $flavour; undef $flavour; }
+
+my $win64;
+my @argregs;
+if ( $flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/ ) {
+    $win64   = 1;
+    @argregs = ( "%rcx", "%rdx", "%r8", "%r9" );
+}
+else {
+    $win64   = 0;
+    @argregs = ( "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" );
+}
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/;
+my $dir = $1;
+my $xlate;
+( $xlate = "${dir}x86_64-xlate.pl" and -f $xlate )
+  or ( $xlate = "${dir}../../../perlasm/x86_64-xlate.pl" and -f $xlate )
+  or die "can't locate x86_64-xlate.pl";
+
+open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
+*STDOUT = *OUT;
+
+my $g_cur_func_name;
+my $g_cur_func_uses_seh;
+my @g_cur_func_saved_gpregs;
+my @g_cur_func_saved_xmmregs;
+
+sub _begin_func {
+    my ( $funcname, $uses_seh ) = @_;
+    $g_cur_func_name          = $funcname;
+    $g_cur_func_uses_seh      = $uses_seh;
+    @g_cur_func_saved_gpregs  = ();
+    @g_cur_func_saved_xmmregs = ();
+    return <<___;
+.globl $funcname
+.type $funcname,\@abi-omnipotent
+.align 32
+$funcname:
+    .cfi_startproc
+    @{[ $uses_seh ? ".seh_startproc" : "" ]}
+    _CET_ENDBR
+___
+}
+
+# Push a list of general purpose registers onto the stack.
+sub _save_gpregs {
+    my @gpregs = @_;
+    my $code   = "";
+    die "_save_gpregs requires uses_seh" unless $g_cur_func_uses_seh;
+    die "_save_gpregs can only be called once per function"
+      if @g_cur_func_saved_gpregs;
+    die "Order must be _save_gpregs, then _save_xmmregs"
+      if @g_cur_func_saved_xmmregs;
+    @g_cur_func_saved_gpregs = @gpregs;
+    for my $reg (@gpregs) {
+        $code .= "push $reg\n";
+        if ($win64) {
+            $code .= ".seh_pushreg $reg\n";
+        }
+        else {
+            $code .= ".cfi_push $reg\n";
+        }
+    }
+    return $code;
+}
+
+# Push a list of xmm registers onto the stack if the target is Windows.
+sub _save_xmmregs {
+    my @xmmregs     = @_;
+    my $num_xmmregs = scalar @xmmregs;
+    my $code        = "";
+    die "_save_xmmregs requires uses_seh" unless $g_cur_func_uses_seh;
+    die "_save_xmmregs can only be called once per function"
+      if @g_cur_func_saved_xmmregs;
+    if ( $win64 and $num_xmmregs > 0 ) {
+        @g_cur_func_saved_xmmregs = @xmmregs;
+        my $is_misaligned = ( scalar @g_cur_func_saved_gpregs ) % 2 == 0;
+        my $alloc_size    = 16 * $num_xmmregs + ( $is_misaligned ? 8 : 0 );
+        $code .= "sub \$$alloc_size, %rsp\n";
+        $code .= ".seh_stackalloc $alloc_size\n";
+        for my $i ( 0 .. $num_xmmregs - 1 ) {
+            my $reg_num = $xmmregs[$i];
+            my $pos     = 16 * $i;
+            $code .= "vmovdqa %xmm$reg_num, $pos(%rsp)\n";
+            $code .= ".seh_savexmm %xmm$reg_num, $pos\n";
+        }
+    }
+    return $code;
+}
+
+sub _end_func {
+    my $code = "";
+
+    # Restore any xmm registers that were saved earlier.
+    my $num_xmmregs = scalar @g_cur_func_saved_xmmregs;
+    if ( $win64 and $num_xmmregs > 0 ) {
+        my $need_alignment = ( scalar @g_cur_func_saved_gpregs ) % 2 == 0;
+        my $alloc_size     = 16 * $num_xmmregs + ( $need_alignment ? 8 : 0 );
+        for my $i ( 0 .. $num_xmmregs - 1 ) {
+            my $reg_num = $g_cur_func_saved_xmmregs[$i];
+            my $pos     = 16 * $i;
+            $code .= "vmovdqa $pos(%rsp), %xmm$reg_num\n";
+        }
+        $code .= "add \$$alloc_size, %rsp\n";
+    }
+
+    # Restore any general purpose registers that were saved earlier.
+    for my $reg ( reverse @g_cur_func_saved_gpregs ) {
+        $code .= "pop $reg\n";
+        if ( !$win64 ) {
+            $code .= ".cfi_pop $reg\n";
+        }
+    }
+
+    $code .= <<___;
+    ret
+    @{[ $g_cur_func_uses_seh ? ".seh_endproc" : "" ]}
+    .cfi_endproc
+    .size   $g_cur_func_name, . - $g_cur_func_name
+___
+    return $code;
+}
+
+my $code = <<___;
+.section .rodata
+.align 64
+
+    # A shuffle mask that reflects the bytes of 16-byte blocks
+.Lbswap_mask:
+    .quad   0x08090a0b0c0d0e0f, 0x0001020304050607
+
+    # This is the GHASH reducing polynomial without its constant term, i.e.
+    # x^128 + x^7 + x^2 + x, represented using the backwards mapping
+    # between bits and polynomial coefficients.
+    #
+    # Alternatively, it can be interpreted as the naturally-ordered
+    # representation of the polynomial x^127 + x^126 + x^121 + 1, i.e. the
+    # "reversed" GHASH reducing polynomial without its x^128 term.
+.Lgfpoly:
+    .quad   1, 0xc200000000000000
+
+    # Same as above, but with the (1 << 64) bit set.
+.Lgfpoly_and_internal_carrybit:
+    .quad   1, 0xc200000000000001
+
+    # Values needed to prepare the initial vector of counter blocks.
+.Lctr_pattern:
+    .quad   0, 0
+    .quad   1, 0
+    .quad   2, 0
+    .quad   3, 0
+
+    # The number of AES blocks per vector, as a 128-bit value.
+.Linc_4blocks:
+    .quad   4, 0
+
+.text
+___
+
+# Number of powers of the hash key stored in the key struct.  The powers are
+# stored from highest (H^NUM_H_POWERS) to lowest (H^1).
+my $NUM_H_POWERS = 16;
+
+my $OFFSETOFEND_H_POWERS = $NUM_H_POWERS * 16;
+
+# Offset to 'rounds' in AES_KEY struct
+my $OFFSETOF_AES_ROUNDS = 240;
+
+# The _ghash_mul macro multiplies the 128-bit lanes of \a by the corresponding
+# 128-bit lanes of \b and stores the reduced products in \dst.  \t0, \t1, and
+# \t2 are temporary registers of the same size as \a and \b.
+#
+# The multiplications are done in GHASH's representation of the finite field
+# GF(2^128).  Elements of GF(2^128) are represented as binary polynomials
+# (i.e. polynomials whose coefficients are bits) modulo a reducing polynomial
+# G.  The GCM specification uses G = x^128 + x^7 + x^2 + x + 1.  Addition is
+# just XOR, while multiplication is more complex and has two parts: (a) do
+# carryless multiplication of two 128-bit input polynomials to get a 256-bit
+# intermediate product polynomial, and (b) reduce the intermediate product to
+# 128 bits by adding multiples of G that cancel out terms in it.  (Adding
+# multiples of G doesn't change which field element the polynomial represents.)
+#
+# Unfortunately, the GCM specification maps bits to/from polynomial
+# coefficients backwards from the natural order.  In each byte it specifies the
+# highest bit to be the lowest order polynomial coefficient, *not* the highest!
+# This makes it nontrivial to work with the GHASH polynomials.  We could
+# reflect the bits, but x86 doesn't have an instruction that does that.
+#
+# Instead, we operate on the values without bit-reflecting them.  This *mostly*
+# just works, since XOR and carryless multiplication are symmetric with respect
+# to bit order, but it has some consequences.  First, due to GHASH's byte
+# order, by skipping bit reflection, *byte* reflection becomes necessary to
+# give the polynomial terms a consistent order.  E.g., considering an N-bit
+# value interpreted using the G = x^128 + x^7 + x^2 + x + 1 convention, bits 0
+# through N-1 of the byte-reflected value represent the coefficients of x^(N-1)
+# through x^0, whereas bits 0 through N-1 of the non-byte-reflected value
+# represent x^7...x^0, x^15...x^8, ..., x^(N-1)...x^(N-8) which can't be worked
+# with.  Fortunately, x86's vpshufb instruction can do byte reflection.
+#
+# Second, forgoing the bit reflection causes an extra multiple of x (still
+# using the G = x^128 + x^7 + x^2 + x + 1 convention) to be introduced by each
+# multiplication.  This is because an M-bit by N-bit carryless multiplication
+# really produces a (M+N-1)-bit product, but in practice it's zero-extended to
+# M+N bits.  In the G = x^128 + x^7 + x^2 + x + 1 convention, which maps bits
+# to polynomial coefficients backwards, this zero-extension actually changes
+# the product by introducing an extra factor of x.  Therefore, users of this
+# macro must ensure that one of the inputs has an extra factor of x^-1, i.e.
+# the multiplicative inverse of x, to cancel out the extra x.
+#
+# Third, the backwards coefficients convention is just confusing to work with,
+# since it makes "low" and "high" in the polynomial math mean the opposite of
+# their normal meaning in computer programming.  This can be solved by using an
+# alternative interpretation: the polynomial coefficients are understood to be
+# in the natural order, and the multiplication is actually \a * \b * x^-128 mod
+# x^128 + x^127 + x^126 + x^121 + 1.  This doesn't change the inputs, outputs,
+# or the implementation at all; it just changes the mathematical interpretation
+# of what each instruction is doing.  Starting from here, we'll use this
+# alternative interpretation, as it's easier to understand the code that way.
+#
+# Moving onto the implementation, the vpclmulqdq instruction does 64 x 64 =>
+# 128-bit carryless multiplication, so we break the 128 x 128 multiplication
+# into parts as follows (the _L and _H suffixes denote low and high 64 bits):
+#
+#     LO = a_L * b_L
+#     MI = (a_L * b_H) + (a_H * b_L)
+#     HI = a_H * b_H
+#
+# The 256-bit product is x^128*HI + x^64*MI + LO.  LO, MI, and HI are 128-bit.
+# Note that MI "overlaps" with LO and HI.  We don't consolidate MI into LO and
+# HI right away, since the way the reduction works makes that unnecessary.
+#
+# For the reduction, we cancel out the low 128 bits by adding multiples of G =
+# x^128 + x^127 + x^126 + x^121 + 1.  This is done by two iterations, each of
+# which cancels out the next lowest 64 bits.  Consider a value x^64*A + B,
+# where A and B are 128-bit.  Adding B_L*G to that value gives:
+#
+#       x^64*A + B + B_L*G
+#     = x^64*A + x^64*B_H + B_L + B_L*(x^128 + x^127 + x^126 + x^121 + 1)
+#     = x^64*A + x^64*B_H + B_L + x^128*B_L + x^64*B_L*(x^63 + x^62 + x^57) + B_L
+#     = x^64*A + x^64*B_H + x^128*B_L + x^64*B_L*(x^63 + x^62 + x^57) + B_L + B_L
+#     = x^64*(A + B_H + x^64*B_L + B_L*(x^63 + x^62 + x^57))
+#
+# So: if we sum A, B with its halves swapped, and the low half of B times x^63
+# + x^62 + x^57, we get a 128-bit value C where x^64*C is congruent to the
+# original value x^64*A + B.  I.e., the low 64 bits got canceled out.
+#
+# We just need to apply this twice: first to fold LO into MI, and second to
+# fold the updated MI into HI.
+#
+# The needed three-argument XORs are done using the vpternlogd instruction with
+# immediate 0x96, since this is faster than two vpxord instructions.
+#
+# A potential optimization, assuming that b is fixed per-key (if a is fixed
+# per-key it would work the other way around), is to use one iteration of the
+# reduction described above to precompute a value c such that x^64*c = b mod G,
+# and then multiply a_L by c (and implicitly by x^64) instead of by b:
+#
+#     MI = (a_L * c_L) + (a_H * b_L)
+#     HI = (a_L * c_H) + (a_H * b_H)
+#
+# This would eliminate the LO part of the intermediate product, which would
+# eliminate the need to fold LO into MI.  This would save two instructions,
+# including a vpclmulqdq.  However, we currently don't use this optimization
+# because it would require twice as many per-key precomputed values.
+#
+# Using Karatsuba multiplication instead of "schoolbook" multiplication
+# similarly would save a vpclmulqdq but does not seem to be worth it.
+sub _ghash_mul {
+    my ( $a, $b, $dst, $gfpoly, $t0, $t1, $t2 ) = @_;
+    return <<___;
+    vpclmulqdq      \$0x00, $a, $b, $t0        # LO = a_L * b_L
+    vpclmulqdq      \$0x01, $a, $b, $t1        # MI_0 = a_L * b_H
+    vpclmulqdq      \$0x10, $a, $b, $t2        # MI_1 = a_H * b_L
+    vpxord          $t2, $t1, $t1              # MI = MI_0 + MI_1
+    vpclmulqdq      \$0x01, $t0, $gfpoly, $t2  # LO_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t0, $t0           # Swap halves of LO
+    vpternlogd      \$0x96, $t2, $t0, $t1      # Fold LO into MI
+    vpclmulqdq      \$0x11, $a, $b, $dst       # HI = a_H * b_H
+    vpclmulqdq      \$0x01, $t1, $gfpoly, $t0  # MI_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t1, $t1           # Swap halves of MI
+    vpternlogd      \$0x96, $t0, $t1, $dst     # Fold MI into HI
+___
+}
+
+# GHASH-multiply the 128-bit lanes of \a by the 128-bit lanes of \b and add the
+# *unreduced* products to \lo, \mi, and \hi.
+sub _ghash_mul_noreduce {
+    my ( $a, $b, $lo, $mi, $hi, $t0, $t1, $t2, $t3 ) = @_;
+    return <<___;
+    vpclmulqdq      \$0x00, $a, $b, $t0      # a_L * b_L
+    vpclmulqdq      \$0x01, $a, $b, $t1      # a_L * b_H
+    vpclmulqdq      \$0x10, $a, $b, $t2      # a_H * b_L
+    vpclmulqdq      \$0x11, $a, $b, $t3      # a_H * b_H
+    vpxord          $t0, $lo, $lo
+    vpternlogd      \$0x96, $t2, $t1, $mi
+    vpxord          $t3, $hi, $hi
+___
+}
+
+# Reduce the unreduced products from \lo, \mi, and \hi and store the 128-bit
+# reduced products in \hi.  See _ghash_mul for explanation of reduction.
+sub _ghash_reduce {
+    my ( $lo, $mi, $hi, $gfpoly, $t0 ) = @_;
+    return <<___;
+    vpclmulqdq      \$0x01, $lo, $gfpoly, $t0
+    vpshufd         \$0x4e, $lo, $lo
+    vpternlogd      \$0x96, $t0, $lo, $mi
+    vpclmulqdq      \$0x01, $mi, $gfpoly, $t0
+    vpshufd         \$0x4e, $mi, $mi
+    vpternlogd      \$0x96, $t0, $mi, $hi
+___
+}
+
+# This is a specialized version of _ghash_mul that computes \a * \a, i.e. it
+# squares \a.  It skips computing MI = (a_L * a_H) + (a_H * a_L) = 0.
+sub _ghash_square {
+    my ( $a, $dst, $gfpoly, $t0, $t1 ) = @_;
+    return <<___;
+    vpclmulqdq      \$0x00, $a, $a, $t0        # LO = a_L * a_L
+    vpclmulqdq      \$0x11, $a, $a, $dst       # HI = a_H * a_H
+    vpclmulqdq      \$0x01, $t0, $gfpoly, $t1  # LO_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t0, $t0           # Swap halves of LO
+    vpxor           $t0, $t1, $t1              # Fold LO into MI
+    vpclmulqdq      \$0x01, $t1, $gfpoly, $t0  # MI_L*(x^63 + x^62 + x^57)
+    vpshufd         \$0x4e, $t1, $t1           # Swap halves of MI
+    vpternlogd      \$0x96, $t0, $t1, $dst     # Fold MI into HI
+___
+}
+
+# void gcm_init_vpclmulqdq_avx512(u128 Htable[16], const uint64_t H[2]);
+#
+# Initialize |Htable| with powers of the GHASH subkey |H|.
+#
+# The powers are stored in the order H^NUM_H_POWERS to H^1.
+$code .= _begin_func "gcm_init_vpclmulqdq_avx512", 0;
+{
+    # Function arguments
+    my ( $HTABLE, $H_PTR ) = @argregs[ 0 .. 1 ];
+
+    # Additional local variables.  %rax is used as a temporary register.
+    my ( $TMP0, $TMP0_YMM, $TMP0_XMM ) = ( "%zmm0", "%ymm0", "%xmm0" );
+    my ( $TMP1, $TMP1_YMM, $TMP1_XMM ) = ( "%zmm1", "%ymm1", "%xmm1" );
+    my ( $TMP2, $TMP2_YMM, $TMP2_XMM ) = ( "%zmm2", "%ymm2", "%xmm2" );
+    my $POWERS_PTR     = "%r8";
+    my $RNDKEYLAST_PTR = "%r9";
+    my ( $H_CUR, $H_CUR_YMM, $H_CUR_XMM )    = ( "%zmm3", "%ymm3", "%xmm3" );
+    my ( $H_INC, $H_INC_YMM, $H_INC_XMM )    = ( "%zmm4", "%ymm4", "%xmm4" );
+    my ( $GFPOLY, $GFPOLY_YMM, $GFPOLY_XMM ) = ( "%zmm5", "%ymm5", "%xmm5" );
+
+    $code .= <<___;
+    # Get pointer to lowest set of key powers (located at end of array).
+    lea             $OFFSETOFEND_H_POWERS-64($HTABLE), $POWERS_PTR
+
+    # Load the byte-reflected hash subkey.  BoringSSL provides it in
+    # byte-reflected form except the two halves are in the wrong order.
+    vpshufd         \$0x4e, ($H_PTR), $H_CUR_XMM
+
+    # Finish preprocessing the first key power, H^1.  Since this GHASH
+    # implementation operates directly on values with the backwards bit
+    # order specified by the GCM standard, it's necessary to preprocess the
+    # raw key as follows.  First, reflect its bytes.  Second, multiply it
+    # by x^-1 mod x^128 + x^7 + x^2 + x + 1 (if using the backwards
+    # interpretation of polynomial coefficients), which can also be
+    # interpreted as multiplication by x mod x^128 + x^127 + x^126 + x^121
+    # + 1 using the alternative, natural interpretation of polynomial
+    # coefficients.  For details, see the comment above _ghash_mul.
+    #
+    # Either way, for the multiplication the concrete operation performed
+    # is a left shift of the 128-bit value by 1 bit, then an XOR with (0xc2
+    # << 120) | 1 if a 1 bit was carried out.  However, there's no 128-bit
+    # wide shift instruction, so instead double each of the two 64-bit
+    # halves and incorporate the internal carry bit into the value XOR'd.
+    vpshufd         \$0xd3, $H_CUR_XMM, $TMP0_XMM
+    vpsrad          \$31, $TMP0_XMM, $TMP0_XMM
+    vpaddq          $H_CUR_XMM, $H_CUR_XMM, $H_CUR_XMM
+    # H_CUR_XMM ^= TMP0_XMM & gfpoly_and_internal_carrybit
+    vpternlogd      \$0x78, .Lgfpoly_and_internal_carrybit(%rip), $TMP0_XMM, $H_CUR_XMM
+
+    # Load the gfpoly constant.
+    vbroadcasti32x4 .Lgfpoly(%rip), $GFPOLY
+
+    # Square H^1 to get H^2.
+    #
+    # Note that as with H^1, all higher key powers also need an extra
+    # factor of x^-1 (or x using the natural interpretation).  Nothing
+    # special needs to be done to make this happen, though: H^1 * H^1 would
+    # end up with two factors of x^-1, but the multiplication consumes one.
+    # So the product H^2 ends up with the desired one factor of x^-1.
+    @{[ _ghash_square  $H_CUR_XMM, $H_INC_XMM, $GFPOLY_XMM,
+                       $TMP0_XMM, $TMP1_XMM ]}
+
+    # Create H_CUR_YMM = [H^2, H^1] and H_INC_YMM = [H^2, H^2].
+    vinserti128     \$1, $H_CUR_XMM, $H_INC_YMM, $H_CUR_YMM
+    vinserti128     \$1, $H_INC_XMM, $H_INC_YMM, $H_INC_YMM
+
+    # Create H_CUR = [H^4, H^3, H^2, H^1] and H_INC = [H^4, H^4, H^4, H^4].
+    @{[ _ghash_mul  $H_INC_YMM, $H_CUR_YMM, $H_INC_YMM, $GFPOLY_YMM,
+                    $TMP0_YMM, $TMP1_YMM, $TMP2_YMM ]}
+    vinserti64x4    \$1, $H_CUR_YMM, $H_INC, $H_CUR
+    vshufi64x2      \$0, $H_INC, $H_INC, $H_INC
+
+    # Store the lowest set of key powers.
+    vmovdqu8        $H_CUR, ($POWERS_PTR)
+
+    # Compute and store the remaining key powers.
+    # Repeatedly multiply [H^(i+3), H^(i+2), H^(i+1), H^i] by
+    # [H^4, H^4, H^4, H^4] to get [H^(i+7), H^(i+6), H^(i+5), H^(i+4)].
+    mov             \$3, %eax
+.Lprecompute_next:
+    sub             \$64, $POWERS_PTR
+    @{[ _ghash_mul  $H_INC, $H_CUR, $H_CUR, $GFPOLY, $TMP0, $TMP1, $TMP2 ]}
+    vmovdqu8        $H_CUR, ($POWERS_PTR)
+    dec             %eax
+    jnz             .Lprecompute_next
+
+    vzeroupper      # This is needed after using ymm or zmm registers.
+___
+}
+$code .= _end_func;
+
+# XOR together the 128-bit lanes of \src (whose low lane is \src_xmm) and store
+# the result in \dst_xmm.  This implicitly zeroizes the other lanes of dst.
+sub _horizontal_xor {
+    my ( $src, $src_xmm, $dst_xmm, $t0_xmm, $t1_xmm, $t2_xmm ) = @_;
+    return <<___;
+    vextracti32x4   \$1, $src, $t0_xmm
+    vextracti32x4   \$2, $src, $t1_xmm
+    vextracti32x4   \$3, $src, $t2_xmm
+    vpxord          $t0_xmm, $src_xmm, $dst_xmm
+    vpternlogd      \$0x96, $t1_xmm, $t2_xmm, $dst_xmm
+___
+}
+
+# Do one step of the GHASH update of the data blocks given in the vector
+# registers GHASHDATA[0-3].  \i specifies the step to do, 0 through 9.  The
+# division into steps allows users of this macro to optionally interleave the
+# computation with other instructions.  This macro uses the vector register
+# GHASH_ACC as input/output; GHASHDATA[0-3] as inputs that are clobbered;
+# H_POW[4-1], GFPOLY, and BSWAP_MASK as inputs that aren't clobbered; and
+# GHASHTMP[0-2] as temporaries.  This macro handles the byte-reflection of the
+# data blocks.  The parameter registers must be preserved across steps.
+#
+# The GHASH update does: GHASH_ACC = H_POW4*(GHASHDATA0 + GHASH_ACC) +
+# H_POW3*GHASHDATA1 + H_POW2*GHASHDATA2 + H_POW1*GHASHDATA3, where the
+# operations are vectorized operations on 512-bit vectors of 128-bit blocks.
+# The vectorized terms correspond to the following non-vectorized terms:
+#
+#       H_POW4*(GHASHDATA0 + GHASH_ACC) => H^16*(blk0 + GHASH_ACC_XMM),
+#              H^15*(blk1 + 0), H^14*(blk2 + 0), and H^13*(blk3 + 0)
+#       H_POW3*GHASHDATA1 => H^12*blk4, H^11*blk5, H^10*blk6, and H^9*blk7
+#       H_POW2*GHASHDATA2 => H^8*blk8,  H^7*blk9,  H^6*blk10, and H^5*blk11
+#       H_POW1*GHASHDATA3 => H^4*blk12, H^3*blk13, H^2*blk14, and H^1*blk15
+#
+# More concretely, this code does:
+#   - Do vectorized "schoolbook" multiplications to compute the intermediate
+#     256-bit product of each block and its corresponding hash key power.
+#   - Sum (XOR) the intermediate 256-bit products across vectors.
+#   - Do a vectorized reduction of these 256-bit intermediate values to 128-bits
+#     each.
+#   - Sum (XOR) these values and store the 128-bit result in GHASH_ACC_XMM.
+#
+# See _ghash_mul for the full explanation of the operations performed for each
+# individual finite field multiplication and reduction.
+sub _ghash_step_4x {
+    my (
+        $i,              $BSWAP_MASK,     $GHASHDATA0,     $GHASHDATA1,
+        $GHASHDATA2,     $GHASHDATA3,     $GHASHDATA0_XMM, $GHASHDATA1_XMM,
+        $GHASHDATA2_XMM, $GHASHDATA3_XMM, $H_POW4,         $H_POW3,
+        $H_POW2,         $H_POW1,         $GFPOLY,         $GHASHTMP0,
+        $GHASHTMP1,      $GHASHTMP2,      $GHASH_ACC,      $GHASH_ACC_XMM
+    ) = @_;
+    if ( $i == 0 ) {
+        return <<___;
+        vpshufb         $BSWAP_MASK, $GHASHDATA0, $GHASHDATA0
+        vpxord          $GHASH_ACC, $GHASHDATA0, $GHASHDATA0
+        vpshufb         $BSWAP_MASK, $GHASHDATA1, $GHASHDATA1
+        vpshufb         $BSWAP_MASK, $GHASHDATA2, $GHASHDATA2
+___
+    }
+    elsif ( $i == 1 ) {
+        return <<___;
+        vpshufb         $BSWAP_MASK, $GHASHDATA3, $GHASHDATA3
+        vpclmulqdq      \$0x00, $H_POW4, $GHASHDATA0, $GHASH_ACC    # LO_0
+        vpclmulqdq      \$0x00, $H_POW3, $GHASHDATA1, $GHASHTMP0    # LO_1
+        vpclmulqdq      \$0x00, $H_POW2, $GHASHDATA2, $GHASHTMP1    # LO_2
+___
+    }
+    elsif ( $i == 2 ) {
+        return <<___;
+        vpxord          $GHASHTMP0, $GHASH_ACC, $GHASH_ACC          # sum(LO_{1,0})
+        vpclmulqdq      \$0x00, $H_POW1, $GHASHDATA3, $GHASHTMP2    # LO_3
+        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASH_ACC  # LO = sum(LO_{3,2,1,0})
+        vpclmulqdq      \$0x01, $H_POW4, $GHASHDATA0, $GHASHTMP0    # MI_0
+___
+    }
+    elsif ( $i == 3 ) {
+        return <<___;
+        vpclmulqdq      \$0x01, $H_POW3, $GHASHDATA1, $GHASHTMP1    # MI_1
+        vpclmulqdq      \$0x01, $H_POW2, $GHASHDATA2, $GHASHTMP2    # MI_2
+        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{2,1,0})
+        vpclmulqdq      \$0x01, $H_POW1, $GHASHDATA3, $GHASHTMP1    # MI_3
+___
+    }
+    elsif ( $i == 4 ) {
+        return <<___;
+        vpclmulqdq      \$0x10, $H_POW4, $GHASHDATA0, $GHASHTMP2    # MI_4
+        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{4,3,2,1,0})
+        vpclmulqdq      \$0x10, $H_POW3, $GHASHDATA1, $GHASHTMP1    # MI_5
+        vpclmulqdq      \$0x10, $H_POW2, $GHASHDATA2, $GHASHTMP2    # MI_6
+___
+    }
+    elsif ( $i == 5 ) {
+        return <<___;
+        vpternlogd      \$0x96, $GHASHTMP2, $GHASHTMP1, $GHASHTMP0  # sum(MI_{6,5,4,3,2,1,0})
+        vpclmulqdq      \$0x01, $GHASH_ACC, $GFPOLY, $GHASHTMP2     # LO_L*(x^63 + x^62 + x^57)
+        vpclmulqdq      \$0x10, $H_POW1, $GHASHDATA3, $GHASHTMP1    # MI_7
+        vpxord          $GHASHTMP1, $GHASHTMP0, $GHASHTMP0          # MI = sum(MI_{7,6,5,4,3,2,1,0})
+___
+    }
+    elsif ( $i == 6 ) {
+        return <<___;
+        vpshufd         \$0x4e, $GHASH_ACC, $GHASH_ACC              # Swap halves of LO
+        vpclmulqdq      \$0x11, $H_POW4, $GHASHDATA0, $GHASHDATA0   # HI_0
+        vpclmulqdq      \$0x11, $H_POW3, $GHASHDATA1, $GHASHDATA1   # HI_1
+        vpclmulqdq      \$0x11, $H_POW2, $GHASHDATA2, $GHASHDATA2   # HI_2
+___
+    }
+    elsif ( $i == 7 ) {
+        return <<___;
+        vpternlogd      \$0x96, $GHASHTMP2, $GHASH_ACC, $GHASHTMP0  # Fold LO into MI
+        vpclmulqdq      \$0x11, $H_POW1, $GHASHDATA3, $GHASHDATA3   # HI_3
+        vpternlogd      \$0x96, $GHASHDATA2, $GHASHDATA1, $GHASHDATA0 # sum(HI_{2,1,0})
+        vpclmulqdq      \$0x01, $GHASHTMP0, $GFPOLY, $GHASHTMP1     # MI_L*(x^63 + x^62 + x^57)
+___
+    }
+    elsif ( $i == 8 ) {
+        return <<___;
+        vpxord          $GHASHDATA3, $GHASHDATA0, $GHASH_ACC        # HI = sum(HI_{3,2,1,0})
+        vpshufd         \$0x4e, $GHASHTMP0, $GHASHTMP0              # Swap halves of MI
+        vpternlogd      \$0x96, $GHASHTMP1, $GHASHTMP0, $GHASH_ACC  # Fold MI into HI
+___
+    }
+    elsif ( $i == 9 ) {
+        return _horizontal_xor $GHASH_ACC, $GHASH_ACC_XMM, $GHASH_ACC_XMM,
+          $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM;
+    }
+}
+
+# Update GHASH with four vectors of data blocks.  See _ghash_step_4x for full
+# explanation.
+sub _ghash_4x {
+    my $code = "";
+    for my $i ( 0 .. 9 ) {
+        $code .= _ghash_step_4x $i, @_;
+    }
+    return $code;
+}
+
+# void gcm_gmult_vpclmulqdq_avx512(uint8_t Xi[16], const u128 Htable[16]);
+$code .= _begin_func "gcm_gmult_vpclmulqdq_avx512", 1;
+{
+    my ( $GHASH_ACC_PTR, $HTABLE ) = @argregs[ 0 .. 1 ];
+    my ( $GHASH_ACC, $BSWAP_MASK, $H_POW1, $GFPOLY, $T0, $T1, $T2 ) =
+      map( "%xmm$_", ( 0 .. 6 ) );
+
+    $code .= <<___;
+    @{[ _save_xmmregs (6) ]}
+    .seh_endprologue
+
+    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC
+    vmovdqu         .Lbswap_mask(%rip), $BSWAP_MASK
+    vmovdqu         $OFFSETOFEND_H_POWERS-16($HTABLE), $H_POW1
+    vmovdqu         .Lgfpoly(%rip), $GFPOLY
+    vpshufb         $BSWAP_MASK, $GHASH_ACC, $GHASH_ACC
+
+    @{[ _ghash_mul  $H_POW1, $GHASH_ACC, $GHASH_ACC, $GFPOLY, $T0, $T1, $T2 ]}
+
+    vpshufb         $BSWAP_MASK, $GHASH_ACC, $GHASH_ACC
+    vmovdqu         $GHASH_ACC, ($GHASH_ACC_PTR)
+
+    # No need for vzeroupper, since only xmm registers were used.
+___
+}
+$code .= _end_func;
+
+# void gcm_ghash_vpclmulqdq_avx512(uint8_t Xi[16], const u128 Htable[16],
+#                                  const uint8_t *in, size_t len);
+#
+# Using the key |Htable|, update the GHASH accumulator |Xi| with the data given
+# by |in| and |len|.  |len| must be a multiple of 16.
+#
+# This function handles large amounts of AAD efficiently, while also keeping the
+# overhead low for small amounts of AAD which is the common case.  TLS uses less
+# than one block of AAD, but (uncommonly) other use cases may use much more.
+$code .= _begin_func "gcm_ghash_vpclmulqdq_avx512", 1;
+{
+    # Function arguments
+    my ( $GHASH_ACC_PTR, $HTABLE, $AAD, $AADLEN ) = @argregs[ 0 .. 3 ];
+
+    # Additional local variables
+    my ( $GHASHDATA0, $GHASHDATA0_XMM ) = ( "%zmm0", "%xmm0" );
+    my ( $GHASHDATA1, $GHASHDATA1_XMM ) = ( "%zmm1", "%xmm1" );
+    my ( $GHASHDATA2, $GHASHDATA2_XMM ) = ( "%zmm2", "%xmm2" );
+    my ( $GHASHDATA3, $GHASHDATA3_XMM ) = ( "%zmm3", "%xmm3" );
+    my @GHASHDATA = ( $GHASHDATA0, $GHASHDATA1, $GHASHDATA2, $GHASHDATA3 );
+    my @GHASHDATA_XMM =
+      ( $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM, $GHASHDATA3_XMM );
+    my ( $BSWAP_MASK, $BSWAP_MASK_XMM ) = ( "%zmm4", "%xmm4" );
+    my ( $GHASH_ACC, $GHASH_ACC_XMM )   = ( "%zmm5", "%xmm5" );
+    my ( $H_POW4, $H_POW3, $H_POW2 )    = ( "%zmm6", "%zmm7", "%zmm8" );
+    my ( $H_POW1, $H_POW1_XMM )         = ( "%zmm9", "%xmm9" );
+    my ( $GFPOLY, $GFPOLY_XMM )         = ( "%zmm10", "%xmm10" );
+    my ( $GHASHTMP0, $GHASHTMP1, $GHASHTMP2 ) =
+      ( "%zmm11", "%zmm12", "%zmm13" );
+
+    $code .= <<___;
+    @{[ _save_xmmregs (6 .. 13) ]}
+    .seh_endprologue
+
+    # Load the bswap_mask and gfpoly constants.  Since AADLEN is usually small,
+    # usually only 128-bit vectors will be used.  So as an optimization, don't
+    # broadcast these constants to all 128-bit lanes quite yet.
+    vmovdqu         .Lbswap_mask(%rip), $BSWAP_MASK_XMM
+    vmovdqu         .Lgfpoly(%rip), $GFPOLY_XMM
+
+    # Load the GHASH accumulator.
+    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC_XMM
+    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+
+    # Optimize for AADLEN < 64 by checking for AADLEN < 64 before AADLEN < 256.
+    cmp             \$64, $AADLEN
+    jb              .Laad_blockbyblock
+
+    # AADLEN >= 64, so we'll operate on full vectors.  Broadcast bswap_mask and
+    # gfpoly to all 128-bit lanes.
+    vshufi64x2      \$0, $BSWAP_MASK, $BSWAP_MASK, $BSWAP_MASK
+    vshufi64x2      \$0, $GFPOLY, $GFPOLY, $GFPOLY
+
+    # Load the lowest set of key powers.
+    vmovdqu8        $OFFSETOFEND_H_POWERS-1*64($HTABLE), $H_POW1
+
+    cmp             \$256, $AADLEN
+    jb              .Laad_loop_1x
+
+    # AADLEN >= 256.  Load the higher key powers.
+    vmovdqu8        $OFFSETOFEND_H_POWERS-4*64($HTABLE), $H_POW4
+    vmovdqu8        $OFFSETOFEND_H_POWERS-3*64($HTABLE), $H_POW3
+    vmovdqu8        $OFFSETOFEND_H_POWERS-2*64($HTABLE), $H_POW2
+
+    # Update GHASH with 256 bytes of AAD at a time.
+.Laad_loop_4x:
+    vmovdqu8        0*64($AAD), $GHASHDATA0
+    vmovdqu8        1*64($AAD), $GHASHDATA1
+    vmovdqu8        2*64($AAD), $GHASHDATA2
+    vmovdqu8        3*64($AAD), $GHASHDATA3
+    @{[ _ghash_4x   $BSWAP_MASK, @GHASHDATA, @GHASHDATA_XMM, $H_POW4, $H_POW3,
+                    $H_POW2, $H_POW1, $GFPOLY, $GHASHTMP0, $GHASHTMP1,
+                    $GHASHTMP2, $GHASH_ACC, $GHASH_ACC_XMM ]}
+    add             \$256, $AAD
+    sub             \$256, $AADLEN
+    cmp             \$256, $AADLEN
+    jae             .Laad_loop_4x
+
+    # Update GHASH with 64 bytes of AAD at a time.
+    cmp             \$64, $AADLEN
+    jb              .Laad_large_done
+.Laad_loop_1x:
+    vmovdqu8        ($AAD), $GHASHDATA0
+    vpshufb         $BSWAP_MASK, $GHASHDATA0, $GHASHDATA0
+    vpxord          $GHASHDATA0, $GHASH_ACC, $GHASH_ACC
+    @{[ _ghash_mul  $H_POW1, $GHASH_ACC, $GHASH_ACC, $GFPOLY,
+                    $GHASHDATA0, $GHASHDATA1, $GHASHDATA2 ]}
+    @{[ _horizontal_xor $GHASH_ACC, $GHASH_ACC_XMM, $GHASH_ACC_XMM,
+                        $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM ]}
+    add             \$64, $AAD
+    sub             \$64, $AADLEN
+    cmp             \$64, $AADLEN
+    jae             .Laad_loop_1x
+
+.Laad_large_done:
+
+    # GHASH the remaining data 16 bytes at a time, using xmm registers only.
+.Laad_blockbyblock:
+    test            $AADLEN, $AADLEN
+    jz              .Laad_done
+    vmovdqu         $OFFSETOFEND_H_POWERS-16($HTABLE), $H_POW1_XMM
+.Laad_loop_blockbyblock:
+    vmovdqu         ($AAD), $GHASHDATA0_XMM
+    vpshufb         $BSWAP_MASK_XMM, $GHASHDATA0_XMM, $GHASHDATA0_XMM
+    vpxor           $GHASHDATA0_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+    @{[ _ghash_mul  $H_POW1_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM, $GFPOLY_XMM,
+                    $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM ]}
+    add             \$16, $AAD
+    sub             \$16, $AADLEN
+    jnz             .Laad_loop_blockbyblock
+
+.Laad_done:
+    # Store the updated GHASH accumulator back to memory.
+    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+    vmovdqu         $GHASH_ACC_XMM, ($GHASH_ACC_PTR)
+
+    vzeroupper      # This is needed after using ymm or zmm registers.
+___
+}
+$code .= _end_func;
+
+# Do one non-last round of AES encryption on the counter blocks in aesdata[0-3]
+# using the round key that has been broadcast to all 128-bit lanes of round_key.
+sub _vaesenc_4x {
+    my ( $round_key, $aesdata0, $aesdata1, $aesdata2, $aesdata3 ) = @_;
+    return <<___;
+    vaesenc         $round_key, $aesdata0, $aesdata0
+    vaesenc         $round_key, $aesdata1, $aesdata1
+    vaesenc         $round_key, $aesdata2, $aesdata2
+    vaesenc         $round_key, $aesdata3, $aesdata3
+___
+}
+
+# Start the AES encryption of four vectors of counter blocks.
+sub _ctr_begin_4x {
+    my (
+        $le_ctr,   $le_ctr_inc, $bswap_mask, $rndkey0,
+        $aesdata0, $aesdata1,   $aesdata2,   $aesdata3
+    ) = @_;
+    return <<___;
+    # Increment le_ctr four times to generate four vectors of little-endian
+    # counter blocks, swap each to big-endian, and store them in aesdata[0-3].
+    vpshufb         $bswap_mask, $le_ctr, $aesdata0
+    vpaddd          $le_ctr_inc, $le_ctr, $le_ctr
+    vpshufb         $bswap_mask, $le_ctr, $aesdata1
+    vpaddd          $le_ctr_inc, $le_ctr, $le_ctr
+    vpshufb         $bswap_mask, $le_ctr, $aesdata2
+    vpaddd          $le_ctr_inc, $le_ctr, $le_ctr
+    vpshufb         $bswap_mask, $le_ctr, $aesdata3
+    vpaddd          $le_ctr_inc, $le_ctr, $le_ctr
+
+    # AES "round zero": XOR in the zero-th round key.
+    vpxord          $rndkey0, $aesdata0, $aesdata0
+    vpxord          $rndkey0, $aesdata1, $aesdata1
+    vpxord          $rndkey0, $aesdata2, $aesdata2
+    vpxord          $rndkey0, $aesdata3, $aesdata3
+___
+}
+
+# Do the last AES round for four vectors of counter blocks, XOR four vectors of
+# source data with the resulting keystream blocks, and write the result to the
+# destination buffer and ghashdata[0-3].  The implementation differs slightly as
+# it takes advantage of the property vaesenclast(key, a) ^ b ==
+# vaesenclast(key ^ b, a) to reduce latency, but it has the same effect.
+sub _aesenclast_and_xor_4x {
+    my (
+        $src,        $dst,        $rndkeylast, $aesdata0,
+        $aesdata1,   $aesdata2,   $aesdata3,   $ghashdata0,
+        $ghashdata1, $ghashdata2, $ghashdata3
+    ) = @_;
+    return <<___;
+    vpxord          0*64($src), $rndkeylast, $ghashdata0
+    vpxord          1*64($src), $rndkeylast, $ghashdata1
+    vpxord          2*64($src), $rndkeylast, $ghashdata2
+    vpxord          3*64($src), $rndkeylast, $ghashdata3
+    vaesenclast     $ghashdata0, $aesdata0, $ghashdata0
+    vaesenclast     $ghashdata1, $aesdata1, $ghashdata1
+    vaesenclast     $ghashdata2, $aesdata2, $ghashdata2
+    vaesenclast     $ghashdata3, $aesdata3, $ghashdata3
+    vmovdqu8        $ghashdata0, 0*64($dst)
+    vmovdqu8        $ghashdata1, 1*64($dst)
+    vmovdqu8        $ghashdata2, 2*64($dst)
+    vmovdqu8        $ghashdata3, 3*64($dst)
+___
+}
+
+my $g_update_macro_expansion_count = 0;
+
+# void aes_gcm_{enc,dec}_update_vaes_avx512(const uint8_t *in, uint8_t *out,
+#                                           size_t len, const AES_KEY *key,
+#                                           const uint8_t ivec[16],
+#                                           const u128 Htable[16],
+#                                           uint8_t Xi[16]);
+#
+# This macro generates a GCM encryption or decryption update function with the
+# above prototype (with \enc selecting which one).  The function computes the
+# next portion of the CTR keystream, XOR's it with |len| bytes from |in|, and
+# writes the resulting encrypted or decrypted data to |out|.  It also updates
+# the GHASH accumulator |Xi| using the next |len| ciphertext bytes.
+#
+# |len| must be a multiple of 16, except on the last call where it can be any
+# length.  The caller must do any buffering needed to ensure this.  Both
+# in-place and out-of-place en/decryption are supported.
+#
+# |ivec| must give the current counter in big-endian format.  This function
+# loads the counter from |ivec| and increments the loaded counter as needed, but
+# it does *not* store the updated counter back to |ivec|.  The caller must
+# update |ivec| if any more data segments follow.  Internally, only the low
+# 32-bit word of the counter is incremented, following the GCM standard.
+sub _aes_gcm_update {
+    my $local_label_suffix = "__func" . ++$g_update_macro_expansion_count;
+    my ($enc)              = @_;
+    my $code               = "";
+
+    # Function arguments
+    my ( $SRC, $DST, $DATALEN, $AESKEY, $BE_CTR_PTR, $HTABLE, $GHASH_ACC_PTR )
+      = $win64
+      ? ( @argregs[ 0 .. 3 ], "%rsi", "%rdi", "%r12" )
+      : ( @argregs[ 0 .. 5 ], "%r12" );
+
+    # Additional local variables.
+    # %rax, %k1, and %k2 are used as temporary registers.  BE_CTR_PTR is
+    # also available as a temporary register after the counter is loaded.
+
+    # AES key length in bytes
+    my ( $AESKEYLEN, $AESKEYLEN64 ) = ( "%r10d", "%r10" );
+
+    # Pointer to the last AES round key for the chosen AES variant
+    my $RNDKEYLAST_PTR = "%r11";
+
+    # AESDATA[0-3] hold the counter blocks that are being encrypted by AES.
+    my ( $AESDATA0, $AESDATA0_XMM ) = ( "%zmm0", "%xmm0" );
+    my ( $AESDATA1, $AESDATA1_XMM ) = ( "%zmm1", "%xmm1" );
+    my ( $AESDATA2, $AESDATA2_XMM ) = ( "%zmm2", "%xmm2" );
+    my ( $AESDATA3, $AESDATA3_XMM ) = ( "%zmm3", "%xmm3" );
+    my @AESDATA = ( $AESDATA0, $AESDATA1, $AESDATA2, $AESDATA3 );
+
+    # GHASHDATA[0-3] hold the ciphertext blocks and GHASH input data.
+    my ( $GHASHDATA0, $GHASHDATA0_XMM ) = ( "%zmm4", "%xmm4" );
+    my ( $GHASHDATA1, $GHASHDATA1_XMM ) = ( "%zmm5", "%xmm5" );
+    my ( $GHASHDATA2, $GHASHDATA2_XMM ) = ( "%zmm6", "%xmm6" );
+    my ( $GHASHDATA3, $GHASHDATA3_XMM ) = ( "%zmm7", "%xmm7" );
+    my @GHASHDATA = ( $GHASHDATA0, $GHASHDATA1, $GHASHDATA2, $GHASHDATA3 );
+    my @GHASHDATA_XMM =
+      ( $GHASHDATA0_XMM, $GHASHDATA1_XMM, $GHASHDATA2_XMM, $GHASHDATA3_XMM );
+
+    # BSWAP_MASK is the shuffle mask for byte-reflecting 128-bit values
+    # using vpshufb, copied to all 128-bit lanes.
+    my ( $BSWAP_MASK, $BSWAP_MASK_XMM ) = ( "%zmm8", "%xmm8" );
+
+    # RNDKEY temporarily holds the next AES round key.
+    my $RNDKEY = "%zmm9";
+
+    # GHASH_ACC is the accumulator variable for GHASH.  When fully reduced,
+    # only the lowest 128-bit lane can be nonzero.  When not fully reduced,
+    # more than one lane may be used, and they need to be XOR'd together.
+    my ( $GHASH_ACC, $GHASH_ACC_XMM ) = ( "%zmm10", "%xmm10" );
+
+    # LE_CTR_INC is the vector of 32-bit words that need to be added to a
+    # vector of little-endian counter blocks to advance it forwards.
+    my $LE_CTR_INC = "%zmm11";
+
+    # LE_CTR contains the next set of little-endian counter blocks.
+    my $LE_CTR = "%zmm12";
+
+    # RNDKEY0, RNDKEYLAST, and RNDKEY_M[9-1] contain cached AES round keys,
+    # copied to all 128-bit lanes.  RNDKEY0 is the zero-th round key,
+    # RNDKEYLAST the last, and RNDKEY_M\i the one \i-th from the last.
+    my (
+        $RNDKEY0,   $RNDKEYLAST, $RNDKEY_M9, $RNDKEY_M8,
+        $RNDKEY_M7, $RNDKEY_M6,  $RNDKEY_M5, $RNDKEY_M4,
+        $RNDKEY_M3, $RNDKEY_M2,  $RNDKEY_M1
+      )
+      = (
+        "%zmm13", "%zmm14", "%zmm15", "%zmm16", "%zmm17", "%zmm18",
+        "%zmm19", "%zmm20", "%zmm21", "%zmm22", "%zmm23"
+      );
+
+    # GHASHTMP[0-2] are temporary variables used by _ghash_step_4x.  These
+    # cannot coincide with anything used for AES encryption, since for
+    # performance reasons GHASH and AES encryption are interleaved.
+    my ( $GHASHTMP0, $GHASHTMP1, $GHASHTMP2 ) =
+      ( "%zmm24", "%zmm25", "%zmm26" );
+
+    # H_POW[4-1] contain the powers of the hash key H^16...H^1.  The descending
+    # numbering reflects the order of the key powers.
+    my ( $H_POW4, $H_POW3, $H_POW2, $H_POW1 ) =
+      ( "%zmm27", "%zmm28", "%zmm29", "%zmm30" );
+
+    # GFPOLY contains the .Lgfpoly constant, copied to all 128-bit lanes.
+    my $GFPOLY = "%zmm31";
+
+    my @ghash_4x_args = (
+        $BSWAP_MASK, @GHASHDATA, @GHASHDATA_XMM, $H_POW4,
+        $H_POW3,     $H_POW2,    $H_POW1,        $GFPOLY,
+        $GHASHTMP0,  $GHASHTMP1, $GHASHTMP2,     $GHASH_ACC,
+        $GHASH_ACC_XMM
+    );
+
+    if ($win64) {
+        $code .= <<___;
+        @{[ _save_gpregs $BE_CTR_PTR, $HTABLE, $GHASH_ACC_PTR ]}
+        mov             64(%rsp), $BE_CTR_PTR     # arg5
+        mov             72(%rsp), $HTABLE         # arg6
+        mov             80(%rsp), $GHASH_ACC_PTR  # arg7
+        @{[ _save_xmmregs (6 .. 15) ]}
+        .seh_endprologue
+___
+    }
+    else {
+        $code .= <<___;
+        @{[ _save_gpregs $GHASH_ACC_PTR ]}
+        mov             16(%rsp), $GHASH_ACC_PTR  # arg7
+___
+    }
+
+    if ($enc) {
+        $code .= <<___;
+#ifdef BORINGSSL_DISPATCH_TEST
+        .extern BORINGSSL_function_hit
+        movb \$1,BORINGSSL_function_hit+7(%rip)
+#endif
+___
+    }
+    $code .= <<___;
+    # Load some constants.
+    vbroadcasti32x4 .Lbswap_mask(%rip), $BSWAP_MASK
+    vbroadcasti32x4 .Lgfpoly(%rip), $GFPOLY
+
+    # Load the GHASH accumulator and the starting counter.
+    # BoringSSL passes these values in big endian format.
+    vmovdqu         ($GHASH_ACC_PTR), $GHASH_ACC_XMM
+    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+    vbroadcasti32x4 ($BE_CTR_PTR), $LE_CTR
+    vpshufb         $BSWAP_MASK, $LE_CTR, $LE_CTR
+
+    # Load the AES key length in bytes.  BoringSSL stores number of rounds
+    # minus 1, so convert using: AESKEYLEN = 4 * aeskey->rounds - 20.
+    movl            $OFFSETOF_AES_ROUNDS($AESKEY), $AESKEYLEN
+    lea             -20(,$AESKEYLEN,4), $AESKEYLEN
+
+    # Make RNDKEYLAST_PTR point to the last AES round key.  This is the
+    # round key with index 10, 12, or 14 for AES-128, AES-192, or AES-256
+    # respectively.  Then load the zero-th and last round keys.
+    lea             6*16($AESKEY,$AESKEYLEN64,4), $RNDKEYLAST_PTR
+    vbroadcasti32x4 ($AESKEY), $RNDKEY0
+    vbroadcasti32x4 ($RNDKEYLAST_PTR), $RNDKEYLAST
+
+    # Finish initializing LE_CTR by adding [0, 1, 2, 3] to its low words.
+    vpaddd          .Lctr_pattern(%rip), $LE_CTR, $LE_CTR
+
+    # Load 4 into all 128-bit lanes of LE_CTR_INC.
+    vbroadcasti32x4 .Linc_4blocks(%rip), $LE_CTR_INC
+
+    # If there are at least 256 bytes of data, then continue into the loop
+    # that processes 256 bytes of data at a time.  Otherwise skip it.
+    cmp             \$256, $DATALEN
+    jb              .Lcrypt_loop_4x_done$local_label_suffix
+
+    # Load powers of the hash key.
+    vmovdqu8        $OFFSETOFEND_H_POWERS-4*64($HTABLE), $H_POW4
+    vmovdqu8        $OFFSETOFEND_H_POWERS-3*64($HTABLE), $H_POW3
+    vmovdqu8        $OFFSETOFEND_H_POWERS-2*64($HTABLE), $H_POW2
+    vmovdqu8        $OFFSETOFEND_H_POWERS-1*64($HTABLE), $H_POW1
+___
+
+    # Main loop: en/decrypt and hash 4 vectors at a time.
+    #
+    # When possible, interleave the AES encryption of the counter blocks
+    # with the GHASH update of the ciphertext blocks.  This improves
+    # performance on many CPUs because the execution ports used by the VAES
+    # instructions often differ from those used by vpclmulqdq and other
+    # instructions used in GHASH.  For example, many Intel CPUs dispatch
+    # vaesenc to ports 0 and 1 and vpclmulqdq to port 5.
+    #
+    # The interleaving is easiest to do during decryption, since during
+    # decryption the ciphertext blocks are immediately available.  For
+    # encryption, instead encrypt the first set of blocks, then hash those
+    # blocks while encrypting the next set of blocks, repeat that as
+    # needed, and finally hash the last set of blocks.
+
+    if ($enc) {
+        $code .= <<___;
+        # Encrypt the first 4 vectors of plaintext blocks.  Leave the resulting
+        # ciphertext in GHASHDATA[0-3] for GHASH.
+        @{[ _ctr_begin_4x $LE_CTR, $LE_CTR_INC, $BSWAP_MASK, $RNDKEY0, @AESDATA ]}
+        lea             16($AESKEY), %rax
+.Lvaesenc_loop_first_4_vecs$local_label_suffix:
+        vbroadcasti32x4 (%rax), $RNDKEY
+        @{[ _vaesenc_4x $RNDKEY, @AESDATA ]}
+        add             \$16, %rax
+        cmp             %rax, $RNDKEYLAST_PTR
+        jne             .Lvaesenc_loop_first_4_vecs$local_label_suffix
+        @{[ _aesenclast_and_xor_4x $SRC, $DST, $RNDKEYLAST, @AESDATA, @GHASHDATA ]}
+        add             \$256, $SRC
+        add             \$256, $DST
+        sub             \$256, $DATALEN
+        cmp             \$256, $DATALEN
+        jb              .Lghash_last_ciphertext_4x$local_label_suffix
+___
+    }
+
+    $code .= <<___;
+    # Cache as many additional AES round keys as possible.
+    vbroadcasti32x4 -9*16($RNDKEYLAST_PTR), $RNDKEY_M9
+    vbroadcasti32x4 -8*16($RNDKEYLAST_PTR), $RNDKEY_M8
+    vbroadcasti32x4 -7*16($RNDKEYLAST_PTR), $RNDKEY_M7
+    vbroadcasti32x4 -6*16($RNDKEYLAST_PTR), $RNDKEY_M6
+    vbroadcasti32x4 -5*16($RNDKEYLAST_PTR), $RNDKEY_M5
+    vbroadcasti32x4 -4*16($RNDKEYLAST_PTR), $RNDKEY_M4
+    vbroadcasti32x4 -3*16($RNDKEYLAST_PTR), $RNDKEY_M3
+    vbroadcasti32x4 -2*16($RNDKEYLAST_PTR), $RNDKEY_M2
+    vbroadcasti32x4 -1*16($RNDKEYLAST_PTR), $RNDKEY_M1
+
+.Lcrypt_loop_4x$local_label_suffix:
+___
+
+    # If decrypting, load more ciphertext blocks into GHASHDATA[0-3].  If
+    # encrypting, GHASHDATA[0-3] already contain the previous ciphertext.
+    if ( !$enc ) {
+        $code .= <<___;
+        vmovdqu8        0*64($SRC), $GHASHDATA0
+        vmovdqu8        1*64($SRC), $GHASHDATA1
+        vmovdqu8        2*64($SRC), $GHASHDATA2
+        vmovdqu8        3*64($SRC), $GHASHDATA3
+___
+    }
+
+    $code .= <<___;
+    # Start the AES encryption of the counter blocks.
+    @{[ _ctr_begin_4x $LE_CTR, $LE_CTR_INC, $BSWAP_MASK, $RNDKEY0, @AESDATA ]}
+    cmp             \$24, $AESKEYLEN
+    jl              .Laes128$local_label_suffix
+    je              .Laes192$local_label_suffix
+    # AES-256
+    vbroadcasti32x4 -13*16($RNDKEYLAST_PTR), $RNDKEY
+    @{[ _vaesenc_4x $RNDKEY, @AESDATA ]}
+    vbroadcasti32x4 -12*16($RNDKEYLAST_PTR), $RNDKEY
+    @{[ _vaesenc_4x $RNDKEY, @AESDATA ]}
+.Laes192$local_label_suffix:
+    vbroadcasti32x4 -11*16($RNDKEYLAST_PTR), $RNDKEY
+    @{[ _vaesenc_4x $RNDKEY, @AESDATA ]}
+    vbroadcasti32x4 -10*16($RNDKEYLAST_PTR), $RNDKEY
+    @{[ _vaesenc_4x $RNDKEY, @AESDATA ]}
+.Laes128$local_label_suffix:
+
+    # Prefetch the source data 512 bytes ahead into the L1 data cache, to
+    # improve performance when the hardware prefetcher is disabled.  Assumes the
+    # L1 data cache line size is 64 bytes (de facto standard on x86_64).
+    prefetcht0      512+0*64($SRC)
+    prefetcht0      512+1*64($SRC)
+    prefetcht0      512+2*64($SRC)
+    prefetcht0      512+3*64($SRC)
+
+    # Finish the AES encryption of the counter blocks in AESDATA[0-3],
+    # interleaved with the GHASH update of the ciphertext blocks in
+    # GHASHDATA[0-3].
+    @{[ _ghash_step_4x  0, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M9, @AESDATA ]}
+    @{[ _ghash_step_4x  1, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M8, @AESDATA ]}
+    @{[ _ghash_step_4x  2, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M7, @AESDATA ]}
+    @{[ _ghash_step_4x  3, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M6, @AESDATA ]}
+    @{[ _ghash_step_4x  4, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M5, @AESDATA ]}
+    @{[ _ghash_step_4x  5, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M4, @AESDATA ]}
+    @{[ _ghash_step_4x  6, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M3, @AESDATA ]}
+    @{[ _ghash_step_4x  7, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M2, @AESDATA ]}
+    @{[ _ghash_step_4x  8, @ghash_4x_args ]}
+    @{[ _vaesenc_4x     $RNDKEY_M1, @AESDATA ]}
+
+    @{[ _ghash_step_4x  9, @ghash_4x_args ]}
+    @{[ _aesenclast_and_xor_4x $SRC, $DST, $RNDKEYLAST, @AESDATA, @GHASHDATA ]}
+    add             \$256, $SRC
+    add             \$256, $DST
+    sub             \$256, $DATALEN
+    cmp             \$256, $DATALEN
+    jae             .Lcrypt_loop_4x$local_label_suffix
+___
+
+    if ($enc) {
+
+        # Update GHASH with the last set of ciphertext blocks.
+        $code .= <<___;
+.Lghash_last_ciphertext_4x$local_label_suffix:
+        @{[ _ghash_4x @ghash_4x_args ]}
+___
+    }
+
+    my $POWERS_PTR = $BE_CTR_PTR;    # BE_CTR_PTR is free to be reused.
+
+    $code .= <<___;
+.Lcrypt_loop_4x_done$local_label_suffix:
+    # Check whether any data remains.
+    test            $DATALEN, $DATALEN
+    jz              .Ldone$local_label_suffix
+
+    # The data length isn't a multiple of 256 bytes.  Process the remaining
+    # data of length 1 <= DATALEN < 256, up to one 64-byte vector at a time.
+    # Going one vector at a time may seem inefficient compared to having
+    # separate code paths for each possible number of vectors remaining.
+    # However, using a loop keeps the code size down, and it performs
+    # surprising well; modern CPUs will start executing the next iteration
+    # before the previous one finishes and also predict the number of loop
+    # iterations.  For a similar reason, we roll up the AES rounds.
+    #
+    # On the last iteration, the remaining length may be less than 64 bytes.
+    # Handle this using masking.
+    #
+    # Since there are enough key powers available for all remaining data,
+    # there is no need to do a GHASH reduction after each iteration.
+    # Instead, multiply each remaining block by its own key power, and only
+    # do a GHASH reduction at the very end.
+
+    # Make POWERS_PTR point to the key powers [H^N, H^(N-1), ...] where N
+    # is the number of blocks that remain.
+    mov             $DATALEN, %rax
+    neg             %rax
+    and             \$-16, %rax  # -round_up(DATALEN, 16)
+    lea             $OFFSETOFEND_H_POWERS($HTABLE,%rax), $POWERS_PTR
+___
+
+    # Start collecting the unreduced GHASH intermediate value LO, MI, HI.
+    my ( $LO, $LO_XMM ) = ( $GHASHDATA0, $GHASHDATA0_XMM );
+    my ( $MI, $MI_XMM ) = ( $GHASHDATA1, $GHASHDATA1_XMM );
+    my ( $HI, $HI_XMM ) = ( $GHASHDATA2, $GHASHDATA2_XMM );
+    $code .= <<___;
+    vpxor           $LO_XMM, $LO_XMM, $LO_XMM
+    vpxor           $MI_XMM, $MI_XMM, $MI_XMM
+    vpxor           $HI_XMM, $HI_XMM, $HI_XMM
+
+    cmp             \$64, $DATALEN
+    jb              .Lpartial_vec$local_label_suffix
+
+.Lcrypt_loop_1x$local_label_suffix:
+    # Process a full 64-byte vector.
+
+    # Encrypt a vector of counter blocks.
+    vpshufb         $BSWAP_MASK, $LE_CTR, $AESDATA0
+    vpaddd          $LE_CTR_INC, $LE_CTR, $LE_CTR
+    vpxord          $RNDKEY0, $AESDATA0, $AESDATA0
+    lea             16($AESKEY), %rax
+.Lvaesenc_loop_tail_full_vec$local_label_suffix:
+    vbroadcasti32x4 (%rax), $RNDKEY
+    vaesenc         $RNDKEY, $AESDATA0, $AESDATA0
+    add             \$16, %rax
+    cmp             %rax, $RNDKEYLAST_PTR
+    jne             .Lvaesenc_loop_tail_full_vec$local_label_suffix
+    vaesenclast     $RNDKEYLAST, $AESDATA0, $AESDATA0
+
+    # XOR the data with the vector of keystream blocks.
+    vmovdqu8        ($SRC), $AESDATA1
+    vpxord          $AESDATA1, $AESDATA0, $AESDATA0
+    vmovdqu8        $AESDATA0, ($DST)
+
+    # Update GHASH with the ciphertext blocks, without reducing.
+    vmovdqu8        ($POWERS_PTR), $H_POW1
+    vpshufb         $BSWAP_MASK, @{[ $enc ? $AESDATA0 : $AESDATA1 ]}, $AESDATA0
+    vpxord          $GHASH_ACC, $AESDATA0, $AESDATA0
+    @{[ _ghash_mul_noreduce $H_POW1, $AESDATA0, $LO, $MI, $HI,
+                            $GHASHDATA3, $AESDATA1, $AESDATA2, $AESDATA3 ]}
+    vpxor           $GHASH_ACC_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+
+    add             \$64, $POWERS_PTR
+    add             \$64, $SRC
+    add             \$64, $DST
+    sub             \$64, $DATALEN
+    cmp             \$64, $DATALEN
+    jae             .Lcrypt_loop_1x$local_label_suffix
+
+    test            $DATALEN, $DATALEN
+    jz              .Lreduce$local_label_suffix
+
+.Lpartial_vec$local_label_suffix:
+    # Process a partial vector of length 1 <= DATALEN < 64.
+
+    # Set the data mask %k1 to DATALEN 1's.
+    # Set the key powers mask %k2 to round_up(DATALEN, 16) 1's.
+    mov             \$-1, %rax
+    bzhi            $DATALEN, %rax, %rax
+    kmovq           %rax, %k1
+    add             \$15, $DATALEN
+    and             \$-16, $DATALEN
+    mov             \$-1, %rax
+    bzhi            $DATALEN, %rax, %rax
+    kmovq           %rax, %k2
+
+    # Encrypt one last vector of counter blocks.  This does not need to be
+    # masked.  The counter does not need to be incremented here.
+    vpshufb         $BSWAP_MASK, $LE_CTR, $AESDATA0
+    vpxord          $RNDKEY0, $AESDATA0, $AESDATA0
+    lea             16($AESKEY), %rax
+.Lvaesenc_loop_tail_partialvec$local_label_suffix:
+    vbroadcasti32x4 (%rax), $RNDKEY
+    vaesenc         $RNDKEY, $AESDATA0, $AESDATA0
+    add             \$16, %rax
+    cmp             %rax, $RNDKEYLAST_PTR
+    jne             .Lvaesenc_loop_tail_partialvec$local_label_suffix
+    vaesenclast     $RNDKEYLAST, $AESDATA0, $AESDATA0
+
+    # XOR the data with the appropriate number of keystream bytes.
+    vmovdqu8        ($SRC), $AESDATA1\{%k1}{z}
+    vpxord          $AESDATA1, $AESDATA0, $AESDATA0
+    vmovdqu8        $AESDATA0, ($DST){%k1}
+
+    # Update GHASH with the ciphertext block(s), without reducing.
+    #
+    # In the case of DATALEN < 64, the ciphertext is zero-padded to 64
+    # bytes.  (If decrypting, it's done by the above masked load.  If
+    # encrypting, it's done by the below masked register-to-register move.)
+    # Note that if DATALEN <= 48, there will be additional padding beyond
+    # the padding of the last block specified by GHASH itself; i.e., there
+    # may be whole block(s) that get processed by the GHASH multiplication
+    # and reduction instructions but should not actually be included in the
+    # GHASH.  However, any such blocks are all-zeroes, and the values that
+    # they're multiplied with are also all-zeroes.  Therefore they just add
+    # 0 * 0 = 0 to the final GHASH result, which makes no difference.
+    vmovdqu8        ($POWERS_PTR), $H_POW1\{%k2}{z}
+    @{[ $enc ? "vmovdqu8 $AESDATA0, $AESDATA1\{%k1}{z}" : "" ]}
+    vpshufb         $BSWAP_MASK, $AESDATA1, $AESDATA0
+    vpxord          $GHASH_ACC, $AESDATA0, $AESDATA0
+    @{[ _ghash_mul_noreduce $H_POW1, $AESDATA0, $LO, $MI, $HI,
+                            $GHASHDATA3, $AESDATA1, $AESDATA2, $AESDATA3 ]}
+
+.Lreduce$local_label_suffix:
+    # Finally, do the GHASH reduction.
+    @{[ _ghash_reduce   $LO, $MI, $HI, $GFPOLY, $AESDATA0 ]}
+    @{[ _horizontal_xor $HI, $HI_XMM, $GHASH_ACC_XMM,
+                        $AESDATA0_XMM, $AESDATA1_XMM, $AESDATA2_XMM ]}
+
+.Ldone$local_label_suffix:
+    # Store the updated GHASH accumulator back to memory.
+    vpshufb         $BSWAP_MASK_XMM, $GHASH_ACC_XMM, $GHASH_ACC_XMM
+    vmovdqu         $GHASH_ACC_XMM, ($GHASH_ACC_PTR)
+
+    vzeroupper      # This is needed after using ymm or zmm registers.
+___
+    return $code;
+}
+
+$code .= _begin_func "aes_gcm_enc_update_vaes_avx512", 1;
+$code .= _aes_gcm_update 1;
+$code .= _end_func;
+
+$code .= _begin_func "aes_gcm_dec_update_vaes_avx512", 1;
+$code .= _aes_gcm_update 0;
+$code .= _end_func;
+
+print $code;
+close STDOUT or die "error closing STDOUT: $!";
+exit 0;
diff --git a/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl b/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl
index 08df44e..930ae14 100644
--- a/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl
+++ b/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl
@@ -3983,64 +3983,7 @@
 ___
 }
 
-sub rex {
-  local *opcode=shift;
-  my ($dst,$src)=@_;
-  my $rex=0;
-
-    $rex|=0x04			if($dst>=8);
-    $rex|=0x01			if($src>=8);
-    push @opcode,$rex|0x40	if($rex);
-}
-
-sub aesni {
-  my $line=shift;
-  my @opcode=(0x66);
-
-    if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-	rex(\@opcode,$4,$3);
-	push @opcode,0x0f,0x3a,0xdf;
-	push @opcode,0xc0|($3&7)|(($4&7)<<3);	# ModR/M
-	my $c=$2;
-	push @opcode,$c=~/^0/?oct($c):$c;
-	return ".byte\t".join(',',@opcode);
-    }
-    elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-	my %opcodelet = (
-		"aesimc" => 0xdb,
-		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
-		"aesdec" => 0xde,	"aesdeclast" => 0xdf
-	);
-	return undef if (!defined($opcodelet{$1}));
-	rex(\@opcode,$3,$2);
-	push @opcode,0x0f,0x38,$opcodelet{$1};
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);	# ModR/M
-	return ".byte\t".join(',',@opcode);
-    }
-    elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
-	my %opcodelet = (
-		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
-		"aesdec" => 0xde,	"aesdeclast" => 0xdf
-	);
-	return undef if (!defined($opcodelet{$1}));
-	my $off = $2;
-	push @opcode,0x44 if ($3>=8);
-	push @opcode,0x0f,0x38,$opcodelet{$1};
-	push @opcode,0x44|(($3&7)<<3),0x24;	# ModR/M
-	push @opcode,($off=~/^0/?oct($off):$off)&0xff;
-	return ".byte\t".join(',',@opcode);
-    }
-    return $line;
-}
-
-sub movbe {
-	".byte	0x0f,0x38,0xf1,0x44,0x24,".shift;
-}
-
 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
-$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
-#$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm;	# debugging artefact
-$code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem;
 
 print $code;
 
diff --git a/src/crypto/fipsmodule/aes/gcm.cc.inc b/src/crypto/fipsmodule/aes/gcm.cc.inc
index c3c68f2..30855ee 100644
--- a/src/crypto/fipsmodule/aes/gcm.cc.inc
+++ b/src/crypto/fipsmodule/aes/gcm.cc.inc
@@ -109,9 +109,9 @@
       aes_gcm_enc_update_vaes_avx2(in, out, len, key, ivec, Htable, Xi);
       CRYPTO_store_u32_be(&ivec[12], CRYPTO_load_u32_be(&ivec[12]) + len / 16);
       return len;
-    case gcm_x86_vaes_avx10_512:
+    case gcm_x86_vaes_avx512:
       len &= kSizeTWithoutLower4Bits;
-      aes_gcm_enc_update_vaes_avx10_512(in, out, len, key, ivec, Htable, Xi);
+      aes_gcm_enc_update_vaes_avx512(in, out, len, key, ivec, Htable, Xi);
       CRYPTO_store_u32_be(&ivec[12], CRYPTO_load_u32_be(&ivec[12]) + len / 16);
       return len;
     default:
@@ -129,9 +129,9 @@
       aes_gcm_dec_update_vaes_avx2(in, out, len, key, ivec, Htable, Xi);
       CRYPTO_store_u32_be(&ivec[12], CRYPTO_load_u32_be(&ivec[12]) + len / 16);
       return len;
-    case gcm_x86_vaes_avx10_512:
+    case gcm_x86_vaes_avx512:
       len &= kSizeTWithoutLower4Bits;
-      aes_gcm_dec_update_vaes_avx10_512(in, out, len, key, ivec, Htable, Xi);
+      aes_gcm_dec_update_vaes_avx512(in, out, len, key, ivec, Htable, Xi);
       CRYPTO_store_u32_be(&ivec[12], CRYPTO_load_u32_be(&ivec[12]) + len / 16);
       return len;
     default:
@@ -179,9 +179,9 @@
     if (CRYPTO_is_VPCLMULQDQ_capable() && CRYPTO_is_AVX2_capable()) {
       if (CRYPTO_is_AVX512BW_capable() && CRYPTO_is_AVX512VL_capable() &&
           CRYPTO_is_BMI2_capable() && !CRYPTO_cpu_avoid_zmm_registers()) {
-        gcm_init_vpclmulqdq_avx10_512(out_table, H);
-        *out_mult = gcm_gmult_vpclmulqdq_avx10;
-        *out_hash = gcm_ghash_vpclmulqdq_avx10_512;
+        gcm_init_vpclmulqdq_avx512(out_table, H);
+        *out_mult = gcm_gmult_vpclmulqdq_avx512;
+        *out_hash = gcm_ghash_vpclmulqdq_avx512;
         return;
       }
       gcm_init_vpclmulqdq_avx2(out_table, H);
@@ -266,9 +266,9 @@
 
 #if !defined(OPENSSL_NO_ASM)
 #if defined(OPENSSL_X86_64)
-  if (gcm_key->ghash == gcm_ghash_vpclmulqdq_avx10_512 &&
+  if (gcm_key->ghash == gcm_ghash_vpclmulqdq_avx512 &&
       CRYPTO_is_VAES_capable()) {
-    gcm_key->impl = gcm_x86_vaes_avx10_512;
+    gcm_key->impl = gcm_x86_vaes_avx512;
   } else if (gcm_key->ghash == gcm_ghash_vpclmulqdq_avx2 &&
              CRYPTO_is_VAES_capable()) {
     gcm_key->impl = gcm_x86_vaes_avx2;
@@ -596,7 +596,7 @@
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
 int crypto_gcm_clmul_enabled(void) {
 #if defined(GHASH_ASM_X86) || defined(GHASH_ASM_X86_64)
-  return CRYPTO_is_FXSR_capable() && CRYPTO_is_PCLMUL_capable();
+  return CRYPTO_is_PCLMUL_capable() && CRYPTO_is_SSSE3_capable();
 #else
   return 0;
 #endif
diff --git a/src/crypto/fipsmodule/aes/gcm_test.cc b/src/crypto/fipsmodule/aes/gcm_test.cc
index 5b8ce5e..4a40fad 100644
--- a/src/crypto/fipsmodule/aes/gcm_test.cc
+++ b/src/crypto/fipsmodule/aes/gcm_test.cc
@@ -111,26 +111,25 @@
       static const uint8_t kKey[16] = {0};
       uint8_t iv[16] = {0};
 
-      CHECK_ABI_SEH(gcm_init_vpclmulqdq_avx10_512, Htable, kH);
-      CHECK_ABI_SEH(gcm_gmult_vpclmulqdq_avx10, X, Htable);
+      CHECK_ABI_SEH(gcm_init_vpclmulqdq_avx512, Htable, kH);
+      CHECK_ABI_SEH(gcm_gmult_vpclmulqdq_avx512, X, Htable);
       for (size_t blocks : kBlockCounts) {
-        CHECK_ABI_SEH(gcm_ghash_vpclmulqdq_avx10_512, X, Htable, buf,
-                      16 * blocks);
+        CHECK_ABI_SEH(gcm_ghash_vpclmulqdq_avx512, X, Htable, buf, 16 * blocks);
       }
 
       aes_hw_set_encrypt_key(kKey, 128, &aes_key);
       for (size_t blocks : kBlockCounts) {
-        CHECK_ABI_SEH(aes_gcm_enc_update_vaes_avx10_512, buf, buf, blocks * 16,
+        CHECK_ABI_SEH(aes_gcm_enc_update_vaes_avx512, buf, buf, blocks * 16,
                       &aes_key, iv, Htable, X);
-        CHECK_ABI_SEH(aes_gcm_enc_update_vaes_avx10_512, buf, buf,
-                      blocks * 16 + 7, &aes_key, iv, Htable, X);
+        CHECK_ABI_SEH(aes_gcm_enc_update_vaes_avx512, buf, buf, blocks * 16 + 7,
+                      &aes_key, iv, Htable, X);
       }
       aes_hw_set_decrypt_key(kKey, 128, &aes_key);
       for (size_t blocks : kBlockCounts) {
-        CHECK_ABI_SEH(aes_gcm_dec_update_vaes_avx10_512, buf, buf, blocks * 16,
+        CHECK_ABI_SEH(aes_gcm_dec_update_vaes_avx512, buf, buf, blocks * 16,
                       &aes_key, iv, Htable, X);
-        CHECK_ABI_SEH(aes_gcm_dec_update_vaes_avx10_512, buf, buf,
-                      blocks * 16 + 7, &aes_key, iv, Htable, X);
+        CHECK_ABI_SEH(aes_gcm_dec_update_vaes_avx512, buf, buf, blocks * 16 + 7,
+                      &aes_key, iv, Htable, X);
       }
     }
 #endif  // GHASH_ASM_X86_64
diff --git a/src/crypto/fipsmodule/aes/internal.h b/src/crypto/fipsmodule/aes/internal.h
index 7bf28b9..23766fe 100644
--- a/src/crypto/fipsmodule/aes/internal.h
+++ b/src/crypto/fipsmodule/aes/internal.h
@@ -12,13 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_AES_INTERNAL_H
-#define OPENSSL_HEADER_AES_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_AES_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_AES_INTERNAL_H
 
 #include <stdlib.h>
 
-#include <openssl/aes.h>
-
+#include "../bcm_interface.h"
 #include "../../internal.h"
 
 extern "C" {
@@ -29,7 +28,7 @@
 // Unlike upstream OpenSSL, it and the other functions in this file hard-code
 // |AES_KEY|. It is undefined in C to call a function pointer with anything
 // other than the original type. Thus we either must match |block128_f| to the
-// type signature of |AES_encrypt| and friends or pass in |void*| wrapper
+// type signature of |BCM_aes_encrypt| and friends or pass in |void*| wrapper
 // functions.
 //
 // These functions are called exclusively with AES, so we use the former.
@@ -314,7 +313,7 @@
   gcm_separate = 0,  // No combined AES-GCM, but may have AES-CTR and GHASH.
   gcm_x86_aesni,
   gcm_x86_vaes_avx2,
-  gcm_x86_vaes_avx10_512,
+  gcm_x86_vaes_avx512,
   gcm_arm64_aes,
 };
 
@@ -455,18 +454,16 @@
                                   const AES_KEY *key, const uint8_t ivec[16],
                                   const u128 Htable[16], uint8_t Xi[16]);
 
-void gcm_init_vpclmulqdq_avx10_512(u128 Htable[16], const uint64_t H[2]);
-void gcm_gmult_vpclmulqdq_avx10(uint8_t Xi[16], const u128 Htable[16]);
-void gcm_ghash_vpclmulqdq_avx10_512(uint8_t Xi[16], const u128 Htable[16],
-                                    const uint8_t *in, size_t len);
-void aes_gcm_enc_update_vaes_avx10_512(const uint8_t *in, uint8_t *out,
-                                       size_t len, const AES_KEY *key,
-                                       const uint8_t ivec[16],
-                                       const u128 Htable[16], uint8_t Xi[16]);
-void aes_gcm_dec_update_vaes_avx10_512(const uint8_t *in, uint8_t *out,
-                                       size_t len, const AES_KEY *key,
-                                       const uint8_t ivec[16],
-                                       const u128 Htable[16], uint8_t Xi[16]);
+void gcm_init_vpclmulqdq_avx512(u128 Htable[16], const uint64_t H[2]);
+void gcm_gmult_vpclmulqdq_avx512(uint8_t Xi[16], const u128 Htable[16]);
+void gcm_ghash_vpclmulqdq_avx512(uint8_t Xi[16], const u128 Htable[16],
+                                 const uint8_t *in, size_t len);
+void aes_gcm_enc_update_vaes_avx512(const uint8_t *in, uint8_t *out, size_t len,
+                                    const AES_KEY *key, const uint8_t ivec[16],
+                                    const u128 Htable[16], uint8_t Xi[16]);
+void aes_gcm_dec_update_vaes_avx512(const uint8_t *in, uint8_t *out, size_t len,
+                                    const AES_KEY *key, const uint8_t ivec[16],
+                                    const u128 Htable[16], uint8_t Xi[16]);
 
 #endif  // OPENSSL_X86_64
 
@@ -572,32 +569,6 @@
                                    block128_f block);
 
 
-// POLYVAL.
-//
-// POLYVAL is a polynomial authenticator that operates over a field very
-// similar to the one that GHASH uses. See
-// https://www.rfc-editor.org/rfc/rfc8452.html#section-3.
-
-struct polyval_ctx {
-  uint8_t S[16];
-  u128 Htable[16];
-  gmult_func gmult;
-  ghash_func ghash;
-};
-
-// CRYPTO_POLYVAL_init initialises |ctx| using |key|.
-void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]);
-
-// CRYPTO_POLYVAL_update_blocks updates the accumulator in |ctx| given the
-// blocks from |in|. Only a whole number of blocks can be processed so |in_len|
-// must be a multiple of 16.
-void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
-                                  size_t in_len);
-
-// CRYPTO_POLYVAL_finish writes the accumulator from |ctx| to |out|.
-void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]);
-
-
 }  // extern C
 
-#endif  // OPENSSL_HEADER_AES_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_AES_INTERNAL_H
diff --git a/src/crypto/fipsmodule/aes/key_wrap.cc.inc b/src/crypto/fipsmodule/aes/key_wrap.cc.inc
index 99c2450..ad1c314 100644
--- a/src/crypto/fipsmodule/aes/key_wrap.cc.inc
+++ b/src/crypto/fipsmodule/aes/key_wrap.cc.inc
@@ -20,6 +20,7 @@
 
 #include <openssl/mem.h>
 
+#include "../bcm_interface.h"
 #include "../../internal.h"
 #include "../service_indicator/internal.h"
 
@@ -53,7 +54,7 @@
   for (unsigned j = 0; j < kBound; j++) {
     for (size_t i = 1; i <= n; i++) {
       OPENSSL_memcpy(A + 8, out + 8 * i, 8);
-      AES_encrypt(A, A, key);
+      BCM_aes_encrypt(A, A, key);
 
       uint32_t t = (uint32_t)(n * j + i);
       A[7] ^= t & 0xff;
@@ -96,7 +97,7 @@
       A[5] ^= (t >> 16) & 0xff;
       A[4] ^= (t >> 24) & 0xff;
       OPENSSL_memcpy(A + 8, out + 8 * (i - 1), 8);
-      AES_decrypt(A, A, key);
+      BCM_aes_decrypt(A, A, key);
       OPENSSL_memcpy(out + 8 * (i - 1), A + 8, 8);
     }
   }
@@ -145,7 +146,7 @@
   if (in_len <= 8) {
     memset(block + 8, 0, 8);
     memcpy(block + 8, in, in_len);
-    AES_encrypt(block, out, key);
+    BCM_aes_encrypt(block, out, key);
     *out_len = AES_BLOCK_SIZE;
     return 1;
   }
@@ -179,7 +180,7 @@
   uint8_t iv[8];
   if (in_len == AES_BLOCK_SIZE) {
     uint8_t block[AES_BLOCK_SIZE];
-    AES_decrypt(in, block, key);
+    BCM_aes_decrypt(in, block, key);
     memcpy(iv, block, sizeof(iv));
     memcpy(out, block + 8, 8);
   } else if (!aes_unwrap_key_inner(key, out, iv, in, in_len)) {
diff --git a/src/crypto/fipsmodule/aes/mode_wrappers.cc.inc b/src/crypto/fipsmodule/aes/mode_wrappers.cc.inc
index be5fba9..fdbab94 100644
--- a/src/crypto/fipsmodule/aes/mode_wrappers.cc.inc
+++ b/src/crypto/fipsmodule/aes/mode_wrappers.cc.inc
@@ -19,6 +19,15 @@
 #include "../aes/internal.h"
 #include "../service_indicator/internal.h"
 
+namespace {
+void aes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+  BCM_aes_encrypt(in, out, key);
+}
+
+void aes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+  BCM_aes_decrypt(in, out, key);
+}
+}
 
 void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
                         const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
@@ -45,9 +54,9 @@
   assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
 
   if (AES_ENCRYPT == enc) {
-    AES_encrypt(in, out, key);
+    BCM_aes_encrypt(in, out, key);
   } else {
-    AES_decrypt(in, out, key);
+    BCM_aes_decrypt(in, out, key);
   }
 
   FIPS_service_indicator_update_state();
@@ -60,9 +69,9 @@
   } else if (!vpaes_capable()) {
     aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
   } else if (enc) {
-    CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt);
+    CRYPTO_cbc128_encrypt(in, out, len, key, ivec, aes_encrypt);
   } else {
-    CRYPTO_cbc128_decrypt(in, out, len, key, ivec, AES_decrypt);
+    CRYPTO_cbc128_decrypt(in, out, len, key, ivec, aes_decrypt);
   }
 
   FIPS_service_indicator_update_state();
@@ -71,7 +80,7 @@
 void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
                         const AES_KEY *key, uint8_t *ivec, int *num) {
   unsigned num_u = (unsigned)(*num);
-  CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u, AES_encrypt);
+  CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u, aes_encrypt);
   *num = (int)num_u;
 }
 
@@ -79,6 +88,6 @@
                         const AES_KEY *key, uint8_t *ivec, int *num,
                         int enc) {
   unsigned num_u = (unsigned)(*num);
-  CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc, AES_encrypt);
+  CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc, aes_encrypt);
   *num = (int)num_u;
 }
diff --git a/src/crypto/fipsmodule/aes/polyval.cc.inc b/src/crypto/fipsmodule/aes/polyval.cc.inc
deleted file mode 100644
index c824cee..0000000
--- a/src/crypto/fipsmodule/aes/polyval.cc.inc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The BoringSSL Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <openssl/base.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include "internal.h"
-#include "../../internal.h"
-
-
-// byte_reverse reverses the order of the bytes in |b->c|.
-static void byte_reverse(uint8_t b[16]) {
-  uint64_t hi = CRYPTO_load_u64_le(b);
-  uint64_t lo = CRYPTO_load_u64_le(b + 8);
-  CRYPTO_store_u64_le(b, CRYPTO_bswap8(lo));
-  CRYPTO_store_u64_le(b + 8, CRYPTO_bswap8(hi));
-}
-
-// reverse_and_mulX_ghash interprets |b| as a reversed element of the GHASH
-// field, multiplies that by 'x' and serialises the result back into |b|, but
-// with GHASH's backwards bit ordering.
-static void reverse_and_mulX_ghash(uint8_t b[16]) {
-  uint64_t hi = CRYPTO_load_u64_le(b);
-  uint64_t lo = CRYPTO_load_u64_le(b + 8);
-  const crypto_word_t carry = constant_time_eq_w(hi & 1, 1);
-  hi >>= 1;
-  hi |= lo << 63;
-  lo >>= 1;
-  lo ^= ((uint64_t) constant_time_select_w(carry, 0xe1, 0)) << 56;
-
-  CRYPTO_store_u64_le(b, CRYPTO_bswap8(lo));
-  CRYPTO_store_u64_le(b + 8, CRYPTO_bswap8(hi));
-}
-
-// POLYVAL(H, X_1, ..., X_n) =
-// ByteReverse(GHASH(mulX_GHASH(ByteReverse(H)), ByteReverse(X_1), ...,
-// ByteReverse(X_n))).
-//
-// See https://www.rfc-editor.org/rfc/rfc8452.html#appendix-A.
-
-void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]) {
-  alignas(8) uint8_t H[16];
-  OPENSSL_memcpy(H, key, 16);
-  reverse_and_mulX_ghash(H);
-
-  CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, ctx->Htable, H);
-  OPENSSL_memset(&ctx->S, 0, sizeof(ctx->S));
-}
-
-void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
-                                  size_t in_len) {
-  assert((in_len & 15) == 0);
-  alignas(8) uint8_t buf[32 * 16];
-
-  while (in_len > 0) {
-    size_t todo = in_len;
-    if (todo > sizeof(buf)) {
-      todo = sizeof(buf);
-    }
-    OPENSSL_memcpy(buf, in, todo);
-    in += todo;
-    in_len -= todo;
-
-    size_t blocks = todo / 16;
-    for (size_t i = 0; i < blocks; i++) {
-      byte_reverse(buf + 16 * i);
-    }
-
-    ctx->ghash(ctx->S, ctx->Htable, buf, todo);
-  }
-}
-
-void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]) {
-  OPENSSL_memcpy(out, &ctx->S, 16);
-  byte_reverse(out);
-}
diff --git a/src/crypto/fipsmodule/bcm.cc b/src/crypto/fipsmodule/bcm.cc
index a23d312..e862014 100644
--- a/src/crypto/fipsmodule/bcm.cc
+++ b/src/crypto/fipsmodule/bcm.cc
@@ -44,7 +44,6 @@
 #include "aes/key_wrap.cc.inc"
 #include "aes/mode_wrappers.cc.inc"
 #include "aes/ofb.cc.inc"
-#include "aes/polyval.cc.inc"
 #include "bn/add.cc.inc"
 #include "bn/asm/x86_64-gcc.cc.inc"
 #include "bn/bn.cc.inc"
@@ -198,7 +197,7 @@
   const uint8_t *const start = BORINGSSL_bcm_text_start;
   const uint8_t *const end = BORINGSSL_bcm_text_end;
 
-  assert_within(start, reinterpret_cast<const void *>(AES_encrypt), end);
+  assert_within(start, reinterpret_cast<const void *>(BCM_aes_encrypt), end);
   assert_within(start, reinterpret_cast<const void *>(RSA_sign), end);
   assert_within(start, reinterpret_cast<const void *>(BCM_rand_bytes), end);
   assert_within(start, reinterpret_cast<const void *>(EC_GROUP_cmp), end);
@@ -258,7 +257,8 @@
 
   const uint8_t *expected = BORINGSSL_bcm_text_hash;
 
-  if (!check_test(expected, result, sizeof(result), "FIPS integrity test")) {
+  if (!BORINGSSL_check_test(expected, result, sizeof(result),
+                            "FIPS integrity test")) {
 #if !defined(BORINGSSL_FIPS_BREAK_TESTS)
     return 0;
 #endif
diff --git a/src/crypto/fipsmodule/bcm_interface.h b/src/crypto/fipsmodule/bcm_interface.h
index 065eec0..a70636d 100644
--- a/src/crypto/fipsmodule/bcm_interface.h
+++ b/src/crypto/fipsmodule/bcm_interface.h
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H
-#define OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_BCM_INTERFACE_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_BCM_INTERFACE_H
 
+// For the moment, we reach out for AES_KEY.
+#include <openssl/aes.h>
 #include <openssl/bcm_public.h>
 
+
 // This header will eventually become the interface between BCM and the
 // rest of libcrypto. More cleanly separating the two is still a work in
 // progress (see https://crbug.com/boringssl/722) so, at the moment, we
@@ -55,6 +58,9 @@
   return result ? bcm_status::approved : bcm_status::failure;
 }
 
+inline bcm_status_t bcm_as_not_approved_status(int result) {
+  return result ? bcm_status::not_approved : bcm_status::failure;
+}
 
 // Random number generator.
 
@@ -290,6 +296,18 @@
     struct BCM_mldsa65_public_key *out_public_key,
     const struct BCM_mldsa65_private_key *private_key);
 
+OPENSSL_EXPORT bcm_status
+BCM_mldsa65_check_key_fips(struct BCM_mldsa65_private_key *private_key);
+
+OPENSSL_EXPORT bcm_status BCM_mldsa65_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
+    uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
+    struct BCM_mldsa65_private_key *out_private_key);
+
+OPENSSL_EXPORT bcm_status BCM_mldsa65_private_key_from_seed_fips(
+    struct BCM_mldsa65_private_key *out_private_key,
+    const uint8_t seed[BCM_MLDSA_SEED_BYTES]);
+
 OPENSSL_EXPORT bcm_status BCM_mldsa65_sign(
     uint8_t out_encoded_signature[BCM_MLDSA65_SIGNATURE_BYTES],
     const struct BCM_mldsa65_private_key *private_key, const uint8_t *msg,
@@ -317,6 +335,11 @@
     struct BCM_mldsa65_private_key *out_private_key,
     const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
 
+OPENSSL_EXPORT bcm_status BCM_mldsa65_generate_key_external_entropy_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
+    struct BCM_mldsa65_private_key *out_private_key,
+    const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
+
 // BCM_mldsa5_sign_internal signs |msg| using |private_key| and writes the
 // signature to |out_encoded_signature|. The |context_prefix| and |context| are
 // prefixed to the message, in that order, before signing. The |randomizer|
@@ -383,6 +406,18 @@
     struct BCM_mldsa87_public_key *out_public_key,
     const struct BCM_mldsa87_private_key *private_key);
 
+OPENSSL_EXPORT bcm_status
+BCM_mldsa87_check_key_fips(struct BCM_mldsa87_private_key *private_key);
+
+OPENSSL_EXPORT bcm_status BCM_mldsa87_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
+    uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
+    struct BCM_mldsa87_private_key *out_private_key);
+
+OPENSSL_EXPORT bcm_status BCM_mldsa87_private_key_from_seed_fips(
+    struct BCM_mldsa87_private_key *out_private_key,
+    const uint8_t seed[BCM_MLDSA_SEED_BYTES]);
+
 OPENSSL_EXPORT bcm_status BCM_mldsa87_sign(
     uint8_t out_encoded_signature[BCM_MLDSA87_SIGNATURE_BYTES],
     const struct BCM_mldsa87_private_key *private_key, const uint8_t *msg,
@@ -410,6 +445,11 @@
     struct BCM_mldsa87_private_key *out_private_key,
     const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
 
+OPENSSL_EXPORT bcm_status BCM_mldsa87_generate_key_external_entropy_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
+    struct BCM_mldsa87_private_key *out_private_key,
+    const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
+
 // BCM_mldsa87_sign_internal signs |msg| using |private_key| and writes the
 // signature to |out_encoded_signature|. The |context_prefix| and |context| are
 // prefixed to the message, in that order, before signing. The |randomizer|
@@ -492,6 +532,8 @@
   } opaque;
 };
 
+
+
 OPENSSL_EXPORT bcm_infallible BCM_mlkem768_generate_key(
     uint8_t out_encoded_public_key[BCM_MLKEM768_PUBLIC_KEY_BYTES],
     uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
@@ -501,6 +543,14 @@
     struct BCM_mlkem768_private_key *out_private_key, const uint8_t *seed,
     size_t seed_len);
 
+OPENSSL_EXPORT bcm_status BCM_mlkem768_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLKEM768_PUBLIC_KEY_BYTES],
+    uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
+    struct BCM_mlkem768_private_key *out_private_key);
+
+OPENSSL_EXPORT bcm_status
+BCM_mlkem768_check_fips(const struct BCM_mlkem768_private_key *private_key);
+
 OPENSSL_EXPORT bcm_infallible BCM_mlkem768_public_from_private(
     struct BCM_mlkem768_public_key *out_public_key,
     const struct BCM_mlkem768_private_key *private_key);
@@ -576,6 +626,14 @@
     uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
     struct BCM_mlkem1024_private_key *out_private_key);
 
+OPENSSL_EXPORT bcm_status BCM_mlkem1024_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLKEM1024_PUBLIC_KEY_BYTES],
+    uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
+    struct BCM_mlkem1024_private_key *out_private_key);
+
+OPENSSL_EXPORT bcm_status
+BCM_mlkem1024_check_fips(const struct BCM_mlkem1024_private_key *private_key);
+
 OPENSSL_EXPORT bcm_status BCM_mlkem1024_private_key_from_seed(
     struct BCM_mlkem1024_private_key *out_private_key, const uint8_t *seed,
     size_t seed_len);
@@ -658,14 +716,22 @@
 // SLH-DSA-SHA2-128s signature.
 #define BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES 7856
 
-// SLHDSA_SHA2_128S_generate_key_from_seed generates an SLH-DSA-SHA2-128s key
-// pair from a 48-byte seed and writes the result to |out_public_key| and
+// BCM_slhdsa_sha2_128s_generate_key_from_seed generates an SLH-DSA-SHA2-128s
+// key pair from a 48-byte seed and writes the result to |out_public_key| and
 // |out_secret_key|.
 OPENSSL_EXPORT bcm_infallible BCM_slhdsa_sha2_128s_generate_key_from_seed(
     uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
     uint8_t out_secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
     const uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N]);
 
+// BCM_slhdsa_sha2_128s_generate_key_from_seed_fips does the same thing as
+// `BCM_slhdsa_sha2_128s_generate_key_from_seed` but implements the required
+// second check before generating a key by testing for nullptr arguments.
+OPENSSL_EXPORT bcm_status BCM_slhdsa_sha2_128s_generate_key_from_seed_fips(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
+    const uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N]);
+
 // BCM_slhdsa_sha2_128s_sign_internal acts like |SLHDSA_SHA2_128S_sign| but
 // accepts an explicit entropy input, which can be PK.seed (bytes 32..48 of
 // the private key) to generate deterministic signatures. It also takes the
@@ -693,6 +759,10 @@
     uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
     uint8_t out_private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]);
 
+OPENSSL_EXPORT bcm_status BCM_slhdsa_sha2_128s_generate_key_fips(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]);
+
 OPENSSL_EXPORT bcm_infallible BCM_slhdsa_sha2_128s_public_from_private(
     uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
     const uint8_t private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]);
@@ -722,8 +792,34 @@
     const uint8_t *context, size_t context_len);
 
 
+// AES
+
+// BCM_aes_encrypt encrypts a single block from |in| to |out| with |key|. The
+// |in| and |out| pointers may overlap.
+OPENSSL_EXPORT bcm_infallible BCM_aes_encrypt(const uint8_t *in, uint8_t *out,
+                                              const AES_KEY *key);
+// BCM_aes_decrypt decrypts a single block from |in| to |out| with |key|. The
+// |in| and |out| pointers may overlap.
+OPENSSL_EXPORT bcm_infallible BCM_aes_decrypt(const uint8_t *in, uint8_t *out,
+                                              const AES_KEY *key);
+
+// BCM_aes_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit
+// key, |key|. |key| must point to |bits|/8 bytes. It will return failure if
+// |bits| is an invalid AES key size.
+OPENSSL_EXPORT bcm_status BCM_aes_set_encrypt_key(const uint8_t *key,
+                                                  unsigned bits,
+                                                  AES_KEY *aeskey);
+
+// BCM_aes_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit
+// key, |key|. |key| must point to |bits|/8 bytes. It will return failure if
+// |bits| is an invalid AES key size.
+OPENSSL_EXPORT bcm_status BCM_aes_set_decrypt_key(const uint8_t *key,
+                                                  unsigned bits,
+                                                  AES_KEY *aeskey);
+
+
 #if defined(__cplusplus)
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_BCM_INTERFACE_H
diff --git a/src/crypto/fipsmodule/bn/asm/armv4-mont.pl b/src/crypto/fipsmodule/bn/asm/armv4-mont.pl
index acae4e5..d3c867d 100644
--- a/src/crypto/fipsmodule/bn/asm/armv4-mont.pl
+++ b/src/crypto/fipsmodule/bn/asm/armv4-mont.pl
@@ -121,14 +121,9 @@
 bn_mul_mont_nohw:
 	ldr	ip,[sp,#4]		@ load num
 	stmdb	sp!,{r0,r2}		@ sp points at argument block
-	cmp	ip,#2
+	@ No return value. Instead, the caller must ensure num >= 2
 	mov	$num,ip			@ load num
-#ifdef	__thumb2__
-	ittt	lt
-#endif
-	movlt	r0,#0
-	addlt	sp,sp,#2*4
-	blt	.Labrt
+	@ No return value
 
 	stmdb	sp!,{r4-r12,lr}		@ save 10 registers
 
@@ -262,8 +257,7 @@
 	add	sp,sp,#4		@ skip over tp[num+1]
 	ldmia	sp!,{r4-r12,lr}		@ restore registers
 	add	sp,sp,#2*4		@ skip over {r0,r2}
-	mov	r0,#1
-.Labrt:
+	@ No return value
 #if __ARM_ARCH>=5
 	ret				@ bx lr
 #else
@@ -717,6 +711,7 @@
 	mov	sp,ip
         vldmia  sp!,{d8-d15}
         ldmia   sp!,{r4-r11}
+	@ No return value
 	ret						@ bx lr
 .size	bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
 #endif
diff --git a/src/crypto/fipsmodule/bn/asm/armv8-mont.pl b/src/crypto/fipsmodule/bn/asm/armv8-mont.pl
index 1ce02ee..fe4d8cf 100644
--- a/src/crypto/fipsmodule/bn/asm/armv8-mont.pl
+++ b/src/crypto/fipsmodule/bn/asm/armv8-mont.pl
@@ -60,7 +60,7 @@
  $lo1,$hi1,$nj,$m1,$nlo,$nhi,
  $ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24);
 
-# int bn_mul_mont(
+# void bn_mul_mont(
 $rp="x0";	# BN_ULONG *rp,
 $ap="x1";	# const BN_ULONG *ap,
 $bp="x2";	# const BN_ULONG *bp,
@@ -270,7 +270,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldr	x29,[sp],#64
 	AARCH64_VALIDATE_LINK_REGISTER
@@ -1044,7 +1044,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
@@ -1505,7 +1505,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
diff --git a/src/crypto/fipsmodule/bn/asm/bn-586.pl b/src/crypto/fipsmodule/bn/asm/bn-586.pl
index 7e3decf..fa7eb12 100644
--- a/src/crypto/fipsmodule/bn/asm/bn-586.pl
+++ b/src/crypto/fipsmodule/bn/asm/bn-586.pl
@@ -28,7 +28,6 @@
 &bn_mul_add_words("bn_mul_add_words");
 &bn_mul_words("bn_mul_words");
 &bn_sqr_words("bn_sqr_words");
-&bn_div_words("bn_div_words");
 &bn_add_words("bn_add_words");
 &bn_sub_words("bn_sub_words");
 
@@ -205,19 +204,6 @@
 	&function_end($name);
 	}
 
-sub bn_div_words
-	{
-	local($name)=@_;
-
-	&function_begin_B($name,"");
-	&mov("edx",&wparam(0));	#
-	&mov("eax",&wparam(1));	#
-	&mov("ecx",&wparam(2));	#
-	&div("ecx");
-	&ret();
-	&function_end_B($name);
-	}
-
 sub bn_add_words
 	{
 	local($name)=@_;
diff --git a/src/crypto/fipsmodule/bn/asm/x86-mont.pl b/src/crypto/fipsmodule/bn/asm/x86-mont.pl
index 3de17a4..c3e30cb 100755
--- a/src/crypto/fipsmodule/bn/asm/x86-mont.pl
+++ b/src/crypto/fipsmodule/bn/asm/x86-mont.pl
@@ -68,11 +68,9 @@
 $_bpend=&DWP(4*7,"esp");
 $frame=32;				# size of above frame rounded up to 16n
 
-	&xor	("eax","eax");
+	# No return value. Instead, the caller must ensure num >= 4
 	&mov	("edi",&wparam(5));	# int num
-	&cmp	("edi",4);
-	&jl	(&label("just_leave"));
-
+	# No return value.
 	&lea	("esi",&wparam(0));	# put aside pointer to argument block
 	&lea	("edx",&wparam(1));	# load ap
 	&add	("edi",2);		# extra two words on top of tp
@@ -326,8 +324,7 @@
 	&jge	(&label("copy"));
 
 	&mov	("esp",$_sp);		# pull saved stack pointer
-	&mov	("eax",1);
-&set_label("just_leave");
+	# No return value
 &function_end("bn_mul_mont");
 
 &asciz("Montgomery Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>");
diff --git a/src/crypto/fipsmodule/bn/asm/x86_64-mont.pl b/src/crypto/fipsmodule/bn/asm/x86_64-mont.pl
index 537b028..c1d4028 100755
--- a/src/crypto/fipsmodule/bn/asm/x86_64-mont.pl
+++ b/src/crypto/fipsmodule/bn/asm/x86_64-mont.pl
@@ -70,7 +70,7 @@
 # output, so this isn't useful anyway.
 $addx = 1;
 
-# int bn_mul_mont_nohw(
+# void bn_mul_mont_nohw(
 $rp="%rdi";	# BN_ULONG *rp,
 $ap="%rsi";	# const BN_ULONG *ap,
 $bp="%rdx";	# const BN_ULONG *bp,
@@ -315,7 +315,7 @@
 
 	mov	8(%rsp,$num,8),%rsi	# restore %rsp
 .cfi_def_cfa	%rsi,8
-	mov	\$1,%rax
+	# No return value
 	mov	-48(%rsi),%r15
 .cfi_restore	%r15
 	mov	-40(%rsi),%r14
@@ -762,7 +762,7 @@
 $code.=<<___;
 	mov	8(%rsp,$num,8),%rsi	# restore %rsp
 .cfi_def_cfa	%rsi, 8
-	mov	\$1,%rax
+	# No return value
 	mov	-48(%rsi),%r15
 .cfi_restore	%r15
 	mov	-40(%rsi),%r14
@@ -785,7 +785,7 @@
 }}}
 {{{
 ######################################################################
-# int bn_sqr8x_mont(
+# void bn_sqr8x_mont(
 my $rptr="%rdi";	# const BN_ULONG *rptr,
 my $aptr="%rsi";	# const BN_ULONG *aptr,
 my $mulx_adx_capable="%rdx"; # Different than upstream!
@@ -976,7 +976,7 @@
 	add	\$32,$num
 	jnz	.Lsqr8x_cond_copy
 
-	mov	\$1,%rax
+	# No return value
 	mov	-48(%rsi),%r15
 .cfi_restore	%r15
 	mov	-40(%rsi),%r14
@@ -1345,7 +1345,7 @@
 
 	mov	%rdx,($tptr)
 
-	mov	\$1,%rax
+	# No return value
 	mov	-48(%rsi),%r15
 .cfi_restore	%r15
 	mov	-40(%rsi),%r14
diff --git a/src/crypto/fipsmodule/bn/div.cc.inc b/src/crypto/fipsmodule/bn/div.cc.inc
index b09f9fe..a29bf9c 100644
--- a/src/crypto/fipsmodule/bn/div.cc.inc
+++ b/src/crypto/fipsmodule/bn/div.cc.inc
@@ -21,10 +21,22 @@
 
 #include "internal.h"
 
+#if (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) && defined(_MSC_VER) && \
+    !defined(__clang__)
+#define HAVE_MSVC_DIV_INTRINSICS
+#include <immintrin.h>
+#if defined(OPENSSL_X86)
+#pragma intrinsic(_udiv64)
+#else
+#pragma intrinsic(_udiv128)
+#endif
+#endif
+
 
 // bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
-// which must fit in a |BN_ULONG|.
+// which must fit in a |BN_ULONG|, i.e. |h < d|.
 static inline BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
+  assert(h < d);
   BN_ULONG dh, dl, q, ret = 0, th, tl, t;
   int i, count = 2;
 
@@ -93,42 +105,49 @@
   return ret;
 }
 
+// bn_div_rem_words divides a double-width numerator (high half |nh| and low
+// half |nl|) with a single-width divisor. It sets |*quotient_out| and
+// |*rem_out| to be the quotient and numerator, respectively. The quotient must
+// fit in a |BN_ULONG|, i.e. |nh < d|.
 static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
-                                    BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
-  // GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
-  // the |BN_ULLONG|-based C code is used.
-  //
-  // GCC bugs:
-  //   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
-  //   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
-  //   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
-  //   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
-  //   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
-  //
-  // Clang bugs:
-  //   * https://github.com/llvm/llvm-project/issues/6769
-  //   * https://github.com/llvm/llvm-project/issues/12790
+                                    BN_ULONG nh, BN_ULONG nl, BN_ULONG d) {
+  assert(nh < d);
+  // This operation is the x86 and x86_64 DIV instruction, but it is difficult
+  // for the compiler to emit it. Dividing a |BN_ULLONG| by a |BN_ULONG| does
+  // not work because, a priori, the quotient may not fit in |BN_ULONG| and DIV
+  // will trap on overflow, not truncate. The compiler will instead emit a call
+  // to a more expensive support function (e.g. |__udivdi3|). Thus we use inline
+  // assembly or intrinsics to get the instruction.
   //
   // These is specific to x86 and x86_64; Arm and RISC-V do not have double-wide
   // division instructions.
 #if defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86)
   __asm__ volatile("divl %4"
                    : "=a"(*quotient_out), "=d"(*rem_out)
-                   : "a"(n1), "d"(n0), "rm"(d0)
+                   : "a"(nl), "d"(nh), "rm"(d)
                    : "cc");
 #elif defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86_64)
   __asm__ volatile("divq %4"
                    : "=a"(*quotient_out), "=d"(*rem_out)
-                   : "a"(n1), "d"(n0), "rm"(d0)
+                   : "a"(nl), "d"(nh), "rm"(d)
                    : "cc");
+#elif defined(HAVE_MSVC_DIV_INTRINSICS) && defined(OPENSSL_X86)
+  BN_ULLONG n = (((BN_ULLONG)nh) << BN_BITS2) | nl;
+  unsigned rem;
+  *quotient_out = _udiv64(n, d, &rem);
+  *rem_out = rem;
+#elif defined(HAVE_MSVC_DIV_INTRINSICS) && defined(OPENSSL_X86_64)
+  unsigned __int64 rem;
+  *quotient_out = _udiv128(nh, nl, d, &rem);
+  *rem_out = rem;
 #else
 #if defined(BN_CAN_DIVIDE_ULLONG)
-  BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
-  *quotient_out = (BN_ULONG)(n / d0);
+  BN_ULLONG n = (((BN_ULLONG)nh) << BN_BITS2) | nl;
+  *quotient_out = (BN_ULONG)(n / d);
 #else
-  *quotient_out = bn_div_words(n0, n1, d0);
-#endif
-  *rem_out = n1 - (*quotient_out * d0);
+  *quotient_out = bn_div_words(nh, nl, d);
+#endif  // BN_CAN_DIVIDE_ULLONG
+  *rem_out = nl - (*quotient_out * d);
 #endif
 }
 
@@ -147,7 +166,7 @@
     return 0;
   }
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   BIGNUM *snum = BN_CTX_get(ctx);
   BIGNUM *sdiv = BN_CTX_get(ctx);
@@ -155,7 +174,7 @@
   int norm_shift, num_n, loop, div_n;
   BN_ULONG d0, d1;
   if (tmp == NULL || snum == NULL || sdiv == NULL || res == NULL) {
-    goto err;
+    return 0;
   }
 
   // Knuth step D1: Normalise the numbers such that the divisor's MSB is set.
@@ -164,7 +183,7 @@
   norm_shift = BN_BITS2 - (BN_num_bits(divisor) % BN_BITS2);
   if (!BN_lshift(sdiv, divisor, norm_shift) ||
       !BN_lshift(snum, numerator, norm_shift)) {
-    goto err;
+    return 0;
   }
 
   // This algorithm relies on |sdiv| being minimal width. We do not use this
@@ -184,7 +203,7 @@
   //   digit in Knuth step D1.)
   num_n = snum->width <= div_n ? div_n + 1 : snum->width + 1;
   if (!bn_resize_words(snum, num_n)) {
-    goto err;
+    return 0;
   }
 
   // Knuth step D2: The quotient's width is the difference between numerator and
@@ -193,7 +212,7 @@
   res->neg = snum->neg ^ sdiv->neg;
   if (!bn_wexpand(res, loop) ||  //
       !bn_wexpand(tmp, div_n + 1)) {
-    goto err;
+    return 0;
   }
   res->width = loop;
 
@@ -312,15 +331,10 @@
 
   // Knuth step D8: Unnormalize. snum now contains the remainder.
   if (rem != NULL && !BN_rshift(rem, snum, norm_shift)) {
-    goto err;
+    return 0;
   }
 
-  BN_CTX_end(ctx);
   return 1;
-
-err:
-  BN_CTX_end(ctx);
-  return 0;
 }
 
 int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) {
@@ -396,8 +410,7 @@
   // but it is simple, easy to make constant-time, and performant enough for RSA
   // key generation.
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *q = quotient, *r = remainder;
   if (quotient == NULL || quotient == numerator || quotient == divisor) {
     q = BN_CTX_get(ctx);
@@ -410,7 +423,7 @@
   if (q == NULL || r == NULL || tmp == NULL ||
       !bn_wexpand(q, numerator->width) || !bn_wexpand(r, divisor->width) ||
       !bn_wexpand(tmp, divisor->width)) {
-    goto err;
+    return 0;
   }
 
   OPENSSL_memset(q->d, 0, numerator->width * sizeof(BN_ULONG));
@@ -461,14 +474,10 @@
 
   if ((quotient != NULL && !BN_copy(quotient, q)) ||
       (remainder != NULL && !BN_copy(remainder, r))) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 static BIGNUM *bn_scratch_space_from_ctx(size_t width, BN_CTX *ctx) {
@@ -510,26 +519,24 @@
 
 int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                      const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_add_consttime(r, a, b, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_add_consttime(r, a, b, m, ctx.get());
 }
 
 int bn_mod_add_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          const BIGNUM *m, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   a = bn_resized_from_ctx(a, m->width, ctx);
   b = bn_resized_from_ctx(b, m->width, ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = a != NULL && b != NULL && tmp != NULL && bn_wexpand(r, m->width);
-  if (ok) {
-    bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
-    r->width = m->width;
-    r->neg = 0;
+  if (a == nullptr || b == nullptr || tmp == nullptr ||
+      !bn_wexpand(r, m->width)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
+  r->width = m->width;
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
@@ -542,58 +549,49 @@
 
 int bn_mod_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          const BIGNUM *m, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   a = bn_resized_from_ctx(a, m->width, ctx);
   b = bn_resized_from_ctx(b, m->width, ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = a != NULL && b != NULL && tmp != NULL && bn_wexpand(r, m->width);
-  if (ok) {
-    bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
-    r->width = m->width;
-    r->neg = 0;
+  if (a == nullptr || b == nullptr || tmp == nullptr ||
+      !bn_wexpand(r, m->width)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
+  r->width = m->width;
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                      const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_sub_consttime(r, a, b, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_sub_consttime(r, a, b, m, ctx.get());
 }
 
 int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
                BN_CTX *ctx) {
-  BIGNUM *t;
-  int ret = 0;
-
-  BN_CTX_start(ctx);
-  t = BN_CTX_get(ctx);
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *t = BN_CTX_get(ctx);
   if (t == NULL) {
-    goto err;
+    return 0;
   }
 
   if (a == b) {
     if (!BN_sqr(t, a, ctx)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_mul(t, a, b, ctx)) {
-      goto err;
+      return 0;
     }
   }
 
   if (!BN_nnmod(r, t, m, ctx)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
@@ -607,25 +605,20 @@
 
 int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
                   BN_CTX *ctx) {
-  BIGNUM *abs_m = NULL;
-  int ret;
-
   if (!BN_nnmod(r, a, m, ctx)) {
     return 0;
   }
 
+  bssl::UniquePtr<BIGNUM> abs_m;
   if (m->neg) {
-    abs_m = BN_dup(m);
-    if (abs_m == NULL) {
+    abs_m.reset(BN_dup(m));
+    if (abs_m == nullptr) {
       return 0;
     }
     abs_m->neg = 0;
   }
 
-  ret = bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m : m), ctx);
-
-  BN_free(abs_m);
-  return ret;
+  return bn_mod_lshift_consttime(r, r, n, (abs_m ? abs_m.get() : m), ctx);
 }
 
 int bn_mod_lshift_consttime(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
@@ -634,24 +627,21 @@
     return 0;
   }
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
-  int ok = tmp != NULL;
-  if (ok) {
-    for (int i = 0; i < n; i++) {
-      bn_mod_add_words(r->d, r->d, r->d, m->d, tmp->d, m->width);
-    }
-    r->neg = 0;
+  if (tmp == nullptr) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  for (int i = 0; i < n; i++) {
+    bn_mod_add_words(r->d, r->d, r->d, m->d, tmp->d, m->width);
+  }
+  r->neg = 0;
+  return 1;
 }
 
 int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_lshift_consttime(r, a, n, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_lshift_consttime(r, a, n, m, ctx.get());
 }
 
 int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
@@ -668,10 +658,8 @@
 }
 
 int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) {
-  BN_CTX *ctx = BN_CTX_new();
-  int ok = ctx != NULL && bn_mod_lshift1_consttime(r, a, m, ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  return ctx != nullptr && bn_mod_lshift1_consttime(r, a, m, ctx.get());
 }
 
 BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
@@ -744,82 +732,3 @@
   }
   return (BN_ULONG)ret;
 }
-
-int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
-  if (e == 0 || a->width == 0) {
-    BN_zero(r);
-    return 1;
-  }
-
-  size_t num_words = 1 + ((e - 1) / BN_BITS2);
-
-  // If |a| definitely has less than |e| bits, just BN_copy.
-  if ((size_t)a->width < num_words) {
-    return BN_copy(r, a) != NULL;
-  }
-
-  // Otherwise, first make sure we have enough space in |r|.
-  // Note that this will fail if num_words > INT_MAX.
-  if (!bn_wexpand(r, num_words)) {
-    return 0;
-  }
-
-  // Copy the content of |a| into |r|.
-  OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
-
-  // If |e| isn't word-aligned, we have to mask off some of our bits.
-  size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
-  if (top_word_exponent != 0) {
-    r->d[num_words - 1] &= (((BN_ULONG)1) << top_word_exponent) - 1;
-  }
-
-  // Fill in the remaining fields of |r|.
-  r->neg = a->neg;
-  r->width = (int)num_words;
-  bn_set_minimal_width(r);
-  return 1;
-}
-
-int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
-  if (!BN_mod_pow2(r, a, e)) {
-    return 0;
-  }
-
-  // If the returned value was non-negative, we're done.
-  if (BN_is_zero(r) || !r->neg) {
-    return 1;
-  }
-
-  size_t num_words = 1 + (e - 1) / BN_BITS2;
-
-  // Expand |r| to the size of our modulus.
-  if (!bn_wexpand(r, num_words)) {
-    return 0;
-  }
-
-  // Clear the upper words of |r|.
-  OPENSSL_memset(&r->d[r->width], 0, (num_words - r->width) * BN_BYTES);
-
-  // Set parameters of |r|.
-  r->neg = 0;
-  r->width = (int)num_words;
-
-  // Now, invert every word. The idea here is that we want to compute 2^e-|x|,
-  // which is actually equivalent to the twos-complement representation of |x|
-  // in |e| bits, which is -x = ~x + 1.
-  for (int i = 0; i < r->width; i++) {
-    r->d[i] = ~r->d[i];
-  }
-
-  // If our exponent doesn't span the top word, we have to mask the rest.
-  size_t top_word_exponent = e % BN_BITS2;
-  if (top_word_exponent != 0) {
-    r->d[r->width - 1] &= (((BN_ULONG)1) << top_word_exponent) - 1;
-  }
-
-  // Keep the minimal-width invariant for |BIGNUM|.
-  bn_set_minimal_width(r);
-
-  // Finally, add one, for the reason described above.
-  return BN_add(r, r, BN_value_one());
-}
diff --git a/src/crypto/fipsmodule/bn/exponentiation.cc.inc b/src/crypto/fipsmodule/bn/exponentiation.cc.inc
index 6c3d448..205f4b4 100644
--- a/src/crypto/fipsmodule/bn/exponentiation.cc.inc
+++ b/src/crypto/fipsmodule/bn/exponentiation.cc.inc
@@ -70,261 +70,6 @@
 
 #endif  // defined(OPENSSL_BN_ASM_MONT5)
 
-int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
-  int i, bits, ret = 0;
-  BIGNUM *v, *rr;
-
-  BN_CTX_start(ctx);
-  if (r == a || r == p) {
-    rr = BN_CTX_get(ctx);
-  } else {
-    rr = r;
-  }
-
-  v = BN_CTX_get(ctx);
-  if (rr == NULL || v == NULL) {
-    goto err;
-  }
-
-  if (BN_copy(v, a) == NULL) {
-    goto err;
-  }
-  bits = BN_num_bits(p);
-
-  if (BN_is_odd(p)) {
-    if (BN_copy(rr, a) == NULL) {
-      goto err;
-    }
-  } else {
-    if (!BN_one(rr)) {
-      goto err;
-    }
-  }
-
-  for (i = 1; i < bits; i++) {
-    if (!BN_sqr(v, v, ctx)) {
-      goto err;
-    }
-    if (BN_is_bit_set(p, i)) {
-      if (!BN_mul(rr, rr, v, ctx)) {
-        goto err;
-      }
-    }
-  }
-
-  if (r != rr && !BN_copy(r, rr)) {
-    goto err;
-  }
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
-}
-
-namespace {
-typedef struct bn_recp_ctx_st {
-  BIGNUM N;   // the divisor
-  BIGNUM Nr;  // the reciprocal
-  int num_bits;
-  int shift;
-  int flags;
-} BN_RECP_CTX;
-}  // namespace
-
-static void BN_RECP_CTX_init(BN_RECP_CTX *recp) {
-  BN_init(&recp->N);
-  BN_init(&recp->Nr);
-  recp->num_bits = 0;
-  recp->shift = 0;
-  recp->flags = 0;
-}
-
-static void BN_RECP_CTX_free(BN_RECP_CTX *recp) {
-  if (recp == nullptr) {
-    return;
-  }
-  BN_free(&recp->N);
-  BN_free(&recp->Nr);
-}
-
-static int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) {
-  if (!BN_copy(&(recp->N), d)) {
-    return 0;
-  }
-  BN_zero(&recp->Nr);
-  recp->num_bits = BN_num_bits(d);
-  recp->shift = 0;
-
-  return 1;
-}
-
-// len is the expected size of the result We actually calculate with an extra
-// word of precision, so we can do faster division if the remainder is not
-// required.
-// r := 2^len / m
-static int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) {
-  int ret = -1;
-  BIGNUM *t;
-
-  BN_CTX_start(ctx);
-  t = BN_CTX_get(ctx);
-  if (t == NULL) {
-    goto err;
-  }
-
-  if (!BN_set_bit(t, len)) {
-    goto err;
-  }
-
-  if (!BN_div(r, NULL, t, m, ctx)) {
-    goto err;
-  }
-
-  ret = len;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
-}
-
-static int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
-                       BN_RECP_CTX *recp, BN_CTX *ctx) {
-  int i, j, ret = 0;
-  BIGNUM *a, *b, *d, *r;
-
-  BN_CTX_start(ctx);
-  a = BN_CTX_get(ctx);
-  b = BN_CTX_get(ctx);
-  if (dv != NULL) {
-    d = dv;
-  } else {
-    d = BN_CTX_get(ctx);
-  }
-
-  if (rem != NULL) {
-    r = rem;
-  } else {
-    r = BN_CTX_get(ctx);
-  }
-
-  if (a == NULL || b == NULL || d == NULL || r == NULL) {
-    goto err;
-  }
-
-  if (BN_ucmp(m, &recp->N) < 0) {
-    BN_zero(d);
-    if (!BN_copy(r, m)) {
-      goto err;
-    }
-    BN_CTX_end(ctx);
-    return 1;
-  }
-
-  // We want the remainder
-  // Given input of ABCDEF / ab
-  // we need multiply ABCDEF by 3 digests of the reciprocal of ab
-
-  // i := max(BN_num_bits(m), 2*BN_num_bits(N))
-  i = BN_num_bits(m);
-  j = recp->num_bits << 1;
-  if (j > i) {
-    i = j;
-  }
-
-  // Nr := round(2^i / N)
-  if (i != recp->shift) {
-    recp->shift =
-        BN_reciprocal(&(recp->Nr), &(recp->N), i,
-                      ctx);  // BN_reciprocal returns i, or -1 for an error
-  }
-
-  if (recp->shift == -1) {
-    goto err;
-  }
-
-  // d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i -
-  // BN_num_bits(N)))|
-  //    = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i -
-  // BN_num_bits(N)))|
-  //   <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
-  //    = |m/N|
-  if (!BN_rshift(a, m, recp->num_bits)) {
-    goto err;
-  }
-  if (!BN_mul(b, a, &(recp->Nr), ctx)) {
-    goto err;
-  }
-  if (!BN_rshift(d, b, i - recp->num_bits)) {
-    goto err;
-  }
-  d->neg = 0;
-
-  if (!BN_mul(b, &(recp->N), d, ctx)) {
-    goto err;
-  }
-  if (!BN_usub(r, m, b)) {
-    goto err;
-  }
-  r->neg = 0;
-
-  j = 0;
-  while (BN_ucmp(r, &(recp->N)) >= 0) {
-    if (j++ > 2) {
-      OPENSSL_PUT_ERROR(BN, BN_R_BAD_RECIPROCAL);
-      goto err;
-    }
-    if (!BN_usub(r, r, &(recp->N))) {
-      goto err;
-    }
-    if (!BN_add_word(d, 1)) {
-      goto err;
-    }
-  }
-
-  r->neg = BN_is_zero(r) ? 0 : m->neg;
-  d->neg = m->neg ^ recp->N.neg;
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
-}
-
-static int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
-                                 BN_RECP_CTX *recp, BN_CTX *ctx) {
-  int ret = 0;
-  BIGNUM *a;
-  const BIGNUM *ca;
-
-  BN_CTX_start(ctx);
-  a = BN_CTX_get(ctx);
-  if (a == NULL) {
-    goto err;
-  }
-
-  if (y != NULL) {
-    if (x == y) {
-      if (!BN_sqr(a, x, ctx)) {
-        goto err;
-      }
-    } else {
-      if (!BN_mul(a, x, y, ctx)) {
-        goto err;
-      }
-    }
-    ca = a;
-  } else {
-    ca = x;  // Just do the mod
-  }
-
-  ret = BN_div_recp(NULL, r, ca, recp, ctx);
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
-}
-
 // BN_window_bits_for_exponent_size returns sliding window size for mod_exp with
 // a |b| bit exponent.
 //
@@ -378,163 +123,6 @@
 // |BN_BITS2| * |BN_SMALL_MAX_WORDS|.
 #define TABLE_SIZE_SMALL (1 << (TABLE_BITS_SMALL - 1))
 
-static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                        const BIGNUM *m, BN_CTX *ctx) {
-  int i, j, ret = 0, wstart, window;
-  int start = 1;
-  BIGNUM *aa;
-  // Table of variables obtained from 'ctx'
-  BIGNUM *val[TABLE_SIZE];
-  BN_RECP_CTX recp;
-
-  // This function is only called on even moduli.
-  assert(!BN_is_odd(m));
-
-  int bits = BN_num_bits(p);
-  if (bits == 0) {
-    return BN_one(r);
-  }
-
-  BN_RECP_CTX_init(&recp);
-  BN_CTX_start(ctx);
-  aa = BN_CTX_get(ctx);
-  val[0] = BN_CTX_get(ctx);
-  if (!aa || !val[0]) {
-    goto err;
-  }
-
-  if (m->neg) {
-    // ignore sign of 'm'
-    if (!BN_copy(aa, m)) {
-      goto err;
-    }
-    aa->neg = 0;
-    if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) {
-      goto err;
-    }
-  } else {
-    if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) {
-      goto err;
-    }
-  }
-
-  if (!BN_nnmod(val[0], a, m, ctx)) {
-    goto err;  // 1
-  }
-  if (BN_is_zero(val[0])) {
-    BN_zero(r);
-    ret = 1;
-    goto err;
-  }
-
-  window = BN_window_bits_for_exponent_size(bits);
-  if (window > 1) {
-    if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx)) {
-      goto err;  // 2
-    }
-    j = 1 << (window - 1);
-    for (i = 1; i < j; i++) {
-      if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
-          !BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx)) {
-        goto err;
-      }
-    }
-  }
-
-  start = 1;          // This is used to avoid multiplication etc
-                      // when there is only the value '1' in the
-                      // buffer.
-  wstart = bits - 1;  // The top bit of the window
-
-  if (!BN_one(r)) {
-    goto err;
-  }
-
-  for (;;) {
-    int wvalue;  // The 'value' of the window
-    int wend;    // The bottom bit of the window
-
-    if (!BN_is_bit_set(p, wstart)) {
-      if (!start) {
-        if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) {
-          goto err;
-        }
-      }
-      if (wstart == 0) {
-        break;
-      }
-      wstart--;
-      continue;
-    }
-
-    // We now have wstart on a 'set' bit, we now need to work out
-    // how bit a window to do.  To do this we need to scan
-    // forward until the last set bit before the end of the
-    // window
-    wvalue = 1;
-    wend = 0;
-    for (i = 1; i < window; i++) {
-      if (wstart - i < 0) {
-        break;
-      }
-      if (BN_is_bit_set(p, wstart - i)) {
-        wvalue <<= (i - wend);
-        wvalue |= 1;
-        wend = i;
-      }
-    }
-
-    // wend is the size of the current window
-    j = wend + 1;
-    // add the 'bytes above'
-    if (!start) {
-      for (i = 0; i < j; i++) {
-        if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) {
-          goto err;
-        }
-      }
-    }
-
-    // wvalue will be an odd number < 2^window
-    if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx)) {
-      goto err;
-    }
-
-    // move the 'window' down further
-    wstart -= wend + 1;
-    start = 0;
-    if (wstart < 0) {
-      break;
-    }
-  }
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  BN_RECP_CTX_free(&recp);
-  return ret;
-}
-
-int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
-               BN_CTX *ctx) {
-  if (m->neg) {
-    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
-    return 0;
-  }
-  if (a->neg || BN_ucmp(a, m) >= 0) {
-    if (!BN_nnmod(r, a, m, ctx)) {
-      return 0;
-    }
-    a = r;
-  }
-
-  if (BN_is_odd(m)) {
-    return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
-  }
-
-  return mod_exp_recp(r, a, p, m, ctx);
-}
-
 int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
                     const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont) {
   if (!BN_is_odd(m)) {
@@ -561,57 +149,55 @@
     return BN_one(rr);
   }
 
-  int ret = 0;
   BIGNUM *val[TABLE_SIZE];
-  BN_MONT_CTX *new_mont = NULL;
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *r = BN_CTX_get(ctx);
   val[0] = BN_CTX_get(ctx);
-  int window, r_is_one, wstart;
   if (r == NULL || val[0] == NULL) {
-    goto err;
+    return 0;
   }
 
   // Allocate a montgomery context if it was not supplied by the caller.
-  if (mont == NULL) {
-    new_mont = BN_MONT_CTX_new_consttime(m, ctx);
-    if (new_mont == NULL) {
-      goto err;
+  bssl::UniquePtr<BN_MONT_CTX> new_mont;
+  if (mont == nullptr) {
+    new_mont.reset(BN_MONT_CTX_new_consttime(m, ctx));
+    if (new_mont == nullptr) {
+      return 0;
     }
-    mont = new_mont;
+    mont = new_mont.get();
   }
 
   // We exponentiate by looking at sliding windows of the exponent and
   // precomputing powers of |a|. Windows may be shifted so they always end on a
   // set bit, so only precompute odd powers. We compute val[i] = a^(2*i + 1)
   // for i = 0 to 2^(window-1), all in Montgomery form.
-  window = BN_window_bits_for_exponent_size(bits);
+  int window = BN_window_bits_for_exponent_size(bits);
   if (!BN_to_montgomery(val[0], a, mont, ctx)) {
-    goto err;
+    return 0;
   }
   if (window > 1) {
     BIGNUM *d = BN_CTX_get(ctx);
     if (d == NULL || !BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) {
-      goto err;
+      return 0;
     }
     for (int i = 1; i < 1 << (window - 1); i++) {
       val[i] = BN_CTX_get(ctx);
       if (val[i] == NULL ||
           !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) {
-        goto err;
+        return 0;
       }
     }
   }
 
   // |p| is non-zero, so at least one window is non-zero. To save some
   // multiplications, defer initializing |r| until then.
-  r_is_one = 1;
-  wstart = bits - 1;  // The top bit of the window.
+  int r_is_one = 1;
+  int wstart = bits - 1;  // The top bit of the window.
   for (;;) {
     if (!BN_is_bit_set(p, wstart)) {
       if (!r_is_one && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-        goto err;
+        return 0;
       }
       if (wstart == 0) {
         break;
@@ -635,7 +221,7 @@
     if (!r_is_one) {
       for (int i = 0; i < wsize + 1; i++) {
         if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-          goto err;
+          return 0;
         }
       }
     }
@@ -644,10 +230,10 @@
     assert(wvalue < (1 << window));
     if (r_is_one) {
       if (!BN_copy(r, val[wvalue >> 1])) {
-        goto err;
+        return 0;
       }
     } else if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) {
-      goto err;
+      return 0;
     }
 
     r_is_one = 0;
@@ -660,15 +246,7 @@
   // |p| is non-zero, so |r_is_one| must be cleared at some point.
   assert(!r_is_one);
 
-  if (!BN_from_montgomery(rr, r, mont, ctx)) {
-    goto err;
-  }
-  ret = 1;
-
-err:
-  BN_MONT_CTX_free(new_mont);
-  BN_CTX_end(ctx);
-  return ret;
+  return BN_from_montgomery(rr, r, mont, ctx);
 }
 
 void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
@@ -835,7 +413,6 @@
                               const BIGNUM *m, BN_CTX *ctx,
                               const BN_MONT_CTX *mont) {
   int i, ret = 0, wvalue;
-  BN_MONT_CTX *new_mont = NULL;
 
   void *powerbuf_free = NULL;
   size_t powerbuf_len = 0;
@@ -871,12 +448,13 @@
 
   // Allocate a montgomery context if it was not supplied by the caller.
   int top, num_powers, window;
-  if (mont == NULL) {
-    new_mont = BN_MONT_CTX_new_consttime(m, ctx);
-    if (new_mont == NULL) {
+  bssl::UniquePtr<BN_MONT_CTX> new_mont;
+  if (mont == nullptr) {
+    new_mont.reset(BN_MONT_CTX_new_consttime(m, ctx));
+    if (new_mont == nullptr) {
       goto err;
     }
-    mont = new_mont;
+    mont = new_mont.get();
   }
 
   // Use the width in |mont->N|, rather than the copy in |m|. The assembly
@@ -1153,75 +731,9 @@
   ret = 1;
 
 err:
-  BN_MONT_CTX_free(new_mont);
   if (powerbuf != NULL && powerbuf_free == NULL) {
     OPENSSL_cleanse(powerbuf, powerbuf_len);
   }
   OPENSSL_free(powerbuf_free);
   return ret;
 }
-
-int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
-                         const BIGNUM *m, BN_CTX *ctx,
-                         const BN_MONT_CTX *mont) {
-  BIGNUM a_bignum;
-  BN_init(&a_bignum);
-
-  int ret = 0;
-
-  // BN_mod_exp_mont requires reduced inputs.
-  if (bn_minimal_width(m) == 1) {
-    a %= m->d[0];
-  }
-
-  if (!BN_set_word(&a_bignum, a)) {
-    OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
-    goto err;
-  }
-
-  ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont);
-
-err:
-  BN_free(&a_bignum);
-
-  return ret;
-}
-
-#define TABLE_SIZE 32
-
-int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
-                     const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
-                     BN_CTX *ctx, const BN_MONT_CTX *mont) {
-  BIGNUM tmp;
-  BN_init(&tmp);
-
-  int ret = 0;
-  BN_MONT_CTX *new_mont = NULL;
-
-  // Allocate a montgomery context if it was not supplied by the caller.
-  if (mont == NULL) {
-    new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
-    if (new_mont == NULL) {
-      goto err;
-    }
-    mont = new_mont;
-  }
-
-  // BN_mod_mul_montgomery removes one Montgomery factor, so passing one
-  // Montgomery-encoded and one non-Montgomery-encoded value gives a
-  // non-Montgomery-encoded result.
-  if (!BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) ||
-      !BN_mod_exp_mont(&tmp, a2, p2, m, ctx, mont) ||
-      !BN_to_montgomery(rr, rr, mont, ctx) ||
-      !BN_mod_mul_montgomery(rr, rr, &tmp, mont, ctx)) {
-    goto err;
-  }
-
-  ret = 1;
-
-err:
-  BN_MONT_CTX_free(new_mont);
-  BN_free(&tmp);
-
-  return ret;
-}
diff --git a/src/crypto/fipsmodule/bn/gcd.cc.inc b/src/crypto/fipsmodule/bn/gcd.cc.inc
index 6e3cc06..e876c4d 100644
--- a/src/crypto/fipsmodule/bn/gcd.cc.inc
+++ b/src/crypto/fipsmodule/bn/gcd.cc.inc
@@ -33,23 +33,20 @@
     return 0;
   }
 
-  BIGNUM *A, *B, *X, *Y;
-  int ret = 0;
   int sign;
-
-  BN_CTX_start(ctx);
-  A = BN_CTX_get(ctx);
-  B = BN_CTX_get(ctx);
-  X = BN_CTX_get(ctx);
-  Y = BN_CTX_get(ctx);
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *A = BN_CTX_get(ctx);
+  BIGNUM *B = BN_CTX_get(ctx);
+  BIGNUM *X = BN_CTX_get(ctx);
+  BIGNUM *Y = BN_CTX_get(ctx);
   BIGNUM *R = out;
   if (Y == NULL) {
-    goto err;
+    return 0;
   }
 
   BN_zero(Y);
   if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) {
-    goto err;
+    return 0;
   }
   A->neg = 0;
   sign = -1;
@@ -80,17 +77,17 @@
 
       if (BN_is_odd(X)) {
         if (!BN_uadd(X, X, n)) {
-          goto err;
+          return 0;
         }
       }
       // now X is even, so we can easily divide it by two
       if (!BN_rshift1(X, X)) {
-        goto err;
+        return 0;
       }
     }
     if (shift > 0) {
       if (!BN_rshift(B, B, shift)) {
-        goto err;
+        return 0;
       }
     }
 
@@ -102,17 +99,17 @@
 
       if (BN_is_odd(Y)) {
         if (!BN_uadd(Y, Y, n)) {
-          goto err;
+          return 0;
         }
       }
       // now Y is even
       if (!BN_rshift1(Y, Y)) {
-        goto err;
+        return 0;
       }
     }
     if (shift > 0) {
       if (!BN_rshift(A, A, shift)) {
-        goto err;
+        return 0;
       }
     }
 
@@ -129,21 +126,21 @@
     if (BN_ucmp(B, A) >= 0) {
       // -sign*(X + Y)*a == B - A  (mod |n|)
       if (!BN_uadd(X, X, Y)) {
-        goto err;
+        return 0;
       }
       // NB: we could use BN_mod_add_quick(X, X, Y, n), but that
       // actually makes the algorithm slower
       if (!BN_usub(B, B, A)) {
-        goto err;
+        return 0;
       }
     } else {
       //  sign*(X + Y)*a == A - B  (mod |n|)
       if (!BN_uadd(Y, Y, X)) {
-        goto err;
+        return 0;
       }
       // as above, BN_mod_add_quick(Y, Y, X, n) would slow things down
       if (!BN_usub(A, A, B)) {
-        goto err;
+        return 0;
       }
     }
   }
@@ -151,7 +148,7 @@
   if (!BN_is_one(A)) {
     *out_no_inverse = 1;
     OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
-    goto err;
+    return 0;
   }
 
   // The while loop (Euclid's algorithm) ends when
@@ -162,7 +159,7 @@
 
   if (sign < 0) {
     if (!BN_sub(Y, n, Y)) {
-      goto err;
+      return 0;
     }
   }
   // Now  Y*a  ==  A  (mod |n|).
@@ -170,61 +167,49 @@
   // Y*a == 1  (mod |n|)
   if (Y->neg || BN_ucmp(Y, n) >= 0) {
     if (!BN_nnmod(Y, Y, n, ctx)) {
-      goto err;
+      return 0;
     }
   }
   if (!BN_copy(R, Y)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
                        BN_CTX *ctx) {
-  BIGNUM *new_out = NULL;
-  if (out == NULL) {
-    new_out = BN_new();
-    if (new_out == NULL) {
-      return NULL;
+  bssl::UniquePtr<BIGNUM> new_out;
+  if (out == nullptr) {
+    new_out.reset(BN_new());
+    if (new_out == nullptr) {
+      return nullptr;
     }
-    out = new_out;
+    out = new_out.get();
   }
 
-  int ok = 0;
-  BIGNUM *a_reduced = NULL;
+  bssl::UniquePtr<BIGNUM> a_reduced;
   if (a->neg || BN_ucmp(a, n) >= 0) {
-    a_reduced = BN_dup(a);
-    if (a_reduced == NULL) {
-      goto err;
+    a_reduced.reset(BN_dup(a));
+    if (a_reduced == nullptr) {
+      return nullptr;
     }
-    if (!BN_nnmod(a_reduced, a_reduced, n, ctx)) {
-      goto err;
+    if (!BN_nnmod(a_reduced.get(), a_reduced.get(), n, ctx)) {
+      return nullptr;
     }
-    a = a_reduced;
+    a = a_reduced.get();
   }
 
   int no_inverse;
   if (!BN_is_odd(n)) {
     if (!bn_mod_inverse_consttime(out, &no_inverse, a, n, ctx)) {
-      goto err;
+      return nullptr;
     }
   } else if (!BN_mod_inverse_odd(out, &no_inverse, a, n, ctx)) {
-    goto err;
+    return nullptr;
   }
 
-  ok = 1;
-
-err:
-  if (!ok) {
-    BN_free(new_out);
-    out = NULL;
-  }
-  BN_free(a_reduced);
+  new_out.release();  // Passed to the caller via |out|.
   return out;
 }
 
@@ -240,9 +225,10 @@
     return 0;
   }
 
-  int ret = 0;
-  BIGNUM blinding_factor;
-  BN_init(&blinding_factor);
+  bssl::UniquePtr<BIGNUM> blinding_factor(BN_new());
+  if (blinding_factor == nullptr) {
+    return 0;
+  }
 
   // |BN_mod_inverse_odd| is leaky, so generate a secret blinding factor and
   // blind |a|. This works because (ar)^-1 * r = a^-1, supposing r is
@@ -253,12 +239,12 @@
   //
   // TODO(crbug.com/boringssl/677): When the PRNG output is marked secret by
   // default, the explicit |bn_secret| call can be removed.
-  if (!BN_rand_range_ex(&blinding_factor, 1, &mont->N)) {
-    goto err;
+  if (!BN_rand_range_ex(blinding_factor.get(), 1, &mont->N)) {
+    return 0;
   }
-  bn_secret(&blinding_factor);
-  if (!BN_mod_mul_montgomery(out, &blinding_factor, a, mont, ctx)) {
-    goto err;
+  bn_secret(blinding_factor.get());
+  if (!BN_mod_mul_montgomery(out, blinding_factor.get(), a, mont, ctx)) {
+    return 0;
   }
 
   // Once blinded, |out| is no longer secret, so it may be passed to a leaky
@@ -266,35 +252,27 @@
   // secret again after multiplying.
   bn_declassify(out);
   if (!BN_mod_inverse_odd(out, out_no_inverse, out, &mont->N, ctx) ||
-      !BN_mod_mul_montgomery(out, &blinding_factor, out, mont, ctx)) {
-    goto err;
+      !BN_mod_mul_montgomery(out, blinding_factor.get(), out, mont, ctx)) {
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_free(&blinding_factor);
-  return ret;
+  return 1;
 }
 
 int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
                          BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *p_minus_2 = BN_CTX_get(ctx);
-  int ok = p_minus_2 != NULL && BN_copy(p_minus_2, p) &&
-           BN_sub_word(p_minus_2, 2) &&
-           BN_mod_exp_mont(out, a, p_minus_2, p, ctx, mont_p);
-  BN_CTX_end(ctx);
-  return ok;
+  return p_minus_2 != nullptr && BN_copy(p_minus_2, p) &&
+         BN_sub_word(p_minus_2, 2) &&
+         BN_mod_exp_mont(out, a, p_minus_2, p, ctx, mont_p);
 }
 
 int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
                                 BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *p_minus_2 = BN_CTX_get(ctx);
-  int ok = p_minus_2 != NULL && BN_copy(p_minus_2, p) &&
-           BN_sub_word(p_minus_2, 2) &&
-           BN_mod_exp_mont_consttime(out, a, p_minus_2, p, ctx, mont_p);
-  BN_CTX_end(ctx);
-  return ok;
+  return p_minus_2 != nullptr && BN_copy(p_minus_2, p) &&
+         BN_sub_word(p_minus_2, 2) &&
+         BN_mod_exp_mont_consttime(out, a, p_minus_2, p, ctx, mont_p);
 }
diff --git a/src/crypto/fipsmodule/bn/gcd_extra.cc.inc b/src/crypto/fipsmodule/bn/gcd_extra.cc.inc
index d8642cd..dc0f072 100644
--- a/src/crypto/fipsmodule/bn/gcd_extra.cc.inc
+++ b/src/crypto/fipsmodule/bn/gcd_extra.cc.inc
@@ -56,19 +56,18 @@
   }
 
   // This is a constant-time implementation of Stein's algorithm (binary GCD).
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *u = BN_CTX_get(ctx);
   BIGNUM *v = BN_CTX_get(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   unsigned x_bits, y_bits, num_iters, shift;
-  if (u == NULL || v == NULL || tmp == NULL ||  //
+  if (u == nullptr || v == nullptr || tmp == nullptr ||  //
       !BN_copy(u, x) ||                         //
       !BN_copy(v, y) ||                         //
       !bn_resize_words(u, width) ||             //
       !bn_resize_words(v, width) ||             //
       !bn_resize_words(tmp, width)) {
-    goto err;
+    return 0;
   }
 
   // Each loop iteration halves at least one of |u| and |v|. Thus we need at
@@ -78,7 +77,7 @@
   num_iters = x_bits + y_bits;
   if (num_iters < x_bits) {
     OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
-    goto err;
+    return 0;
   }
 
   shift = 0;
@@ -114,11 +113,7 @@
   }
 
   *out_shift = shift;
-  ret = bn_set_words(r, v->d, width);
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return bn_set_words(r, v->d, width);
 }
 
 int BN_gcd(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) {
@@ -128,12 +123,11 @@
 
 int bn_is_relatively_prime(int *out_relatively_prime, const BIGNUM *x,
                            const BIGNUM *y, BN_CTX *ctx) {
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   unsigned shift;
   BIGNUM *gcd = BN_CTX_get(ctx);
-  if (gcd == NULL || !bn_gcd_consttime(gcd, &shift, x, y, ctx)) {
-    goto err;
+  if (gcd == nullptr || !bn_gcd_consttime(gcd, &shift, x, y, ctx)) {
+    return 0;
   }
 
   // Check that 2^|shift| * |gcd| is one.
@@ -146,25 +140,20 @@
     }
     *out_relatively_prime = mask == 0;
   }
-  ret = 1;
 
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   unsigned shift;
   BIGNUM *gcd = BN_CTX_get(ctx);
-  int ret = gcd != NULL &&  //
-            bn_mul_consttime(r, a, b, ctx) &&
-            bn_gcd_consttime(gcd, &shift, a, b, ctx) &&
-            // |gcd| has a secret bit width.
-            bn_div_consttime(r, NULL, r, gcd, /*divisor_min_bits=*/0, ctx) &&
-            bn_rshift_secret_shift(r, r, shift, ctx);
-  BN_CTX_end(ctx);
-  return ret;
+  return gcd != nullptr &&  //
+         bn_mul_consttime(r, a, b, ctx) &&
+         bn_gcd_consttime(gcd, &shift, a, b, ctx) &&
+         // |gcd| has a secret bit width.
+         bn_div_consttime(r, nullptr, r, gcd, /*divisor_min_bits=*/0, ctx) &&
+         bn_rshift_secret_shift(r, r, shift, ctx);
 }
 
 int bn_mod_inverse_consttime(BIGNUM *r, int *out_no_inverse, const BIGNUM *a,
@@ -207,8 +196,7 @@
     a_width = n_width;
   }
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *u = BN_CTX_get(ctx);
   BIGNUM *v = BN_CTX_get(ctx);
   BIGNUM *A = BN_CTX_get(ctx);
@@ -218,14 +206,14 @@
   BIGNUM *tmp = BN_CTX_get(ctx);
   BIGNUM *tmp2 = BN_CTX_get(ctx);
   size_t a_bits, num_iters, n_bits;
-  if (u == NULL ||       //
-      v == NULL ||       //
-      A == NULL ||       //
-      B == NULL ||       //
-      C == NULL ||       //
-      D == NULL ||       //
-      tmp == NULL ||     //
-      tmp2 == NULL ||    //
+  if (u == nullptr ||       //
+      v == nullptr ||       //
+      A == nullptr ||       //
+      B == nullptr ||       //
+      C == nullptr ||       //
+      D == nullptr ||       //
+      tmp == nullptr ||     //
+      tmp2 == nullptr ||    //
       !BN_copy(u, a) ||  //
       !BN_copy(v, n) ||  //
       !BN_one(A) ||      //
@@ -242,7 +230,7 @@
       // |tmp| and |tmp2| may be used at either size.
       !bn_resize_words(tmp, n_width) ||  //
       !bn_resize_words(tmp2, n_width)) {
-    goto err;
+    return 0;
   }
 
   // Each loop iteration halves at least one of |u| and |v|. Thus we need at
@@ -254,7 +242,7 @@
   num_iters = a_bits + n_bits;
   if (num_iters < a_bits) {
     OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
-    goto err;
+    return 0;
   }
 
   // Before and after each loop iteration, the following hold:
@@ -328,12 +316,8 @@
   if (constant_time_declassify_int(!BN_is_one(u))) {
     *out_no_inverse = 1;
     OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
-    goto err;
+    return 0;
   }
 
-  ret = BN_copy(r, A) != NULL;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return BN_copy(r, A) != nullptr;
 }
diff --git a/src/crypto/fipsmodule/bn/internal.h b/src/crypto/fipsmodule/bn/internal.h
index 0a9997d..9dfc114 100644
--- a/src/crypto/fipsmodule/bn/internal.h
+++ b/src/crypto/fipsmodule/bn/internal.h
@@ -13,15 +13,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_BN_INTERNAL_H
-#define OPENSSL_HEADER_BN_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_INTERNAL_H
 
 #include <openssl/bn.h>
 
 #if defined(OPENSSL_X86_64) && defined(_MSC_VER)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <intrin.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #pragma intrinsic(__umulh, _umul128)
 #endif
 
@@ -263,11 +261,15 @@
 int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive,
                          const BIGNUM *max_exclusive);
 
-// BN_MONTGOMERY_MAX_WORDS is the maximum numer of words allowed in a |BIGNUM|
+// BN_MONTGOMERY_MAX_WORDS is the maximum number of words allowed in a |BIGNUM|
 // used with Montgomery reduction. Ideally this limit would be applied to all
 // |BIGNUM|s, in |bn_wexpand|, but the exactfloat library needs to create 8 MiB
 // values for other operations.
-#define BN_MONTGOMERY_MAX_WORDS (8 * 1024 / sizeof(BN_ULONG))
+//
+// TODO(crbug.com/402677800): This is not quite tight enough to limit the
+// |bn_mul_mont| allocation to under a page. Lower the maximum RSA key and then
+// lower this to match.
+#define BN_MONTGOMERY_MAX_WORDS (16384 / BN_BITS2)
 
 #if !defined(OPENSSL_NO_ASM) &&                         \
     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
@@ -275,14 +277,14 @@
 #define OPENSSL_BN_ASM_MONT
 // bn_mul_mont writes |ap| * |bp| mod |np| to |rp|, each |num| words
 // long. Inputs and outputs are in Montgomery form. |n0| is a pointer to the
-// corresponding field in |BN_MONT_CTX|. It returns one if |bn_mul_mont| handles
-// inputs of this size and zero otherwise.
+// corresponding field in |BN_MONT_CTX|.
 //
 // If at least one of |ap| or |bp| is fully reduced, |rp| will be fully reduced.
 // If neither is fully-reduced, the output may not be either.
 //
-// This function allocates |num| words on the stack, so |num| should be at most
-// |BN_MONTGOMERY_MAX_WORDS|.
+// This function allocates up to 2 * |num| words (plus a constant allocation) on
+// the stack, so |num| should be at most |BN_MONTGOMERY_MAX_WORDS|.
+// Additionally, |num| must be at least 128 / |BN_BITS2|.
 //
 // TODO(davidben): The x86_64 implementation expects a 32-bit input and masks
 // off upper bits. The aarch64 implementation expects a 64-bit input and does
@@ -291,39 +293,39 @@
 //
 // See also discussion in |ToWord| in abi_test.h for notes on smaller-than-word
 // inputs.
-int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                 const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 
 #if defined(OPENSSL_X86_64)
 inline int bn_mulx_adx_capable(void) {
   // MULX is in BMI2.
   return CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable();
 }
-int bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                     const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                      const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 inline int bn_mul4x_mont_capable(size_t num) {
   return num >= 8 && (num & 3) == 0;
 }
-int bn_mul4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                  const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mul4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                   const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 inline int bn_mulx4x_mont_capable(size_t num) {
   return bn_mul4x_mont_capable(num) && bn_mulx_adx_capable();
 }
-int bn_mulx4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                   const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mulx4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                    const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 inline int bn_sqr8x_mont_capable(size_t num) {
   return num >= 8 && (num & 7) == 0;
 }
-int bn_sqr8x_mont(BN_ULONG *rp, const BN_ULONG *ap, BN_ULONG mulx_adx_capable,
-                  const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_sqr8x_mont(BN_ULONG *rp, const BN_ULONG *ap, BN_ULONG mulx_adx_capable,
+                   const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 #elif defined(OPENSSL_ARM)
 inline int bn_mul8x_mont_neon_capable(size_t num) {
   return (num & 7) == 0 && CRYPTO_is_NEON_capable();
 }
-int bn_mul8x_mont_neon(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                       const BN_ULONG *np, const BN_ULONG *n0, size_t num);
-int bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                     const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mul8x_mont_neon(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                        const BN_ULONG *np, const BN_ULONG *n0, size_t num);
+void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                      const BN_ULONG *np, const BN_ULONG *n0, size_t num);
 #endif
 
 #endif  // OPENSSL_BN_ASM_MONT
@@ -721,4 +723,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_BN_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_INTERNAL_H
diff --git a/src/crypto/fipsmodule/bn/jacobi.cc.inc b/src/crypto/fipsmodule/bn/jacobi.cc.inc
index 0ac6f67..1c1c51f 100644
--- a/src/crypto/fipsmodule/bn/jacobi.cc.inc
+++ b/src/crypto/fipsmodule/bn/jacobi.cc.inc
@@ -42,32 +42,29 @@
     return -2;
   }
 
-  int ret = -2;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *A = BN_CTX_get(ctx);
   BIGNUM *B = BN_CTX_get(ctx);
   if (B == NULL) {
-    goto end;
+    return -2;
   }
 
   if (!BN_copy(A, a) ||
       !BN_copy(B, b)) {
-    goto end;
+    return -2;
   }
 
   // Adapted from logic to compute the Kronecker symbol, originally implemented
   // according to Henri Cohen, "A Course in Computational Algebraic Number
   // Theory" (algorithm 1.4.10).
 
-  ret = 1;
-
+  int ret = 1;
   while (1) {
     // Cohen's step 3:
 
     // B is positive and odd
     if (BN_is_zero(A)) {
-      ret = BN_is_one(B) ? ret : 0;
-      goto end;
+      return BN_is_one(B) ? ret : 0;
     }
 
     // now A is non-zero
@@ -76,8 +73,7 @@
       i++;
     }
     if (!BN_rshift(A, A, i)) {
-      ret = -2;
-      goto end;
+      return -2;
     }
     if (i & 1) {
       // i is odd
@@ -93,16 +89,11 @@
 
     // (A, B) := (B mod |A|, |A|)
     if (!BN_nnmod(B, B, A, ctx)) {
-      ret = -2;
-      goto end;
+      return -2;
     }
     BIGNUM *tmp = A;
     A = B;
     B = tmp;
     tmp->neg = 0;
   }
-
-end:
-  BN_CTX_end(ctx);
-  return ret;
 }
diff --git a/src/crypto/fipsmodule/bn/montgomery.cc.inc b/src/crypto/fipsmodule/bn/montgomery.cc.inc
index e73f805..4bafb11 100644
--- a/src/crypto/fipsmodule/bn/montgomery.cc.inc
+++ b/src/crypto/fipsmodule/bn/montgomery.cc.inc
@@ -245,21 +245,13 @@
 
 int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
                        BN_CTX *ctx) {
-  int ret = 0;
-  BIGNUM *t;
-
-  BN_CTX_start(ctx);
-  t = BN_CTX_get(ctx);
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *t = BN_CTX_get(ctx);
   if (t == NULL || !BN_copy(t, a)) {
-    goto err;
+    return 0;
   }
 
-  ret = BN_from_montgomery_word(r, t, mont);
-
-err:
-  BN_CTX_end(ctx);
-
-  return ret;
+  return BN_from_montgomery_word(r, t, mont);
 }
 
 int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx) {
@@ -286,34 +278,28 @@
                                           const BIGNUM *b,
                                           const BN_MONT_CTX *mont,
                                           BN_CTX *ctx) {
-  int ret = 0;
-
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   if (tmp == NULL) {
-    goto err;
+    return 0;
   }
 
   if (a == b) {
     if (!bn_sqr_consttime(tmp, a, ctx)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!bn_mul_consttime(tmp, a, b, ctx)) {
-      goto err;
+      return 0;
     }
   }
 
   // reduce from aRR to aR
   if (!BN_from_montgomery_word(r, tmp, mont)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
@@ -324,7 +310,7 @@
   }
 
 #if defined(OPENSSL_BN_ASM_MONT)
-  // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
+  // |bn_mul_mont| requires at least 128 bits of limbs.
   int num = mont->N.width;
   if (num >= (128 / BN_BITS2) && a->width == num && b->width == num) {
     if (!bn_wexpand(r, num)) {
@@ -333,12 +319,7 @@
     // This bound is implied by |bn_mont_ctx_set_N_and_n0|. |bn_mul_mont|
     // allocates |num| words on the stack, so |num| cannot be too large.
     assert((size_t)num <= BN_MONTGOMERY_MAX_WORDS);
-    if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
-      // The check above ensures this won't happen.
-      assert(0);
-      OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
+    bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num);
     r->neg = 0;
     r->width = num;
     return 1;
@@ -379,11 +360,9 @@
   }
 
 #if defined(OPENSSL_BN_ASM_MONT)
-  // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
+  // |bn_mul_mont| requires at least 128 bits of limbs.
   if (num >= (128 / BN_BITS2)) {
-    if (!bn_mul_mont(r, a, b, mont->N.d, mont->n0, num)) {
-      abort();  // The check above ensures this won't happen.
-    }
+    bn_mul_mont(r, a, b, mont->N.d, mont->n0, num);
     return;
   }
 #endif
@@ -404,27 +383,27 @@
 }
 
 #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_X86_64)
-int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
                 const BN_ULONG *np, const BN_ULONG *n0, size_t num) {
   if (ap == bp && bn_sqr8x_mont_capable(num)) {
-    return bn_sqr8x_mont(rp, ap, bn_mulx_adx_capable(), np, n0, num);
+    bn_sqr8x_mont(rp, ap, bn_mulx_adx_capable(), np, n0, num);
+  } else if (bn_mulx4x_mont_capable(num)) {
+    bn_mulx4x_mont(rp, ap, bp, np, n0, num);
+  } else if (bn_mul4x_mont_capable(num)) {
+    bn_mul4x_mont(rp, ap, bp, np, n0, num);
+  } else {
+    bn_mul_mont_nohw(rp, ap, bp, np, n0, num);
   }
-  if (bn_mulx4x_mont_capable(num)) {
-    return bn_mulx4x_mont(rp, ap, bp, np, n0, num);
-  }
-  if (bn_mul4x_mont_capable(num)) {
-    return bn_mul4x_mont(rp, ap, bp, np, n0, num);
-  }
-  return bn_mul_mont_nohw(rp, ap, bp, np, n0, num);
 }
 #endif
 
 #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_ARM)
-int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
-                const BN_ULONG *np, const BN_ULONG *n0, size_t num) {
+void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+                 const BN_ULONG *np, const BN_ULONG *n0, size_t num) {
   if (bn_mul8x_mont_neon_capable(num)) {
-    return bn_mul8x_mont_neon(rp, ap, bp, np, n0, num);
+    bn_mul8x_mont_neon(rp, ap, bp, np, n0, num);
+  } else {
+    bn_mul_mont_nohw(rp, ap, bp, np, n0, num);
   }
-  return bn_mul_mont_nohw(rp, ap, bp, np, n0, num);
 }
 #endif
diff --git a/src/crypto/fipsmodule/bn/mul.cc.inc b/src/crypto/fipsmodule/bn/mul.cc.inc
index 6dc8d52..9f75dde 100644
--- a/src/crypto/fipsmodule/bn/mul.cc.inc
+++ b/src/crypto/fipsmodule/bn/mul.cc.inc
@@ -137,15 +137,14 @@
   int cl = a->width < b->width ? a->width : b->width;
   int dl = a->width - b->width;
   int r_len = a->width < b->width ? b->width : a->width;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
-  int ok = tmp != NULL && bn_wexpand(r, r_len) && bn_wexpand(tmp, r_len);
-  if (ok) {
-    bn_abs_sub_part_words(r->d, a->d, b->d, cl, dl, tmp->d);
-    r->width = r_len;
+  if (tmp == nullptr || !bn_wexpand(r, r_len) || !bn_wexpand(tmp, r_len)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ok;
+  bn_abs_sub_part_words(r->d, a->d, b->d, cl, dl, tmp->d);
+  r->width = r_len;
+  return 1;
 }
 
 // Karatsuba recursive multiplication algorithm
@@ -377,13 +376,13 @@
     return 1;
   }
 
-  int ret = 0, i, top;
+  int i, top;
   BIGNUM *rr;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   if (r == a || r == b) {
     rr = BN_CTX_get(ctx);
     if (rr == NULL) {
-      goto err;
+      return 0;
     }
   } else {
     rr = r;
@@ -394,7 +393,7 @@
   if (i == 0) {
     if (al == 8) {
       if (!bn_wexpand(rr, 16)) {
-        goto err;
+        return 0;
       }
       rr->width = 16;
       bn_mul_comba8(rr->d, a->d, b->d);
@@ -403,6 +402,10 @@
   }
 
   top = al + bl;
+  // TODO(crbug.com/406497222): The recursive implementation is actually worse
+  // for cryptographic use cases, but we need to retain it in |BN_mul| for the
+  // projects misusing BIGNUM as a general-purpose calculator library with
+  // giant integers. Disconnect this code from our cryptographic primitives.
   static const int kMulNormalSize = 16;
   if (al >= kMulNormalSize && bl >= kMulNormalSize) {
     if (-1 <= i && i <= 1) {
@@ -417,7 +420,7 @@
       assert(j <= al || j <= bl);
       BIGNUM *t = BN_CTX_get(ctx);
       if (t == NULL) {
-        goto err;
+        return 0;
       }
       if (al > j || bl > j) {
         // We know |al| and |bl| are at most one from each other, so if al > j,
@@ -428,7 +431,7 @@
         // https://boringssl-review.googlesource.com/q/I0bd604e2cd6a75c266f64476c23a730ca1721ea6
         assert(al >= j && bl >= j);
         if (!bn_wexpand(t, j * 8) || !bn_wexpand(rr, j * 4)) {
-          goto err;
+          return 0;
         }
         bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
       } else {
@@ -436,7 +439,7 @@
         // of al - j or bl - j is zero. The other, by the bound on |i| above, is
         // zero or -1. Thus, we can use |bn_mul_recursive|.
         if (!bn_wexpand(t, j * 4) || !bn_wexpand(rr, j * 2)) {
-          goto err;
+          return 0;
         }
         bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
       }
@@ -446,20 +449,16 @@
   }
 
   if (!bn_wexpand(rr, top)) {
-    goto err;
+    return 0;
   }
   rr->width = top;
   bn_mul_normal(rr->d, a->d, al, b->d, bl);
 
 end:
   if (r != rr && !BN_copy(r, rr)) {
-    goto err;
+    return 0;
   }
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
@@ -623,17 +622,16 @@
     return 1;
   }
 
-  int ret = 0, max;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *rr = (a != r) ? r : BN_CTX_get(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   if (!rr || !tmp) {
-    goto err;
+    return 0;
   }
 
-  max = 2 * al;  // Non-zero (from above)
+  int max = 2 * al;  // Non-zero (from above)
   if (!bn_wexpand(rr, max)) {
-    goto err;
+    return 0;
   }
 
   if (al == 4) {
@@ -646,14 +644,20 @@
       bn_sqr_normal(rr->d, a->d, al, t);
     } else {
       // If |al| is a power of two, we can use |bn_sqr_recursive|.
+      //
+      // TODO(crbug.com/406497222): The recursive implementation is actually
+      // worse for cryptographic use cases, but we need to retain it in |BN_mul|
+      // for the projects misusing BIGNUM as a general-purpose calculator
+      // library with giant integers. Disconnect this code from our
+      // cryptographic primitives.
       if (al != 0 && (al & (al - 1)) == 0) {
         if (!bn_wexpand(tmp, al * 4)) {
-          goto err;
+          return 0;
         }
         bn_sqr_recursive(rr->d, a->d, al, tmp->d);
       } else {
         if (!bn_wexpand(tmp, max)) {
-          goto err;
+          return 0;
         }
         bn_sqr_normal(rr->d, a->d, al, tmp->d);
       }
@@ -664,13 +668,9 @@
   rr->width = max;
 
   if (rr != r && !BN_copy(r, rr)) {
-    goto err;
+    return 0;
   }
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) {
diff --git a/src/crypto/fipsmodule/bn/prime.cc.inc b/src/crypto/fipsmodule/bn/prime.cc.inc
index 0471246..fabb545 100644
--- a/src/crypto/fipsmodule/bn/prime.cc.inc
+++ b/src/crypto/fipsmodule/bn/prime.cc.inc
@@ -290,9 +290,7 @@
 int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
                          const BIGNUM *rem, BN_GENCB *cb) {
   BIGNUM *t;
-  int found = 0;
   int i, j, c1 = 0;
-  BN_CTX *ctx;
   int checks = BN_prime_checks_for_size(bits);
 
   if (bits < 2) {
@@ -305,43 +303,43 @@
     return 0;
   }
 
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
-  BN_CTX_start(ctx);
-  t = BN_CTX_get(ctx);
+  bssl::BN_CTXScope scope(ctx.get());
+  t = BN_CTX_get(ctx.get());
   if (!t) {
-    goto err;
+    return 0;
   }
 
 loop:
   // make a random number and set the top and bottom bits
   if (add == NULL) {
     if (!probable_prime(ret, bits)) {
-      goto err;
+      return 0;
     }
   } else {
     if (safe) {
-      if (!probable_prime_dh_safe(ret, bits, add, rem, ctx)) {
-        goto err;
+      if (!probable_prime_dh_safe(ret, bits, add, rem, ctx.get())) {
+        return 0;
       }
     } else {
-      if (!probable_prime_dh(ret, bits, add, rem, ctx)) {
-        goto err;
+      if (!probable_prime_dh(ret, bits, add, rem, ctx.get())) {
+        return 0;
       }
     }
   }
 
   if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, c1++)) {
     // aborted
-    goto err;
+    return 0;
   }
 
   if (!safe) {
-    i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
+    i = BN_is_prime_fasttest_ex(ret, checks, ctx.get(), 0, cb);
     if (i == -1) {
-      goto err;
+      return 0;
     } else if (i == 0) {
       goto loop;
     }
@@ -349,7 +347,7 @@
     // for "safe prime" generation, check that (p-1)/2 is prime. Since a prime
     // is odd, We just need to divide by 2
     if (!BN_rshift1(t, ret)) {
-      goto err;
+      return 0;
     }
 
     // Interleave |ret| and |t|'s primality tests to avoid paying the full
@@ -358,37 +356,29 @@
     // TODO(davidben): This doesn't quite work because an iteration count of 1
     // still runs the blinding mechanism.
     for (i = 0; i < checks; i++) {
-      j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, NULL);
+      j = BN_is_prime_fasttest_ex(ret, 1, ctx.get(), 0, NULL);
       if (j == -1) {
-        goto err;
+        return 0;
       } else if (j == 0) {
         goto loop;
       }
 
-      j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, NULL);
+      j = BN_is_prime_fasttest_ex(t, 1, ctx.get(), 0, NULL);
       if (j == -1) {
-        goto err;
+        return 0;
       } else if (j == 0) {
         goto loop;
       }
 
       if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i)) {
-        goto err;
+        return 0;
       }
       // We have a safe prime test pass
     }
   }
 
   // we have a prime :-)
-  found = 1;
-
-err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-
-  return found;
+  return 1;
 }
 
 static int bn_trial_division(uint16_t *out, const BIGNUM *bn) {
@@ -453,8 +443,7 @@
                               int *out_is_possibly_prime, const BIGNUM *b,
                               const BN_MONT_CTX *mont, BN_CTX *ctx) {
   // This function corresponds to steps 4.3 through 4.5 of FIPS 186-4, C.3.1.
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
 
   // Step 4.3. We use Montgomery-encoding for better performance and to avoid
   // timing leaks.
@@ -464,7 +453,7 @@
   if (z == NULL ||
       !BN_mod_exp_mont_consttime(z, b, miller_rabin->m, w, ctx, mont) ||
       !BN_to_montgomery(z, z, mont, ctx)) {
-    goto err;
+    return 0;
   }
 
   // is_possibly_prime is all ones if we have determined |b| is not a composite
@@ -493,7 +482,7 @@
 
     // Step 4.5.1.
     if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) {
-      goto err;
+      return 0;
     }
 
     // Step 4.5.2. If z = w-1 and the loop is not done, this is not a composite
@@ -513,11 +502,7 @@
   }
 
   *out_is_possibly_prime = constant_time_declassify_w(is_possibly_prime) & 1;
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
@@ -598,26 +583,25 @@
     checks = BN_prime_checks_for_size(BN_num_bits(w));
   }
 
-  BN_CTX *new_ctx = NULL;
-  if (ctx == NULL) {
-    new_ctx = BN_CTX_new();
-    if (new_ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> new_ctx;
+  if (ctx == nullptr) {
+    new_ctx.reset(BN_CTX_new());
+    if (new_ctx == nullptr) {
       return 0;
     }
-    ctx = new_ctx;
+    ctx = new_ctx.get();
   }
 
   // See C.3.1 from FIPS 186-4.
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *b = BN_CTX_get(ctx);
-  BN_MONT_CTX *mont = BN_MONT_CTX_new_consttime(w, ctx);
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new_consttime(w, ctx));
   BN_MILLER_RABIN miller_rabin;
   crypto_word_t uniform_iterations = 0;
-  if (b == NULL || mont == NULL ||
+  if (b == nullptr || mont == nullptr ||
       // Steps 1-3.
-      !bn_miller_rabin_init(&miller_rabin, mont, ctx)) {
-    goto err;
+      !bn_miller_rabin_init(&miller_rabin, mont.get(), ctx)) {
+    return 0;
   }
 
   // The following loop performs in inner iteration of the Miller-Rabin
@@ -657,39 +641,32 @@
     // Step 4.1-4.2
     int is_uniform;
     if (!bn_rand_secret_range(b, &is_uniform, 2, miller_rabin.w1)) {
-      goto err;
+      return 0;
     }
     uniform_iterations += is_uniform;
 
     // Steps 4.3-4.5
     int is_possibly_prime = 0;
-    if (!bn_miller_rabin_iteration(&miller_rabin, &is_possibly_prime, b, mont,
-                                   ctx)) {
-      goto err;
+    if (!bn_miller_rabin_iteration(&miller_rabin, &is_possibly_prime, b,
+                                   mont.get(), ctx)) {
+      return 0;
     }
 
     if (!is_possibly_prime) {
       // Step 4.6. We did not see z = w-1 before z = 1, so w must be composite.
       *out_is_probably_prime = 0;
-      ret = 1;
-      goto err;
+      return 1;
     }
 
     // Step 4.7
     if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
-      goto err;
+      return 0;
     }
   }
 
   declassify_assert(uniform_iterations >= (crypto_word_t)checks);
   *out_is_probably_prime = 1;
-  ret = 1;
-
-err:
-  BN_MONT_CTX_free(mont);
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
+  return 1;
 }
 
 int BN_is_prime_ex(const BIGNUM *candidate, int checks, BN_CTX *ctx,
@@ -720,41 +697,36 @@
     checks = BN_prime_checks_for_size(BN_num_bits(w));
   }
 
-  int ret = 0;
-  BN_MONT_CTX *mont = NULL;
-
-  BN_CTX_start(ctx);
-
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *w1 = BN_CTX_get(ctx);
-  BIGNUM *b, *g, *z, *x, *x1, *m;
-  int a;
-  if (w1 == NULL || !BN_copy(w1, w) || !BN_sub_word(w1, 1)) {
-    goto err;
+  if (w1 == nullptr || !BN_copy(w1, w) || !BN_sub_word(w1, 1)) {
+    return 0;
   }
 
   // Write w1 as m*2^a (Steps 1 and 2).
-  a = 0;
+  int a = 0;
   while (!BN_is_bit_set(w1, a)) {
     a++;
   }
-  m = BN_CTX_get(ctx);
-  if (m == NULL || !BN_rshift(m, w1, a)) {
-    goto err;
+  BIGNUM *m = BN_CTX_get(ctx);
+  if (m == nullptr || !BN_rshift(m, w1, a)) {
+    return 0;
   }
 
-  b = BN_CTX_get(ctx);
-  g = BN_CTX_get(ctx);
-  z = BN_CTX_get(ctx);
-  x = BN_CTX_get(ctx);
-  x1 = BN_CTX_get(ctx);
-  if (b == NULL || g == NULL || z == NULL || x == NULL || x1 == NULL) {
-    goto err;
+  BIGNUM *b = BN_CTX_get(ctx);
+  BIGNUM *g = BN_CTX_get(ctx);
+  BIGNUM *z = BN_CTX_get(ctx);
+  BIGNUM *x = BN_CTX_get(ctx);
+  BIGNUM *x1 = BN_CTX_get(ctx);
+  if (b == nullptr || g == nullptr || z == nullptr || x == nullptr ||
+      x1 == nullptr) {
+    return 0;
   }
 
   // Montgomery setup for computations mod w
-  mont = BN_MONT_CTX_new_for_modulus(w, ctx);
-  if (mont == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new_for_modulus(w, ctx));
+  if (mont == nullptr) {
+    return 0;
   }
 
   // The following loop performs in inner iteration of the Enhanced Miller-Rabin
@@ -762,22 +734,21 @@
   for (int i = 1; i <= checks; i++) {
     // Step 4.1-4.2
     if (!BN_rand_range_ex(b, 2, w1)) {
-      goto err;
+      return 0;
     }
 
     // Step 4.3-4.4
     if (!BN_gcd(g, b, w, ctx)) {
-      goto err;
+      return 0;
     }
     if (BN_cmp_word(g, 1) > 0) {
       *out_result = bn_composite;
-      ret = 1;
-      goto err;
+      return 1;
     }
 
     // Step 4.5
-    if (!BN_mod_exp_mont(z, b, m, w, ctx, mont)) {
-      goto err;
+    if (!BN_mod_exp_mont(z, b, m, w, ctx, mont.get())) {
+      return 0;
     }
 
     // Step 4.6
@@ -788,7 +759,7 @@
     // Step 4.7
     for (int j = 1; j < a; j++) {
       if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) {
-        goto err;
+        return 0;
       }
       if (BN_cmp(z, w1) == 0) {
         goto loop;
@@ -800,18 +771,18 @@
 
     // Step 4.8-4.9
     if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) {
-      goto err;
+      return 0;
     }
 
     // Step 4.10-4.11
     if (!BN_is_one(z) && !BN_copy(x, z)) {
-      goto err;
+      return 0;
     }
 
   composite:
     // Step 4.12-4.14
     if (!BN_copy(x1, x) || !BN_sub_word(x1, 1) || !BN_gcd(g, x1, w, ctx)) {
-      goto err;
+      return 0;
     }
     if (BN_cmp_word(g, 1) > 0) {
       *out_result = bn_composite;
@@ -819,24 +790,17 @@
       *out_result = bn_non_prime_power_composite;
     }
 
-    ret = 1;
-    goto err;
+    return 1;
 
   loop:
     // Step 4.15
     if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
-      goto err;
+      return 0;
     }
   }
 
   *out_result = bn_probably_prime;
-  ret = 1;
-
-err:
-  BN_MONT_CTX_free(mont);
-  BN_CTX_end(ctx);
-
-  return ret;
+  return 1;
 }
 
 static int probable_prime(BIGNUM *rnd, int bits) {
@@ -850,111 +814,99 @@
 
 static int probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add,
                              const BIGNUM *rem, BN_CTX *ctx) {
-  int ret = 0;
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *t1;
-
-  BN_CTX_start(ctx);
-  size_t num_primes;
-  if ((t1 = BN_CTX_get(ctx)) == NULL) {
-    goto err;
+  if ((t1 = BN_CTX_get(ctx)) == nullptr) {
+    return 0;
   }
 
   if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) {
-    goto err;
+    return 0;
   }
 
   // we need ((rnd-rem) % add) == 0
-
   if (!BN_mod(t1, rnd, add, ctx)) {
-    goto err;
+    return 0;
   }
   if (!BN_sub(rnd, rnd, t1)) {
-    goto err;
+    return 0;
   }
-  if (rem == NULL) {
+  if (rem == nullptr) {
     if (!BN_add_word(rnd, 1)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_add(rnd, rnd, rem)) {
-      goto err;
+      return 0;
     }
   }
   // we now have a random number 'rand' to test.
 
-  num_primes = num_trial_division_primes(rnd);
+  size_t num_primes = num_trial_division_primes(rnd);
 loop:
   for (size_t i = 1; i < num_primes; i++) {
     // check that rnd is a prime
     if (bn_mod_u16_consttime(rnd, kPrimes[i]) <= 1) {
       if (!BN_add(rnd, rnd, add)) {
-        goto err;
+        return 0;
       }
       goto loop;
     }
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
                                   const BIGNUM *rem, BN_CTX *ctx) {
-  int ret = 0;
-  BIGNUM *t1, *qadd, *q;
-
   bits--;
-  BN_CTX_start(ctx);
-  t1 = BN_CTX_get(ctx);
-  q = BN_CTX_get(ctx);
-  qadd = BN_CTX_get(ctx);
-  size_t num_primes;
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *t1 = BN_CTX_get(ctx);
+  BIGNUM *q = BN_CTX_get(ctx);
+  BIGNUM *qadd = BN_CTX_get(ctx);
   if (qadd == NULL) {
-    goto err;
+    return 0;
   }
 
   if (!BN_rshift1(qadd, padd)) {
-    goto err;
+    return 0;
   }
 
   if (!BN_rand(q, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) {
-    goto err;
+    return 0;
   }
 
   // we need ((rnd-rem) % add) == 0
   if (!BN_mod(t1, q, qadd, ctx)) {
-    goto err;
+    return 0;
   }
 
   if (!BN_sub(q, q, t1)) {
-    goto err;
+    return 0;
   }
 
   if (rem == NULL) {
     if (!BN_add_word(q, 1)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_rshift1(t1, rem)) {
-      goto err;
+      return 0;
     }
     if (!BN_add(q, q, t1)) {
-      goto err;
+      return 0;
     }
   }
 
   // we now have a random number 'rand' to test.
   if (!BN_lshift1(p, q)) {
-    goto err;
+    return 0;
   }
   if (!BN_add_word(p, 1)) {
-    goto err;
+    return 0;
   }
 
-  num_primes = num_trial_division_primes(p);
+  size_t num_primes = num_trial_division_primes(p);
 loop:
   for (size_t i = 1; i < num_primes; i++) {
     // check that p and q are prime
@@ -963,18 +915,14 @@
     if (bn_mod_u16_consttime(p, kPrimes[i]) == 0 ||
         bn_mod_u16_consttime(q, kPrimes[i]) == 0) {
       if (!BN_add(p, p, padd)) {
-        goto err;
+        return 0;
       }
       if (!BN_add(q, q, qadd)) {
-        goto err;
+        return 0;
       }
       goto loop;
     }
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
diff --git a/src/crypto/fipsmodule/bn/rsaz_exp.h b/src/crypto/fipsmodule/bn/rsaz_exp.h
index e0e9aa2..2e1d59e 100644
--- a/src/crypto/fipsmodule/bn/rsaz_exp.h
+++ b/src/crypto/fipsmodule/bn/rsaz_exp.h
@@ -17,8 +17,8 @@
 // (1) Intel Corporation, Israel Development Center, Haifa, Israel
 // (2) University of Haifa, Israel
 
-#ifndef OPENSSL_HEADER_BN_RSAZ_EXP_H
-#define OPENSSL_HEADER_BN_RSAZ_EXP_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_RSAZ_EXP_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_RSAZ_EXP_H
 
 #include <openssl/bn.h>
 
@@ -108,4 +108,4 @@
 }  // extern "C"
 #endif
 
-#endif  // OPENSSL_HEADER_BN_RSAZ_EXP_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_BN_RSAZ_EXP_H
diff --git a/src/crypto/fipsmodule/bn/shift.cc.inc b/src/crypto/fipsmodule/bn/shift.cc.inc
index 2739c5a..491c796 100644
--- a/src/crypto/fipsmodule/bn/shift.cc.inc
+++ b/src/crypto/fipsmodule/bn/shift.cc.inc
@@ -129,12 +129,11 @@
 
 int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, unsigned n,
                            BN_CTX *ctx) {
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   unsigned max_bits;
   if (tmp == NULL || !BN_copy(r, a) || !bn_wexpand(tmp, r->width)) {
-    goto err;
+    return 0;
   }
 
   // Shift conditionally by powers of two.
@@ -147,11 +146,7 @@
                     r->d /* ignore shift */, r->width);
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num) {
diff --git a/src/crypto/fipsmodule/bn/sqrt.cc.inc b/src/crypto/fipsmodule/bn/sqrt.cc.inc
index cb70f19..56d89e0 100644
--- a/src/crypto/fipsmodule/bn/sqrt.cc.inc
+++ b/src/crypto/fipsmodule/bn/sqrt.cc.inc
@@ -63,7 +63,7 @@
     return ret;
   }
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   A = BN_CTX_get(ctx);
   b = BN_CTX_get(ctx);
   q = BN_CTX_get(ctx);
@@ -378,82 +378,5 @@
     }
     ret = NULL;
   }
-  BN_CTX_end(ctx);
   return ret;
 }
-
-int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) {
-  BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2;
-  int ok = 0, last_delta_valid = 0;
-
-  if (in->neg) {
-    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
-    return 0;
-  }
-  if (BN_is_zero(in)) {
-    BN_zero(out_sqrt);
-    return 1;
-  }
-
-  BN_CTX_start(ctx);
-  if (out_sqrt == in) {
-    estimate = BN_CTX_get(ctx);
-  } else {
-    estimate = out_sqrt;
-  }
-  tmp = BN_CTX_get(ctx);
-  last_delta = BN_CTX_get(ctx);
-  delta = BN_CTX_get(ctx);
-  if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) {
-    goto err;
-  }
-
-  // We estimate that the square root of an n-bit number is 2^{n/2}.
-  if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
-    goto err;
-  }
-
-  // This is Newton's method for finding a root of the equation |estimate|^2 -
-  // |in| = 0.
-  for (;;) {
-    // |estimate| = 1/2 * (|estimate| + |in|/|estimate|)
-    if (!BN_div(tmp, NULL, in, estimate, ctx) ||
-        !BN_add(tmp, tmp, estimate) ||
-        !BN_rshift1(estimate, tmp) ||
-        // |tmp| = |estimate|^2
-        !BN_sqr(tmp, estimate, ctx) ||
-        // |delta| = |in| - |tmp|
-        !BN_sub(delta, in, tmp)) {
-      OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB);
-      goto err;
-    }
-
-    delta->neg = 0;
-    // The difference between |in| and |estimate| squared is required to always
-    // decrease. This ensures that the loop always terminates, but I don't have
-    // a proof that it always finds the square root for a given square.
-    if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) {
-      break;
-    }
-
-    last_delta_valid = 1;
-
-    tmp2 = last_delta;
-    last_delta = delta;
-    delta = tmp2;
-  }
-
-  if (BN_cmp(tmp, in) != 0) {
-    OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
-    goto err;
-  }
-
-  ok = 1;
-
-err:
-  if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) {
-    ok = 0;
-  }
-  BN_CTX_end(ctx);
-  return ok;
-}
diff --git a/src/crypto/fipsmodule/cipher/e_aes.cc.inc b/src/crypto/fipsmodule/cipher/e_aes.cc.inc
index 3ee6c7b..f0089c8 100644
--- a/src/crypto/fipsmodule/cipher/e_aes.cc.inc
+++ b/src/crypto/fipsmodule/cipher/e_aes.cc.inc
@@ -31,9 +31,6 @@
 #include "internal.h"
 
 
-OPENSSL_MSVC_PRAGMA(warning(push))
-OPENSSL_MSVC_PRAGMA(warning(disable : 4702))  // Unreachable code.
-
 #define AES_GCM_NONCE_LENGTH 12
 
 typedef struct {
@@ -1126,7 +1123,6 @@
   struct aead_aes_gcm_ctx gcm_ctx;
   uint64_t min_next_nonce;
   uint64_t mask;
-  uint8_t first;
 };
 }  // namespace
 
@@ -1143,7 +1139,6 @@
       (struct aead_aes_gcm_tls13_ctx *)&ctx->state;
 
   gcm_ctx->min_next_nonce = 0;
-  gcm_ctx->first = 1;
 
   size_t actual_tag_len;
   if (!aead_aes_gcm_init_impl(&gcm_ctx->gcm_ctx, &actual_tag_len, key, key_len,
@@ -1174,20 +1169,20 @@
   uint64_t given_counter =
       CRYPTO_load_u64_be(nonce + nonce_len - sizeof(uint64_t));
 
-  if (gcm_ctx->first) {
+  if (gcm_ctx->min_next_nonce == 0) {
     // In the first call the sequence number will be zero and therefore the
     // given nonce will be 0 ^ mask = mask.
     gcm_ctx->mask = given_counter;
-    gcm_ctx->first = 0;
+    gcm_ctx->min_next_nonce = 1;
+  } else {
+    given_counter ^= gcm_ctx->mask;
+    if (given_counter == UINT64_MAX ||
+        given_counter < gcm_ctx->min_next_nonce) {
+      OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
+      return 0;
+    }
+    gcm_ctx->min_next_nonce = given_counter + 1;
   }
-  given_counter ^= gcm_ctx->mask;
-
-  if (given_counter == UINT64_MAX || given_counter < gcm_ctx->min_next_nonce) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
-    return 0;
-  }
-
-  gcm_ctx->min_next_nonce = given_counter + 1;
 
   if (!aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len,
                                  max_out_tag_len, nonce, nonce_len, in, in_len,
@@ -1238,5 +1233,3 @@
   return 0;
 #endif
 }
-
-OPENSSL_MSVC_PRAGMA(warning(pop))
diff --git a/src/crypto/fipsmodule/cipher/internal.h b/src/crypto/fipsmodule/cipher/internal.h
index d4a06f7..c5373bb 100644
--- a/src/crypto/fipsmodule/cipher/internal.h
+++ b/src/crypto/fipsmodule/cipher/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CIPHER_INTERNAL_H
-#define OPENSSL_HEADER_CIPHER_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_CIPHER_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_CIPHER_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -110,4 +110,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CIPHER_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_CIPHER_INTERNAL_H
diff --git a/src/crypto/fipsmodule/delocate.h b/src/crypto/fipsmodule/delocate.h
index 26d3d41..ae7781e 100644
--- a/src/crypto/fipsmodule/delocate.h
+++ b/src/crypto/fipsmodule/delocate.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_FIPSMODULE_DELOCATE_H
-#define OPENSSL_HEADER_FIPSMODULE_DELOCATE_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_DELOCATE_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_DELOCATE_H
 
 #include <openssl/base.h>
 
@@ -22,11 +22,18 @@
 
 #if !defined(BORINGSSL_SHARED_LIBRARY) && defined(BORINGSSL_FIPS) && \
     !defined(OPENSSL_ASAN) && !defined(OPENSSL_MSAN)
-#define DEFINE_BSS_GET(type, name, init_value)         \
-  static type name __attribute__((used)) = init_value; \
-  extern "C" {                                         \
-  type *name##_bss_get(void) __attribute__((const));   \
-  }
+#define DEFINE_BSS_GET(type, name, init_value)                                 \
+  /* delocate needs C linkage and for |name| to be unique across BCM. */       \
+  extern "C" {                                                                 \
+  extern type bcm_##name;                                                      \
+  type bcm_##name = init_value;                                                \
+  type *bcm_##name##_bss_get(void) __attribute__((const));                     \
+  } /* extern "C" */                                                           \
+                                                                               \
+  /* The getter functions are exported, but static variables are usually named \
+   * with short names. Define a static wrapper function so the caller can use  \
+   * a short name, while the symbol itself is prefixed. */                     \
+  static type *name##_bss_get(void) { return bcm_##name##_bss_get(); }
 // For FIPS builds we require that CRYPTO_ONCE_INIT be zero.
 #define DEFINE_STATIC_ONCE(name) \
   DEFINE_BSS_GET(CRYPTO_once_t, name, CRYPTO_ONCE_INIT)
@@ -89,4 +96,4 @@
 
 #define DEFINE_LOCAL_DATA(type, name) DEFINE_DATA(type, name, static const)
 
-#endif  // OPENSSL_HEADER_FIPSMODULE_DELOCATE_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_DELOCATE_H
diff --git a/src/crypto/fipsmodule/dh/check.cc.inc b/src/crypto/fipsmodule/dh/check.cc.inc
index 19beb31..4d023d5 100644
--- a/src/crypto/fipsmodule/dh/check.cc.inc
+++ b/src/crypto/fipsmodule/dh/check.cc.inc
@@ -17,9 +17,14 @@
 #include <openssl/bn.h>
 #include <openssl/err.h>
 
+#include "../bn/internal.h"
 #include "internal.h"
 
 
+static_assert(OPENSSL_DH_MAX_MODULUS_BITS <=
+                  BN_MONTGOMERY_MAX_WORDS * BN_BITS2,
+              "Max DH size too big for Montgomery arithmetic");
+
 int dh_check_params_fast(const DH *dh) {
   // Most operations scale with p and q.
   if (BN_is_negative(dh->p) || !BN_is_odd(dh->p) ||
@@ -50,13 +55,11 @@
     return 0;
   }
 
-  BN_CTX *ctx = BN_CTX_new();
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
   if (ctx == NULL) {
     return 0;
   }
-  BN_CTX_start(ctx);
-
-  int ok = 0;
+  bssl::BN_CTXScope scope(ctx.get());
 
   // Check |pub_key| is greater than 1.
   if (BN_cmp(pub_key, BN_value_one()) <= 0) {
@@ -64,11 +67,11 @@
   }
 
   // Check |pub_key| is less than |dh->p| - 1.
-  BIGNUM *tmp = BN_CTX_get(ctx);
+  BIGNUM *tmp = BN_CTX_get(ctx.get());
   if (tmp == NULL ||
       !BN_copy(tmp, dh->p) ||
       !BN_sub_word(tmp, 1)) {
-    goto err;
+    return 0;
   }
   if (BN_cmp(pub_key, tmp) >= 0) {
     *out_flags |= DH_CHECK_PUBKEY_TOO_LARGE;
@@ -78,23 +81,17 @@
     // Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
     // groups which are not safe primes but pick a generator on a prime-order
     // subgroup of size |dh->q|.
-    if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) {
-      goto err;
+    if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx.get(), NULL)) {
+      return 0;
     }
     if (!BN_is_one(tmp)) {
       *out_flags |= DH_CHECK_PUBKEY_INVALID;
     }
   }
 
-  ok = 1;
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(ctx);
-  return ok;
+  return 1;
 }
 
-
 int DH_check(const DH *dh, int *out_flags) {
   *out_flags = 0;
   if (!dh_check_params_fast(dh)) {
@@ -107,23 +104,18 @@
   //   for 3, p mod 12 == 5
   //   for 5, p mod 10 == 3 or 7
   // should hold.
-  int ok = 0, r;
-  BN_CTX *ctx = NULL;
-  BN_ULONG l;
-  BIGNUM *t1 = NULL, *t2 = NULL;
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
-  BN_CTX_start(ctx);
-  t1 = BN_CTX_get(ctx);
-  if (t1 == NULL) {
-    goto err;
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *t1 = BN_CTX_get(ctx.get());
+  if (t1 == nullptr) {
+    return 0;
   }
-  t2 = BN_CTX_get(ctx);
-  if (t2 == NULL) {
-    goto err;
+  BIGNUM *t2 = BN_CTX_get(ctx.get());
+  if (t2 == nullptr) {
+    return 0;
   }
 
   if (dh->q) {
@@ -133,39 +125,40 @@
       *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
     } else {
       // Check g^q == 1 mod p
-      if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) {
-        goto err;
+      if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx.get(), nullptr)) {
+        return 0;
       }
       if (!BN_is_one(t1)) {
         *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
       }
     }
-    r = BN_is_prime_ex(dh->q, BN_prime_checks_for_validation, ctx, NULL);
+    int r = BN_is_prime_ex(dh->q, BN_prime_checks_for_validation, ctx.get(),
+                           nullptr);
     if (r < 0) {
-      goto err;
+      return 0;
     }
     if (!r) {
       *out_flags |= DH_CHECK_Q_NOT_PRIME;
     }
     // Check p == 1 mod q  i.e. q divides p - 1
-    if (!BN_div(t1, t2, dh->p, dh->q, ctx)) {
-      goto err;
+    if (!BN_div(t1, t2, dh->p, dh->q, ctx.get())) {
+      return 0;
     }
     if (!BN_is_one(t2)) {
       *out_flags |= DH_CHECK_INVALID_Q_VALUE;
     }
   } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
-    l = BN_mod_word(dh->p, 24);
+    BN_ULONG l = BN_mod_word(dh->p, 24);
     if (l == (BN_ULONG)-1) {
-      goto err;
+      return 0;
     }
     if (l != 11) {
       *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
     }
   } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
-    l = BN_mod_word(dh->p, 10);
+    BN_ULONG l = BN_mod_word(dh->p, 10);
     if (l == (BN_ULONG)-1) {
-      goto err;
+      return 0;
     }
     if (l != 3 && l != 7) {
       *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
@@ -174,30 +167,24 @@
     *out_flags |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR;
   }
 
-  r = BN_is_prime_ex(dh->p, BN_prime_checks_for_validation, ctx, NULL);
+  int r =
+      BN_is_prime_ex(dh->p, BN_prime_checks_for_validation, ctx.get(), nullptr);
   if (r < 0) {
-    goto err;
+    return 0;
   }
   if (!r) {
     *out_flags |= DH_CHECK_P_NOT_PRIME;
   } else if (!dh->q) {
     if (!BN_rshift1(t1, dh->p)) {
-      goto err;
+      return 0;
     }
-    r = BN_is_prime_ex(t1, BN_prime_checks_for_validation, ctx, NULL);
+    r = BN_is_prime_ex(t1, BN_prime_checks_for_validation, ctx.get(), nullptr);
     if (r < 0) {
-      goto err;
+      return 0;
     }
     if (!r) {
       *out_flags |= DH_CHECK_P_NOT_SAFE_PRIME;
     }
   }
-  ok = 1;
-
-err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  return ok;
+  return 1;
 }
diff --git a/src/crypto/fipsmodule/dh/dh.cc.inc b/src/crypto/fipsmodule/dh/dh.cc.inc
index 6f1267f..0a62215 100644
--- a/src/crypto/fipsmodule/dh/dh.cc.inc
+++ b/src/crypto/fipsmodule/dh/dh.cc.inc
@@ -147,28 +147,27 @@
   }
 
   int ok = 0;
-  int generate_new_key = 0;
-  BN_CTX *ctx = NULL;
-  BIGNUM *pub_key = NULL, *priv_key = NULL, *priv_key_limit = NULL;
+  bool generate_new_key = false;
+  BIGNUM *pub_key = nullptr, *priv_key = nullptr;
 
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
     goto err;
   }
 
-  if (dh->priv_key == NULL) {
+  if (dh->priv_key == nullptr) {
     priv_key = BN_new();
-    if (priv_key == NULL) {
+    if (priv_key == nullptr) {
       goto err;
     }
-    generate_new_key = 1;
+    generate_new_key = true;
   } else {
     priv_key = dh->priv_key;
   }
 
-  if (dh->pub_key == NULL) {
+  if (dh->pub_key == nullptr) {
     pub_key = BN_new();
-    if (pub_key == NULL) {
+    if (pub_key == nullptr) {
       goto err;
     }
   } else {
@@ -176,7 +175,7 @@
   }
 
   if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
-                              dh->p, ctx)) {
+                              dh->p, ctx.get())) {
     goto err;
   }
 
@@ -202,30 +201,30 @@
       // clamp |dh->priv_length| before invoking the algorithm.
 
       // Compute M = min(2^N, q).
-      priv_key_limit = BN_new();
-      if (priv_key_limit == NULL) {
+      bssl::UniquePtr<BIGNUM> priv_key_limit(BN_new());
+      if (priv_key_limit == nullptr) {
         goto err;
       }
       if (dh->priv_length == 0 || dh->priv_length >= BN_num_bits(dh->p) - 1) {
         // M = q = (p - 1) / 2.
-        if (!BN_rshift1(priv_key_limit, dh->p)) {
+        if (!BN_rshift1(priv_key_limit.get(), dh->p)) {
           goto err;
         }
       } else {
         // M = 2^N.
-        if (!BN_set_bit(priv_key_limit, dh->priv_length)) {
+        if (!BN_set_bit(priv_key_limit.get(), dh->priv_length)) {
           goto err;
         }
       }
 
       // Choose a private key uniformly from [1, M-1].
-      if (!BN_rand_range_ex(priv_key, 1, priv_key_limit)) {
+      if (!BN_rand_range_ex(priv_key, 1, priv_key_limit.get())) {
         goto err;
       }
     }
   }
 
-  if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
+  if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx.get(),
                                  dh->method_mont_p)) {
     goto err;
   }
@@ -239,14 +238,12 @@
     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
   }
 
-  if (dh->pub_key == NULL) {
+  if (dh->pub_key == nullptr) {
     BN_free(pub_key);
   }
-  if (dh->priv_key == NULL) {
+  if (dh->priv_key == nullptr) {
     BN_free(priv_key);
   }
-  BN_free(priv_key_limit);
-  BN_CTX_free(ctx);
   return ok;
 }
 
@@ -267,56 +264,46 @@
     return 0;
   }
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *p_minus_1 = BN_CTX_get(ctx);
-
   if (!p_minus_1 ||
       !BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
                               dh->p, ctx)) {
-    goto err;
+    return 0;
   }
 
   if (!BN_mod_exp_mont_consttime(out_shared_key, peers_key, dh->priv_key, dh->p,
                                  ctx, dh->method_mont_p) ||
       !BN_copy(p_minus_1, dh->p) || !BN_sub_word(p_minus_1, 1)) {
     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
-    goto err;
+    return 0;
   }
 
   // This performs the check required by SP 800-56Ar3 section 5.7.1.1 step two.
   if (BN_cmp_word(out_shared_key, 1) <= 0 ||
       BN_cmp(out_shared_key, p_minus_1) == 0) {
     OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int dh_compute_key_padded_no_self_test(unsigned char *out,
                                        const BIGNUM *peers_key, DH *dh) {
-  BN_CTX *ctx = BN_CTX_new();
-  if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
     return -1;
   }
-  BN_CTX_start(ctx);
-
+  bssl::BN_CTXScope scope(ctx.get());
   int dh_size = DH_size(dh);
-  int ret = -1;
-  BIGNUM *shared_key = BN_CTX_get(ctx);
-  if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx) &&
-      BN_bn2bin_padded(out, dh_size, shared_key)) {
-    ret = dh_size;
+  BIGNUM *shared_key = BN_CTX_get(ctx.get());
+  if (shared_key == nullptr ||
+      !dh_compute_key(dh, shared_key, peers_key, ctx.get()) ||
+      !BN_bn2bin_padded(out, dh_size, shared_key)) {
+    return -1;
   }
-
-  BN_CTX_end(ctx);
-  BN_CTX_free(ctx);
-  return ret;
+  return dh_size;
 }
 
 int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
@@ -328,22 +315,18 @@
 int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
   boringssl_ensure_ffdh_self_test();
 
-  BN_CTX *ctx = BN_CTX_new();
-  if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
     return -1;
   }
-  BN_CTX_start(ctx);
-
-  int ret = -1;
-  BIGNUM *shared_key = BN_CTX_get(ctx);
-  if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
-    // A |BIGNUM|'s byte count fits in |int|.
-    ret = (int)BN_bn2bin(shared_key, out);
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *shared_key = BN_CTX_get(ctx.get());
+  if (shared_key == nullptr ||
+      !dh_compute_key(dh, shared_key, peers_key, ctx.get())) {
+    return -1;
   }
-
-  BN_CTX_end(ctx);
-  BN_CTX_free(ctx);
-  return ret;
+  // A |BIGNUM|'s byte count fits in |int|.
+  return static_cast<int>(BN_bn2bin(shared_key, out));
 }
 
 int DH_compute_key_hashed(DH *dh, uint8_t *out, size_t *out_len,
@@ -415,29 +398,27 @@
       TOBN(0xadf85458, 0xa2bb4a9a), TOBN(0xffffffff, 0xffffffff),
   };
 
-  BIGNUM *const ffdhe2048_p = BN_new();
-  BIGNUM *const ffdhe2048_q = BN_new();
-  BIGNUM *const ffdhe2048_g = BN_new();
-  DH *const dh = DH_new();
-
+  bssl::UniquePtr<BIGNUM> ffdhe2048_p(BN_new());
+  bssl::UniquePtr<BIGNUM> ffdhe2048_q(BN_new());
+  bssl::UniquePtr<BIGNUM> ffdhe2048_g(BN_new());
+  bssl::UniquePtr<DH> dh(DH_new());
   if (!ffdhe2048_p || !ffdhe2048_q || !ffdhe2048_g || !dh) {
-    goto err;
+    return nullptr;
   }
 
-  bn_set_static_words(ffdhe2048_p, kFFDHE2048Data,
+  bn_set_static_words(ffdhe2048_p.get(), kFFDHE2048Data,
                       OPENSSL_ARRAY_SIZE(kFFDHE2048Data));
 
-  if (!BN_rshift1(ffdhe2048_q, ffdhe2048_p) || !BN_set_word(ffdhe2048_g, 2) ||
-      !DH_set0_pqg(dh, ffdhe2048_p, ffdhe2048_q, ffdhe2048_g)) {
-    goto err;
+  if (!BN_rshift1(ffdhe2048_q.get(), ffdhe2048_p.get()) ||
+      !BN_set_word(ffdhe2048_g.get(), 2) ||
+      !DH_set0_pqg(dh.get(), ffdhe2048_p.get(), ffdhe2048_q.get(),
+                   ffdhe2048_g.get())) {
+    return nullptr;
   }
+  // |DH_set0_pqg| takes ownership on success.
+  ffdhe2048_p.release();
+  ffdhe2048_q.release();
+  ffdhe2048_g.release();
 
-  return dh;
-
-err:
-  BN_free(ffdhe2048_p);
-  BN_free(ffdhe2048_q);
-  BN_free(ffdhe2048_g);
-  DH_free(dh);
-  return NULL;
+  return dh.release();
 }
diff --git a/src/crypto/fipsmodule/digest/digest.cc.inc b/src/crypto/fipsmodule/digest/digest.cc.inc
index dc22ad4..2edef42 100644
--- a/src/crypto/fipsmodule/digest/digest.cc.inc
+++ b/src/crypto/fipsmodule/digest/digest.cc.inc
@@ -212,16 +212,10 @@
 
 int EVP_Digest(const void *data, size_t count, uint8_t *out_md,
                unsigned int *out_size, const EVP_MD *type, ENGINE *impl) {
-  EVP_MD_CTX ctx;
-  int ret;
-
-  EVP_MD_CTX_init(&ctx);
-  ret = EVP_DigestInit_ex(&ctx, type, impl) &&
-        EVP_DigestUpdate(&ctx, data, count) &&
-        EVP_DigestFinal_ex(&ctx, out_md, out_size);
-  EVP_MD_CTX_cleanup(&ctx);
-
-  return ret;
+  bssl::ScopedEVP_MD_CTX ctx;
+  return EVP_DigestInit_ex(ctx.get(), type, impl) &&
+         EVP_DigestUpdate(ctx.get(), data, count) &&
+         EVP_DigestFinal_ex(ctx.get(), out_md, out_size);
 }
 
 const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx) {
diff --git a/src/crypto/fipsmodule/digest/internal.h b/src/crypto/fipsmodule/digest/internal.h
index 0cef38e..0e850c9 100644
--- a/src/crypto/fipsmodule/digest/internal.h
+++ b/src/crypto/fipsmodule/digest/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_DIGEST_INTERNAL_H
-#define OPENSSL_HEADER_DIGEST_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -67,4 +67,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_DIGEST_INTERNAL
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_INTERNAL_H
diff --git a/src/crypto/fipsmodule/digest/md32_common.h b/src/crypto/fipsmodule/digest/md32_common.h
index 6cba40a..b64f20b 100644
--- a/src/crypto/fipsmodule/digest/md32_common.h
+++ b/src/crypto/fipsmodule/digest/md32_common.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_DIGEST_MD32_COMMON_H
-#define OPENSSL_HEADER_DIGEST_MD32_COMMON_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_MD32_COMMON_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_MD32_COMMON_H
 
 #include <openssl/base.h>
 
@@ -158,4 +158,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_DIGEST_MD32_COMMON_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_DIGEST_MD32_COMMON_H
diff --git a/src/crypto/fipsmodule/ec/ec.cc.inc b/src/crypto/fipsmodule/ec/ec.cc.inc
index f741840..14916ee 100644
--- a/src/crypto/fipsmodule/ec/ec.cc.inc
+++ b/src/crypto/fipsmodule/ec/ec.cc.inc
@@ -175,47 +175,44 @@
                                  const BIGNUM *b, BN_CTX *ctx) {
   if (BN_num_bytes(p) > EC_MAX_BYTES) {
     OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
-    return NULL;
+    return nullptr;
   }
 
-  BN_CTX *new_ctx = NULL;
-  if (ctx == NULL) {
-    ctx = new_ctx = BN_CTX_new();
-    if (ctx == NULL) {
-      return NULL;
+  bssl::UniquePtr<BN_CTX> new_ctx;
+  if (ctx == nullptr) {
+    new_ctx.reset(BN_CTX_new());
+    if (new_ctx == nullptr) {
+      return nullptr;
     }
+    ctx = new_ctx.get();
   }
 
   // Historically, |a| and |b| were not required to be fully reduced.
   // TODO(davidben): Can this be removed?
-  EC_GROUP *ret = NULL;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *a_reduced = BN_CTX_get(ctx);
   BIGNUM *b_reduced = BN_CTX_get(ctx);
-  if (a_reduced == NULL || b_reduced == NULL ||
-      !BN_nnmod(a_reduced, a, p, ctx) || !BN_nnmod(b_reduced, b, p, ctx)) {
-    goto err;
+  if (a_reduced == nullptr || b_reduced == nullptr ||
+      !BN_nnmod(a_reduced, a, p, ctx) ||  //
+      !BN_nnmod(b_reduced, b, p, ctx)) {
+    return nullptr;
   }
 
-  ret = reinterpret_cast<EC_GROUP *>(OPENSSL_zalloc(sizeof(EC_GROUP)));
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<EC_GROUP> ret(
+      reinterpret_cast<EC_GROUP *>(OPENSSL_zalloc(sizeof(EC_GROUP))));
+  if (ret == nullptr) {
+    return nullptr;
   }
   ret->references = 1;
   ret->meth = EC_GFp_mont_method();
   bn_mont_ctx_init(&ret->field);
   bn_mont_ctx_init(&ret->order);
-  ret->generator.group = ret;
-  if (!ec_GFp_simple_group_set_curve(ret, p, a_reduced, b_reduced, ctx)) {
-    EC_GROUP_free(ret);
-    ret = NULL;
-    goto err;
+  ret->generator.group = ret.get();
+  if (!ec_GFp_simple_group_set_curve(ret.get(), p, a_reduced, b_reduced, ctx)) {
+    return nullptr;
   }
 
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
+  return ret.release();
 }
 
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
@@ -246,20 +243,19 @@
   // Note any curve which did not satisfy this must have been invalid or use a
   // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
   // the ECDSA implementation.
-  int ret = 0;
-  BIGNUM *tmp = BN_new();
-  if (tmp == NULL || !BN_lshift1(tmp, order)) {
-    goto err;
+  bssl::UniquePtr<BIGNUM> tmp(BN_new());
+  if (tmp == nullptr || !BN_lshift1(tmp.get(), order)) {
+    return 0;
   }
-  if (BN_cmp(tmp, &group->field.N) <= 0) {
+  if (BN_cmp(tmp.get(), &group->field.N) <= 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
-    goto err;
+    return 0;
   }
 
   EC_AFFINE affine;
   if (!ec_jacobian_to_affine(group, &affine, &generator->raw) ||
       !BN_MONT_CTX_set(&group->order, order, NULL)) {
-    goto err;
+    return 0;
   }
 
   group->field_greater_than_order = BN_cmp(&group->field.N, order) > 0;
@@ -267,11 +263,7 @@
   group->generator.raw.Y = affine.Y;
   // |raw.Z| was set to 1 by |EC_GROUP_new_curve_GFp|.
   group->has_order = 1;
-  ret = 1;
-
-err:
-  BN_free(tmp);
-  return ret;
+  return 1;
 }
 
 EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
@@ -663,12 +655,10 @@
   ERR_clear_error();
 
   // This is an unusual input, so we do not guarantee constant-time processing.
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
-  int ok = tmp != NULL && BN_nnmod(tmp, in, EC_GROUP_get0_order(group), ctx) &&
-           ec_bignum_to_scalar(group, out, tmp);
-  BN_CTX_end(ctx);
-  return ok;
+  return tmp != nullptr && BN_nnmod(tmp, in, EC_GROUP_get0_order(group), ctx) &&
+         ec_bignum_to_scalar(group, out, tmp);
 }
 
 int ec_point_mul_no_self_test(const EC_GROUP *group, EC_POINT *r,
@@ -689,14 +679,13 @@
     return 0;
   }
 
-  int ret = 0;
-  BN_CTX *new_ctx = NULL;
+  bssl::UniquePtr<BN_CTX> new_ctx;
   if (ctx == NULL) {
-    new_ctx = BN_CTX_new();
+    new_ctx.reset(BN_CTX_new());
     if (new_ctx == NULL) {
-      goto err;
+      return 0;
     }
-    ctx = new_ctx;
+    ctx = new_ctx.get();
   }
 
   // If both |g_scalar| and |p_scalar| are non-NULL,
@@ -714,7 +703,7 @@
     EC_SCALAR scalar;
     if (!arbitrary_bignum_to_scalar(group, &scalar, g_scalar, ctx) ||
         !ec_point_mul_scalar_base(group, &r->raw, &scalar)) {
-      goto err;
+      return 0;
     }
   }
 
@@ -723,7 +712,7 @@
     EC_JACOBIAN tmp;
     if (!arbitrary_bignum_to_scalar(group, &scalar, p_scalar, ctx) ||
         !ec_point_mul_scalar(group, &tmp, &p->raw, &scalar)) {
-      goto err;
+      return 0;
     }
     if (g_scalar == NULL) {
       OPENSSL_memcpy(&r->raw, &tmp, sizeof(EC_JACOBIAN));
@@ -732,11 +721,7 @@
     }
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_free(new_ctx);
-  return ret;
+  return 1;
 }
 
 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
diff --git a/src/crypto/fipsmodule/ec/ec_key.cc.inc b/src/crypto/fipsmodule/ec/ec_key.cc.inc
index 8c402f4..01fbe93 100644
--- a/src/crypto/fipsmodule/ec/ec_key.cc.inc
+++ b/src/crypto/fipsmodule/ec/ec_key.cc.inc
@@ -316,40 +316,33 @@
 
 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, const BIGNUM *x,
                                              const BIGNUM *y) {
-  EC_POINT *point = NULL;
-  int ok = 0;
-
   if (!key || !key->group || !x || !y) {
     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
     return 0;
   }
 
-  point = EC_POINT_new(key->group);
-  if (point == NULL ||
-      !EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, NULL) ||
-      !EC_KEY_set_public_key(key, point) || !EC_KEY_check_key(key)) {
-    goto err;
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(key->group));
+  if (point == nullptr ||
+      !EC_POINT_set_affine_coordinates_GFp(key->group, point.get(), x, y,
+                                           nullptr) ||
+      !EC_KEY_set_public_key(key, point.get()) ||  //
+      !EC_KEY_check_key(key)) {
+    return 0;
   }
 
-  ok = 1;
-
-err:
-  EC_POINT_free(point);
-  return ok;
+  return 1;
 }
 
 int EC_KEY_oct2key(EC_KEY *key, const uint8_t *in, size_t len, BN_CTX *ctx) {
-  if (key->group == NULL) {
+  if (key->group == nullptr) {
     OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
     return 0;
   }
 
-  EC_POINT *point = EC_POINT_new(key->group);
-  int ok = point != NULL &&
-           EC_POINT_oct2point(key->group, point, in, len, ctx) &&
-           EC_KEY_set_public_key(key, point);
-  EC_POINT_free(point);
-  return ok;
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(key->group));
+  return point != nullptr &&
+         EC_POINT_oct2point(key->group, point.get(), in, len, ctx) &&
+         EC_KEY_set_public_key(key, point.get());
 }
 
 size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
diff --git a/src/crypto/fipsmodule/ec/internal.h b/src/crypto/fipsmodule/ec/internal.h
index 4599c3c..2c610ba 100644
--- a/src/crypto/fipsmodule/ec/internal.h
+++ b/src/crypto/fipsmodule/ec/internal.h
@@ -13,8 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_EC_INTERNAL_H
-#define OPENSSL_HEADER_EC_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -706,4 +706,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_EC_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_INTERNAL_H
diff --git a/src/crypto/fipsmodule/ec/oct.cc.inc b/src/crypto/fipsmodule/ec/oct.cc.inc
index 15c3a2f..69323dc 100644
--- a/src/crypto/fipsmodule/ec/oct.cc.inc
+++ b/src/crypto/fipsmodule/ec/oct.cc.inc
@@ -116,35 +116,30 @@
   // for primes which are not 3 (mod 4), namely P-224 and custom curves. P-224's
   // prime is particularly inconvenient for compressed coordinates. See
   // https://cr.yp.to/papers/sqroot.pdf
-  BN_CTX *new_ctx = NULL;
-  if (ctx == NULL) {
-    ctx = new_ctx = BN_CTX_new();
-    if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> new_ctx;
+  if (ctx == nullptr) {
+    new_ctx.reset(BN_CTX_new());
+    if (new_ctx == nullptr) {
       return 0;
     }
+    ctx = new_ctx.get();
   }
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *x = BN_CTX_get(ctx);
-  if (x == NULL || !BN_bin2bn(buf + 1, field_len, x)) {
-    goto err;
+  if (x == nullptr || !BN_bin2bn(buf + 1, field_len, x)) {
+    return 0;
   }
   if (BN_ucmp(x, &group->field.N) >= 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
-    goto err;
+    return 0;
   }
 
   if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
+  return 1;
 }
 
 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
@@ -214,28 +209,27 @@
     return 0;
   }
 
-  BN_CTX *new_ctx = NULL;
-  int ret = 0;
-
   ERR_clear_error();
 
-  if (ctx == NULL) {
-    ctx = new_ctx = BN_CTX_new();
-    if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> new_ctx;
+  if (ctx == nullptr) {
+    new_ctx.reset(BN_CTX_new());
+    if (new_ctx == nullptr) {
       return 0;
     }
+    ctx = new_ctx.get();
   }
 
   y_bit = (y_bit != 0);
 
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp1 = BN_CTX_get(ctx);
   BIGNUM *tmp2 = BN_CTX_get(ctx);
   BIGNUM *a = BN_CTX_get(ctx);
   BIGNUM *b = BN_CTX_get(ctx);
   BIGNUM *y = BN_CTX_get(ctx);
   if (y == NULL || !EC_GROUP_get_curve_GFp(group, NULL, a, b, ctx)) {
-    goto err;
+    return 0;
   }
 
   // Recover y.  We have a Weierstrass equation
@@ -245,7 +239,7 @@
   // tmp1 := x^3
   if (!BN_mod_sqr(tmp2, x, field, ctx) ||
       !BN_mod_mul(tmp1, tmp2, x, field, ctx)) {
-    goto err;
+    return 0;
   }
 
   // tmp1 := tmp1 + a*x
@@ -253,18 +247,18 @@
     if (!bn_mod_lshift1_consttime(tmp2, x, field, ctx) ||
         !bn_mod_add_consttime(tmp2, tmp2, x, field, ctx) ||
         !bn_mod_sub_consttime(tmp1, tmp1, tmp2, field, ctx)) {
-      goto err;
+      return 0;
     }
   } else {
     if (!BN_mod_mul(tmp2, a, x, field, ctx) ||
         !bn_mod_add_consttime(tmp1, tmp1, tmp2, field, ctx)) {
-      goto err;
+      return 0;
     }
   }
 
   // tmp1 := tmp1 + b
   if (!bn_mod_add_consttime(tmp1, tmp1, b, field, ctx)) {
-    goto err;
+    return 0;
   }
 
   if (!BN_mod_sqrt(y, tmp1, field, ctx)) {
@@ -276,31 +270,26 @@
     } else {
       OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
     }
-    goto err;
+    return 0;
   }
 
   if (y_bit != BN_is_odd(y)) {
     if (BN_is_zero(y)) {
       OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
-      goto err;
+      return 0;
     }
     if (!BN_usub(y, field, y)) {
-      goto err;
+      return 0;
     }
   }
   if (y_bit != BN_is_odd(y)) {
     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
-    goto err;
+    return 0;
   }
 
   if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
+  return 1;
 }
diff --git a/src/crypto/fipsmodule/ec/p256-nistz.h b/src/crypto/fipsmodule/ec/p256-nistz.h
index be6b5ec..326e38d 100644
--- a/src/crypto/fipsmodule/ec/p256-nistz.h
+++ b/src/crypto/fipsmodule/ec/p256-nistz.h
@@ -21,8 +21,8 @@
 // S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
 //                          256 Bit Primes"
 
-#ifndef OPENSSL_HEADER_EC_P256_X86_64_H
-#define OPENSSL_HEADER_EC_P256_X86_64_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_P256_NISTZ_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_P256_NISTZ_H
 
 #include <openssl/base.h>
 
@@ -204,4 +204,4 @@
 }  // extern C++
 #endif
 
-#endif  // OPENSSL_HEADER_EC_P256_X86_64_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_EC_P256_NISTZ_H
diff --git a/src/crypto/fipsmodule/ec/simple.cc.inc b/src/crypto/fipsmodule/ec/simple.cc.inc
index f053ea1..59a130b 100644
--- a/src/crypto/fipsmodule/ec/simple.cc.inc
+++ b/src/crypto/fipsmodule/ec/simple.cc.inc
@@ -45,11 +45,10 @@
     return 0;
   }
 
-  int ret = 0;
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
-  if (tmp == NULL) {
-    goto err;
+  if (tmp == nullptr) {
+    return 0;
   }
 
   if (!BN_MONT_CTX_set(&group->field, p, ctx) ||
@@ -57,21 +56,17 @@
       !ec_bignum_to_felem(group, &group->b, b) ||
       // Reuse Z from the generator to cache the value one.
       !ec_bignum_to_felem(group, &group->generator.raw.Z, BN_value_one())) {
-    goto err;
+    return 0;
   }
 
   // group->a_is_minus3
   if (!BN_copy(tmp, a) ||
       !BN_add_word(tmp, 3)) {
-    goto err;
+    return 0;
   }
   group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field.N));
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
diff --git a/src/crypto/fipsmodule/keccak/internal.h b/src/crypto/fipsmodule/keccak/internal.h
index f5a15f5..273e666 100644
--- a/src/crypto/fipsmodule/keccak/internal.h
+++ b/src/crypto/fipsmodule/keccak/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CRYPTO_KECCAK_INTERNAL_H
-#define OPENSSL_HEADER_CRYPTO_KECCAK_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_KECCAK_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_KECCAK_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -67,4 +67,4 @@
 }
 #endif
 
-#endif  // OPENSSL_HEADER_CRYPTO_KECCAK_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_KECCAK_INTERNAL_H
diff --git a/src/crypto/fipsmodule/mldsa/fips_known_values.inc b/src/crypto/fipsmodule/mldsa/fips_known_values.inc
new file mode 100644
index 0000000..948fb5c
--- /dev/null
+++ b/src/crypto/fipsmodule/mldsa/fips_known_values.inc
@@ -0,0 +1,1345 @@
+const uint8_t kGenerateKeyEntropy[BCM_MLDSA_SEED_BYTES] = {
+    0x47, 0x90, 0x52, 0x10, 0x30, 0x27, 0xbd, 0xf1, 0x7e, 0xb1, 0x22,
+    0xd7, 0x84, 0xfb, 0x3c, 0xf0, 0x40, 0xd2, 0xf4, 0x97, 0x11, 0x7e,
+    0x01, 0x38, 0xc4, 0xce, 0x9c, 0xac, 0x94, 0x71, 0xab, 0x39};
+
+const uint8_t kExpectedPublicKey[BCM_MLDSA65_PUBLIC_KEY_BYTES] = {
+    0x0c, 0x6f, 0x38, 0x7d, 0x2a, 0xb4, 0x33, 0x87, 0xf0, 0x21, 0xb0, 0xda,
+    0x81, 0x6c, 0x71, 0xf0, 0xbc, 0x81, 0x5e, 0xf0, 0xb1, 0x6a, 0xf1, 0x12,
+    0x4f, 0x35, 0x4c, 0x27, 0x3e, 0xed, 0xb4, 0x2f, 0xe5, 0x4a, 0x01, 0x9a,
+    0x97, 0x9c, 0xfa, 0x12, 0xde, 0xca, 0xef, 0xe1, 0x56, 0x9a, 0x90, 0x6d,
+    0x54, 0x21, 0x58, 0xa6, 0x59, 0x4c, 0x99, 0x28, 0x53, 0x79, 0xce, 0xb8,
+    0x90, 0xc6, 0xed, 0x4a, 0x4c, 0xe5, 0x9b, 0x9c, 0x87, 0x41, 0xae, 0x95,
+    0x26, 0x83, 0xca, 0x91, 0x38, 0x62, 0xc0, 0x32, 0x82, 0x42, 0x8e, 0xdf,
+    0x92, 0xf5, 0xcf, 0xc7, 0xd5, 0x69, 0xfa, 0xfb, 0x1f, 0x18, 0x96, 0xc5,
+    0x9f, 0xd8, 0xbb, 0xd6, 0xb7, 0xf4, 0x4f, 0x20, 0x12, 0x51, 0x2a, 0x08,
+    0xba, 0xae, 0x5d, 0x87, 0xf9, 0x14, 0x8f, 0xb0, 0x76, 0xba, 0x1d, 0xae,
+    0x38, 0x14, 0xad, 0x4f, 0x68, 0xf0, 0xc4, 0xf6, 0xdb, 0x32, 0x30, 0x9b,
+    0xa3, 0x2f, 0xe3, 0x9b, 0x72, 0x5a, 0xee, 0xb0, 0x97, 0x4d, 0x01, 0xa3,
+    0x70, 0x29, 0x9a, 0xd6, 0x08, 0xed, 0xbf, 0x0a, 0xa4, 0x17, 0x8d, 0x18,
+    0x5f, 0x13, 0xef, 0xd2, 0x59, 0xbc, 0x50, 0x65, 0xf4, 0xef, 0xd1, 0xbb,
+    0x74, 0x22, 0x38, 0xfb, 0x5d, 0x75, 0xc4, 0xe5, 0xf9, 0x8f, 0x39, 0xf2,
+    0x6f, 0x93, 0xc4, 0x06, 0x1a, 0xff, 0x46, 0x7a, 0xa0, 0xaa, 0xfb, 0x1c,
+    0x9c, 0xa2, 0xe0, 0x66, 0x74, 0xa1, 0x0f, 0xd5, 0x87, 0x7f, 0x45, 0x9d,
+    0x5e, 0xcb, 0xec, 0xc6, 0xd0, 0x9f, 0x8a, 0x36, 0xd9, 0xce, 0x37, 0xf1,
+    0x17, 0x5c, 0x7c, 0x15, 0x1d, 0x46, 0xa3, 0x5d, 0x97, 0x21, 0xbd, 0x93,
+    0xf5, 0xe9, 0x8f, 0x77, 0xb4, 0xb2, 0xc2, 0x26, 0x82, 0xcb, 0xd4, 0x46,
+    0xc2, 0x18, 0xa2, 0xa8, 0xfe, 0xee, 0xf5, 0x15, 0xc7, 0x03, 0x0c, 0xa3,
+    0x46, 0xcf, 0x85, 0x61, 0x68, 0x8c, 0xaa, 0xd6, 0x83, 0x9f, 0xd8, 0xf4,
+    0x8c, 0x0c, 0xc6, 0xe7, 0xef, 0x17, 0xe4, 0x47, 0x41, 0xcf, 0x35, 0x2a,
+    0x6a, 0x19, 0xa0, 0x55, 0xc0, 0x16, 0x4f, 0xaa, 0xdc, 0x96, 0xc5, 0x34,
+    0xfa, 0xee, 0xbf, 0x3f, 0x3d, 0x76, 0x06, 0x82, 0x86, 0x40, 0x7b, 0x85,
+    0x7f, 0x76, 0x6d, 0x9f, 0x82, 0x9e, 0x21, 0x99, 0xd3, 0x61, 0x34, 0xf7,
+    0x17, 0xf5, 0x46, 0x41, 0xad, 0x6c, 0x32, 0xd1, 0x33, 0xf8, 0x8f, 0x6e,
+    0xc9, 0x13, 0xc5, 0xb3, 0x3e, 0xa7, 0x6f, 0xc9, 0x8d, 0xb0, 0x00, 0x9c,
+    0x5e, 0x7b, 0xcb, 0x0b, 0x03, 0x85, 0x91, 0x4b, 0x8d, 0x74, 0xd1, 0x32,
+    0x0e, 0x0b, 0x37, 0xc5, 0x80, 0x8c, 0x06, 0xd3, 0x4b, 0xab, 0xb3, 0xd4,
+    0x3f, 0xb7, 0x4c, 0x46, 0xcd, 0x28, 0xde, 0x15, 0x9d, 0xf5, 0x95, 0x0c,
+    0x57, 0x56, 0x7a, 0xf9, 0xde, 0x97, 0x47, 0x72, 0x95, 0xf7, 0x4a, 0x3a,
+    0x1b, 0xbb, 0x51, 0xc6, 0x83, 0x7f, 0x37, 0x18, 0x6a, 0x79, 0x2c, 0xe3,
+    0x82, 0x20, 0x53, 0x96, 0x10, 0xe4, 0x45, 0x32, 0xf2, 0x66, 0x35, 0x5e,
+    0xb8, 0x2d, 0x8d, 0xf5, 0x90, 0x66, 0x09, 0xb2, 0xfa, 0x0e, 0xdd, 0x0b,
+    0x19, 0x41, 0x4a, 0x58, 0xc0, 0x83, 0x9d, 0x6d, 0x05, 0x43, 0x84, 0x6e,
+    0x5b, 0x6e, 0x7e, 0xd0, 0xc9, 0xb1, 0x55, 0x7f, 0xd0, 0x59, 0x40, 0x94,
+    0x2d, 0x8c, 0xdb, 0xe1, 0xa4, 0xd8, 0x8a, 0x78, 0x3a, 0x0a, 0x50, 0x55,
+    0x84, 0xc2, 0xd9, 0xd8, 0x55, 0x3a, 0xef, 0x93, 0xc2, 0xe9, 0x86, 0x43,
+    0x30, 0x08, 0xd6, 0x54, 0x1f, 0xfd, 0x04, 0xac, 0x4c, 0x2d, 0x5f, 0xf5,
+    0x4d, 0x4f, 0xe9, 0x70, 0x77, 0x0b, 0x9a, 0x07, 0x91, 0x1e, 0xdf, 0x9c,
+    0x4e, 0xaa, 0xf5, 0x05, 0x51, 0xc9, 0x7b, 0x48, 0x35, 0xc9, 0x30, 0xd4,
+    0x02, 0x14, 0x8b, 0xb4, 0x2c, 0x1f, 0x25, 0x6d, 0xf4, 0xa6, 0x52, 0x1b,
+    0x63, 0x48, 0x85, 0x31, 0x82, 0xf8, 0xd5, 0xb3, 0x11, 0x77, 0x5a, 0xa3,
+    0xfe, 0x2e, 0x31, 0xc7, 0xdb, 0xda, 0x0b, 0x35, 0x6f, 0x56, 0xb8, 0xb8,
+    0x64, 0xb7, 0x8c, 0xde, 0x69, 0x2d, 0x88, 0x83, 0xbe, 0x2c, 0xc1, 0xc2,
+    0x90, 0xd4, 0x19, 0xb7, 0x21, 0x3a, 0x71, 0x81, 0x64, 0x88, 0x7e, 0xed,
+    0xc2, 0xb8, 0x92, 0xce, 0x36, 0xc0, 0x4d, 0x36, 0x66, 0x75, 0x35, 0xa0,
+    0x6e, 0x1e, 0xef, 0xb1, 0x9e, 0xb1, 0x9c, 0x16, 0xf7, 0x3a, 0x7e, 0xf7,
+    0x8a, 0x36, 0xd0, 0x8f, 0x9d, 0x13, 0x04, 0x4a, 0xac, 0x0d, 0x71, 0xd9,
+    0x1f, 0x52, 0xa6, 0xb4, 0x52, 0xfd, 0x12, 0xd2, 0xa8, 0xc2, 0x38, 0xbf,
+    0x14, 0x4b, 0x42, 0xcf, 0xfc, 0x2d, 0x72, 0xa3, 0x5d, 0xdb, 0x4e, 0xfd,
+    0xbc, 0xa6, 0xde, 0x41, 0x21, 0x88, 0xe9, 0x05, 0xe5, 0x6a, 0x80, 0xf1,
+    0x0e, 0xc6, 0x58, 0x24, 0x0a, 0x0b, 0xdd, 0x32, 0xef, 0x68, 0xf6, 0x5e,
+    0x84, 0xba, 0xbb, 0xc4, 0x14, 0x10, 0x58, 0xcd, 0x8a, 0x00, 0xce, 0xd2,
+    0x54, 0xfb, 0x9d, 0x75, 0x69, 0x2b, 0x68, 0x89, 0x4e, 0x71, 0xda, 0x6f,
+    0x98, 0x88, 0x38, 0x96, 0xe6, 0x34, 0x99, 0x9f, 0x69, 0x2a, 0x9e, 0xa3,
+    0xb8, 0xe7, 0x0c, 0x97, 0xb9, 0x96, 0x58, 0x2a, 0x79, 0x85, 0x8e, 0x4b,
+    0xcd, 0x5e, 0xc5, 0x05, 0xbf, 0x44, 0x49, 0x60, 0x9c, 0xa5, 0x49, 0x9f,
+    0x2f, 0x30, 0x07, 0x79, 0x54, 0x18, 0xc1, 0x84, 0x79, 0xc6, 0x79, 0xc5,
+    0x83, 0x51, 0x44, 0x18, 0x33, 0xcb, 0xf5, 0xe6, 0x72, 0x13, 0x8e, 0x6d,
+    0x3d, 0xbe, 0x1d, 0xce, 0x70, 0x31, 0x4b, 0x0d, 0x33, 0x8d, 0x9a, 0xac,
+    0xbf, 0xf7, 0x17, 0xd5, 0x62, 0xe3, 0x2f, 0xc0, 0x60, 0x25, 0xf6, 0xc1,
+    0x66, 0xd5, 0x49, 0x18, 0x64, 0x4f, 0x34, 0xca, 0xa9, 0xdd, 0x11, 0x81,
+    0x36, 0x93, 0xdf, 0xc0, 0xc6, 0x5e, 0x21, 0xc8, 0xbd, 0x15, 0x1e, 0x92,
+    0xc7, 0x8d, 0xa0, 0x85, 0xdc, 0x14, 0xb9, 0xa0, 0x6d, 0x93, 0x15, 0x2b,
+    0xce, 0x8d, 0x1c, 0x37, 0x75, 0xbb, 0x5a, 0x5b, 0x41, 0x95, 0xb1, 0xff,
+    0x82, 0xe9, 0xa0, 0xbb, 0x01, 0x03, 0x15, 0x4b, 0xa1, 0x4e, 0xc6, 0xc2,
+    0xb2, 0x77, 0x78, 0x75, 0xd2, 0x13, 0x5e, 0xe0, 0x82, 0xee, 0x6c, 0xd9,
+    0x6f, 0x1e, 0x7e, 0xc4, 0x5b, 0x89, 0x10, 0x0e, 0x0b, 0x85, 0x6f, 0xe0,
+    0x86, 0xf2, 0x86, 0xc9, 0x20, 0xe0, 0xa5, 0x09, 0x3d, 0x30, 0xed, 0x50,
+    0x5e, 0xb5, 0x2b, 0xb9, 0xbe, 0x55, 0x60, 0xa9, 0x25, 0x79, 0xed, 0x3f,
+    0xfe, 0xce, 0xc2, 0x63, 0x5a, 0x17, 0xa0, 0xf9, 0x81, 0xe4, 0x79, 0x0b,
+    0x0a, 0x8f, 0x32, 0x1f, 0x9b, 0x92, 0xf4, 0x88, 0x68, 0xf4, 0xd8, 0x06,
+    0xa9, 0x01, 0x26, 0x6a, 0x5d, 0x67, 0xc7, 0x29, 0x67, 0xd3, 0x47, 0xd0,
+    0x69, 0x76, 0xd8, 0x79, 0x43, 0x40, 0xaa, 0xdd, 0x82, 0x3e, 0xc9, 0x2b,
+    0x1f, 0x90, 0xb9, 0x27, 0x74, 0x21, 0xb9, 0x29, 0xcd, 0x09, 0x12, 0xb9,
+    0x72, 0x2c, 0x73, 0x3c, 0x0e, 0x94, 0x69, 0x37, 0xbd, 0xca, 0x54, 0x31,
+    0x93, 0xce, 0x54, 0x21, 0x5b, 0x51, 0xa4, 0xc4, 0x0e, 0xf4, 0x37, 0xa1,
+    0x6a, 0x9d, 0x05, 0x6b, 0xec, 0xfb, 0x88, 0x8d, 0xd1, 0x20, 0x33, 0x7d,
+    0xbe, 0xf1, 0xda, 0x3b, 0xcf, 0x34, 0x9a, 0x1e, 0xbc, 0x18, 0x3a, 0x44,
+    0xd3, 0x62, 0x0e, 0x2e, 0x18, 0x88, 0x05, 0x13, 0x97, 0x7f, 0x09, 0x3a,
+    0xb3, 0x18, 0x86, 0x59, 0x1a, 0x9b, 0x15, 0xfc, 0x20, 0xcf, 0xe8, 0x88,
+    0xf9, 0x75, 0x06, 0x3b, 0xf5, 0xac, 0x02, 0xd6, 0xee, 0x8c, 0x3c, 0x5c,
+    0xda, 0x5b, 0x9e, 0x9b, 0x81, 0xff, 0x5c, 0x70, 0x1c, 0xb4, 0xe1, 0xb6,
+    0x9f, 0xd5, 0x15, 0xe8, 0xc0, 0x24, 0xe7, 0x8d, 0xbd, 0x66, 0xd4, 0x82,
+    0x97, 0x93, 0xf8, 0x95, 0x66, 0xc7, 0xe5, 0x3a, 0x02, 0x0d, 0xc5, 0x7d,
+    0x0d, 0x4f, 0x9a, 0xb6, 0x41, 0xb8, 0x6f, 0x48, 0x68, 0x01, 0x84, 0xe8,
+    0x0b, 0x2c, 0x77, 0x1d, 0x79, 0x16, 0x86, 0xc3, 0xf0, 0xa9, 0x41, 0xf1,
+    0xda, 0xd5, 0x6f, 0x49, 0x8d, 0xb6, 0x6b, 0x53, 0xc1, 0x63, 0xff, 0x0a,
+    0x95, 0xb8, 0x92, 0xf8, 0x21, 0xc2, 0x17, 0xc5, 0xd6, 0xcf, 0x18, 0xda,
+    0x1a, 0xb9, 0x71, 0x7e, 0x03, 0x30, 0xfb, 0x40, 0xca, 0xc6, 0xd4, 0x18,
+    0xe8, 0xe4, 0x8f, 0xe9, 0x23, 0xd1, 0x02, 0xb2, 0x8d, 0xa1, 0xe2, 0x0f,
+    0x88, 0xc8, 0x88, 0x42, 0xb8, 0x32, 0xf7, 0x2d, 0x94, 0x2a, 0xa8, 0x99,
+    0x7a, 0x25, 0x3f, 0x2b, 0xf1, 0xc1, 0xdb, 0x83, 0x53, 0xe6, 0x2f, 0x6f,
+    0x58, 0x38, 0x18, 0x53, 0x6c, 0x50, 0x4f, 0xf8, 0xec, 0xe8, 0x19, 0x36,
+    0x0f, 0xa8, 0xba, 0x9a, 0x2e, 0xb8, 0x8b, 0xab, 0xd7, 0x59, 0xa6, 0x81,
+    0xd2, 0x34, 0x03, 0x57, 0x12, 0xaa, 0x2c, 0x92, 0x52, 0xe8, 0x90, 0x59,
+    0x19, 0x20, 0xb5, 0x24, 0x1e, 0x0c, 0xa8, 0x66, 0xf9, 0x00, 0xeb, 0xa4,
+    0xc5, 0x45, 0xfe, 0x94, 0x92, 0x92, 0x0e, 0xc9, 0x7b, 0x33, 0x11, 0xb0,
+    0x92, 0x8e, 0xac, 0xf6, 0xa5, 0x3f, 0x49, 0xd5, 0x29, 0x3a, 0xcf, 0x4f,
+    0xf6, 0x59, 0x68, 0x1d, 0x24, 0x1d, 0x67, 0xa0, 0x80, 0x72, 0x37, 0x6f,
+    0xa8, 0x0c, 0x84, 0x09, 0xe0, 0x02, 0xa9, 0xa8, 0xcc, 0xc4, 0x01, 0xa2,
+    0x50, 0x02, 0xc7, 0xa3, 0xf9, 0x42, 0xbe, 0x55, 0x40, 0xdb, 0xdf, 0x46,
+    0x56, 0x5c, 0xd7, 0x9a, 0xe9, 0x28, 0xd4, 0xc7, 0xc7, 0x4e, 0x6b, 0x8e,
+    0x5f, 0x52, 0xd4, 0x8d, 0x1b, 0x97, 0x9d, 0xad, 0x87, 0x1a, 0x5d, 0x79,
+    0xfa, 0x47, 0xad, 0x3e, 0x70, 0x82, 0x3a, 0x87, 0x49, 0xd7, 0xc4, 0xb3,
+    0xd5, 0xb8, 0x48, 0x9a, 0x30, 0x5e, 0x59, 0x88, 0xb4, 0xbf, 0xf9, 0x5a,
+    0x7a, 0x11, 0xb3, 0x57, 0x27, 0x3c, 0x24, 0x22, 0x5a, 0x9d, 0x0c, 0x9a,
+    0xd4, 0x0d, 0x26, 0xf6, 0xd2, 0x7b, 0x91, 0x68, 0xfe, 0x44, 0xff, 0x54,
+    0xd0, 0xef, 0x87, 0xcb, 0x29, 0x4c, 0x23, 0xe2, 0xce, 0x4b, 0xf6, 0x36,
+    0x10, 0x6d, 0x54, 0x2a, 0xf0, 0x21, 0xf9, 0x51, 0x25, 0x5f, 0x11, 0x93,
+    0xc9, 0x3f, 0x2e, 0x40, 0xed, 0x28, 0x5e, 0x1a, 0xb8, 0x98, 0xc9, 0x63,
+    0x94, 0xe7, 0x44, 0x11, 0x76, 0xb8, 0x3b, 0xfd, 0xc4, 0x20, 0x47, 0x26,
+    0x62, 0x26, 0x86, 0x92, 0x3d, 0x2f, 0xdb, 0xed, 0xd0, 0x60, 0x0b, 0x2d,
+    0x4d, 0xb9, 0xae, 0x76, 0x35, 0xb4, 0xfb, 0x22, 0x7f, 0xcb, 0x5d, 0x76,
+    0xca, 0xe7, 0x07, 0xd7, 0x1b, 0xd8, 0x2b, 0x20, 0xf4, 0xad, 0xad, 0x8a,
+    0x78, 0xc2, 0xb1, 0xc4, 0x9e, 0x08, 0x63, 0x98, 0x0f, 0xd8, 0x3b, 0xfc,
+    0xfa, 0x7c, 0x88, 0x99, 0x50, 0x0c, 0x3b, 0x0f, 0x5a, 0x28, 0xd0, 0xa4,
+    0x9f, 0x55, 0xc5, 0xf9, 0x18, 0xea, 0x76, 0x3b, 0xf5, 0x28, 0x61, 0x0e,
+    0x0c, 0x17, 0x2b, 0x04, 0x19, 0x56, 0xa3, 0x83, 0xf5, 0xc6, 0x09, 0xb9,
+    0x7e, 0xad, 0xa6, 0x63, 0xb1, 0x8d, 0x8d, 0x7f, 0x28, 0xdd, 0x10, 0x7a,
+    0x38, 0xa9, 0xeb, 0x72, 0xd1, 0x85, 0x15, 0x93, 0xae, 0x86, 0xe6, 0x41,
+    0xd8, 0xec, 0x57, 0x5b, 0x4e, 0x2f, 0x59, 0x93, 0x01, 0xac, 0x12, 0xd5,
+    0x7f, 0x9d, 0x5d, 0xb3, 0x06, 0x3d, 0x80, 0xd3, 0x91, 0xd5, 0x90, 0x8b,
+    0xa5, 0xef, 0x19, 0xb0, 0xf1, 0x33, 0x9e, 0x6d, 0x30, 0xbd, 0x24, 0x21,
+    0x65, 0x87, 0x71, 0x0c, 0x8e, 0x27, 0x05, 0xee, 0x7d, 0xd0, 0x50, 0xf4,
+    0x09, 0xf0, 0x24, 0x69, 0xf0, 0x15, 0x43, 0xa6, 0x47, 0xdd, 0x0a, 0x26,
+    0x17, 0xa8, 0x1c, 0xad, 0x17, 0x9e, 0xbb, 0x3d, 0x84, 0xf3, 0x2f, 0x53,
+    0xe8, 0x87, 0x28, 0x2d, 0xb1, 0xf6, 0xa3, 0xe2, 0x24, 0xa1, 0x2c, 0x35,
+    0x9d, 0x1d, 0x48, 0xf0, 0xd4, 0x03, 0xde, 0x4a, 0x31, 0xda, 0x94, 0x7b,
+    0x67, 0x6f, 0x97, 0x38, 0x59, 0xc6, 0xdc, 0x07, 0xd0, 0xf5, 0xe7, 0xec,
+    0x33, 0x95, 0x0c, 0xf4, 0xb3, 0x6f, 0x9e, 0x71, 0x09, 0x59, 0x1d, 0x55,
+    0x1b, 0x3d, 0xc8, 0x89, 0x55, 0xae, 0x95, 0x05, 0xe2, 0x09, 0x55, 0xa1,
+    0x2d, 0xd3, 0x19, 0xd7, 0x89, 0x88, 0xf5, 0x3b, 0xae, 0xc5, 0xf2, 0x80,
+    0x1d, 0xe4, 0x27, 0xcf, 0xbe, 0x90, 0x99, 0x8b, 0x01, 0xeb, 0xb3, 0xc8,
+    0xfe, 0xf2, 0xdd, 0xd5, 0x95, 0x95, 0x9a, 0xa5, 0xe9, 0xec, 0x9f, 0x63,
+    0x26, 0x20, 0xca, 0x98, 0x37, 0xe9, 0x5e, 0xcd, 0x95, 0x17, 0x4f, 0xbb,
+    0xff, 0xdb, 0x8b, 0xc7, 0x80, 0xee, 0xb1, 0x5d, 0x27, 0x83, 0xd1, 0x9c,
+    0x6d, 0xfd, 0x1a, 0x98, 0x99, 0x71, 0x4d, 0x06, 0xbc, 0x47, 0x34, 0xf9,
+    0x23, 0x9a, 0xd4, 0x3e, 0x92, 0xd4, 0xd5, 0x6c, 0x6c, 0x5c, 0xab, 0xd0,
+    0xaf, 0x19, 0xf9, 0x48, 0xfe, 0xbd, 0x62, 0x72, 0x1d, 0x1e, 0xbc, 0x8a,
+    0xa6, 0x21, 0x59, 0xe6, 0xd9, 0xbc, 0x5e, 0xc9, 0x3b, 0x88, 0x38, 0x26,
+    0xf4, 0x8e, 0xfc, 0x95, 0xbe, 0x6b, 0xf9, 0x1b, 0x7f, 0x37, 0xd0, 0xfc,
+    0x00, 0x4d, 0x08, 0xfd, 0x75, 0xf8, 0x85, 0x48, 0x2e, 0x40, 0x91, 0x9a,
+    0xa0, 0xfa, 0x9f, 0x78, 0x39, 0xde, 0x44, 0x73, 0xf9, 0xa4, 0xb7, 0x50,
+    0x61, 0x9f, 0x93, 0x0a, 0x09, 0xb5, 0x47, 0x91, 0x0f, 0x21, 0x42, 0x7c,
+    0xa5, 0x25, 0xdb, 0xa8, 0x4e, 0xa1, 0x77, 0x35, 0xf7, 0xb6, 0xb3, 0x0b,
+    0x36, 0xeb, 0xcc, 0xb4, 0xb8, 0x70, 0xf9, 0xb2, 0xdd, 0x0b, 0x69, 0xaa,
+    0xd3, 0x47, 0x03, 0xb9, 0x28, 0xba, 0x80, 0x48, 0xf5, 0xcd, 0x6a, 0x7f,
+    0x16, 0x4d, 0xc5, 0xce, 0x8c, 0xbc, 0x95, 0x0f, 0x5a, 0x24, 0xb0, 0x8f,
+    0x84, 0xd6, 0xed, 0x79, 0x8e, 0x46, 0x79, 0x82, 0x75, 0x0f, 0x10, 0x3f,
+    0x51, 0x8e, 0xb0, 0xc9, 0x40, 0x5b, 0xa3, 0xe0, 0x35, 0xf8, 0x4a, 0xf9,
+    0x7e, 0x38, 0x3f, 0xe9, 0x05, 0xb2, 0x44, 0x7d, 0x76, 0xfe, 0xfd, 0x1e,
+    0x5b, 0xb7, 0xd6, 0x44, 0x13, 0x53, 0xd7, 0xa2, 0xb0, 0x00, 0xfa, 0xf1,
+    0x0b, 0x4d, 0xed, 0x1b, 0x46, 0x97, 0x37, 0xa3, 0xbd, 0x90, 0x0c, 0xed,
+    0xc3, 0x0c, 0x40, 0xcd, 0xba, 0x88, 0x09, 0x47, 0x0d, 0x63, 0xc5, 0xa3,
+    0x33, 0x2c, 0x9a, 0xef, 0x50, 0xf9, 0xa7, 0xcb, 0x6c, 0xc9, 0xeb, 0xbe,
+    0xff, 0x60, 0x88, 0x7e, 0x71, 0xa3, 0xea, 0x0a, 0x6d, 0x54, 0x8d, 0x3d,
+    0x54, 0x6e, 0x15, 0xad, 0xaf, 0x4c, 0xbc, 0x62, 0x4b, 0x2e, 0x0e, 0xfb,
+    0x07, 0xef, 0xab, 0x56, 0xae, 0xc3, 0xb0, 0xec, 0x11, 0xe5, 0x97, 0xc6,
+    0x25, 0xd0, 0x03, 0xd5, 0xc5, 0x0e, 0x35, 0x2c, 0x7a, 0x73, 0xb9, 0x1a,
+    0x81, 0xcb, 0x01, 0xf6, 0x01, 0xae, 0x35, 0x7f};
+
+const uint8_t kExpectedPrivateKey[BCM_MLDSA65_PRIVATE_KEY_BYTES] = {
+    0x0c, 0x6f, 0x38, 0x7d, 0x2a, 0xb4, 0x33, 0x87, 0xf0, 0x21, 0xb0, 0xda,
+    0x81, 0x6c, 0x71, 0xf0, 0xbc, 0x81, 0x5e, 0xf0, 0xb1, 0x6a, 0xf1, 0x12,
+    0x4f, 0x35, 0x4c, 0x27, 0x3e, 0xed, 0xb4, 0x2f, 0xbf, 0x0e, 0xfa, 0x56,
+    0x57, 0x0f, 0xbe, 0xb6, 0x30, 0x07, 0x57, 0xe6, 0xc2, 0xf4, 0xc3, 0x35,
+    0xbe, 0x49, 0x22, 0xba, 0xa2, 0xb7, 0x4f, 0x56, 0x52, 0xb5, 0x7c, 0x3a,
+    0x45, 0x78, 0x0e, 0x2b, 0x63, 0xf6, 0xaf, 0x3b, 0x98, 0xd7, 0xa9, 0x79,
+    0x3e, 0xa4, 0x2c, 0xb3, 0xf4, 0x21, 0xb4, 0x8f, 0xb8, 0x3e, 0x93, 0x20,
+    0x5f, 0x61, 0x51, 0x07, 0x30, 0x25, 0x7f, 0xf9, 0x81, 0x7b, 0x77, 0x6b,
+    0x9d, 0xb4, 0x05, 0x26, 0x15, 0x79, 0x8d, 0xda, 0x47, 0x6f, 0xd5, 0x45,
+    0x4a, 0xe4, 0xe4, 0xfc, 0xb7, 0xeb, 0xe4, 0x40, 0x2d, 0x6b, 0xe1, 0xeb,
+    0x5f, 0xcf, 0x52, 0xea, 0xfe, 0xf4, 0x38, 0x37, 0x36, 0x50, 0x31, 0x60,
+    0x03, 0x68, 0x60, 0x26, 0x36, 0x50, 0x45, 0x16, 0x42, 0x22, 0x51, 0x23,
+    0x54, 0x28, 0x60, 0x51, 0x32, 0x83, 0x06, 0x01, 0x63, 0x13, 0x86, 0x52,
+    0x26, 0x32, 0x05, 0x86, 0x80, 0x01, 0x06, 0x74, 0x06, 0x86, 0x43, 0x87,
+    0x28, 0x72, 0x85, 0x32, 0x14, 0x12, 0x71, 0x68, 0x76, 0x10, 0x32, 0x57,
+    0x55, 0x27, 0x47, 0x38, 0x20, 0x50, 0x81, 0x22, 0x61, 0x67, 0x62, 0x64,
+    0x51, 0x43, 0x01, 0x23, 0x38, 0x73, 0x77, 0x34, 0x02, 0x72, 0x83, 0x86,
+    0x34, 0x28, 0x72, 0x64, 0x88, 0x68, 0x15, 0x86, 0x27, 0x16, 0x14, 0x02,
+    0x45, 0x10, 0x43, 0x13, 0x41, 0x73, 0x45, 0x02, 0x55, 0x45, 0x06, 0x42,
+    0x35, 0x28, 0x70, 0x22, 0x81, 0x48, 0x15, 0x36, 0x31, 0x82, 0x18, 0x33,
+    0x46, 0x01, 0x64, 0x70, 0x32, 0x82, 0x14, 0x02, 0x41, 0x21, 0x28, 0x70,
+    0x67, 0x55, 0x56, 0x44, 0x57, 0x40, 0x81, 0x05, 0x00, 0x66, 0x56, 0x81,
+    0x42, 0x04, 0x34, 0x83, 0x77, 0x55, 0x05, 0x47, 0x64, 0x54, 0x36, 0x53,
+    0x63, 0x63, 0x72, 0x46, 0x60, 0x12, 0x25, 0x25, 0x03, 0x25, 0x65, 0x64,
+    0x84, 0x64, 0x83, 0x34, 0x30, 0x73, 0x11, 0x68, 0x32, 0x56, 0x06, 0x64,
+    0x05, 0x40, 0x52, 0x47, 0x37, 0x51, 0x44, 0x06, 0x75, 0x57, 0x36, 0x22,
+    0x63, 0x28, 0x25, 0x48, 0x64, 0x21, 0x38, 0x47, 0x01, 0x18, 0x18, 0x82,
+    0x10, 0x00, 0x65, 0x33, 0x65, 0x70, 0x46, 0x76, 0x38, 0x63, 0x15, 0x11,
+    0x31, 0x73, 0x08, 0x00, 0x37, 0x71, 0x41, 0x16, 0x21, 0x44, 0x72, 0x45,
+    0x01, 0x71, 0x55, 0x05, 0x01, 0x87, 0x82, 0x14, 0x70, 0x52, 0x32, 0x00,
+    0x76, 0x45, 0x74, 0x62, 0x22, 0x77, 0x47, 0x74, 0x56, 0x26, 0x56, 0x73,
+    0x42, 0x84, 0x15, 0x03, 0x44, 0x64, 0x23, 0x73, 0x37, 0x28, 0x67, 0x15,
+    0x76, 0x28, 0x81, 0x57, 0x52, 0x70, 0x12, 0x31, 0x13, 0x03, 0x32, 0x27,
+    0x03, 0x05, 0x86, 0x27, 0x47, 0x68, 0x26, 0x75, 0x22, 0x38, 0x45, 0x04,
+    0x87, 0x05, 0x46, 0x35, 0x51, 0x45, 0x37, 0x03, 0x06, 0x58, 0x78, 0x36,
+    0x33, 0x07, 0x36, 0x08, 0x23, 0x41, 0x35, 0x30, 0x88, 0x25, 0x03, 0x72,
+    0x26, 0x12, 0x60, 0x06, 0x62, 0x74, 0x51, 0x66, 0x41, 0x70, 0x87, 0x82,
+    0x55, 0x22, 0x76, 0x26, 0x50, 0x03, 0x54, 0x03, 0x68, 0x70, 0x71, 0x61,
+    0x76, 0x00, 0x45, 0x14, 0x64, 0x41, 0x00, 0x46, 0x44, 0x42, 0x62, 0x34,
+    0x38, 0x28, 0x80, 0x06, 0x52, 0x20, 0x67, 0x88, 0x62, 0x75, 0x48, 0x07,
+    0x87, 0x61, 0x40, 0x85, 0x55, 0x76, 0x48, 0x24, 0x04, 0x52, 0x00, 0x83,
+    0x46, 0x54, 0x20, 0x66, 0x52, 0x55, 0x87, 0x50, 0x65, 0x40, 0x43, 0x65,
+    0x01, 0x61, 0x87, 0x25, 0x30, 0x17, 0x72, 0x46, 0x73, 0x60, 0x74, 0x46,
+    0x22, 0x76, 0x21, 0x51, 0x01, 0x30, 0x87, 0x38, 0x38, 0x57, 0x88, 0x55,
+    0x22, 0x64, 0x80, 0x34, 0x83, 0x20, 0x01, 0x42, 0x04, 0x24, 0x08, 0x04,
+    0x87, 0x34, 0x18, 0x26, 0x25, 0x03, 0x13, 0x02, 0x42, 0x81, 0x07, 0x47,
+    0x55, 0x53, 0x51, 0x73, 0x07, 0x08, 0x72, 0x32, 0x32, 0x06, 0x13, 0x76,
+    0x42, 0x61, 0x11, 0x10, 0x34, 0x22, 0x65, 0x80, 0x18, 0x05, 0x01, 0x64,
+    0x44, 0x65, 0x13, 0x20, 0x81, 0x26, 0x03, 0x50, 0x15, 0x34, 0x76, 0x71,
+    0x86, 0x52, 0x58, 0x87, 0x53, 0x84, 0x53, 0x57, 0x75, 0x43, 0x13, 0x71,
+    0x85, 0x66, 0x41, 0x01, 0x52, 0x15, 0x60, 0x43, 0x24, 0x66, 0x42, 0x83,
+    0x02, 0x37, 0x53, 0x44, 0x53, 0x88, 0x15, 0x20, 0x25, 0x77, 0x34, 0x66,
+    0x23, 0x70, 0x06, 0x62, 0x81, 0x37, 0x32, 0x05, 0x16, 0x05, 0x26, 0x44,
+    0x26, 0x21, 0x58, 0x85, 0x17, 0x75, 0x57, 0x70, 0x47, 0x14, 0x61, 0x21,
+    0x26, 0x13, 0x00, 0x48, 0x47, 0x46, 0x27, 0x48, 0x52, 0x50, 0x67, 0x62,
+    0x07, 0x27, 0x04, 0x38, 0x72, 0x60, 0x02, 0x74, 0x00, 0x60, 0x80, 0x13,
+    0x58, 0x63, 0x74, 0x13, 0x47, 0x57, 0x84, 0x52, 0x18, 0x46, 0x36, 0x18,
+    0x72, 0x65, 0x18, 0x20, 0x57, 0x68, 0x76, 0x11, 0x24, 0x02, 0x45, 0x06,
+    0x16, 0x46, 0x78, 0x73, 0x86, 0x22, 0x25, 0x16, 0x12, 0x36, 0x66, 0x81,
+    0x57, 0x82, 0x80, 0x33, 0x08, 0x74, 0x62, 0x48, 0x85, 0x27, 0x56, 0x01,
+    0x88, 0x44, 0x35, 0x44, 0x01, 0x05, 0x38, 0x44, 0x60, 0x46, 0x67, 0x87,
+    0x23, 0x43, 0x76, 0x66, 0x52, 0x71, 0x88, 0x87, 0x27, 0x23, 0x14, 0x78,
+    0x16, 0x87, 0x80, 0x52, 0x56, 0x13, 0x17, 0x06, 0x07, 0x40, 0x86, 0x62,
+    0x12, 0x72, 0x45, 0x25, 0x50, 0x03, 0x32, 0x14, 0x81, 0x70, 0x41, 0x01,
+    0x32, 0x81, 0x13, 0x13, 0x13, 0x72, 0x77, 0x00, 0x48, 0x26, 0x64, 0x81,
+    0x58, 0x07, 0x23, 0x85, 0x27, 0x13, 0x01, 0x60, 0x26, 0x65, 0x37, 0x61,
+    0x84, 0x17, 0x38, 0x08, 0x10, 0x22, 0x01, 0x70, 0x58, 0x65, 0x68, 0x18,
+    0x66, 0x40, 0x80, 0x46, 0x50, 0x87, 0x24, 0x70, 0x06, 0x88, 0x37, 0x66,
+    0x15, 0x03, 0x31, 0x63, 0x05, 0x73, 0x32, 0x57, 0x72, 0x52, 0x12, 0x76,
+    0x72, 0x67, 0x26, 0x13, 0x34, 0x18, 0x75, 0x20, 0x06, 0x83, 0x22, 0x26,
+    0x68, 0x84, 0x44, 0x24, 0x47, 0x08, 0x84, 0x44, 0x13, 0x15, 0x86, 0x45,
+    0x16, 0x58, 0x63, 0x51, 0x50, 0x34, 0x77, 0x00, 0x58, 0x81, 0x86, 0x32,
+    0x78, 0x57, 0x10, 0x25, 0x58, 0x63, 0x48, 0x53, 0x78, 0x75, 0x42, 0x67,
+    0x77, 0x52, 0x63, 0x03, 0x33, 0x51, 0x66, 0x11, 0x83, 0x40, 0x76, 0x01,
+    0x11, 0x53, 0x64, 0x36, 0x30, 0x11, 0x71, 0x75, 0x76, 0x23, 0x26, 0x81,
+    0x32, 0x27, 0x02, 0x56, 0x66, 0x75, 0x07, 0x14, 0x66, 0x35, 0x87, 0x64,
+    0x62, 0x56, 0x33, 0x47, 0x82, 0x26, 0x54, 0x73, 0x38, 0x15, 0x41, 0x58,
+    0x25, 0x84, 0x80, 0x04, 0x57, 0x83, 0x86, 0x83, 0x77, 0x83, 0x22, 0x83,
+    0x65, 0x25, 0x34, 0x58, 0x82, 0x43, 0x33, 0x36, 0x66, 0x68, 0x60, 0x31,
+    0x85, 0x48, 0x88, 0x13, 0x57, 0x24, 0x51, 0x34, 0x16, 0x48, 0x60, 0x37,
+    0x24, 0x21, 0x62, 0x71, 0x06, 0x25, 0x60, 0x32, 0x82, 0x45, 0x52, 0x43,
+    0x15, 0x11, 0x47, 0x77, 0x60, 0x07, 0x15, 0x04, 0x71, 0x53, 0x58, 0x82,
+    0x17, 0x68, 0x40, 0x35, 0x21, 0x13, 0x88, 0x88, 0x61, 0x46, 0x24, 0x41,
+    0x80, 0x10, 0x22, 0x80, 0x88, 0x37, 0x06, 0x30, 0x76, 0x67, 0x70, 0x03,
+    0x18, 0x43, 0x10, 0x74, 0x46, 0x62, 0x21, 0x25, 0x45, 0x56, 0x63, 0x14,
+    0x28, 0x11, 0x37, 0x26, 0x88, 0x86, 0x22, 0x35, 0x51, 0x48, 0x78, 0x78,
+    0x48, 0x26, 0x40, 0x54, 0x82, 0x12, 0x70, 0x71, 0x78, 0x06, 0x05, 0x87,
+    0x17, 0x41, 0x44, 0x00, 0x27, 0x84, 0x33, 0x81, 0x00, 0x16, 0x70, 0x67,
+    0x20, 0x62, 0x78, 0x58, 0x46, 0x25, 0x88, 0x06, 0x50, 0x23, 0x44, 0x04,
+    0x28, 0x44, 0x35, 0x17, 0x62, 0x61, 0x40, 0x41, 0x50, 0x75, 0x27, 0x50,
+    0x76, 0x13, 0x40, 0x40, 0x50, 0x18, 0x22, 0x32, 0x23, 0x51, 0x34, 0x76,
+    0x01, 0x25, 0x81, 0x75, 0x23, 0x66, 0x11, 0x48, 0x41, 0x34, 0x57, 0x36,
+    0x21, 0x73, 0x75, 0x87, 0x01, 0x88, 0x75, 0x28, 0x72, 0x46, 0x13, 0x70,
+    0x77, 0x14, 0x04, 0x80, 0x73, 0x50, 0x27, 0x56, 0x37, 0x22, 0x65, 0x76,
+    0x47, 0x78, 0x41, 0x22, 0x38, 0x24, 0x26, 0x82, 0x18, 0x31, 0x10, 0x71,
+    0x88, 0x62, 0x73, 0x05, 0x30, 0x27, 0x31, 0x76, 0x80, 0x78, 0x13, 0x21,
+    0x31, 0x35, 0x21, 0x54, 0x64, 0x44, 0x86, 0x36, 0x52, 0x42, 0x02, 0x53,
+    0x86, 0x07, 0x72, 0x04, 0x07, 0x70, 0x20, 0x80, 0x20, 0x71, 0x50, 0x03,
+    0x52, 0x14, 0x24, 0x55, 0x52, 0x06, 0x20, 0x11, 0x40, 0x41, 0x14, 0x44,
+    0x15, 0x23, 0x76, 0x00, 0x35, 0x41, 0x88, 0x11, 0x14, 0x57, 0x14, 0x24,
+    0x11, 0x62, 0x18, 0x01, 0x23, 0x87, 0x12, 0x73, 0x54, 0x72, 0x32, 0x13,
+    0x55, 0x04, 0x65, 0x26, 0x76, 0x22, 0x06, 0x51, 0x01, 0x53, 0x81, 0x08,
+    0x24, 0x51, 0x11, 0x88, 0x14, 0x75, 0x37, 0x52, 0x57, 0x18, 0x34, 0x66,
+    0x80, 0x78, 0x41, 0x00, 0x64, 0x57, 0x38, 0x28, 0x07, 0x30, 0x56, 0x13,
+    0x37, 0x27, 0x68, 0x75, 0x01, 0x60, 0x47, 0x32, 0x40, 0x38, 0x71, 0x00,
+    0x70, 0x83, 0x45, 0x32, 0x36, 0x66, 0x56, 0x61, 0x14, 0x28, 0x23, 0x46,
+    0x67, 0x27, 0x41, 0x13, 0x06, 0x38, 0x68, 0x02, 0x08, 0x71, 0x68, 0x75,
+    0x24, 0x51, 0x70, 0x16, 0x01, 0x61, 0x54, 0x75, 0x75, 0x76, 0x08, 0x77,
+    0x76, 0x42, 0x68, 0x48, 0x31, 0x66, 0x16, 0x74, 0x84, 0x60, 0x52, 0x05,
+    0x02, 0x47, 0x40, 0x26, 0x12, 0x75, 0x28, 0x73, 0x18, 0x86, 0x80, 0x78,
+    0x66, 0x54, 0x28, 0x60, 0x30, 0x52, 0x76, 0x45, 0x66, 0x33, 0x52, 0x15,
+    0x03, 0x44, 0x46, 0x62, 0x82, 0x67, 0x41, 0x25, 0x57, 0x84, 0x28, 0x67,
+    0x62, 0x52, 0x34, 0x74, 0x53, 0x86, 0x40, 0x52, 0x62, 0x40, 0x37, 0x78,
+    0x77, 0x45, 0x67, 0x88, 0x08, 0x53, 0x32, 0x21, 0x84, 0x13, 0x34, 0x01,
+    0x41, 0x65, 0x62, 0x31, 0x68, 0x30, 0x07, 0x13, 0x04, 0x13, 0x84, 0x40,
+    0x30, 0x77, 0x72, 0x73, 0x07, 0x86, 0x73, 0x34, 0x51, 0x52, 0x30, 0x28,
+    0x18, 0x02, 0x21, 0x28, 0x61, 0x37, 0x76, 0x60, 0x11, 0x13, 0x01, 0x47,
+    0x36, 0x18, 0x08, 0x10, 0x21, 0x17, 0x11, 0x20, 0x87, 0x72, 0x21, 0x04,
+    0x42, 0x34, 0x58, 0x58, 0x04, 0x13, 0x58, 0x11, 0x84, 0x86, 0x75, 0x85,
+    0x62, 0x73, 0x26, 0x10, 0x70, 0x37, 0x55, 0x45, 0x68, 0x06, 0x25, 0x41,
+    0x53, 0x75, 0x81, 0x58, 0x84, 0x27, 0x83, 0x08, 0x37, 0x83, 0x13, 0x38,
+    0x86, 0x42, 0x70, 0x82, 0x67, 0x61, 0x48, 0x54, 0x20, 0x41, 0x82, 0x32,
+    0x57, 0x81, 0x64, 0x32, 0x12, 0x60, 0x53, 0x75, 0x48, 0x16, 0x22, 0x78,
+    0x16, 0x21, 0x25, 0x36, 0x27, 0x37, 0x83, 0x24, 0x52, 0x82, 0x20, 0x74,
+    0x74, 0x53, 0x76, 0x58, 0x46, 0x72, 0x88, 0x50, 0x23, 0x83, 0x36, 0x02,
+    0x13, 0x12, 0x23, 0x37, 0x08, 0x54, 0x85, 0x11, 0x46, 0x52, 0x74, 0x85,
+    0x41, 0x00, 0x06, 0x01, 0x36, 0x70, 0x51, 0x00, 0x16, 0x57, 0x05, 0x10,
+    0x00, 0x86, 0x20, 0x06, 0x11, 0x05, 0x33, 0x05, 0x12, 0x08, 0x75, 0x10,
+    0x19, 0x3a, 0x4a, 0xa5, 0x53, 0xcb, 0xe3, 0xe7, 0x69, 0xd3, 0x04, 0x28,
+    0x29, 0x68, 0xf1, 0x94, 0x49, 0xcd, 0xee, 0xa9, 0x25, 0xe3, 0x95, 0x74,
+    0x57, 0xa7, 0x1e, 0xac, 0xf1, 0x2f, 0xc5, 0xa6, 0x63, 0x2a, 0xa6, 0x15,
+    0x98, 0x98, 0x6e, 0x15, 0x83, 0xc0, 0xab, 0x5d, 0x8e, 0xbf, 0x69, 0xe4,
+    0x50, 0xb7, 0x47, 0x8a, 0x81, 0x63, 0x9b, 0xdf, 0x71, 0x61, 0x59, 0x62,
+    0x77, 0xd1, 0x3e, 0xd2, 0xf0, 0xa3, 0xc9, 0xa4, 0xed, 0x0a, 0x28, 0xcf,
+    0x5d, 0x8b, 0x3e, 0x29, 0xbc, 0x0e, 0x5c, 0x04, 0x10, 0x8d, 0x13, 0xcd,
+    0x58, 0xc2, 0x02, 0x8d, 0xb8, 0x2e, 0xfa, 0x1a, 0x86, 0x12, 0x61, 0x4f,
+    0x8b, 0xc7, 0x90, 0x01, 0x65, 0x61, 0x1c, 0xa5, 0x9a, 0x32, 0x32, 0x59,
+    0x90, 0x56, 0xb6, 0x5c, 0xbd, 0x6a, 0x85, 0x8a, 0x14, 0xd6, 0x4d, 0xf2,
+    0x68, 0xe9, 0x6b, 0x61, 0x66, 0x3a, 0x9c, 0x79, 0xed, 0xc4, 0x5f, 0x13,
+    0xab, 0x8d, 0x71, 0xe4, 0x5d, 0x0d, 0xee, 0xd4, 0x11, 0xdf, 0x53, 0x21,
+    0x75, 0x64, 0x61, 0x48, 0x6c, 0xf0, 0x30, 0xca, 0x60, 0x92, 0xf2, 0x02,
+    0x5d, 0xc4, 0x11, 0x18, 0x14, 0xfb, 0xb4, 0xf2, 0xc2, 0x58, 0x99, 0xc8,
+    0x73, 0x0b, 0xf9, 0xcf, 0x0b, 0xf7, 0x7a, 0x86, 0x36, 0xa0, 0xb5, 0x02,
+    0x48, 0x5b, 0x42, 0x21, 0xf7, 0x82, 0x03, 0x16, 0x4d, 0x9f, 0x32, 0x2f,
+    0xca, 0xfe, 0x06, 0x5a, 0xd4, 0xc9, 0x47, 0x73, 0x6e, 0xdc, 0x4d, 0x6a,
+    0xc7, 0x70, 0x4c, 0xf9, 0x99, 0xba, 0x1c, 0xfe, 0xf4, 0xf3, 0x0d, 0x55,
+    0x89, 0x74, 0x73, 0xd9, 0xef, 0x0f, 0x0b, 0xce, 0x3c, 0xc0, 0xd3, 0x50,
+    0xf2, 0xc8, 0x1e, 0x64, 0x35, 0xb0, 0x3b, 0x50, 0xb0, 0x10, 0xb5, 0x6b,
+    0x5b, 0x4f, 0xdd, 0xad, 0xd3, 0x41, 0x31, 0x40, 0x9b, 0x22, 0xbb, 0x7d,
+    0xf5, 0x5f, 0x26, 0x23, 0x4c, 0x58, 0x3d, 0x12, 0x58, 0x5a, 0x60, 0x48,
+    0x73, 0xff, 0x81, 0x4f, 0xa0, 0xaf, 0xa5, 0x86, 0xc9, 0xb3, 0xea, 0x33,
+    0x00, 0x16, 0x6a, 0x8a, 0xff, 0x64, 0xcc, 0x2e, 0x6c, 0xae, 0x70, 0x2c,
+    0x51, 0x4b, 0x7e, 0xea, 0x83, 0x46, 0xe4, 0x2f, 0x01, 0xfb, 0x85, 0x4c,
+    0x6e, 0x37, 0x8f, 0x61, 0x1d, 0x73, 0xc9, 0x11, 0xf4, 0x2d, 0xec, 0xac,
+    0x6e, 0x76, 0x0b, 0xe1, 0x03, 0xf0, 0xa0, 0x5c, 0x55, 0x81, 0xdc, 0xa7,
+    0x27, 0x17, 0xcd, 0xad, 0xc7, 0x9c, 0x1a, 0x99, 0x20, 0x92, 0xb8, 0x25,
+    0x05, 0x1b, 0x3f, 0x80, 0xbe, 0x35, 0x28, 0x98, 0x58, 0x47, 0x10, 0xc7,
+    0xdc, 0x07, 0x2c, 0xe3, 0x22, 0x55, 0xff, 0xbc, 0x57, 0x23, 0xd5, 0x04,
+    0xb0, 0x2c, 0x4e, 0x65, 0x1b, 0x60, 0xc9, 0x9b, 0xb6, 0x19, 0x7b, 0x6a,
+    0xf3, 0xf6, 0xb6, 0xa5, 0x98, 0x18, 0xea, 0xe8, 0x47, 0xc5, 0x99, 0xe5,
+    0x0f, 0xe5, 0x66, 0x32, 0x8e, 0x55, 0x6b, 0x61, 0x4d, 0xde, 0x30, 0x01,
+    0x91, 0xc7, 0x82, 0xac, 0xc0, 0xe0, 0x17, 0x5b, 0x3f, 0xa4, 0xf3, 0x70,
+    0x2d, 0x2c, 0xc5, 0x82, 0x1b, 0x6b, 0xae, 0x3e, 0xe4, 0x04, 0xa7, 0xce,
+    0x36, 0x27, 0x47, 0xd1, 0xf2, 0xf8, 0xc3, 0x79, 0xce, 0xa1, 0xdf, 0xdc,
+    0xc8, 0x32, 0x80, 0xb1, 0x3d, 0x39, 0xc0, 0xd4, 0x80, 0x9f, 0xcf, 0x7e,
+    0x85, 0x76, 0x25, 0xcc, 0x57, 0xb1, 0xf1, 0xcf, 0x6c, 0xc5, 0x41, 0x11,
+    0xac, 0x48, 0xfe, 0xd1, 0x52, 0xed, 0xde, 0xb9, 0xa4, 0x73, 0x6d, 0x85,
+    0x54, 0x40, 0x5f, 0x6e, 0x5d, 0x7d, 0x1b, 0xc9, 0xcb, 0x5a, 0x1e, 0xc5,
+    0xdd, 0x98, 0x94, 0x7d, 0xbe, 0x84, 0x8a, 0x40, 0x6a, 0x27, 0x45, 0x61,
+    0x2c, 0x8a, 0x04, 0x9e, 0x0b, 0xa3, 0xc2, 0x95, 0xb0, 0x65, 0xf6, 0xb5,
+    0xc8, 0xff, 0x13, 0x47, 0x10, 0xa9, 0xb4, 0xa1, 0x75, 0x94, 0xcd, 0x98,
+    0xf4, 0x22, 0x3f, 0xa6, 0x1c, 0x9b, 0xd1, 0xaf, 0x33, 0x69, 0xcb, 0x9a,
+    0x88, 0x67, 0x16, 0xf6, 0x90, 0x4e, 0xdd, 0x61, 0x91, 0x84, 0xe3, 0xf0,
+    0x74, 0x73, 0x7e, 0x19, 0x4e, 0x75, 0xd7, 0x5a, 0xcb, 0x40, 0x13, 0x12,
+    0x5f, 0x6f, 0xe5, 0x77, 0x0c, 0x5e, 0x3c, 0x6b, 0x87, 0xbf, 0xdf, 0x61,
+    0xbe, 0x97, 0xbd, 0x38, 0xcd, 0xf7, 0x36, 0xee, 0x23, 0xcc, 0x7e, 0xd0,
+    0x0a, 0xc2, 0xfe, 0x4e, 0xec, 0x9c, 0x9a, 0x07, 0xec, 0xd3, 0xb2, 0x1c,
+    0x1c, 0x88, 0xfa, 0xfa, 0x26, 0x61, 0x97, 0x93, 0x87, 0xa4, 0xc8, 0xaa,
+    0x4e, 0xf6, 0x8c, 0x22, 0xd4, 0xe8, 0x36, 0x97, 0x9c, 0x11, 0xe6, 0xf2,
+    0x2b, 0x1c, 0x6c, 0x33, 0xea, 0xc4, 0xdc, 0xd6, 0x7b, 0xe7, 0x96, 0xe6,
+    0xbc, 0x14, 0xa6, 0xc4, 0x7c, 0x78, 0x1f, 0xfa, 0x34, 0xd6, 0xaf, 0x28,
+    0x29, 0xe6, 0x0a, 0xab, 0xca, 0x87, 0xaf, 0xb8, 0x2f, 0xab, 0x5f, 0x4a,
+    0xc3, 0xfa, 0xd2, 0xa7, 0xef, 0xef, 0x21, 0xbd, 0xef, 0x9c, 0xb9, 0x59,
+    0x1c, 0xa2, 0x8c, 0x1f, 0x0e, 0x86, 0xa5, 0xc9, 0x8b, 0x3d, 0xbe, 0x6e,
+    0xba, 0x8c, 0xef, 0xa8, 0xb6, 0x0d, 0x54, 0x1e, 0x6f, 0x5d, 0x22, 0xf4,
+    0x0c, 0x2e, 0x8b, 0x27, 0xaa, 0xc5, 0x9e, 0x43, 0x5a, 0xfd, 0x2f, 0x4b,
+    0x49, 0x63, 0x69, 0x57, 0x02, 0x8b, 0xb2, 0xef, 0x21, 0xad, 0xdf, 0x3d,
+    0x4a, 0x67, 0x0f, 0xad, 0xf7, 0x45, 0x17, 0xb3, 0x6e, 0xdd, 0x21, 0x9a,
+    0xc2, 0x69, 0x3e, 0xc1, 0x9e, 0xe1, 0x96, 0x96, 0xad, 0xeb, 0x16, 0x69,
+    0xa7, 0x8b, 0x14, 0x95, 0x6e, 0x47, 0xf9, 0x9f, 0x34, 0x3e, 0x66, 0x9d,
+    0xcb, 0x0a, 0xb5, 0xff, 0xae, 0x2c, 0xff, 0x4e, 0x4d, 0xf5, 0x02, 0xa6,
+    0xc9, 0xe8, 0x29, 0x56, 0xb3, 0xa8, 0x8c, 0xf5, 0xe6, 0x97, 0xa7, 0x00,
+    0x1b, 0x98, 0x8f, 0xd3, 0xe9, 0x14, 0x0e, 0xf2, 0x85, 0x2f, 0xa9, 0xb7,
+    0xb6, 0xca, 0x99, 0x06, 0x17, 0x1b, 0xf6, 0xce, 0x9e, 0x50, 0xf1, 0x33,
+    0x62, 0xd0, 0xe5, 0xa0, 0x05, 0x01, 0x0d, 0xf8, 0x56, 0xf0, 0x35, 0x04,
+    0xbd, 0xf2, 0x2c, 0x15, 0x75, 0x96, 0x89, 0xd9, 0x3c, 0xca, 0x84, 0x14,
+    0x2b, 0x37, 0x64, 0x1b, 0x28, 0x62, 0xda, 0xb3, 0xc5, 0x2d, 0x26, 0x38,
+    0x0f, 0x29, 0x39, 0x03, 0x3b, 0x75, 0x82, 0xeb, 0x6a, 0xd7, 0x1f, 0x57,
+    0xb0, 0x66, 0x6f, 0xd3, 0xb6, 0xe5, 0xd2, 0x68, 0x14, 0x8f, 0xe8, 0xd7,
+    0x09, 0x53, 0x98, 0xb6, 0xff, 0xa4, 0x85, 0x21, 0x7a, 0x07, 0x4a, 0xf3,
+    0xe8, 0xe2, 0xc7, 0x20, 0x31, 0x77, 0x79, 0x37, 0xf3, 0x27, 0xe6, 0xd3,
+    0xfb, 0x8b, 0xa8, 0xf4, 0x71, 0x27, 0xe4, 0xea, 0x63, 0xaf, 0xce, 0x9f,
+    0x0b, 0x25, 0x01, 0x84, 0x31, 0x60, 0x30, 0x06, 0x11, 0x19, 0x31, 0x74,
+    0xf2, 0xce, 0x17, 0x6a, 0x22, 0xfe, 0x62, 0x0e, 0xfb, 0x54, 0xdf, 0xe4,
+    0xfd, 0x96, 0x69, 0x99, 0x1d, 0x95, 0xed, 0xcb, 0x9f, 0xb1, 0x89, 0xce,
+    0x77, 0x84, 0x46, 0x87, 0x7d, 0x71, 0xb0, 0xd6, 0x35, 0xd1, 0x3d, 0xcd,
+    0xb5, 0xa1, 0xaa, 0xee, 0xa2, 0x66, 0xb5, 0xf0, 0x1f, 0x4a, 0x12, 0x88,
+    0xc8, 0x95, 0x02, 0x2c, 0x1a, 0xe8, 0x49, 0xda, 0x28, 0x10, 0x1a, 0xd0,
+    0xc0, 0x33, 0x6c, 0xb6, 0x69, 0xb2, 0x1a, 0xa4, 0xf5, 0x47, 0xc8, 0x05,
+    0x12, 0x22, 0xf3, 0xb5, 0xa4, 0x50, 0xa8, 0x1f, 0xab, 0x2c, 0xef, 0x5d,
+    0x8d, 0xfe, 0x98, 0x9e, 0xdb, 0x1f, 0x63, 0xf3, 0x34, 0x1a, 0x82, 0xce,
+    0xaf, 0x59, 0x61, 0xa5, 0x78, 0xfd, 0x5f, 0xef, 0xd9, 0xfe, 0xab, 0x06,
+    0xd0, 0x14, 0xf1, 0x8a, 0x18, 0xbc, 0x32, 0xe2, 0xc0, 0x1b, 0x3d, 0xb1,
+    0x72, 0x77, 0xa6, 0x94, 0x8c, 0x6e, 0x05, 0xa2, 0x6b, 0x80, 0xd0, 0x1b,
+    0xd7, 0x59, 0xe3, 0x59, 0x5e, 0x6e, 0x10, 0x53, 0xd4, 0x2c, 0x68, 0x82,
+    0x9a, 0xfc, 0x39, 0x9d, 0x19, 0xb3, 0x84, 0x3d, 0x4c, 0xaa, 0xe6, 0x71,
+    0x59, 0x01, 0x29, 0x96, 0xcb, 0x96, 0xb2, 0x68, 0x5e, 0x8f, 0xdb, 0xc4,
+    0x4e, 0xca, 0x20, 0x4b, 0xe5, 0x52, 0x37, 0xd6, 0xce, 0x36, 0xc0, 0x01,
+    0xb7, 0xae, 0x7d, 0xe2, 0x2b, 0xd6, 0xcb, 0xb1, 0x9c, 0x66, 0xd9, 0x67,
+    0xf8, 0x54, 0xcc, 0x2e, 0x2b, 0x2c, 0x58, 0xd0, 0x56, 0xba, 0x71, 0x62,
+    0x1f, 0xda, 0xfc, 0xd2, 0xe5, 0xf2, 0xf7, 0xbd, 0x49, 0xcf, 0xa4, 0x7f,
+    0x91, 0x53, 0xac, 0x08, 0x9e, 0xba, 0xd0, 0x85, 0x4d, 0x51, 0x30, 0xd1,
+    0x58, 0x3c, 0x4c, 0xbe, 0x3d, 0x80, 0x7a, 0x5b, 0xe6, 0xb1, 0x49, 0x88,
+    0xc6, 0xf8, 0xf7, 0xc6, 0xf4, 0xbc, 0xbb, 0x98, 0x59, 0x88, 0x61, 0xff,
+    0xe1, 0x9e, 0x8a, 0xbc, 0x83, 0x11, 0xf0, 0xe0, 0x47, 0xa5, 0xea, 0x02,
+    0x2e, 0xc6, 0xdd, 0x5a, 0xf5, 0x0d, 0x24, 0xf9, 0x00, 0x5f, 0xcc, 0xc9,
+    0xe7, 0x16, 0x0d, 0xaa, 0x32, 0x34, 0xfe, 0x5c, 0x7b, 0x26, 0x47, 0x0a,
+    0xb5, 0x61, 0xa2, 0x6c, 0x39, 0x46, 0x87, 0xca, 0xac, 0x75, 0xfe, 0x34,
+    0x38, 0x92, 0x62, 0xbd, 0xfe, 0xa3, 0x75, 0x97, 0x2b, 0xf1, 0xc2, 0xbb,
+    0x37, 0xf2, 0x52, 0xad, 0xdb, 0xc0, 0xfe, 0x76, 0x0f, 0x1f, 0x3a, 0xe6,
+    0xae, 0xde, 0xb8, 0x67, 0x62, 0x94, 0xc4, 0x2f, 0xc8, 0x6a, 0xc8, 0x49,
+    0x11, 0x90, 0x80, 0x0c, 0xca, 0x46, 0x66, 0x52, 0x7e, 0x51, 0x1d, 0x4d,
+    0x19, 0x73, 0xf7, 0x10, 0xa0, 0x77, 0xdd, 0x0b, 0x38, 0x2c, 0x79, 0xa4,
+    0x6e, 0xe3, 0xce, 0x5f, 0x1c, 0xf8, 0xcd, 0x96, 0x7a, 0xed, 0x48, 0x9e,
+    0x14, 0x32, 0x69, 0x8a, 0xb3, 0xaf, 0xe1, 0x22, 0xb0, 0x29, 0xb3, 0x3b,
+    0x61, 0x8f, 0xfc, 0xf4, 0xc3, 0xf8, 0x7d, 0x2a, 0x9c, 0x0a, 0x30, 0xe9,
+    0x43, 0x56, 0xdc, 0xd8, 0xbf, 0xe3, 0x95, 0x6e, 0xa4, 0x25, 0x9b, 0x92,
+    0xae, 0x30, 0xdc, 0x07, 0x76, 0x39, 0x08, 0x22, 0xe2, 0xd0, 0xf0, 0x4c,
+    0xb6, 0x0b, 0xa5, 0x69, 0x2b, 0xe9, 0x58, 0x24, 0x85, 0x6b, 0x92, 0xb9,
+    0x4b, 0xf7, 0x25, 0xdc, 0xbe, 0x77, 0x6c, 0xc0, 0xf3, 0xa9, 0x81, 0x01,
+    0x8d, 0x95, 0x62, 0x5b, 0x8b, 0x78, 0x76, 0xb8, 0x75, 0x1f, 0xbe, 0x4e,
+    0x19, 0xb1, 0x69, 0xb5, 0xdf, 0x96, 0x35, 0x51, 0x11, 0x05, 0x81, 0x29,
+    0xd5, 0x20, 0x21, 0x48, 0xc2, 0xc5, 0x94, 0xdc, 0xf4, 0x2a, 0xc3, 0x45,
+    0xc5, 0x88, 0xc0, 0x5f, 0x16, 0xd4, 0x42, 0x55, 0x84, 0xe9, 0x14, 0x85,
+    0xe1, 0x7c, 0x01, 0x33, 0xd5, 0x6a, 0x9b, 0x56, 0x49, 0x8a, 0xd6, 0x79,
+    0xc4, 0x2b, 0x3d, 0x0d, 0xce, 0x83, 0x48, 0xee, 0x92, 0x31, 0xec, 0xc0,
+    0x6e, 0xf0, 0x05, 0xa9, 0xe3, 0x02, 0x8f, 0x5b, 0xdb, 0xc4, 0x1b, 0xff,
+    0x55, 0x8f, 0x02, 0xbd, 0xfb, 0x37, 0xfa, 0x7c, 0x84, 0x22, 0x36, 0xd6,
+    0x45, 0xf9, 0xf1, 0x95, 0xad, 0xe1, 0xb4, 0xee, 0xc2, 0x23, 0xba, 0xa6,
+    0x8b, 0xbf, 0xe6, 0xa0, 0x72, 0x1b, 0x3e, 0x98, 0xed, 0x90, 0x4c, 0x33,
+    0x2f, 0x90, 0x14, 0x9e, 0x45, 0x2f, 0xf6, 0x42, 0xfc, 0x99, 0xef, 0x8e,
+    0xb3, 0x29, 0x37, 0x2a, 0x8a, 0xe3, 0xc0, 0xb9, 0x69, 0xcd, 0x7f, 0x9b,
+    0x54, 0x37, 0x91, 0x46, 0x5a, 0xb5, 0x7a, 0x20, 0x9f, 0xff, 0x48, 0x08,
+    0xc3, 0xa7, 0xf4, 0x4d, 0xa5, 0x84, 0x4e, 0x14, 0x08, 0x45, 0xa3, 0x09,
+    0x03, 0x30, 0x9e, 0x7f, 0x83, 0xf4, 0x30, 0xe7, 0xfb, 0x8b, 0x49, 0xaf,
+    0xe2, 0xde, 0x3c, 0x65, 0x16, 0x2d, 0xa1, 0x77, 0x53, 0xd1, 0x4b, 0xda,
+    0x43, 0xcb, 0xbe, 0xaf, 0x5c, 0x47, 0x25, 0x47, 0x3a, 0x99, 0xb7, 0x1e,
+    0x4e, 0x02, 0xf9, 0xba, 0x34, 0xe2, 0xb9, 0xbf, 0x48, 0x16, 0xba, 0x6f,
+    0x42, 0xfa, 0xfa, 0x85, 0x9d, 0x02, 0x64, 0xd1, 0x8e, 0x8a, 0x93, 0x62,
+    0x5e, 0x32, 0x35, 0x13, 0xdb, 0xb5, 0x55, 0x36, 0x29, 0x20, 0xc7, 0xf9,
+    0x5b, 0x6b, 0xd1, 0x85, 0xc5, 0xcd, 0x10, 0x7a, 0x1d, 0x91, 0x83, 0x3d,
+    0xc2, 0x7d, 0x23, 0x24, 0x13, 0xff, 0x9b, 0xa9, 0x00, 0x9d, 0x90, 0x3f,
+    0xc6, 0xcc, 0xdf, 0x4b, 0x9f, 0xc8, 0x0f, 0x5a, 0xef, 0x4b, 0x39, 0x3b,
+    0x5a, 0x46, 0x8d, 0x60, 0xb1, 0xa1, 0x22, 0xf3, 0xcc, 0x61, 0x3a, 0x77,
+    0x69, 0x30, 0x02, 0x14, 0x78, 0xf4, 0xb8, 0x78, 0xce, 0x4e, 0x52, 0xaa,
+    0x48, 0x39, 0xb2, 0x0f, 0x52, 0x3b, 0xb7, 0xca, 0x7a, 0x94, 0x50, 0x20,
+    0x05, 0x37, 0x65, 0x21, 0x95, 0x7f, 0x99, 0x21, 0xdc, 0x76, 0xd7, 0x4d,
+    0xed, 0x38, 0xb5, 0x87, 0x3a, 0xab, 0x53, 0x77, 0xf1, 0xf3, 0xfc, 0x5d,
+    0x23, 0xe2, 0x09, 0x14, 0x60, 0x0b, 0x8a, 0xe6, 0x2c, 0xb4, 0x8b, 0x73,
+    0x44, 0x82, 0x16, 0x58, 0x20, 0x77, 0x0b, 0xa1, 0xd0, 0x31, 0x23, 0x2b,
+    0xf7, 0x5e, 0x9e, 0xc2, 0x50, 0x8e, 0x75, 0x28, 0x6a, 0x63, 0x4e, 0xed,
+    0xac, 0x93, 0xdb, 0x08, 0x27, 0x50, 0x54, 0x47, 0x0d, 0xc4, 0x64, 0xc4,
+    0x1d, 0x28, 0x58, 0xfc, 0xd8, 0x0e, 0x05, 0x89, 0xd0, 0x83, 0x11, 0x36,
+    0x95, 0xdd, 0xcf, 0xc2, 0x4a, 0x8c, 0x47, 0xc4, 0x8a, 0xf5, 0xe2, 0x20,
+    0x4a, 0x15, 0x50, 0xf1, 0xfc, 0xbe, 0xa0, 0x3e, 0xe6, 0xed, 0x7c, 0x33,
+    0xd9, 0x93, 0x2b, 0xb8, 0x6b, 0xc9, 0x6c, 0x3a, 0x75, 0xd7, 0xd4, 0xd3,
+    0x92, 0x9f, 0xa9, 0x58, 0x77, 0xd1, 0x23, 0x91, 0x6e, 0x5e, 0x21, 0x8b,
+    0x05, 0x40, 0x6f, 0x16, 0x25, 0x5d, 0x13, 0xf3, 0x5a, 0xfc, 0x1b, 0xd0,
+    0x4e, 0x43, 0x6b, 0x3f, 0x83, 0xfc, 0xb2, 0xe1, 0x8a, 0x50, 0x6a, 0xad,
+    0x68, 0xe4, 0x11, 0x15, 0x77, 0x65, 0x47, 0xf8, 0x36, 0xba, 0x3a, 0x0f,
+    0x97, 0x16, 0xcc, 0xaf, 0xc1, 0x84, 0x2e, 0x20, 0x40, 0x96, 0x56, 0xb9,
+    0x36, 0x13, 0x9e, 0xcb, 0x0d, 0x68, 0xd0, 0xfe, 0x6c, 0x9d, 0xc3, 0x81,
+    0xa0, 0xb9, 0x4b, 0x59, 0xfb, 0x13, 0xb9, 0xa4, 0xd5, 0xae, 0x32, 0x0a,
+    0x5f, 0xac, 0x53, 0x83, 0x2b, 0x60, 0x57, 0x63, 0x22, 0xa8, 0x57, 0x18,
+    0xbd, 0xb9, 0xe5, 0x4c, 0x3c, 0xb0, 0x4a, 0x70, 0x66, 0xc3, 0x90, 0xcf,
+    0x46, 0x67, 0xaa, 0x9b, 0xbb, 0x7d, 0x48, 0x58, 0xbf, 0x22, 0x00, 0xf3,
+    0x2a, 0xad, 0xe8, 0xb5, 0x80, 0xf7, 0x53, 0xf1, 0xf6, 0xd4, 0xe2, 0x2d,
+    0xdf, 0xde, 0x76, 0x91, 0x45, 0x29, 0x65, 0x39, 0xfe, 0xba, 0x5b, 0xd8,
+    0x77, 0x18, 0x3b, 0x89, 0xe2, 0x3a, 0xe5, 0x03, 0x79, 0xd5, 0x47, 0xa1,
+    0x37, 0xb5, 0x86, 0x55, 0xef, 0x01, 0xcc, 0x35, 0x7f, 0x1b, 0x68, 0xc1,
+    0xde, 0x36, 0xc9, 0x72, 0x5d, 0xf6, 0xa2, 0x04, 0x74, 0x62, 0xda, 0x30,
+    0xe1, 0x7a, 0x37, 0xdd, 0x34, 0x77, 0x5b, 0x4b, 0xc3, 0xf8, 0xe9, 0x47,
+    0xcf, 0x97, 0xd3, 0x4d, 0x30, 0xee, 0x20, 0x6b, 0x29, 0xd8, 0x9c, 0x7f,
+    0x26, 0xab, 0x31, 0x57, 0x9d, 0xb9, 0x6a, 0xac, 0x42, 0x54, 0x99, 0x8c,
+    0xa6, 0x04, 0x08, 0x73, 0x92, 0x0b, 0xf4, 0x92, 0x3f, 0x8a, 0x2f, 0xea,
+    0x03, 0xdf, 0x8e, 0xa0, 0xcb, 0x99, 0x3a, 0x97, 0x18, 0xc5, 0xd2, 0x67,
+    0x1b, 0xf0, 0x19, 0x63, 0xbd, 0x12, 0x89, 0x3f, 0x2c, 0xd5, 0xbe, 0x11,
+    0x64, 0xdb, 0x1a, 0xe1, 0x23, 0x4a, 0x59, 0x67, 0xf3, 0x2f, 0xe1, 0x8e,
+    0x4e, 0x97, 0x26, 0xbf, 0x04, 0xab, 0xe4, 0x08, 0x4e, 0x6e, 0x77, 0x3c,
+    0xe0, 0x09, 0x65, 0x5e, 0xf0, 0xba, 0xac, 0x29, 0x6b, 0xf9, 0x1d, 0xea,
+    0xe5, 0x8d, 0x5c, 0x96, 0x2a, 0x34, 0x32, 0x99, 0x59, 0x1e, 0xb6, 0x41,
+    0x45, 0xfc, 0x42, 0x9b, 0x4a, 0x27, 0x2c, 0x29, 0x53, 0xc7, 0xa9, 0x85,
+    0x5f, 0x07, 0xdd, 0xb0, 0x96, 0xbf, 0x55, 0x86, 0x1d, 0x04, 0xb3, 0x0e,
+    0x32, 0x31, 0x34, 0xd6, 0x01, 0x82, 0x79, 0xb4, 0x9d, 0x48, 0xf3, 0x25,
+    0x2f, 0xb4, 0xf9, 0x7d, 0xe7, 0xfa, 0x23, 0x92, 0x36, 0x87, 0x2f, 0xa2,
+    0xf9, 0x99, 0x5c, 0x7e, 0x7c, 0xdb, 0x5b, 0x64, 0xcf, 0xb7, 0x74, 0x91,
+    0xb7, 0x4a, 0x9f, 0xe7, 0x1f, 0x9a, 0x74, 0x1a, 0x6b, 0xdc, 0x7c, 0xa7,
+    0x8a, 0x20, 0x94, 0x0a, 0x2d, 0xc7, 0xc6, 0xcf, 0x6e, 0x25, 0xe9, 0xa8,
+    0x2c, 0xd9, 0xed, 0x78, 0x05, 0xa4, 0x65, 0x20, 0xa6, 0xa9, 0xed, 0x61,
+    0xd9, 0xb7, 0xf8, 0x43, 0xf1, 0xcc, 0xff, 0x59, 0xcd, 0x6b, 0x9e, 0x7b,
+    0x4c, 0x91, 0xe9, 0xab, 0x7a, 0x6f, 0x87, 0x7e, 0x66, 0x4a, 0xfb, 0xac,
+    0xd6, 0xec, 0x95, 0xab, 0xa4, 0x4c, 0x68, 0x69, 0x4e, 0xb4, 0x80, 0xf5,
+    0x32, 0x2b, 0xd4, 0xa5, 0x08, 0x88, 0x9f, 0x19, 0xf2, 0x12, 0x5c, 0xc1,
+    0xcb, 0xcc, 0x46, 0xb5, 0xcc, 0x77, 0xbb, 0xc4, 0xc4, 0x01, 0xd9, 0xd6,
+    0x49, 0x79, 0xe9, 0x62, 0x96, 0xe6, 0xc0, 0x43, 0xde, 0x00, 0x0d, 0xae,
+    0x60, 0x06, 0x47, 0xb9, 0x5c, 0x81, 0x39, 0xa0, 0x06, 0x05, 0x2a, 0x62,
+    0xab, 0xe5, 0x15, 0x47, 0xc9, 0x0a, 0xe3, 0x16, 0x6a, 0xfc, 0x4d, 0x73,
+    0xbf, 0xee, 0x0b, 0x3f, 0x4d, 0x08, 0xee, 0x1c, 0x66, 0x03, 0x42, 0x56,
+    0xd9, 0xfb, 0xe2, 0x8e, 0xd2, 0xf1, 0xc7, 0x41, 0x3d, 0x32, 0xa8, 0x64,
+    0xa6, 0x81, 0x28, 0x7d, 0x0e, 0x6e, 0xb3, 0x2c, 0xb5, 0x64, 0xda, 0xda,
+    0xf9, 0x0c, 0x4b, 0x77, 0x5a, 0xa2, 0xf3, 0xff, 0x96, 0xed, 0x47, 0x5b,
+    0xe8, 0x03, 0xc1, 0x0a, 0x77, 0x25, 0x4b, 0x3c, 0xa1, 0x92, 0x30, 0xf0,
+    0xa0, 0xfd, 0x3f, 0xac, 0x2d, 0xbd, 0x33, 0x05, 0x07, 0xfc, 0x48, 0x60,
+    0xc2, 0xe7, 0x46, 0xc0, 0xf8, 0xcb, 0x4e, 0xed, 0xf5, 0x1e, 0xec, 0xd1,
+    0x56, 0x6a, 0xcc, 0xfd, 0x4c, 0xb6, 0x18, 0xce, 0xa2, 0x79, 0xba, 0x81,
+    0x3e, 0x8a, 0x41, 0x73, 0x76, 0xba, 0xde, 0xed, 0x44, 0x11, 0xd3, 0x62,
+    0xa5, 0x99, 0xbc, 0x63, 0x32, 0xca, 0x42, 0xbf, 0xbf, 0x42, 0xc2, 0x70,
+    0x64, 0x60, 0xd0, 0x4a, 0x9f, 0x33, 0x06, 0x0f, 0xed, 0x38, 0xa8, 0x3b,
+    0xe7, 0xf6, 0x05, 0x46, 0x8d, 0x6f, 0x7b, 0x84, 0xb8, 0x90, 0x98, 0xd8,
+    0x91, 0x93, 0xf8, 0x74, 0xee, 0xd6, 0x03, 0x96, 0x02, 0x15, 0x08, 0xcf,
+    0x4a, 0xe4, 0xa0, 0x70, 0xa8, 0x5a, 0x3e, 0x77, 0x37, 0x20, 0xd9, 0xae,
+    0x5e, 0x2e, 0x6f, 0xf7, 0xf9, 0x1a, 0x2d, 0xa9, 0x07, 0xa5, 0x48, 0x39,
+    0x60, 0x95, 0x4e, 0x58, 0x6e, 0xff, 0xaa, 0x14, 0x50, 0x3a, 0x8f, 0x31,
+    0x23, 0xb8, 0x54, 0x17, 0x78, 0xf2, 0x65, 0xcc, 0xf0, 0x7a, 0x8e, 0x60,
+    0x35, 0x7e, 0x99, 0x89, 0x7f, 0x4f, 0xf7, 0xc2, 0x21, 0xc7, 0x11, 0xbf,
+    0xf2, 0x20, 0xa3, 0x56, 0x91, 0xab, 0x26, 0xfe, 0x17, 0xf1, 0xa5, 0xf3};
+
+const uint8_t kSignEntropy[BCM_MLDSA_SEED_BYTES] = {
+    0x7c, 0xf6, 0x8e, 0x63, 0x14, 0x04, 0x0b, 0x08, 0x20, 0x9b, 0x00,
+    0x8c, 0x31, 0x48, 0xee, 0xd3, 0xe1, 0x6d, 0x5f, 0x71, 0x3b, 0xc7,
+    0x08, 0x78, 0x05, 0x4b, 0x12, 0x4f, 0xf1, 0xf3, 0x50, 0x07};
+
+const uint8_t kExpectedCase1Signature[BCM_MLDSA65_SIGNATURE_BYTES] = {
+    0xf8, 0xc7, 0x25, 0x84, 0x8b, 0x39, 0xd9, 0xd9, 0x80, 0xf0, 0x2f, 0xf7,
+    0xa0, 0x24, 0x19, 0x08, 0x70, 0x65, 0xe2, 0xc8, 0x0a, 0xc4, 0xd3, 0xd5,
+    0x97, 0x49, 0x31, 0xea, 0x7b, 0xd6, 0x64, 0xb6, 0x6e, 0x6b, 0xf3, 0xc7,
+    0x5f, 0xcb, 0xe3, 0x42, 0xd5, 0x5e, 0xa2, 0xa8, 0x8a, 0x01, 0x9a, 0xfe,
+    0x44, 0xe2, 0xa7, 0x87, 0xd7, 0x70, 0xab, 0x9d, 0xa8, 0xf0, 0x9c, 0x67,
+    0xfb, 0x4c, 0x16, 0xa6, 0x86, 0x91, 0xe2, 0x26, 0x9b, 0xa2, 0xda, 0x94,
+    0x96, 0x6d, 0xfc, 0x4e, 0xf2, 0x2f, 0x2b, 0xcf, 0xf3, 0xc2, 0x7e, 0xe5,
+    0x73, 0x1a, 0xac, 0xa3, 0x2c, 0x4d, 0x82, 0x28, 0x82, 0xa5, 0x82, 0x40,
+    0x3d, 0x9a, 0xf6, 0x4b, 0xee, 0xae, 0xb7, 0x37, 0xd8, 0x2d, 0x80, 0xdd,
+    0xcb, 0x52, 0xce, 0xea, 0xde, 0x51, 0xb9, 0x3e, 0x34, 0x7a, 0xfd, 0x3d,
+    0x79, 0x38, 0xf6, 0xe9, 0x48, 0x1c, 0x07, 0x5f, 0xb8, 0x02, 0xa5, 0xa4,
+    0xab, 0x45, 0xe7, 0x66, 0xf5, 0x9a, 0x23, 0xfe, 0x72, 0xcb, 0xd0, 0xa0,
+    0x18, 0x74, 0x75, 0xc2, 0x1c, 0xcf, 0xd6, 0x69, 0x62, 0xa0, 0xe3, 0xde,
+    0xa7, 0x2b, 0x0a, 0xf0, 0x1c, 0xb3, 0x51, 0x41, 0xf9, 0xfe, 0x2c, 0xff,
+    0x82, 0xa3, 0x46, 0x6f, 0xb5, 0x55, 0x0d, 0xaa, 0xd1, 0x0e, 0xc8, 0x31,
+    0xc6, 0xdf, 0x61, 0xe8, 0x96, 0x78, 0x85, 0x08, 0xf4, 0x62, 0x48, 0xfd,
+    0x1d, 0x82, 0xf7, 0x9b, 0x7b, 0xbe, 0xee, 0x47, 0xcf, 0x17, 0xf7, 0x5a,
+    0xed, 0xfa, 0x89, 0x94, 0x3e, 0xc3, 0xba, 0x37, 0xa5, 0xe4, 0xfb, 0x72,
+    0x32, 0x90, 0xc2, 0x46, 0xd3, 0x02, 0x3f, 0xf5, 0xb1, 0x73, 0xbd, 0x9f,
+    0x09, 0xa8, 0x61, 0x13, 0x75, 0xf2, 0xa6, 0xfc, 0x19, 0x44, 0xe7, 0xfd,
+    0x1c, 0xcf, 0xa2, 0x24, 0x79, 0x39, 0x3a, 0xf1, 0xe4, 0x96, 0xe0, 0xd8,
+    0xcb, 0x9b, 0x1f, 0xab, 0x20, 0x7e, 0x21, 0xbb, 0xf7, 0xe2, 0x7e, 0xd0,
+    0xaf, 0x2b, 0x04, 0xbf, 0x35, 0xad, 0x04, 0x09, 0x11, 0xfa, 0x45, 0xaa,
+    0xee, 0x30, 0x62, 0xd4, 0x41, 0x39, 0xed, 0x00, 0xe3, 0x06, 0x7d, 0x0c,
+    0x91, 0x2d, 0x4b, 0x8d, 0xdb, 0xf6, 0x98, 0x5b, 0x0b, 0x26, 0x9a, 0x79,
+    0x19, 0x58, 0x2f, 0x3d, 0x80, 0xb7, 0x7a, 0x49, 0xc7, 0x6d, 0xfb, 0xd6,
+    0xa6, 0x86, 0xef, 0x5b, 0xd2, 0x4d, 0xa6, 0x14, 0xb9, 0x01, 0xe9, 0x30,
+    0xd1, 0xf1, 0xcf, 0x05, 0x93, 0xb1, 0x35, 0xdd, 0xa2, 0x6c, 0x99, 0x41,
+    0x37, 0x61, 0xa4, 0x49, 0x72, 0xb2, 0x75, 0xe7, 0x2c, 0x16, 0xd1, 0x9e,
+    0xc3, 0x57, 0x74, 0x23, 0x29, 0x66, 0x3f, 0xd2, 0xa3, 0x0f, 0xfe, 0xda,
+    0xd2, 0xa8, 0x7a, 0xce, 0x18, 0x34, 0x1b, 0x15, 0xf8, 0x7d, 0x07, 0x9e,
+    0x8e, 0x6b, 0x2c, 0x50, 0xa8, 0xfb, 0x81, 0x8e, 0x2b, 0xe5, 0x54, 0xb7,
+    0xc9, 0x17, 0x26, 0xa5, 0xbf, 0x70, 0xf0, 0x45, 0xf0, 0xfb, 0x92, 0x55,
+    0x94, 0x90, 0x53, 0x3a, 0xc3, 0x36, 0x4a, 0xe7, 0xa7, 0xae, 0x9f, 0x76,
+    0x2b, 0x09, 0x12, 0xf2, 0xe6, 0x10, 0x98, 0xf1, 0x6d, 0x9f, 0x4e, 0x5d,
+    0xdf, 0x79, 0x30, 0xf4, 0x1d, 0x6a, 0x21, 0xa0, 0x9b, 0xf7, 0x6c, 0x67,
+    0xa5, 0x62, 0x55, 0x61, 0xa2, 0x31, 0xc9, 0xc9, 0x4b, 0x94, 0xd4, 0x91,
+    0xc1, 0xba, 0xb0, 0x9d, 0x65, 0x68, 0xb9, 0x92, 0xcb, 0xd4, 0x2a, 0x86,
+    0x81, 0x23, 0xff, 0x64, 0x7e, 0x70, 0xce, 0xfc, 0xab, 0x7f, 0x9f, 0xce,
+    0xcb, 0x34, 0xff, 0xe7, 0xbc, 0xbb, 0x65, 0x45, 0x08, 0x7e, 0xc7, 0xa1,
+    0x89, 0x89, 0x9c, 0x85, 0xbf, 0x05, 0x2e, 0x68, 0x7e, 0x33, 0x44, 0x7d,
+    0x4e, 0xdb, 0xed, 0xf5, 0xe3, 0xee, 0x6a, 0x05, 0x11, 0x40, 0xad, 0xf0,
+    0xa4, 0x3a, 0x92, 0xf1, 0x3b, 0x40, 0xa1, 0x61, 0xb9, 0x76, 0xc8, 0xd6,
+    0x77, 0xf9, 0x9e, 0xb5, 0x95, 0x97, 0xdb, 0x1f, 0x5c, 0xbc, 0x31, 0x57,
+    0x5b, 0xf4, 0x2d, 0x9a, 0x68, 0x2b, 0x1b, 0x44, 0xb3, 0xdc, 0xb6, 0x29,
+    0xa5, 0x9a, 0xea, 0xcd, 0x28, 0xb0, 0xcf, 0xbc, 0xbd, 0xaf, 0x68, 0x81,
+    0xd5, 0xd1, 0xfe, 0xb2, 0xd7, 0xfa, 0xd7, 0x76, 0xc8, 0xec, 0x01, 0xc4,
+    0x7f, 0x73, 0xd4, 0x50, 0x30, 0xc6, 0x12, 0x3c, 0x9f, 0xa9, 0x88, 0xe9,
+    0xdb, 0x6e, 0x8d, 0x1e, 0xeb, 0xa0, 0xfa, 0x46, 0x30, 0x2f, 0x84, 0x53,
+    0x24, 0xe4, 0xeb, 0x4d, 0xdb, 0x83, 0xf5, 0x5b, 0x53, 0xc4, 0xeb, 0x02,
+    0x39, 0xb5, 0x7f, 0x7e, 0x30, 0x53, 0x03, 0x48, 0xd3, 0x2f, 0x85, 0xf9,
+    0xf8, 0x25, 0xf4, 0x80, 0x78, 0x7a, 0x7a, 0xf9, 0x95, 0x52, 0xb1, 0xc9,
+    0x6b, 0x75, 0xc2, 0x55, 0x9d, 0xd2, 0xa5, 0x03, 0x54, 0x24, 0xec, 0xf3,
+    0xef, 0x1b, 0x9c, 0xae, 0xde, 0xad, 0xd1, 0x7e, 0x9b, 0xdc, 0x7b, 0x7c,
+    0x1b, 0x9b, 0xae, 0x00, 0x53, 0xba, 0xa0, 0x64, 0xb0, 0x16, 0xa6, 0xc8,
+    0xe0, 0x24, 0xb0, 0xa1, 0x0d, 0xbd, 0xa0, 0x88, 0x49, 0x4d, 0x18, 0xd2,
+    0x3d, 0xf2, 0x82, 0x3e, 0x5e, 0xbf, 0x08, 0x30, 0xa0, 0x6d, 0xa7, 0xd8,
+    0xa5, 0x53, 0xd7, 0xa5, 0xaa, 0x3e, 0x63, 0xcc, 0xeb, 0x16, 0x97, 0xb9,
+    0x2a, 0x4f, 0xcc, 0x92, 0x36, 0x70, 0xb9, 0xf2, 0xd3, 0xf6, 0x45, 0x90,
+    0x41, 0x9e, 0x88, 0xc4, 0x28, 0x4c, 0x28, 0x72, 0x51, 0xdf, 0xd1, 0x97,
+    0xa3, 0xe2, 0xe4, 0xa8, 0x6f, 0x79, 0x38, 0x56, 0x27, 0x17, 0xb5, 0x21,
+    0x60, 0x3a, 0xd9, 0x21, 0x5c, 0x69, 0x41, 0xaa, 0x75, 0xa3, 0x98, 0x6c,
+    0x2e, 0xb3, 0x79, 0xac, 0xd2, 0x16, 0x26, 0x09, 0x26, 0xc0, 0x05, 0x0a,
+    0x6a, 0x60, 0xaf, 0x65, 0x78, 0xb2, 0x3f, 0xcd, 0xa5, 0x3b, 0xda, 0x7b,
+    0x2d, 0x94, 0x66, 0xc1, 0x24, 0x4b, 0x52, 0xd8, 0x6b, 0xa5, 0x14, 0x8b,
+    0xc3, 0x6d, 0xa6, 0x5c, 0xea, 0x4b, 0x32, 0x22, 0xad, 0x1d, 0xf3, 0x6b,
+    0x7c, 0x89, 0xfa, 0xd6, 0xc4, 0x9e, 0x8a, 0x77, 0xef, 0x79, 0xcb, 0x59,
+    0x4f, 0x2c, 0x3b, 0xba, 0xbd, 0xd9, 0xb3, 0x9d, 0x91, 0x29, 0xd5, 0xf6,
+    0x57, 0xf8, 0x39, 0x7a, 0xf0, 0x0f, 0x1a, 0x89, 0xcb, 0xcb, 0x22, 0x15,
+    0x08, 0x6d, 0xca, 0x01, 0x8a, 0x15, 0xb3, 0x47, 0xe6, 0x23, 0x7c, 0xe6,
+    0xec, 0x10, 0xdc, 0x70, 0x16, 0xec, 0x53, 0x39, 0x1d, 0x77, 0x07, 0x8b,
+    0xbf, 0x8b, 0x85, 0x92, 0x82, 0x3b, 0xf5, 0xe2, 0x8c, 0x80, 0x28, 0x4c,
+    0xb8, 0x1e, 0xca, 0x57, 0x76, 0x95, 0xeb, 0x97, 0xfd, 0x3d, 0x47, 0x9a,
+    0xf8, 0x3e, 0x0e, 0xda, 0xb2, 0x41, 0x09, 0xa8, 0x26, 0x1f, 0x11, 0x80,
+    0xde, 0x18, 0xa5, 0x5c, 0x07, 0x54, 0x57, 0xe3, 0xd5, 0x3e, 0x3f, 0x78,
+    0x3f, 0x5b, 0x2d, 0x77, 0x69, 0x15, 0x0b, 0xd6, 0x8c, 0xbc, 0x98, 0xf2,
+    0x86, 0x53, 0x0b, 0x91, 0x46, 0x87, 0x03, 0xfc, 0x05, 0x7f, 0x5b, 0x40,
+    0x39, 0xa8, 0xe7, 0xbf, 0xe6, 0x18, 0x09, 0xd5, 0x91, 0xa9, 0xec, 0x06,
+    0x1f, 0x85, 0xc5, 0xf7, 0x94, 0xbe, 0x72, 0x03, 0x2e, 0xaa, 0xbc, 0xbb,
+    0x4e, 0x8d, 0xfd, 0x27, 0x7c, 0xb4, 0x09, 0x63, 0x8d, 0xca, 0x33, 0x9e,
+    0x51, 0xc3, 0xa3, 0x5c, 0xcd, 0x02, 0xe0, 0x62, 0x60, 0x53, 0xf2, 0x7f,
+    0x4a, 0xa9, 0xcb, 0x46, 0xc1, 0xaf, 0x0e, 0x5e, 0x3f, 0xa9, 0x72, 0x14,
+    0x99, 0x30, 0x0a, 0x81, 0x5c, 0xf3, 0x13, 0xbc, 0x61, 0xf2, 0xf5, 0x6d,
+    0x89, 0xc1, 0x6f, 0x48, 0xeb, 0x43, 0xc3, 0x48, 0xcf, 0xb7, 0x18, 0x36,
+    0x88, 0x9e, 0x1b, 0xc0, 0x1f, 0xa7, 0xea, 0x95, 0x12, 0xd3, 0x07, 0x4d,
+    0xc6, 0xad, 0xb7, 0xef, 0x6c, 0x59, 0xb3, 0xee, 0x04, 0xec, 0x4b, 0xff,
+    0x4a, 0xcc, 0x7c, 0x33, 0x7d, 0x8b, 0xd3, 0x29, 0x31, 0x77, 0xbd, 0x73,
+    0x1e, 0x10, 0x53, 0x5a, 0x79, 0x70, 0xca, 0xb5, 0x9f, 0x20, 0x0b, 0x0b,
+    0x31, 0xd5, 0x5d, 0xd9, 0x2b, 0x4a, 0xc4, 0x87, 0x55, 0xd9, 0xaa, 0x2e,
+    0x8b, 0x65, 0xb0, 0xf4, 0x06, 0xc7, 0xf2, 0x9a, 0xa0, 0x65, 0xcc, 0x30,
+    0x24, 0x8d, 0x1a, 0x61, 0x3f, 0xc7, 0x72, 0x3c, 0xf3, 0x17, 0xff, 0x0a,
+    0x58, 0x82, 0xcf, 0x42, 0x96, 0x49, 0x67, 0x55, 0x79, 0x15, 0x12, 0x96,
+    0xfa, 0x28, 0xfe, 0x77, 0xfc, 0x8f, 0x30, 0x96, 0x03, 0xf6, 0x79, 0x03,
+    0x38, 0x49, 0x70, 0x48, 0x5c, 0xb8, 0x8e, 0x65, 0x67, 0xe1, 0x85, 0x6b,
+    0x70, 0x3c, 0x69, 0xd0, 0x43, 0x0f, 0x4b, 0xa4, 0x04, 0x06, 0xd8, 0xec,
+    0x26, 0xea, 0xac, 0xd5, 0xd9, 0x6c, 0x8b, 0xb4, 0x13, 0xd0, 0x07, 0xd3,
+    0x41, 0x28, 0xa7, 0xbf, 0x0c, 0xe4, 0x5b, 0xa9, 0xb7, 0x3d, 0x2d, 0x5d,
+    0x10, 0xbc, 0xbe, 0xa8, 0x26, 0xe0, 0x0a, 0x92, 0xae, 0xc2, 0x80, 0xd1,
+    0x85, 0x94, 0x0e, 0x78, 0x24, 0xd6, 0xd5, 0x11, 0x87, 0xa3, 0xd4, 0x3c,
+    0x63, 0x49, 0x12, 0x64, 0x3e, 0xee, 0xd9, 0x79, 0x2b, 0x84, 0xa1, 0x08,
+    0x07, 0xcc, 0xa8, 0xc2, 0x8b, 0x91, 0x4c, 0xad, 0x39, 0x1b, 0xb7, 0x1d,
+    0xa1, 0x22, 0x1a, 0x60, 0x5a, 0x5b, 0x9b, 0x5f, 0x5b, 0x10, 0x46, 0x25,
+    0x34, 0xe1, 0x3f, 0x6c, 0xc2, 0xd9, 0xab, 0x32, 0x73, 0xa4, 0xde, 0xf1,
+    0x34, 0x05, 0x04, 0x0a, 0x4c, 0x05, 0xa8, 0x7e, 0xad, 0x1d, 0x98, 0x50,
+    0xf9, 0x11, 0xe1, 0x9a, 0x90, 0x7b, 0x3c, 0x39, 0xf9, 0x2d, 0x98, 0x28,
+    0x9e, 0xf5, 0xc4, 0xa5, 0xc9, 0x4d, 0xa5, 0x74, 0xaf, 0x2f, 0x03, 0x97,
+    0xd5, 0x20, 0x81, 0x40, 0xf3, 0x3e, 0x67, 0x18, 0xb9, 0x98, 0x57, 0xee,
+    0xc0, 0x8e, 0x9b, 0x21, 0x4a, 0x87, 0xc2, 0x21, 0x9b, 0x42, 0xf7, 0xd1,
+    0x51, 0x81, 0x23, 0x6c, 0x06, 0xa0, 0xcc, 0x09, 0x15, 0x1a, 0xa6, 0x7b,
+    0xe9, 0xbe, 0x9f, 0xac, 0x8b, 0x08, 0x8b, 0xb8, 0xa3, 0x7d, 0x04, 0xb0,
+    0xc0, 0x49, 0x62, 0x85, 0x7e, 0xb7, 0xd0, 0x3d, 0x1d, 0x78, 0xfc, 0x6a,
+    0x76, 0xfb, 0x5c, 0x60, 0x22, 0xe4, 0xec, 0x09, 0xe0, 0x40, 0xde, 0x03,
+    0xe5, 0xb1, 0x5e, 0xd7, 0x06, 0xc7, 0x06, 0xf6, 0x6c, 0x66, 0x4b, 0xb6,
+    0x72, 0xaf, 0x59, 0xd7, 0x04, 0x34, 0xee, 0x64, 0xbe, 0x1b, 0xd2, 0xdf,
+    0x74, 0x20, 0x05, 0xc8, 0x83, 0xf2, 0xfd, 0x62, 0xb4, 0xb6, 0x85, 0x46,
+    0x14, 0x33, 0x23, 0x1d, 0xcc, 0xd3, 0x4b, 0x37, 0x96, 0xe4, 0x04, 0xb5,
+    0x92, 0x0c, 0x6f, 0x52, 0xc9, 0xe2, 0xe7, 0xb2, 0xca, 0x01, 0x9e, 0xc6,
+    0x51, 0x7a, 0x9e, 0xce, 0xb2, 0x76, 0xf8, 0x74, 0xa2, 0x4c, 0xaa, 0x66,
+    0x9a, 0x7d, 0x64, 0x24, 0x4f, 0xe3, 0x33, 0xa4, 0xca, 0x26, 0xdd, 0x24,
+    0xf0, 0xd0, 0x38, 0xf3, 0x81, 0x0a, 0xf1, 0x06, 0xd7, 0x07, 0xe9, 0x1a,
+    0x85, 0x98, 0x9d, 0x3e, 0xb3, 0x80, 0x9d, 0xaf, 0xeb, 0x48, 0xee, 0xee,
+    0x04, 0x6c, 0xb1, 0x6a, 0x81, 0x97, 0x26, 0x14, 0x60, 0x16, 0xfd, 0x0e,
+    0x6a, 0xda, 0xb6, 0x0e, 0xff, 0xd5, 0x6c, 0x65, 0x1c, 0xd1, 0xe2, 0xfa,
+    0xcc, 0x75, 0x6c, 0xb6, 0x10, 0x03, 0x5d, 0x41, 0xe6, 0x47, 0x95, 0x43,
+    0xa5, 0x7a, 0xd1, 0xc5, 0xc5, 0xd9, 0xdd, 0x7f, 0x6c, 0xcb, 0x4d, 0x9c,
+    0x77, 0x04, 0x57, 0x74, 0x90, 0x08, 0x03, 0x5f, 0x3a, 0xb1, 0x08, 0x3f,
+    0x64, 0xaa, 0x7c, 0x75, 0x9e, 0xfa, 0x14, 0x8b, 0x3c, 0x76, 0xba, 0x20,
+    0x8b, 0x9b, 0xee, 0x4d, 0xf1, 0x3a, 0x79, 0xdc, 0x97, 0xe6, 0x14, 0x28,
+    0xee, 0x8b, 0xa4, 0x55, 0x9d, 0xe8, 0x08, 0x83, 0xa9, 0x27, 0x11, 0xd8,
+    0x24, 0x5d, 0x0e, 0x0a, 0xab, 0x67, 0xfb, 0xd5, 0xda, 0x38, 0x36, 0x7b,
+    0x25, 0x79, 0xef, 0xb1, 0x30, 0x50, 0x36, 0xf7, 0xfa, 0x8d, 0xc0, 0x82,
+    0x7a, 0xec, 0x74, 0xde, 0x7a, 0x9d, 0xe4, 0x46, 0xe9, 0x23, 0x9e, 0xa9,
+    0x90, 0x18, 0x6e, 0xbe, 0xc8, 0x37, 0xc7, 0x47, 0xb3, 0x17, 0x76, 0x2a,
+    0x4a, 0x97, 0x75, 0x42, 0xee, 0x23, 0x7e, 0x98, 0x89, 0xd6, 0x86, 0x09,
+    0x28, 0x9c, 0x24, 0xdf, 0x74, 0xa0, 0x2d, 0x3d, 0x17, 0x27, 0x9b, 0x90,
+    0x51, 0xdd, 0xce, 0xc2, 0xef, 0x4f, 0xce, 0x38, 0x97, 0x69, 0x4e, 0xe9,
+    0xb6, 0xdf, 0x0e, 0x5f, 0xcb, 0x1f, 0x3b, 0x31, 0xaa, 0xbf, 0xc7, 0x10,
+    0x29, 0xea, 0xb7, 0x30, 0x9f, 0x43, 0x7d, 0x37, 0xcd, 0x72, 0x1c, 0x27,
+    0x2b, 0xf7, 0x56, 0x9c, 0x94, 0xe7, 0xc8, 0x1a, 0x2a, 0xad, 0xa1, 0xfe,
+    0x90, 0xe0, 0xdd, 0xb2, 0x75, 0xe4, 0xd9, 0x36, 0x55, 0xed, 0x9f, 0x5d,
+    0x07, 0xa8, 0x5c, 0x63, 0x67, 0x8a, 0x12, 0x35, 0xa1, 0xef, 0x78, 0x85,
+    0xf0, 0x37, 0x6f, 0x37, 0xce, 0x34, 0x75, 0x9a, 0x3c, 0x54, 0xcb, 0x36,
+    0x8f, 0xfc, 0x41, 0x70, 0x23, 0x19, 0xd1, 0x15, 0xb3, 0x6c, 0xc5, 0x0b,
+    0x51, 0x9d, 0xf2, 0x83, 0xc9, 0x4b, 0x62, 0x84, 0x12, 0xba, 0x6b, 0xee,
+    0xd3, 0x4f, 0x80, 0xa7, 0xe3, 0x30, 0x19, 0xe3, 0x20, 0x44, 0xb1, 0x25,
+    0xe2, 0x5a, 0xaa, 0xb0, 0x81, 0x1a, 0x6a, 0x6a, 0xd7, 0xb2, 0xc4, 0x64,
+    0x87, 0x25, 0x7e, 0xe1, 0x5f, 0x82, 0x17, 0x1f, 0xce, 0x1a, 0x2d, 0x04,
+    0x58, 0xad, 0x5f, 0x2a, 0x3d, 0xd2, 0xb8, 0xa9, 0xa2, 0x72, 0x19, 0x24,
+    0x8d, 0x1b, 0x04, 0x89, 0x62, 0xf5, 0x6b, 0xdd, 0xb0, 0x66, 0x62, 0x59,
+    0x0d, 0xb3, 0xa9, 0x03, 0x07, 0x11, 0x55, 0x51, 0xfa, 0x14, 0x49, 0x31,
+    0xe6, 0x38, 0x66, 0x79, 0x07, 0xa8, 0xeb, 0xc5, 0x4b, 0x61, 0x8f, 0x59,
+    0xb1, 0x18, 0x55, 0x28, 0x5c, 0x82, 0xff, 0x4a, 0xd3, 0x28, 0x47, 0xcc,
+    0xc1, 0xba, 0xa4, 0xce, 0x2a, 0x9d, 0x28, 0x24, 0x69, 0x28, 0x13, 0x4f,
+    0x06, 0x0f, 0xa3, 0x71, 0x6b, 0x17, 0x7b, 0xf4, 0x2c, 0x6d, 0xdb, 0xcc,
+    0x6c, 0x4e, 0x8a, 0x04, 0x58, 0x20, 0x26, 0x54, 0xf9, 0x4d, 0x7c, 0x67,
+    0xb8, 0x63, 0x55, 0x23, 0x94, 0xe6, 0x3c, 0xf7, 0x11, 0x61, 0x38, 0x9c,
+    0x1a, 0x40, 0x5c, 0x3d, 0xb2, 0x35, 0xde, 0x35, 0x1f, 0x38, 0x48, 0xc5,
+    0x15, 0x59, 0x2f, 0xa7, 0x81, 0xe8, 0x53, 0xe8, 0x46, 0x59, 0x3e, 0xf4,
+    0xc8, 0x01, 0x33, 0xd6, 0xdd, 0xe6, 0xf3, 0xa5, 0x2a, 0x09, 0x54, 0x1a,
+    0x92, 0x37, 0x3e, 0x9f, 0x54, 0xb6, 0x81, 0x5d, 0xf3, 0x74, 0x6b, 0x56,
+    0x01, 0xc9, 0xfd, 0x4b, 0xa5, 0x54, 0x08, 0x27, 0x54, 0x21, 0xb2, 0xad,
+    0x6c, 0x17, 0xdf, 0x4a, 0x29, 0x1e, 0xf8, 0xde, 0xc7, 0x51, 0x59, 0x55,
+    0xa9, 0x3a, 0xf8, 0xe8, 0xa8, 0x56, 0x5c, 0x8a, 0x04, 0xff, 0x51, 0x8c,
+    0x10, 0xd2, 0x22, 0xc7, 0x3b, 0x3c, 0xa4, 0xb1, 0x6d, 0x41, 0xb6, 0xaa,
+    0x5b, 0x24, 0x17, 0x3b, 0x87, 0xb0, 0xa8, 0xd9, 0x93, 0x3f, 0x6b, 0xff,
+    0x56, 0x83, 0xcc, 0x09, 0x5c, 0x15, 0xe8, 0x99, 0xa6, 0x17, 0xc3, 0xef,
+    0xa1, 0x4b, 0xf7, 0x81, 0x7b, 0x62, 0x3a, 0x8a, 0x6a, 0x5c, 0x57, 0x4f,
+    0x6d, 0xf4, 0x79, 0x7f, 0x69, 0xd9, 0xde, 0x40, 0xb8, 0xb0, 0x96, 0x70,
+    0x1c, 0xaf, 0x94, 0xb5, 0x45, 0x02, 0xff, 0xf7, 0x23, 0x04, 0x7e, 0xc0,
+    0xa1, 0x93, 0x2f, 0x9e, 0x7d, 0xc0, 0x81, 0x00, 0x4f, 0xed, 0xb5, 0xaa,
+    0x7c, 0x25, 0x5f, 0x8b, 0x76, 0xd8, 0x45, 0xee, 0xf2, 0x9f, 0xc6, 0xb4,
+    0x0c, 0x08, 0xd8, 0x7d, 0x1f, 0x25, 0xcc, 0x8f, 0x1e, 0x5b, 0xaa, 0x75,
+    0x0b, 0xec, 0x61, 0xcf, 0xe2, 0x08, 0xc1, 0x45, 0x9d, 0x08, 0x7e, 0xc0,
+    0xa8, 0x73, 0xc8, 0x2e, 0xcb, 0xa7, 0x5a, 0x71, 0xce, 0x8f, 0x7f, 0xe6,
+    0xf6, 0x35, 0xe5, 0xcf, 0xac, 0x24, 0xf7, 0x71, 0x18, 0x27, 0x60, 0x3e,
+    0xf8, 0x37, 0x3a, 0x81, 0x66, 0xee, 0x41, 0xf0, 0x72, 0x3b, 0x43, 0x40,
+    0xa2, 0xd7, 0x99, 0x34, 0xda, 0xa3, 0xcc, 0xf4, 0xb7, 0x66, 0xd7, 0xad,
+    0xab, 0x58, 0xee, 0x52, 0xa0, 0xb1, 0xbb, 0xd4, 0x3d, 0x30, 0x6d, 0x31,
+    0xe5, 0xf8, 0x1e, 0xc8, 0x5d, 0x78, 0x35, 0x2a, 0xd5, 0x36, 0xd9, 0x08,
+    0x20, 0x5f, 0x51, 0x07, 0x58, 0x02, 0x5f, 0x3a, 0x81, 0x90, 0x03, 0x35,
+    0x74, 0xb4, 0x87, 0xae, 0x18, 0xe0, 0xeb, 0x73, 0x05, 0x63, 0xf1, 0x42,
+    0x7e, 0x49, 0x26, 0xbd, 0xce, 0x8c, 0xab, 0x18, 0x70, 0xf7, 0x88, 0x22,
+    0xc7, 0x6a, 0xe4, 0x55, 0xab, 0x31, 0x7e, 0xaa, 0x0b, 0x22, 0xff, 0xdd,
+    0x4c, 0x80, 0x1f, 0x94, 0x64, 0xb0, 0x7d, 0x18, 0x69, 0x33, 0xf2, 0xc8,
+    0x0a, 0x2e, 0x33, 0x8a, 0x0f, 0x47, 0x10, 0xeb, 0x6c, 0x5a, 0x6f, 0x4f,
+    0x80, 0xb9, 0x29, 0x9f, 0x88, 0x88, 0x23, 0x75, 0x1e, 0xb8, 0xad, 0x76,
+    0x75, 0x3a, 0x18, 0xbb, 0x9d, 0x92, 0x76, 0x53, 0x5b, 0x6d, 0x5b, 0x7a,
+    0xc4, 0x34, 0x1c, 0x6e, 0xc7, 0xb4, 0x24, 0x7c, 0xd8, 0x27, 0x47, 0x74,
+    0xb5, 0xf5, 0x5f, 0xcb, 0x90, 0x54, 0x00, 0x8e, 0xdd, 0xe1, 0x81, 0xf0,
+    0xbb, 0xc5, 0xf9, 0x7d, 0x28, 0x07, 0x8d, 0xb2, 0x9b, 0x0c, 0x56, 0x80,
+    0xa7, 0xa7, 0x2f, 0x84, 0x9a, 0xef, 0x70, 0xa9, 0x92, 0x40, 0xcc, 0xf9,
+    0xd5, 0xee, 0xbe, 0x65, 0x8a, 0x79, 0xc8, 0xfb, 0x31, 0x4b, 0x6f, 0x79,
+    0xfc, 0xc9, 0x52, 0x47, 0x38, 0xb9, 0x36, 0x08, 0xe7, 0xab, 0xb4, 0x60,
+    0xe6, 0x9d, 0xc8, 0xb6, 0x77, 0x28, 0x53, 0x62, 0x70, 0x8a, 0x9a, 0xe1,
+    0xbb, 0xc0, 0xa9, 0xae, 0x4f, 0xd5, 0x1b, 0x96, 0xdc, 0x7e, 0x8c, 0x4d,
+    0x96, 0xe2, 0x23, 0x15, 0xaa, 0x6c, 0xf2, 0xca, 0x42, 0xae, 0xb8, 0xfa,
+    0xea, 0x69, 0xcf, 0xe2, 0xcb, 0x95, 0x87, 0xa9, 0xfa, 0x27, 0x28, 0xdb,
+    0xa4, 0xa2, 0xb2, 0x89, 0x6c, 0x8a, 0x8b, 0x70, 0x9c, 0xae, 0x45, 0xb1,
+    0xce, 0x2a, 0xf4, 0x09, 0xeb, 0x52, 0x55, 0x67, 0xb8, 0x48, 0x60, 0xe2,
+    0xae, 0x6d, 0x5b, 0x6f, 0xa4, 0x43, 0x08, 0xb6, 0x0b, 0x76, 0xce, 0x3c,
+    0xbf, 0xb3, 0xc6, 0x09, 0x67, 0x18, 0xe6, 0x81, 0xea, 0x41, 0x13, 0x74,
+    0x4a, 0x07, 0x95, 0x1f, 0xdb, 0x06, 0xa6, 0x45, 0x28, 0x0a, 0x65, 0x0e,
+    0x4a, 0x4a, 0x55, 0x18, 0x9e, 0x0d, 0x22, 0x6c, 0xdb, 0x58, 0xde, 0x8f,
+    0x5d, 0x56, 0xd3, 0xdf, 0xdc, 0xb9, 0x3c, 0x9e, 0xc9, 0xe5, 0x9a, 0xb1,
+    0x33, 0xca, 0x09, 0x18, 0x89, 0x94, 0x08, 0xad, 0xa8, 0xc4, 0x97, 0x23,
+    0x6c, 0xc4, 0x06, 0x44, 0xd7, 0xa2, 0x94, 0x88, 0x60, 0xfe, 0x56, 0x0e,
+    0xd4, 0x71, 0xd8, 0xd5, 0xbf, 0x3d, 0x50, 0x92, 0xc4, 0x4a, 0xf0, 0x74,
+    0x79, 0x70, 0x11, 0xaa, 0x49, 0xb7, 0x18, 0x83, 0xf7, 0xe6, 0x1b, 0x53,
+    0xcd, 0x39, 0xf6, 0xe8, 0xed, 0x93, 0xa4, 0x36, 0xb9, 0x74, 0xee, 0x80,
+    0x67, 0x0b, 0xa9, 0xd6, 0x0c, 0x8e, 0xdc, 0x54, 0x32, 0x81, 0x27, 0x95,
+    0x9c, 0x5b, 0x5a, 0x44, 0x99, 0x0d, 0xb8, 0x89, 0xb0, 0xef, 0x01, 0x42,
+    0x92, 0x6f, 0xb1, 0x28, 0x81, 0x5b, 0xd8, 0xd0, 0x54, 0xcf, 0x90, 0x4c,
+    0xc7, 0x6c, 0xd3, 0x8b, 0x0f, 0xf4, 0x34, 0xca, 0x6e, 0xb0, 0x4e, 0xe8,
+    0xb8, 0x1c, 0x14, 0x63, 0x91, 0x94, 0x3e, 0xcc, 0xa8, 0xbc, 0xb4, 0x28,
+    0xb3, 0x78, 0x6b, 0xe3, 0x98, 0xfe, 0x80, 0xe8, 0xd9, 0xd7, 0x42, 0xd0,
+    0x36, 0x1b, 0x3a, 0x22, 0xd3, 0x25, 0x64, 0x37, 0xb2, 0xa7, 0x56, 0x41,
+    0xa0, 0xf3, 0xb3, 0x7f, 0x11, 0x0c, 0x0f, 0x41, 0x44, 0x92, 0xa5, 0xeb,
+    0xf6, 0xd4, 0x56, 0x19, 0x41, 0xd4, 0x7e, 0x57, 0x57, 0xa3, 0xb6, 0x12,
+    0x1d, 0xaf, 0xa6, 0xab, 0x62, 0xc3, 0x5d, 0x74, 0x4f, 0x44, 0xe1, 0xdc,
+    0xcc, 0x45, 0xbd, 0x34, 0xce, 0x2e, 0x60, 0xcb, 0x21, 0x7d, 0x8b, 0xd8,
+    0xfe, 0xbc, 0xdc, 0x2e, 0x72, 0xb8, 0xa7, 0x0e, 0x2f, 0x79, 0xc9, 0xc2,
+    0xf7, 0xf1, 0xd4, 0xf4, 0x36, 0xec, 0x53, 0x31, 0x79, 0x18, 0x85, 0xa3,
+    0xb4, 0xb0, 0x0e, 0xc1, 0xc9, 0x41, 0xdb, 0x7a, 0x7f, 0xd2, 0x34, 0x35,
+    0x5c, 0x4b, 0x52, 0x83, 0x80, 0xe6, 0xf2, 0x18, 0x6f, 0xae, 0x37, 0x8c,
+    0x95, 0x38, 0x8b, 0x44, 0x8d, 0x22, 0x84, 0xd1, 0xd5, 0xc1, 0x01, 0x9c,
+    0xf0, 0x56, 0x8e, 0x48, 0x5d, 0xab, 0x2d, 0x70, 0x6a, 0x29, 0xca, 0x91,
+    0x0c, 0x03, 0xaa, 0xaf, 0x8c, 0x28, 0xd2, 0x97, 0x4a, 0x60, 0xac, 0xf4,
+    0x9c, 0x26, 0xc3, 0xe8, 0x7d, 0xac, 0xc0, 0xc8, 0xe4, 0xf4, 0xad, 0x94,
+    0x01, 0xcc, 0x5f, 0x13, 0x83, 0x3a, 0x2c, 0xf2, 0xc8, 0xc0, 0xc6, 0x7d,
+    0x1a, 0x00, 0x54, 0x7e, 0xee, 0xa1, 0xb0, 0x33, 0x21, 0x7f, 0x3f, 0x45,
+    0xff, 0xdb, 0x6e, 0x9d, 0xca, 0x65, 0xe0, 0x60, 0x8f, 0x40, 0x56, 0x91,
+    0x57, 0x75, 0x83, 0x8d, 0xd4, 0x03, 0x4a, 0x60, 0x0e, 0x46, 0x27, 0x02,
+    0x4e, 0x9d, 0xfb, 0xfe, 0xf2, 0xbe, 0x44, 0xa2, 0x8a, 0xc3, 0x2e, 0x46,
+    0x29, 0x59, 0x8d, 0xb9, 0x61, 0x5a, 0x18, 0x96, 0x1b, 0xaa, 0x7a, 0xea,
+    0x45, 0xfe, 0x93, 0x17, 0xb8, 0xb8, 0x6c, 0x42, 0xb3, 0xc8, 0xf5, 0x70,
+    0xe3, 0x98, 0x46, 0xf4, 0x73, 0x61, 0x32, 0xee, 0x8e, 0xb1, 0x9f, 0x12,
+    0xf5, 0xeb, 0xf3, 0xb7, 0xbc, 0x94, 0x32, 0xa5, 0xc4, 0xd0, 0x60, 0x95,
+    0x0d, 0xd8, 0x11, 0x15, 0xad, 0xde, 0xea, 0xb5, 0xcb, 0xdb, 0x27, 0xe4,
+    0x0f, 0x55, 0x1f, 0x65, 0xff, 0x02, 0xa3, 0xb8, 0xfb, 0x38, 0xe9, 0x7e,
+    0x3d, 0x1f, 0xb9, 0xce, 0x06, 0xa2, 0x57, 0xca, 0x7a, 0xd9, 0x18, 0x90,
+    0xef, 0xc3, 0x52, 0x50, 0xfc, 0xa6, 0xbf, 0x84, 0x7b, 0x8e, 0xd8, 0xf7,
+    0x9c, 0x6a, 0x53, 0xc9, 0x10, 0x81, 0x9c, 0xd4, 0x67, 0xef, 0x1c, 0xd2,
+    0x58, 0x86, 0x66, 0x45, 0x00, 0x26, 0x78, 0x11, 0x61, 0x53, 0xce, 0x50,
+    0xda, 0x0c, 0xd4, 0x1b, 0xf7, 0xa4, 0xda, 0xab, 0xe2, 0x93, 0xed, 0x8b,
+    0x34, 0x42, 0x3a, 0xf4, 0xae, 0x3d, 0x46, 0x86, 0xea, 0xae, 0x5f, 0xc2,
+    0x5a, 0xd8, 0xed, 0x63, 0xc4, 0xd6, 0x51, 0x57, 0x81, 0xea, 0x59, 0x68,
+    0xf4, 0x58, 0x8c, 0x02, 0xfc, 0xe9, 0x0a, 0x96, 0xa7, 0x29, 0xac, 0xaf,
+    0xf2, 0x39, 0x17, 0xc8, 0xe0, 0x6e, 0x2a, 0x6d, 0x21, 0xb8, 0xf4, 0xe9,
+    0x02, 0xd7, 0xbf, 0xc7, 0xf6, 0x09, 0xa0, 0x67, 0x6c, 0x98, 0x83, 0xba,
+    0x7b, 0x71, 0x4a, 0xea, 0x3d, 0x89, 0x0a, 0x0e, 0x86, 0x6b, 0xa0, 0x25,
+    0xf1, 0x3a, 0xa3, 0x66, 0x54, 0xff, 0x83, 0x2b, 0xca, 0x1f, 0x74, 0x1d,
+    0x31, 0x93, 0xfc, 0x84, 0xcd, 0x3c, 0xc9, 0xf0, 0x7e, 0x39, 0xb7, 0x95,
+    0xf7, 0xa9, 0x9c, 0x67, 0xcf, 0x10, 0x0f, 0xef, 0xc7, 0xce, 0x6b, 0x46,
+    0x4c, 0x2a, 0x07, 0xb4, 0x24, 0xc4, 0x0a, 0x66, 0xaa, 0x35, 0xbb, 0xe9,
+    0xe5, 0xcf, 0xd4, 0x19, 0x6b, 0x37, 0x56, 0x54, 0x34, 0x73, 0xd2, 0x63,
+    0x5f, 0x43, 0xb7, 0x6b, 0xa7, 0x6f, 0x96, 0x2a, 0x58, 0xfc, 0xcd, 0x4d,
+    0x8c, 0x15, 0x6c, 0x4c, 0x28, 0x8b, 0x68, 0xd1, 0xa1, 0x73, 0xb2, 0x72,
+    0xa8, 0x42, 0x82, 0x2f, 0x2c, 0xa3, 0xff, 0x02, 0x4d, 0x84, 0xce, 0xb6,
+    0x13, 0x7b, 0xd3, 0x7a, 0xdc, 0x62, 0xe1, 0xdc, 0xdb, 0x6b, 0xb0, 0x08,
+    0x69, 0xe6, 0xbc, 0x53, 0xb2, 0xb0, 0xf7, 0x57, 0xe9, 0x7f, 0x52, 0x97,
+    0xcc, 0xbd, 0x65, 0x65, 0x77, 0xe0, 0x0a, 0x5a, 0xb0, 0xbb, 0xc7, 0x6e,
+    0x11, 0x4a, 0x0b, 0x62, 0x0c, 0x9d, 0xaa, 0xff, 0x82, 0x1f, 0x0c, 0xd9,
+    0xe4, 0xf1, 0x9c, 0x32, 0x9d, 0xdf, 0x48, 0xde, 0x14, 0xe9, 0xb1, 0x00,
+    0xd9, 0xb4, 0xd4, 0xb5, 0xd4, 0x45, 0x59, 0xd6, 0x55, 0x8a, 0x28, 0xc6,
+    0xf7, 0xdc, 0xe3, 0x73, 0x77, 0xec, 0xc0, 0xfa, 0x02, 0x0b, 0xd6, 0x62,
+    0x87, 0x58, 0xfe, 0x3c, 0x2c, 0x8b, 0x2a, 0xaf, 0x58, 0x33, 0x93, 0x91,
+    0x61, 0x9e, 0xf6, 0x35, 0x54, 0x70, 0x84, 0x22, 0x96, 0x64, 0x71, 0xd4,
+    0xde, 0x8a, 0x18, 0xd5, 0x43, 0xa7, 0x6e, 0x31, 0xb2, 0x9f, 0x88, 0x41,
+    0x93, 0x7d, 0x4e, 0x61, 0x17, 0x39, 0xe7, 0x1f, 0x4f, 0xa2, 0x21, 0x40,
+    0x2d, 0x2b, 0x56, 0xb4, 0xbd, 0xf7, 0x7c, 0xef, 0x0a, 0x70, 0xa8, 0x56,
+    0x71, 0x87, 0x6a, 0x26, 0xb9, 0xfe, 0xba, 0x9c, 0x72, 0x74, 0x7a, 0x8b,
+    0xa3, 0xaa, 0x0e, 0x19, 0x29, 0x2d, 0x84, 0x8c, 0xa7, 0xd2, 0xd4, 0x27,
+    0x30, 0x3b, 0x67, 0xb5, 0xb7, 0xc3, 0x02, 0x17, 0x30, 0x3b, 0x47, 0x6e,
+    0xc2, 0xf3, 0xf7, 0xfd, 0x41, 0x76, 0x99, 0xec, 0x92, 0xb8, 0xbd, 0xf3,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x06, 0x0f, 0x16, 0x20, 0x24, 0x28};
+const uint8_t kExpectedCase2Signature[BCM_MLDSA65_SIGNATURE_BYTES] = {
+    0xef, 0xbf, 0xd8, 0x29, 0xd3, 0x48, 0xaf, 0x86, 0x0d, 0xe5, 0x31, 0xde,
+    0xfc, 0xe8, 0x90, 0xc3, 0x1d, 0x9a, 0xda, 0x49, 0xd4, 0xb2, 0xab, 0x5e,
+    0x19, 0x8e, 0x31, 0x6f, 0x73, 0x3f, 0x7f, 0x77, 0xf8, 0xda, 0x71, 0x90,
+    0xf9, 0xad, 0x47, 0xdd, 0x9f, 0xed, 0xb9, 0x79, 0xbc, 0x70, 0xf7, 0x80,
+    0x43, 0xa1, 0xf1, 0x68, 0x71, 0x25, 0x05, 0x54, 0x1f, 0x91, 0xc3, 0xd9,
+    0xc1, 0xad, 0xbc, 0xb9, 0xa2, 0xd9, 0x80, 0x8d, 0xf4, 0xe4, 0xd2, 0xa6,
+    0x63, 0x6b, 0x94, 0x5f, 0x16, 0xf4, 0xe1, 0xe6, 0x28, 0x6d, 0x8a, 0xb9,
+    0x58, 0x72, 0xb7, 0xda, 0x42, 0xbd, 0xa7, 0xaa, 0x85, 0x72, 0x1e, 0xa6,
+    0xe9, 0xf0, 0x57, 0x13, 0x98, 0x13, 0x88, 0x23, 0x81, 0x41, 0xe4, 0x8b,
+    0x8b, 0x77, 0x50, 0x98, 0x20, 0x28, 0xc5, 0x0b, 0x66, 0x16, 0x3b, 0xad,
+    0xf5, 0xf4, 0xd5, 0xe7, 0xe5, 0x99, 0xab, 0x21, 0x9b, 0x0f, 0xbd, 0x02,
+    0x4c, 0x46, 0x25, 0xc4, 0x2f, 0x14, 0x35, 0x52, 0x12, 0x70, 0xe3, 0x22,
+    0xa9, 0xa1, 0x99, 0x44, 0x40, 0xeb, 0xb3, 0x8d, 0xc7, 0xec, 0x42, 0x55,
+    0x10, 0xe9, 0x6b, 0xbb, 0x20, 0xb7, 0x1d, 0xc4, 0x23, 0x11, 0x91, 0x2b,
+    0x41, 0x3c, 0xc7, 0xe2, 0xda, 0xdf, 0xb6, 0x0a, 0xac, 0x43, 0x2e, 0xfe,
+    0x6e, 0x01, 0x8f, 0xb7, 0x75, 0x4f, 0xa6, 0x2e, 0x1e, 0xff, 0x04, 0xfe,
+    0x06, 0x73, 0xed, 0xba, 0x96, 0xad, 0x9f, 0xff, 0xb1, 0xea, 0x89, 0xfa,
+    0x9f, 0xc9, 0xae, 0x26, 0x68, 0xec, 0xe3, 0x93, 0xaa, 0x35, 0xe6, 0xc6,
+    0x1b, 0x99, 0xf3, 0xc1, 0xef, 0x8f, 0x56, 0xf4, 0xd9, 0x1f, 0xf3, 0xe0,
+    0x96, 0xe3, 0x77, 0x76, 0x90, 0xbc, 0xba, 0xcf, 0x3f, 0x2b, 0x24, 0xda,
+    0x48, 0xf5, 0x7f, 0x1d, 0x58, 0xe9, 0x69, 0x3c, 0xd6, 0x0b, 0x21, 0x7f,
+    0xad, 0x7e, 0xc7, 0xce, 0x08, 0x52, 0x6c, 0x7a, 0xb9, 0xaf, 0xdb, 0x4f,
+    0xc4, 0x56, 0x05, 0x3a, 0x3d, 0x94, 0xa0, 0xdc, 0x92, 0x14, 0x20, 0x3c,
+    0xf1, 0x2a, 0xf7, 0x9f, 0xab, 0x6f, 0x1b, 0x7a, 0xb1, 0x0e, 0x7d, 0x72,
+    0xdc, 0x65, 0xb1, 0x10, 0xa5, 0x1f, 0x83, 0x9d, 0x4c, 0x2a, 0x37, 0x4a,
+    0x0d, 0xaa, 0xd4, 0x35, 0x13, 0x3e, 0x68, 0x24, 0x12, 0x31, 0x80, 0xbc,
+    0x9a, 0x1d, 0x4a, 0xea, 0x31, 0x50, 0x7d, 0x57, 0x95, 0x56, 0x3c, 0x6a,
+    0x5e, 0xbf, 0x82, 0x47, 0x53, 0x5d, 0x38, 0xce, 0x2b, 0xac, 0x03, 0xe6,
+    0x50, 0xfd, 0x6a, 0x6a, 0xbb, 0x79, 0x83, 0xee, 0xe2, 0x10, 0xef, 0xb1,
+    0xc1, 0x2b, 0x01, 0x9d, 0xdc, 0xae, 0x2d, 0xaf, 0x18, 0x48, 0x6d, 0xd2,
+    0x00, 0x62, 0x96, 0x9e, 0x9d, 0xf9, 0x1e, 0xa5, 0xbc, 0x8e, 0x5f, 0x10,
+    0x08, 0x63, 0x87, 0x8d, 0x18, 0x4f, 0xd3, 0x8f, 0x99, 0xa7, 0xb6, 0x80,
+    0x4d, 0xf2, 0x44, 0x22, 0x0b, 0x2e, 0x5c, 0x78, 0x36, 0x93, 0xcb, 0x68,
+    0x17, 0x00, 0xfc, 0x85, 0x89, 0xd4, 0x3b, 0x1e, 0xed, 0x69, 0xa8, 0xa3,
+    0x3d, 0xd1, 0x79, 0x7d, 0x18, 0xd8, 0xea, 0xde, 0xf8, 0x4f, 0xd7, 0x82,
+    0x84, 0x3e, 0x57, 0xf7, 0x6e, 0x6c, 0x7a, 0xd7, 0xa2, 0x35, 0x9b, 0xe0,
+    0x81, 0xfb, 0xcf, 0x3e, 0xd5, 0xbf, 0x13, 0x25, 0x9d, 0x1e, 0x0d, 0x85,
+    0x69, 0x17, 0xbc, 0x45, 0xfd, 0xe1, 0xb9, 0x1c, 0xbb, 0x48, 0x46, 0x9d,
+    0x4e, 0x99, 0x0c, 0x8c, 0xba, 0xb0, 0x3d, 0x6f, 0x6d, 0xea, 0x62, 0xb4,
+    0x70, 0xfb, 0xf9, 0xae, 0x20, 0x44, 0xfc, 0x5d, 0x61, 0xce, 0x7d, 0x1b,
+    0x44, 0xae, 0x20, 0xee, 0x0f, 0x9f, 0xaa, 0xa1, 0x3e, 0x6b, 0x53, 0xb4,
+    0x2e, 0x44, 0x2b, 0xdc, 0x83, 0xa5, 0x2a, 0xd5, 0xda, 0x23, 0x10, 0xbf,
+    0x3f, 0xb1, 0x3b, 0xa8, 0x0f, 0x01, 0x06, 0xcd, 0xff, 0x01, 0x3e, 0x33,
+    0x98, 0xb8, 0xf7, 0x26, 0x31, 0x19, 0x07, 0x96, 0x83, 0x94, 0x67, 0x70,
+    0xac, 0xeb, 0xb1, 0x2f, 0x42, 0x63, 0x36, 0xf2, 0xf4, 0x13, 0x61, 0x72,
+    0x3e, 0x70, 0xbb, 0xfe, 0xe5, 0x11, 0xc5, 0x77, 0x2f, 0xa2, 0x12, 0xa3,
+    0x19, 0xff, 0xea, 0x9c, 0xf2, 0xcf, 0x6a, 0x49, 0x09, 0x00, 0x54, 0x1e,
+    0xae, 0x8c, 0xb3, 0xfe, 0x12, 0x68, 0x24, 0x04, 0x7c, 0x48, 0x84, 0x29,
+    0xb3, 0x5f, 0x71, 0x45, 0xc7, 0x62, 0xcf, 0xaf, 0xca, 0xe2, 0x8c, 0xd5,
+    0xb5, 0xc9, 0x82, 0x69, 0x98, 0x0d, 0x16, 0x58, 0x31, 0xb3, 0x38, 0x68,
+    0x20, 0x82, 0xd5, 0x51, 0xb6, 0xb3, 0x57, 0xb0, 0xa6, 0x7c, 0x6d, 0xf3,
+    0x82, 0x85, 0xc6, 0xf2, 0x06, 0x67, 0x40, 0x4f, 0x0c, 0x58, 0xfb, 0xc2,
+    0xa2, 0x73, 0x00, 0x38, 0x00, 0xcc, 0x70, 0x93, 0x6d, 0x6c, 0x3b, 0xd4,
+    0x4f, 0xcf, 0xb5, 0x1a, 0x26, 0x4e, 0xdb, 0x43, 0xf1, 0x02, 0x9c, 0xe9,
+    0xe6, 0x0d, 0x1b, 0xa2, 0xae, 0xaf, 0xee, 0x48, 0x21, 0x50, 0x9c, 0xfe,
+    0xe7, 0xa1, 0x0a, 0x14, 0xf2, 0x59, 0x15, 0x04, 0xd1, 0x8f, 0x37, 0xfa,
+    0x22, 0x7c, 0xe0, 0x91, 0x83, 0xc8, 0x5d, 0x10, 0xcc, 0xaa, 0x38, 0x03,
+    0x4b, 0xb4, 0xee, 0xea, 0x7b, 0x1b, 0x9a, 0xfd, 0x92, 0x1b, 0x35, 0x5a,
+    0x0e, 0xa9, 0xfe, 0xa9, 0x11, 0x42, 0xc1, 0xc9, 0x3d, 0xb8, 0x06, 0xcb,
+    0x39, 0x59, 0xb0, 0xb2, 0xf2, 0x2d, 0x25, 0x98, 0xf5, 0xde, 0x94, 0xd3,
+    0x9e, 0xcd, 0x39, 0xbc, 0x6a, 0xae, 0x85, 0x62, 0x36, 0x33, 0x7b, 0xe1,
+    0x2f, 0x0f, 0x77, 0x25, 0x7a, 0xe1, 0x88, 0xb4, 0xcb, 0x6a, 0x5f, 0x2a,
+    0x15, 0x02, 0x0b, 0xbd, 0xe2, 0x0c, 0x7b, 0xeb, 0x15, 0xe3, 0x02, 0xd9,
+    0x56, 0x78, 0xcb, 0x71, 0x07, 0xc9, 0x40, 0xa6, 0xe3, 0x96, 0x79, 0xa2,
+    0xb3, 0xe5, 0xe0, 0xfe, 0x78, 0xf8, 0xa1, 0x2a, 0x5d, 0xa8, 0x5d, 0x43,
+    0x08, 0x52, 0xf1, 0xcd, 0x4e, 0x13, 0xc5, 0x85, 0x8d, 0x81, 0xa3, 0x18,
+    0x1a, 0x23, 0x03, 0x85, 0xf4, 0x13, 0x60, 0xf5, 0x31, 0x02, 0xfb, 0xb9,
+    0x6c, 0xe5, 0x06, 0x6b, 0xf3, 0x78, 0xf9, 0x03, 0x9c, 0x62, 0xf1, 0xcc,
+    0xeb, 0xe5, 0x97, 0xe8, 0xf7, 0xb2, 0x70, 0xbd, 0xca, 0x37, 0x7c, 0x15,
+    0xa3, 0x2f, 0xce, 0x0b, 0xb8, 0xd2, 0xd7, 0x9d, 0xea, 0x96, 0xc7, 0x49,
+    0xf6, 0xc1, 0x21, 0x7b, 0x7c, 0x41, 0x48, 0x71, 0x71, 0x21, 0xfa, 0x72,
+    0x41, 0x48, 0x79, 0x80, 0x4e, 0x9a, 0xd6, 0xbc, 0x9e, 0x21, 0x76, 0x08,
+    0x78, 0x33, 0xe3, 0x84, 0x5a, 0xcb, 0x0d, 0xc6, 0x59, 0x73, 0xc8, 0x9e,
+    0x11, 0x55, 0x7b, 0x67, 0xff, 0x1d, 0xa5, 0x2a, 0x1f, 0x8c, 0x1d, 0x58,
+    0x82, 0x1f, 0xde, 0x56, 0x79, 0x36, 0xe0, 0x80, 0x8a, 0xe2, 0xc0, 0xbc,
+    0x56, 0x7d, 0xdd, 0xc1, 0x58, 0xae, 0x14, 0xe2, 0x50, 0x51, 0x8b, 0xc2,
+    0xf8, 0xde, 0x6c, 0x81, 0xb2, 0x20, 0xfe, 0x09, 0x8d, 0x01, 0xb4, 0xf5,
+    0xf0, 0xf6, 0x6c, 0xc9, 0x98, 0xcf, 0x86, 0x86, 0xf8, 0x9c, 0x7a, 0x0e,
+    0x76, 0x38, 0xf3, 0x84, 0x48, 0xaf, 0x1f, 0x10, 0x08, 0x14, 0x43, 0xbb,
+    0x04, 0x34, 0x8b, 0x72, 0x23, 0x9c, 0x81, 0x54, 0x36, 0x0f, 0x72, 0x7e,
+    0xae, 0xac, 0xe9, 0x14, 0x11, 0x80, 0x40, 0xbd, 0x5d, 0xe0, 0xcd, 0xe9,
+    0xea, 0x91, 0x63, 0x99, 0x22, 0x2e, 0x0a, 0x3a, 0x09, 0x06, 0xb7, 0xe5,
+    0x01, 0x3d, 0xc2, 0xb7, 0x8f, 0xaf, 0x6e, 0x6a, 0xd1, 0xd5, 0x64, 0x54,
+    0x69, 0x22, 0x9f, 0x4e, 0xb1, 0x7a, 0xd6, 0x7e, 0x2b, 0xb1, 0xac, 0x54,
+    0xb6, 0x45, 0x70, 0x22, 0xa0, 0x7c, 0xdf, 0x59, 0xba, 0x9a, 0x80, 0x83,
+    0xdd, 0x58, 0x16, 0xbc, 0x13, 0x23, 0xee, 0x14, 0x9d, 0x1c, 0xd0, 0x50,
+    0x6d, 0x7f, 0x16, 0xab, 0x59, 0x54, 0xe4, 0xdb, 0x51, 0xbf, 0x7a, 0x33,
+    0xf1, 0x58, 0xad, 0xd8, 0xcb, 0xe3, 0x16, 0xa5, 0x22, 0xc1, 0xe8, 0x5a,
+    0x79, 0x09, 0x8a, 0x54, 0x86, 0x53, 0xd7, 0x20, 0x79, 0x30, 0x34, 0x5e,
+    0x18, 0x66, 0x8e, 0x3f, 0x25, 0x02, 0x46, 0x31, 0x59, 0x1a, 0x97, 0x04,
+    0x1f, 0x81, 0x2d, 0xdf, 0x11, 0xeb, 0xb0, 0xe2, 0x20, 0xcc, 0x24, 0x25,
+    0x3a, 0x04, 0x06, 0x6d, 0xf5, 0x6a, 0xf0, 0x5d, 0x6f, 0xb6, 0x77, 0x47,
+    0xf2, 0xfb, 0x50, 0x8d, 0xf8, 0xc4, 0xdf, 0x5d, 0x7d, 0xb2, 0x36, 0x95,
+    0xe1, 0x63, 0x78, 0x29, 0x09, 0xce, 0xe1, 0x34, 0xaf, 0x8f, 0x87, 0x85,
+    0x09, 0xd5, 0x0b, 0xc0, 0x25, 0x8c, 0x5f, 0x9a, 0xc8, 0xf0, 0xf7, 0x32,
+    0x08, 0xae, 0x32, 0xbe, 0x9f, 0xf3, 0xc9, 0x64, 0x1f, 0x09, 0xe4, 0x9e,
+    0x96, 0xbb, 0xed, 0x32, 0x0c, 0x43, 0xad, 0x86, 0x06, 0xc2, 0xb6, 0x52,
+    0xce, 0xf0, 0x60, 0x4e, 0x53, 0xf7, 0x36, 0xa0, 0x37, 0x13, 0xcd, 0x9f,
+    0xfc, 0xf2, 0x4b, 0x69, 0xf2, 0x3a, 0xa4, 0xa0, 0x7c, 0x4f, 0xbc, 0x1f,
+    0xd0, 0x5a, 0xf6, 0x8e, 0x86, 0xe6, 0x4f, 0xe2, 0xc8, 0xb8, 0x4a, 0xb5,
+    0xb5, 0xec, 0x5c, 0x5d, 0x06, 0xd2, 0xd8, 0xf0, 0xb9, 0x22, 0xd3, 0x6d,
+    0x6a, 0x26, 0xae, 0x09, 0xbe, 0x1a, 0x9a, 0x80, 0xdf, 0x6c, 0x29, 0xa0,
+    0xa2, 0xa2, 0xbc, 0xb9, 0xbf, 0xd9, 0xac, 0x10, 0xc5, 0x5d, 0x3d, 0xe4,
+    0x89, 0x12, 0x99, 0x4e, 0xab, 0x7b, 0x6a, 0x1c, 0xd4, 0x60, 0x20, 0x20,
+    0x91, 0xfe, 0xf4, 0x2f, 0x0f, 0xfa, 0x5a, 0x77, 0xd0, 0x4c, 0x72, 0x3e,
+    0x20, 0x14, 0xbf, 0x40, 0xb4, 0x2d, 0x7f, 0x10, 0x93, 0x77, 0x73, 0xb7,
+    0x5d, 0xce, 0x64, 0x01, 0xe8, 0x7c, 0xc3, 0xae, 0xdc, 0xc6, 0x91, 0x11,
+    0xb0, 0x4c, 0x00, 0x2a, 0xdb, 0xa8, 0xbb, 0xa9, 0x3e, 0x0d, 0x2a, 0x8b,
+    0x75, 0x93, 0x1b, 0xcb, 0xb6, 0xc1, 0xcd, 0x33, 0xf7, 0x5f, 0x64, 0xe7,
+    0xb4, 0x07, 0x7d, 0xdf, 0x9d, 0x1b, 0x4e, 0x38, 0xc1, 0x4e, 0xe0, 0xa4,
+    0x18, 0xab, 0xdc, 0x7c, 0x33, 0x50, 0xdb, 0xd5, 0x33, 0xbb, 0xb9, 0x74,
+    0x6e, 0xa5, 0x9f, 0x93, 0x6a, 0x4b, 0x8a, 0xf6, 0x6f, 0x10, 0xfa, 0x85,
+    0xe0, 0x72, 0xfa, 0x58, 0x25, 0x79, 0x38, 0xe0, 0xfa, 0x80, 0xde, 0x35,
+    0xe7, 0x4e, 0x37, 0x54, 0x5a, 0xf8, 0xb9, 0x77, 0x15, 0xc7, 0xa1, 0x6f,
+    0x91, 0x98, 0x1d, 0x3d, 0x8c, 0xd4, 0x5b, 0xe9, 0x56, 0x20, 0x87, 0x2a,
+    0x6a, 0x6f, 0xd1, 0x88, 0x02, 0x16, 0x46, 0x7b, 0x96, 0x03, 0x99, 0x17,
+    0x51, 0x1a, 0x74, 0x9d, 0x13, 0x5f, 0xb2, 0xa6, 0xf2, 0xf6, 0x6f, 0x8c,
+    0xb8, 0xd7, 0x3c, 0x41, 0xd8, 0x51, 0xb4, 0x4d, 0x70, 0x22, 0xb6, 0x93,
+    0x76, 0xab, 0x82, 0x49, 0x76, 0x8b, 0xe2, 0x99, 0x3d, 0x25, 0x97, 0x74,
+    0x8b, 0x8b, 0xd6, 0xdd, 0xab, 0xf7, 0x0d, 0xa1, 0xc9, 0x96, 0xb8, 0xfa,
+    0xcb, 0xfb, 0x2c, 0xb6, 0xe5, 0x60, 0x7d, 0x7f, 0x7c, 0x4b, 0x05, 0x5b,
+    0xe6, 0xee, 0xc5, 0x7c, 0x60, 0xba, 0x66, 0x7a, 0xc1, 0xc6, 0x9c, 0xce,
+    0xae, 0xa7, 0x93, 0xb7, 0x5a, 0xc8, 0x7f, 0x9d, 0xaa, 0xe2, 0xc0, 0x4b,
+    0xb8, 0x05, 0x1d, 0x68, 0x00, 0x17, 0x2e, 0x8e, 0xad, 0xe4, 0x01, 0xa7,
+    0x82, 0x96, 0xd3, 0x31, 0x0e, 0xd3, 0x8f, 0xae, 0x83, 0xd3, 0xab, 0xa4,
+    0xd2, 0x5e, 0x45, 0x99, 0x47, 0x97, 0x8b, 0x88, 0xcf, 0x0f, 0xa2, 0x7b,
+    0x11, 0xc3, 0xb5, 0x5a, 0x39, 0x2a, 0x39, 0x7a, 0x57, 0x09, 0x0b, 0x1e,
+    0x3e, 0xe7, 0x08, 0x89, 0xee, 0xeb, 0x0c, 0xce, 0x14, 0x60, 0x33, 0x1e,
+    0xa1, 0x51, 0xf2, 0x72, 0x3c, 0xe3, 0xb1, 0xd5, 0x2a, 0x11, 0x96, 0xe9,
+    0x1c, 0x40, 0xcd, 0x65, 0x01, 0x2a, 0xc5, 0x75, 0xea, 0x28, 0xfd, 0x8b,
+    0xf6, 0x45, 0xd6, 0x4c, 0xde, 0x31, 0x7f, 0xa4, 0xfc, 0x8f, 0x9c, 0xd9,
+    0x4a, 0xf2, 0xbc, 0xf6, 0x76, 0xdd, 0xef, 0xc4, 0x44, 0xd4, 0x16, 0xac,
+    0x79, 0x44, 0x63, 0xb2, 0x0b, 0x9e, 0x73, 0x49, 0x5f, 0x2b, 0xc5, 0x5a,
+    0xc7, 0x0a, 0xe3, 0x18, 0xd0, 0x49, 0xf6, 0x4d, 0x8d, 0x23, 0x22, 0xa9,
+    0xa7, 0x07, 0x37, 0xa0, 0x1b, 0xf3, 0x81, 0xf2, 0xb1, 0x03, 0x16, 0x5c,
+    0x5a, 0x0a, 0xe6, 0xa5, 0x26, 0x5c, 0xaf, 0x03, 0x16, 0x89, 0x4b, 0xe3,
+    0x93, 0xcc, 0x1d, 0xc5, 0x67, 0x30, 0x66, 0xbf, 0x3d, 0x1b, 0xc9, 0x80,
+    0xdb, 0x7c, 0xfa, 0xeb, 0x79, 0x32, 0x69, 0x61, 0x90, 0x21, 0xbb, 0x35,
+    0x2a, 0xb9, 0x94, 0xc2, 0xfa, 0x8a, 0xe2, 0x1c, 0xb2, 0xc5, 0x77, 0x7d,
+    0xd0, 0x0e, 0x20, 0xa3, 0x39, 0xd1, 0x2b, 0x5f, 0x97, 0x82, 0xf0, 0x9e,
+    0x67, 0xe3, 0x15, 0xc8, 0x36, 0x2e, 0x75, 0x20, 0x90, 0x24, 0x61, 0xd4,
+    0x32, 0xc6, 0x97, 0x41, 0xf0, 0xb4, 0x0e, 0xa2, 0xa2, 0x1e, 0x2b, 0x77,
+    0xc2, 0x4c, 0x17, 0x35, 0xe1, 0x1a, 0x15, 0x1e, 0x3f, 0xf7, 0xf1, 0x3b,
+    0x91, 0x77, 0xe9, 0x84, 0x73, 0x2c, 0x61, 0xe9, 0x41, 0x45, 0x56, 0xd1,
+    0x3b, 0xe4, 0x54, 0x79, 0x15, 0x75, 0x51, 0xe2, 0xbe, 0xed, 0x32, 0xd0,
+    0xef, 0x34, 0xf1, 0x1f, 0x2e, 0xa8, 0x8e, 0x6b, 0x59, 0x65, 0xb1, 0x2a,
+    0x54, 0xf7, 0x4c, 0x1a, 0x6b, 0x3c, 0x18, 0xeb, 0x97, 0x3b, 0x94, 0xd4,
+    0xfe, 0xe4, 0xae, 0x76, 0x2c, 0xf0, 0xbb, 0x4a, 0x63, 0xd6, 0x87, 0xe0,
+    0x94, 0xee, 0xc9, 0x5a, 0xba, 0x80, 0x28, 0x5e, 0x6b, 0x14, 0x73, 0x7b,
+    0xe6, 0x4b, 0x0a, 0x81, 0x80, 0x87, 0x68, 0xe0, 0xcb, 0xb8, 0x20, 0x8e,
+    0x47, 0x69, 0xd2, 0x39, 0x10, 0x8b, 0xc7, 0x29, 0x41, 0x6b, 0x8d, 0xe5,
+    0x29, 0xd9, 0xad, 0xb1, 0x69, 0x8c, 0xc2, 0xa1, 0x50, 0xd2, 0xe3, 0x80,
+    0xe4, 0x09, 0xa2, 0xd6, 0xae, 0x75, 0x65, 0xca, 0x45, 0x75, 0xe9, 0xab,
+    0x2c, 0x99, 0xc6, 0xe9, 0x04, 0xd0, 0xcc, 0x9d, 0xea, 0xc7, 0x85, 0x4c,
+    0xb2, 0xb1, 0x6f, 0x49, 0xf1, 0xe5, 0x51, 0xce, 0xa6, 0x7e, 0x68, 0xe5,
+    0x2b, 0xbe, 0xed, 0x21, 0x12, 0x9f, 0x3b, 0x03, 0x6f, 0x84, 0xd6, 0x47,
+    0x27, 0x76, 0x7f, 0x7b, 0xb8, 0x45, 0x8f, 0xa0, 0xff, 0xb1, 0xa8, 0x8e,
+    0x4a, 0x33, 0x3b, 0xfe, 0x5a, 0x37, 0x90, 0xe7, 0x37, 0x7b, 0xfc, 0xf4,
+    0xb3, 0x5f, 0x1c, 0xf7, 0x77, 0xb7, 0x09, 0x77, 0xa1, 0x4d, 0x4e, 0x59,
+    0xcb, 0x8d, 0x61, 0x8f, 0xee, 0x5a, 0xfb, 0xc0, 0x0b, 0x4e, 0x05, 0x76,
+    0xa0, 0xd0, 0xc8, 0x8e, 0x2c, 0xba, 0x11, 0xde, 0xa0, 0xc9, 0x69, 0xf4,
+    0x53, 0xda, 0xc7, 0xda, 0x13, 0x62, 0x94, 0xe4, 0x2f, 0x73, 0x21, 0xca,
+    0xaf, 0x3f, 0xd2, 0xaf, 0xbe, 0x8e, 0xea, 0x8f, 0xd6, 0x88, 0x74, 0x94,
+    0x95, 0x42, 0x04, 0xb4, 0x4c, 0x9a, 0xad, 0xf6, 0x7f, 0xe0, 0xad, 0xf4,
+    0x86, 0x52, 0x09, 0x36, 0x02, 0xb8, 0x61, 0x43, 0xe5, 0x2c, 0xd0, 0xd5,
+    0x59, 0xc0, 0xf9, 0x99, 0x7c, 0x76, 0xc3, 0xb2, 0xb6, 0x59, 0x9a, 0x4f,
+    0xd1, 0x0c, 0xc4, 0x76, 0x86, 0xfc, 0xd5, 0x23, 0x3e, 0x3c, 0x07, 0x9b,
+    0x23, 0xac, 0x64, 0x58, 0x91, 0xb8, 0xd6, 0x96, 0xdc, 0x77, 0xaf, 0x32,
+    0x32, 0x38, 0xda, 0xeb, 0xc5, 0x43, 0xb6, 0x96, 0x70, 0xbb, 0x63, 0x46,
+    0x0b, 0xfd, 0xe5, 0x93, 0xdc, 0xb2, 0xaf, 0x80, 0x94, 0xb8, 0xd1, 0x94,
+    0x59, 0x1e, 0xcb, 0x2d, 0xa5, 0xa2, 0xd6, 0xcd, 0x1a, 0x23, 0xd5, 0x61,
+    0x03, 0xa7, 0x49, 0xc7, 0xb5, 0xd5, 0x1a, 0x16, 0x60, 0xc6, 0xc7, 0x94,
+    0xbe, 0x79, 0x99, 0xf0, 0x11, 0x4f, 0x4b, 0x03, 0xdc, 0xfc, 0xb2, 0xd4,
+    0x7a, 0xf8, 0xe0, 0xa4, 0x77, 0xd6, 0xa4, 0x01, 0xe2, 0x1f, 0xf1, 0x9b,
+    0xdb, 0xba, 0x8b, 0x42, 0xe6, 0x5e, 0xa6, 0x89, 0x11, 0xab, 0xf1, 0xe9,
+    0xad, 0x7b, 0x58, 0xfa, 0x68, 0x18, 0x17, 0xff, 0xe3, 0xe2, 0xa0, 0x94,
+    0xb5, 0xf0, 0x72, 0x40, 0x65, 0x12, 0xfb, 0x11, 0xc9, 0x56, 0x56, 0xce,
+    0xb1, 0x86, 0x5c, 0x50, 0x74, 0x49, 0x96, 0xf8, 0x43, 0x52, 0x9c, 0xaa,
+    0xd2, 0x39, 0x84, 0xb3, 0x02, 0xc5, 0xa5, 0x8f, 0xbd, 0x6c, 0xc4, 0x74,
+    0xf2, 0xc1, 0x0a, 0x08, 0xd0, 0xd9, 0x69, 0xff, 0xf2, 0x80, 0x50, 0x35,
+    0x63, 0x88, 0x45, 0x0b, 0x8c, 0xd2, 0x48, 0x55, 0x0d, 0xba, 0xa9, 0x4c,
+    0x7e, 0xd2, 0xaa, 0xb0, 0x7d, 0x46, 0x60, 0x15, 0x23, 0x4b, 0xa6, 0x4d,
+    0x68, 0x85, 0x31, 0x12, 0xc5, 0x58, 0xdc, 0x2f, 0x26, 0x51, 0xf2, 0x96,
+    0x7e, 0x2b, 0x67, 0xad, 0x66, 0x80, 0x33, 0x87, 0x33, 0x71, 0x52, 0x5d,
+    0xd9, 0x4a, 0x1e, 0x23, 0x95, 0x70, 0xec, 0x85, 0x2d, 0x1d, 0x94, 0x33,
+    0x40, 0xca, 0xef, 0x61, 0x3f, 0x77, 0x38, 0x65, 0x32, 0x9d, 0x94, 0x00,
+    0xd6, 0x12, 0x4a, 0x37, 0x20, 0xe3, 0xc8, 0xc7, 0xdc, 0x59, 0x9b, 0x43,
+    0xbe, 0x97, 0x33, 0x66, 0xc0, 0xc9, 0xa5, 0xbc, 0xfe, 0xec, 0x02, 0xf6,
+    0x52, 0x18, 0x64, 0x24, 0x0c, 0x55, 0xc7, 0x0f, 0x62, 0x56, 0x45, 0xa2,
+    0x7c, 0x93, 0xa3, 0xea, 0x0f, 0x87, 0xd1, 0xba, 0x23, 0x42, 0x80, 0xd9,
+    0xc2, 0xb3, 0xd6, 0x25, 0x73, 0x10, 0x5b, 0x1a, 0xc1, 0xed, 0x4f, 0xa2,
+    0x8d, 0x8e, 0x4d, 0x1b, 0x55, 0x64, 0xfd, 0xe3, 0x89, 0xab, 0xd6, 0xe6,
+    0x45, 0x49, 0x6f, 0x91, 0x68, 0xb9, 0x26, 0xa4, 0xdd, 0x9f, 0x55, 0xa0,
+    0x5f, 0x35, 0x69, 0x27, 0xd1, 0xb6, 0x5a, 0x3f, 0xcc, 0x52, 0x40, 0xad,
+    0xda, 0x10, 0x8d, 0x2f, 0xd6, 0x8c, 0x01, 0xe1, 0x32, 0x73, 0xe1, 0x32,
+    0xc3, 0xe7, 0x7e, 0xac, 0xba, 0x8c, 0xac, 0x38, 0x8f, 0x02, 0x0d, 0x67,
+    0xa9, 0xc4, 0xab, 0x4e, 0xb5, 0x31, 0x77, 0xa2, 0x12, 0xd6, 0xaa, 0x58,
+    0x57, 0xe7, 0xeb, 0xa6, 0x66, 0xd7, 0x36, 0xdc, 0x5c, 0x21, 0x86, 0xa4,
+    0x76, 0x0a, 0x9c, 0x27, 0xb8, 0xeb, 0x0c, 0xc7, 0x2c, 0xf5, 0xe5, 0x49,
+    0x8c, 0x62, 0x39, 0x82, 0xc0, 0xc4, 0x73, 0x8c, 0x74, 0x5d, 0xeb, 0xba,
+    0xa5, 0x5a, 0xe2, 0x50, 0xdc, 0x06, 0xb7, 0x0b, 0x6c, 0xb9, 0x7e, 0x3d,
+    0x01, 0xb7, 0x48, 0x2d, 0x4b, 0x90, 0xe7, 0x6d, 0x99, 0x58, 0xe1, 0xab,
+    0x2b, 0xf1, 0x06, 0x5e, 0x25, 0x08, 0x9b, 0xc3, 0x79, 0xaf, 0xe0, 0x5e,
+    0x01, 0xbb, 0x61, 0xb7, 0xc5, 0x22, 0x1c, 0xaf, 0x68, 0xef, 0x7f, 0xbb,
+    0x41, 0x8b, 0x99, 0x19, 0xf0, 0x68, 0xe9, 0x94, 0x74, 0xe5, 0xda, 0xd4,
+    0xf3, 0x8c, 0x4f, 0xdf, 0x09, 0x8f, 0x74, 0xd3, 0xbf, 0xe5, 0xee, 0x58,
+    0xc0, 0x22, 0xa0, 0x91, 0x1e, 0xfa, 0x6b, 0x3b, 0x02, 0x2a, 0x03, 0xab,
+    0x6a, 0xe2, 0xaa, 0xfe, 0x64, 0xbd, 0x77, 0xd0, 0x77, 0xc8, 0xbb, 0x75,
+    0x9d, 0xb3, 0x3e, 0xe7, 0xc3, 0x57, 0x14, 0xb1, 0x75, 0x44, 0x98, 0x15,
+    0x97, 0xef, 0x4c, 0xd2, 0x94, 0x50, 0x93, 0x89, 0x3a, 0x6f, 0xfa, 0x10,
+    0x78, 0x90, 0xde, 0xef, 0xcb, 0x7d, 0x5d, 0xae, 0xbc, 0xfa, 0x48, 0x08,
+    0x81, 0xc9, 0x0b, 0xdd, 0x90, 0x38, 0x34, 0x70, 0x66, 0x1a, 0x0e, 0xb1,
+    0xe8, 0x99, 0x4e, 0x05, 0xf6, 0xa9, 0x88, 0x7f, 0xa6, 0x22, 0x19, 0x68,
+    0xe1, 0xf5, 0x6b, 0xfc, 0xe7, 0xeb, 0xaa, 0x5b, 0xc4, 0x62, 0x8c, 0x19,
+    0x45, 0xb9, 0x77, 0x8e, 0xcc, 0x31, 0xb4, 0xb3, 0x64, 0x43, 0xec, 0x95,
+    0xe5, 0xd7, 0x63, 0x06, 0x29, 0xd8, 0x0c, 0xcb, 0xeb, 0x97, 0xa6, 0xad,
+    0x37, 0x28, 0x7c, 0x8c, 0x28, 0xd6, 0x97, 0xa9, 0xc6, 0x3f, 0x9e, 0x1c,
+    0x26, 0x0d, 0xf1, 0xba, 0xb1, 0x55, 0x96, 0xde, 0x86, 0xbf, 0x4e, 0x36,
+    0x1f, 0x6c, 0x1c, 0xc6, 0xf5, 0x35, 0xb3, 0xb3, 0x74, 0xa0, 0x23, 0x86,
+    0xda, 0x9e, 0x9a, 0xfd, 0xb7, 0xe8, 0x43, 0x67, 0x51, 0x26, 0x2d, 0xb3,
+    0x72, 0x75, 0x6f, 0xd5, 0x2a, 0xae, 0xa3, 0xea, 0x04, 0xed, 0x83, 0x96,
+    0xbb, 0xd1, 0x0d, 0x13, 0xdb, 0xc0, 0xb3, 0x26, 0x93, 0x54, 0x03, 0x2b,
+    0x6e, 0x6a, 0x85, 0x8f, 0x50, 0x6f, 0xa3, 0xd3, 0x43, 0xda, 0x05, 0x1a,
+    0x67, 0x86, 0x4e, 0xc5, 0x8f, 0xb2, 0x26, 0x71, 0xea, 0x4a, 0xcb, 0x24,
+    0x4b, 0x00, 0x2e, 0xf0, 0xac, 0xaa, 0xae, 0x47, 0x0c, 0x01, 0x3b, 0x20,
+    0xd0, 0x03, 0x58, 0xff, 0x4f, 0x00, 0xaf, 0xb0, 0xd1, 0x01, 0x41, 0xaf,
+    0xfb, 0xdc, 0xcd, 0xa9, 0xe7, 0xa1, 0xeb, 0x81, 0x17, 0x41, 0x74, 0x6c,
+    0x9b, 0xfb, 0x0d, 0xeb, 0x0c, 0x7a, 0xd0, 0x85, 0x6b, 0x0a, 0x30, 0x2b,
+    0xa5, 0x1a, 0x67, 0xb2, 0x1a, 0x5e, 0x34, 0x89, 0x18, 0x37, 0x3e, 0xbe,
+    0xd9, 0x81, 0x06, 0xd6, 0xcf, 0x8f, 0xdf, 0x4d, 0x94, 0x49, 0xc9, 0x12,
+    0xe2, 0xb6, 0xc5, 0xc3, 0xdf, 0x05, 0xdb, 0x7c, 0xf0, 0x4a, 0xdf, 0x90,
+    0xfa, 0x7e, 0xce, 0x89, 0x93, 0xf7, 0x28, 0x37, 0xd0, 0x1f, 0x3e, 0x7c,
+    0x6d, 0x0e, 0x75, 0x5f, 0x55, 0xcb, 0xd1, 0x9e, 0x06, 0xed, 0xdd, 0x27,
+    0xae, 0xb3, 0xce, 0xc0, 0x18, 0xce, 0x4a, 0x4f, 0x43, 0x81, 0x0d, 0x4c,
+    0x29, 0x53, 0x91, 0xda, 0x5f, 0x22, 0x29, 0xed, 0x49, 0xbe, 0xed, 0x55,
+    0x37, 0xf1, 0xa6, 0xfc, 0x7d, 0x10, 0xd7, 0xd0, 0xd3, 0xf2, 0xaf, 0x19,
+    0xf3, 0x40, 0x2f, 0xfd, 0xe0, 0x16, 0x7e, 0x00, 0xb5, 0x4d, 0x57, 0x65,
+    0xe6, 0x68, 0xef, 0xdb, 0x49, 0xe2, 0xaa, 0x39, 0xfc, 0x8d, 0x19, 0xa2,
+    0x61, 0x6f, 0xdf, 0x43, 0xf4, 0x18, 0x5d, 0x16, 0xd9, 0x68, 0x92, 0x45,
+    0x0d, 0x7f, 0x8d, 0x6f, 0xfd, 0x63, 0x26, 0x6d, 0x64, 0xfc, 0xf7, 0xa2,
+    0x29, 0xda, 0x40, 0x65, 0x98, 0xfa, 0x2e, 0xba, 0x9f, 0x54, 0xfb, 0xc1,
+    0xe4, 0x8f, 0xbc, 0x6e, 0x57, 0xe5, 0x9a, 0x9d, 0x1c, 0x63, 0x04, 0xc9,
+    0x89, 0xf7, 0xe2, 0xdf, 0x3b, 0x83, 0xc8, 0x99, 0x65, 0xb7, 0x30, 0x7a,
+    0x7b, 0x54, 0x95, 0x3f, 0x4e, 0x26, 0x05, 0xa6, 0x86, 0x40, 0x63, 0x4a,
+    0xb8, 0x53, 0x33, 0x0c, 0x4e, 0x52, 0x26, 0x50, 0xf2, 0x81, 0x2f, 0x69,
+    0xb0, 0x9d, 0x9e, 0x46, 0x2c, 0x1d, 0xfe, 0x79, 0x79, 0xff, 0x60, 0x83,
+    0x05, 0x3f, 0xab, 0xcf, 0x04, 0x45, 0xe0, 0x19, 0xb7, 0xb3, 0x50, 0xc7,
+    0x5e, 0x49, 0xe7, 0xed, 0x4c, 0x76, 0x60, 0x3e, 0xc9, 0x55, 0x11, 0xdc,
+    0x54, 0xc7, 0x93, 0x13, 0xa8, 0x97, 0x0b, 0x46, 0xfb, 0xad, 0xa5, 0xeb,
+    0xfc, 0xaa, 0x4a, 0x41, 0xc1, 0xc2, 0xee, 0xbd, 0x15, 0xb5, 0x91, 0x04,
+    0x77, 0x93, 0xf1, 0x72, 0x38, 0x3f, 0x0b, 0x1e, 0x18, 0xdd, 0x93, 0x2c,
+    0x1f, 0x32, 0x60, 0x12, 0x4f, 0x1b, 0x06, 0x34, 0xcb, 0xa5, 0x3a, 0x0f,
+    0x07, 0xff, 0x9b, 0x39, 0xc0, 0x7c, 0xd8, 0xd7, 0x97, 0xe0, 0x08, 0x3b,
+    0x55, 0xc7, 0x80, 0xc4, 0x07, 0xf6, 0x11, 0x9c, 0x5b, 0x25, 0x02, 0xc4,
+    0x61, 0xb5, 0xa9, 0x8f, 0xec, 0x01, 0x5c, 0x17, 0xd8, 0x90, 0x48, 0xc5,
+    0xd4, 0x2a, 0x0d, 0x8b, 0x40, 0x87, 0x46, 0x5e, 0xa2, 0x83, 0xf2, 0x64,
+    0xf5, 0xb1, 0xeb, 0x52, 0xb2, 0x19, 0x9d, 0x2c, 0x29, 0x59, 0x3e, 0xde,
+    0x6e, 0x33, 0xa3, 0x17, 0xd7, 0xf8, 0x58, 0x21, 0x42, 0x49, 0x7f, 0x5e,
+    0x5c, 0xd9, 0x7f, 0x9f, 0xa0, 0x99, 0xa6, 0xfd, 0x66, 0x0c, 0x15, 0x64,
+    0x5f, 0x1e, 0x01, 0x9d, 0x36, 0x20, 0xa9, 0xa4, 0x13, 0x2c, 0xc0, 0x80,
+    0x92, 0x44, 0xd5, 0x61, 0xad, 0xd5, 0x9c, 0xf2, 0xdd, 0xc2, 0x0b, 0xc2,
+    0x24, 0x1f, 0x69, 0x38, 0x48, 0x2c, 0x68, 0xf8, 0x19, 0xbe, 0x34, 0x21,
+    0x38, 0xd0, 0x9c, 0xe5, 0xc0, 0xb8, 0x2b, 0x33, 0x24, 0x4c, 0x83, 0xe4,
+    0x7d, 0xdb, 0x75, 0x7e, 0x60, 0xb4, 0x71, 0xaf, 0xb0, 0xc5, 0xb6, 0x4a,
+    0xba, 0x9a, 0x83, 0x0b, 0x40, 0xf4, 0x96, 0x5a, 0xe2, 0x78, 0x20, 0x33,
+    0xbb, 0x87, 0xba, 0x09, 0xf2, 0xd0, 0x24, 0x81, 0x23, 0xf5, 0x1b, 0x85,
+    0x75, 0x12, 0x5d, 0x3e, 0xc5, 0x13, 0xc8, 0x03, 0xb7, 0xd5, 0x45, 0x70,
+    0x64, 0x25, 0xfa, 0x58, 0xb5, 0x38, 0x11, 0x1f, 0xe7, 0x9e, 0x89, 0x5a,
+    0x90, 0x59, 0xef, 0x7b, 0xd9, 0x14, 0x28, 0x2e, 0xf6, 0x30, 0x04, 0xf4,
+    0xd0, 0x13, 0xba, 0xfc, 0x95, 0x39, 0x1a, 0xf4, 0xf4, 0xfd, 0x38, 0x83,
+    0x46, 0x48, 0xc1, 0x31, 0x87, 0x0b, 0xa3, 0x1e, 0x67, 0x76, 0x83, 0xff,
+    0x00, 0x52, 0x6b, 0xe8, 0xf4, 0x70, 0xa6, 0xba, 0xc0, 0xc4, 0x38, 0x9b,
+    0xe0, 0x01, 0x07, 0x23, 0x3f, 0x58, 0x68, 0x7d, 0xbe, 0xdc, 0x0a, 0x4b,
+    0xcc, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x04, 0x09, 0x0e, 0x11, 0x1a, 0x1f};
+
+const uint8_t kExpectedVerifySignature[] = {
+    0x49, 0x23, 0xce, 0xa1, 0x29, 0x3b, 0x24, 0x00, 0xcc, 0xc3, 0xb1, 0x9f,
+    0x1e, 0x80, 0x3e, 0xd8, 0x5a, 0x0d, 0x6e, 0x0b, 0xa6, 0x4f, 0x35, 0xf8,
+    0x45, 0xf4, 0x20, 0xd8, 0x48, 0xe1, 0x85, 0x82, 0x05, 0x88, 0x3f, 0xdd,
+    0xd4, 0xbd, 0xa0, 0xd9, 0xe3, 0x35, 0xca, 0x31, 0x02, 0x72, 0x95, 0x2c,
+    0xd4, 0xfa, 0xf8, 0x76, 0x7a, 0xe1, 0x35, 0xcb, 0x7e, 0x93, 0xdd, 0x27,
+    0xb9, 0x5d, 0x71, 0x0a, 0x08, 0xaf, 0xc2, 0x09, 0xbb, 0x74, 0xfa, 0xd9,
+    0x46, 0x3b, 0x2f, 0x00, 0x53, 0xee, 0x74, 0x1c, 0x85, 0x15, 0xa8, 0x4b,
+    0xa7, 0xf9, 0x0b, 0xbf, 0x9c, 0xde, 0x84, 0x03, 0xe3, 0x4f, 0x12, 0x21,
+    0xe9, 0x1e, 0x7a, 0x06, 0x70, 0xd9, 0x68, 0x84, 0x53, 0x83, 0xcd, 0x72,
+    0x4c, 0xe5, 0xcd, 0x6c, 0x30, 0x47, 0xd9, 0x28, 0x59, 0x64, 0x46, 0x57,
+    0x93, 0xb5, 0x58, 0xe0, 0x8d, 0x92, 0x15, 0x16, 0xd0, 0x05, 0x09, 0x9f,
+    0xdc, 0xcc, 0x2e, 0xfd, 0x8e, 0x13, 0x47, 0x41, 0x44, 0x15, 0x6c, 0x32,
+    0x9f, 0x37, 0xfe, 0xe0, 0x31, 0xfb, 0xcb, 0x94, 0xec, 0x83, 0x37, 0x3e,
+    0x72, 0x91, 0x0c, 0xab, 0xe0, 0x19, 0x57, 0xb8, 0xd0, 0xfb, 0x3f, 0x1c,
+    0xe2, 0xb6, 0xf9, 0xc5, 0x9c, 0x91, 0x92, 0x1b, 0x2e, 0x0f, 0x6f, 0xf1,
+    0xe6, 0x5a, 0xf1, 0x3c, 0x1a, 0x2c, 0xa6, 0xfb, 0x9d, 0x48, 0x86, 0x33,
+    0xab, 0x94, 0xdf, 0x0b, 0x6b, 0xa8, 0xf0, 0x08, 0xb6, 0x59, 0xd4, 0xad,
+    0xad, 0x9e, 0xe6, 0x07, 0x26, 0x00, 0x9a, 0x34, 0xc8, 0x2c, 0x7b, 0xd5,
+    0x2e, 0xe0, 0x47, 0xd8, 0x0b, 0xd0, 0x34, 0x87, 0x62, 0xc5, 0x4d, 0x00,
+    0xbc, 0x18, 0x62, 0x0b, 0x7f, 0xb7, 0xb6, 0x88, 0x43, 0x9f, 0x3f, 0x77,
+    0x87, 0xec, 0xad, 0x21, 0xc2, 0xec, 0xfc, 0x99, 0x2f, 0xb6, 0x97, 0xab,
+    0x40, 0xb3, 0xc2, 0x57, 0x33, 0x27, 0xde, 0x4b, 0xc6, 0x8e, 0x69, 0x47,
+    0x59, 0x16, 0xe6, 0x49, 0xf7, 0x69, 0xe9, 0x3a, 0x08, 0xca, 0xd4, 0xd4,
+    0x29, 0x44, 0x6d, 0xf3, 0x10, 0x56, 0x6f, 0x4b, 0x1d, 0x47, 0xb8, 0x9e,
+    0x66, 0x5e, 0x11, 0x46, 0xec, 0xa8, 0x45, 0xc9, 0x66, 0xc1, 0x4a, 0x0c,
+    0x62, 0x01, 0x2a, 0x05, 0xc6, 0xda, 0xb0, 0xd9, 0x95, 0x09, 0xc0, 0x97,
+    0xe0, 0x33, 0xa2, 0x89, 0x36, 0xf6, 0xab, 0xa0, 0x7f, 0x65, 0xff, 0x2c,
+    0xf5, 0xb9, 0x06, 0x74, 0x8b, 0xc2, 0x10, 0xc7, 0x7f, 0xdb, 0xfd, 0x6d,
+    0xfe, 0xa8, 0xed, 0xd9, 0x41, 0x3b, 0x1d, 0x40, 0x96, 0xc8, 0xf5, 0x7c,
+    0x23, 0x7b, 0xfc, 0x80, 0x5a, 0xb3, 0x1d, 0xfd, 0x29, 0x37, 0xfc, 0x12,
+    0xa5, 0x64, 0x18, 0x93, 0xea, 0xc3, 0x15, 0xf6, 0x36, 0x3e, 0x92, 0xd6,
+    0x31, 0x1c, 0xe2, 0x70, 0x89, 0xd9, 0x55, 0x4f, 0x42, 0x9e, 0x5e, 0xd2,
+    0x80, 0x4a, 0x71, 0x31, 0xfc, 0x8f, 0xc2, 0x7f, 0xfc, 0xed, 0x8e, 0x48,
+    0x8c, 0xc1, 0x7b, 0xa8, 0x73, 0xd3, 0x25, 0xd6, 0xe2, 0x1e, 0x14, 0x5e,
+    0xbb, 0xd1, 0x3e, 0x44, 0x4c, 0x97, 0x99, 0xc4, 0xb9, 0xce, 0x42, 0xa1,
+    0x0c, 0x0d, 0xa2, 0xd1, 0x60, 0xfe, 0x58, 0xf6, 0xf5, 0x4a, 0x27, 0x07,
+    0xac, 0x49, 0x10, 0x71, 0x85, 0xc4, 0xdf, 0xab, 0x73, 0xde, 0x82, 0x17,
+    0xb6, 0x0c, 0x97, 0x77, 0x8a, 0xd6, 0x88, 0x1e, 0x0b, 0xb5, 0x87, 0xa9,
+    0xc5, 0xcb, 0x34, 0x48, 0x19, 0x86, 0xf1, 0x72, 0x68, 0xd9, 0xdc, 0x4b,
+    0x6e, 0x06, 0x6c, 0x7d, 0x39, 0x47, 0xfe, 0xf9, 0x78, 0x23, 0x63, 0xa2,
+    0x3c, 0xdc, 0xd0, 0x23, 0x44, 0x64, 0x49, 0x06, 0x12, 0x43, 0x35, 0xc6,
+    0xcb, 0xd1, 0x87, 0x07, 0xaa, 0x9a, 0x03, 0x30, 0x93, 0xc7, 0xac, 0x92,
+    0x28, 0xb5, 0xbd, 0x43, 0xc2, 0x86, 0xda, 0x36, 0xf1, 0xc1, 0x81, 0x68,
+    0xd9, 0xcd, 0x00, 0x2d, 0x44, 0x16, 0xa7, 0x21, 0x37, 0x26, 0x87, 0xc8,
+    0x0a, 0xf4, 0x8b, 0x40, 0x29, 0x84, 0xe8, 0x70, 0x56, 0xb4, 0x3f, 0xc6,
+    0xc8, 0x96, 0xb5, 0xea, 0xc0, 0x7b, 0x4a, 0x67, 0x2b, 0x6d, 0xd0, 0x0d,
+    0xd4, 0x79, 0x2d, 0xbd, 0xe1, 0xf1, 0xb3, 0x50, 0x2e, 0xac, 0x22, 0xf4,
+    0x40, 0xec, 0x1b, 0xdc, 0xd5, 0x3d, 0xea, 0x7d, 0xa4, 0x53, 0x6a, 0x66,
+    0x0b, 0x85, 0xa2, 0x57, 0xb6, 0x0d, 0xfe, 0x8f, 0xc5, 0x55, 0x1d, 0xcc,
+    0xe1, 0x39, 0xc0, 0x32, 0xb5, 0x22, 0x35, 0x8b, 0x01, 0x0c, 0xb5, 0x4b,
+    0xd5, 0x1a, 0xd7, 0x39, 0xa0, 0x32, 0x47, 0x50, 0x30, 0xef, 0x74, 0xf3,
+    0x52, 0x53, 0x29, 0x8c, 0xaa, 0x24, 0x94, 0xb8, 0xc0, 0xb9, 0xc3, 0x18,
+    0x5a, 0x49, 0x6d, 0x0e, 0xe4, 0xcc, 0xa0, 0xfb, 0xb9, 0x45, 0xe2, 0x2f,
+    0x89, 0x00, 0x8c, 0x5a, 0xc8, 0x1c, 0x61, 0x21, 0x6c, 0x35, 0x05, 0xc9,
+    0x83, 0x07, 0x32, 0x73, 0x73, 0xa6, 0x34, 0x89, 0x83, 0x86, 0xb1, 0xa8,
+    0x49, 0xaa, 0xec, 0x0c, 0x9a, 0x32, 0xc6, 0x34, 0xbd, 0x9b, 0xbe, 0x74,
+    0x06, 0x3d, 0x6d, 0x83, 0x7d, 0x47, 0x4b, 0xb3, 0x45, 0x78, 0x3d, 0x8b,
+    0xbf, 0xca, 0xdc, 0x0c, 0xfb, 0xc5, 0x01, 0xe4, 0x0b, 0xcc, 0x9b, 0x05,
+    0xbf, 0x16, 0x05, 0xff, 0x2b, 0xd8, 0x20, 0xbc, 0xe2, 0xd8, 0xa0, 0x4c,
+    0xcd, 0x4f, 0xc3, 0xe7, 0x3b, 0xbd, 0x1d, 0x82, 0xf8, 0x6c, 0xce, 0x6f,
+    0x62, 0x05, 0x37, 0x9c, 0xb8, 0x26, 0x6a, 0x9f, 0x76, 0xcc, 0x97, 0xac,
+    0x1d, 0x8b, 0xde, 0x9b, 0x20, 0x52, 0x29, 0x3d, 0x96, 0x01, 0x31, 0x56,
+    0x4a, 0xea, 0x14, 0xf1, 0xdd, 0x2f, 0x6b, 0x91, 0x46, 0x58, 0x0d, 0xa8,
+    0xff, 0xcc, 0x4f, 0x95, 0xbc, 0x2e, 0x18, 0x9e, 0x55, 0xfc, 0x27, 0x6a,
+    0x15, 0x64, 0x68, 0x33, 0x5f, 0xa9, 0xda, 0xe4, 0x10, 0xe1, 0x41, 0x3b,
+    0x59, 0xd7, 0x61, 0x5c, 0xa4, 0x7b, 0x3d, 0x28, 0x09, 0x59, 0x45, 0x65,
+    0x68, 0xe9, 0xc8, 0x09, 0x13, 0xa3, 0x61, 0xac, 0xba, 0x98, 0x6d, 0x98,
+    0xe3, 0x03, 0xa1, 0xe6, 0xf3, 0x5f, 0xb0, 0x1e, 0x72, 0x0b, 0x46, 0xc8,
+    0x51, 0x26, 0xbf, 0xf9, 0x3e, 0x55, 0xc0, 0x9b, 0x7e, 0x09, 0x63, 0x85,
+    0x92, 0x18, 0xf2, 0xf4, 0x17, 0x2e, 0x7d, 0x05, 0x99, 0x5e, 0x1d, 0xb2,
+    0x3e, 0xad, 0x68, 0x29, 0x6d, 0x21, 0xe9, 0xb1, 0x38, 0xd5, 0x3e, 0xcc,
+    0x5f, 0xe5, 0xd1, 0x16, 0xa8, 0x33, 0x4f, 0xbc, 0x28, 0x21, 0x14, 0x38,
+    0xdd, 0x45, 0x0d, 0xa7, 0x00, 0x41, 0x5d, 0x5f, 0x98, 0x42, 0x7c, 0x54,
+    0x16, 0x4f, 0x25, 0xf1, 0x46, 0x76, 0xe4, 0x67, 0x58, 0x5b, 0x65, 0x73,
+    0xdf, 0xfd, 0x1c, 0x52, 0x61, 0x4d, 0x95, 0xb7, 0x78, 0x47, 0x50, 0x2d,
+    0xc9, 0xab, 0x14, 0x1c, 0xae, 0x9c, 0xdc, 0x17, 0xdd, 0xcc, 0xe2, 0x5c,
+    0x03, 0x0e, 0xe0, 0x2a, 0x81, 0xf0, 0xa7, 0xb9, 0x23, 0x21, 0x04, 0xbe,
+    0x5c, 0xc9, 0x55, 0x58, 0x17, 0x26, 0x0c, 0xb4, 0x52, 0x24, 0xb7, 0x5a,
+    0xb7, 0x0d, 0x7b, 0xfe, 0xe9, 0xd3, 0xda, 0x16, 0x43, 0xfa, 0x3b, 0xb3,
+    0xa1, 0x3e, 0x48, 0xe1, 0x68, 0xf5, 0x51, 0xb1, 0xf3, 0x62, 0x06, 0x93,
+    0x26, 0xe8, 0xa2, 0x9d, 0x9a, 0x7d, 0xf7, 0xa2, 0x8f, 0xe0, 0xe7, 0xa9,
+    0x6e, 0xa3, 0xce, 0x7f, 0xfb, 0x94, 0x56, 0xc8, 0x2d, 0x6b, 0xcd, 0x2f,
+    0xa0, 0x1f, 0x9b, 0x7b, 0x7a, 0xd4, 0x35, 0xe6, 0xa0, 0xa9, 0x09, 0x1b,
+    0x7c, 0x89, 0xc0, 0xd1, 0xd1, 0x34, 0x99, 0x59, 0xb5, 0x6b, 0xb3, 0x29,
+    0x54, 0xbf, 0xf0, 0xe7, 0x81, 0xee, 0x86, 0x28, 0x6e, 0x68, 0xb2, 0x22,
+    0xc2, 0x08, 0x84, 0xb7, 0x12, 0xfc, 0x14, 0x55, 0x61, 0xea, 0x36, 0x59,
+    0x51, 0x14, 0x28, 0x21, 0x30, 0xc3, 0x87, 0x91, 0xad, 0x1b, 0x9d, 0x50,
+    0x53, 0xf8, 0x1e, 0x2c, 0x90, 0x14, 0x54, 0x67, 0xcf, 0x39, 0x76, 0x4d,
+    0xfb, 0x4c, 0x7e, 0x0c, 0x3d, 0xa5, 0x79, 0x8c, 0x03, 0x72, 0xcb, 0xf3,
+    0xd0, 0x2f, 0x20, 0xc3, 0xc0, 0x00, 0x38, 0x90, 0x1d, 0x9f, 0x97, 0xd6,
+    0xc2, 0x5c, 0xc8, 0xb5, 0x86, 0x94, 0x30, 0x9d, 0x7a, 0x06, 0xb4, 0x4d,
+    0x40, 0x04, 0xa4, 0x67, 0xb1, 0x12, 0x38, 0xf9, 0x77, 0x45, 0xc0, 0x57,
+    0x4c, 0xc3, 0x24, 0x96, 0xf6, 0xf0, 0x99, 0x97, 0x50, 0x2e, 0x78, 0xe3,
+    0x61, 0x93, 0x32, 0x33, 0x43, 0x6c, 0x2b, 0x38, 0xa2, 0xd3, 0xe3, 0xc5,
+    0xe1, 0x8a, 0xe1, 0xa5, 0x9a, 0x59, 0xa0, 0xdc, 0x49, 0x9c, 0x81, 0x69,
+    0x24, 0x0b, 0xc6, 0xf7, 0x4e, 0x8c, 0xc7, 0x66, 0xd5, 0x98, 0xc1, 0x88,
+    0x63, 0xa9, 0xeb, 0x4d, 0xaa, 0x9c, 0x6c, 0xfe, 0xb1, 0x3b, 0x69, 0x47,
+    0x99, 0xc1, 0xbd, 0x8a, 0x4c, 0xf7, 0xad, 0x9c, 0x54, 0x5b, 0xca, 0x99,
+    0x23, 0x3b, 0xef, 0x25, 0x77, 0xa1, 0x0f, 0x0a, 0x1c, 0xf9, 0x08, 0x7e,
+    0xee, 0x26, 0xd8, 0x4d, 0x14, 0xc7, 0x62, 0xb9, 0x44, 0xb6, 0xbb, 0x3c,
+    0xaa, 0x3b, 0x22, 0x48, 0xfb, 0x8e, 0x3b, 0xed, 0x08, 0x3d, 0x89, 0x9b,
+    0xf8, 0x44, 0xca, 0xfa, 0x26, 0x78, 0x29, 0xde, 0xd6, 0xf1, 0x7b, 0x59,
+    0x5a, 0xe6, 0xd1, 0x24, 0x27, 0x11, 0xd6, 0x7d, 0x07, 0x49, 0xdd, 0xff,
+    0x6d, 0x62, 0x5b, 0x9d, 0x12, 0x81, 0x00, 0xd7, 0xda, 0x00, 0xfb, 0xf7,
+    0x4f, 0x2d, 0xf4, 0x64, 0xf1, 0xfb, 0x07, 0x23, 0x97, 0xe9, 0x0b, 0x22,
+    0x9a, 0x3d, 0xf6, 0x87, 0xd8, 0x23, 0xf8, 0x54, 0x36, 0xa0, 0xab, 0xb8,
+    0x99, 0x8b, 0x83, 0x98, 0x67, 0x33, 0x79, 0x2f, 0x60, 0x99, 0x16, 0x26,
+    0x50, 0xfc, 0x9d, 0xea, 0xdc, 0x92, 0xf4, 0x7c, 0x44, 0xef, 0xed, 0x23,
+    0x5e, 0x11, 0x0c, 0x6a, 0xc9, 0xf5, 0x9b, 0x64, 0x65, 0x58, 0x34, 0xc0,
+    0x18, 0xc2, 0x3c, 0xf4, 0x4f, 0x5c, 0x06, 0x71, 0x59, 0xa9, 0xcd, 0xad,
+    0x8b, 0xfd, 0x93, 0x05, 0xfc, 0x48, 0x92, 0xa2, 0xed, 0x9d, 0xa5, 0x89,
+    0x29, 0x35, 0x76, 0x16, 0x2a, 0x69, 0xeb, 0x0c, 0xef, 0xe6, 0x90, 0xa8,
+    0x18, 0x8b, 0x7e, 0x0e, 0x2c, 0xed, 0x34, 0x37, 0x23, 0xc3, 0x24, 0x7b,
+    0x67, 0x53, 0x84, 0xbe, 0x5c, 0xe9, 0x8c, 0x37, 0x8e, 0x0e, 0x53, 0xb9,
+    0xaa, 0x60, 0x64, 0x5e, 0x67, 0x88, 0x88, 0x72, 0x27, 0xb6, 0x8a, 0x72,
+    0x44, 0xdf, 0xe1, 0x69, 0xb7, 0x1c, 0x35, 0x79, 0xce, 0xab, 0x3a, 0x04,
+    0x60, 0xa3, 0x60, 0xd8, 0x84, 0x81, 0x61, 0xbc, 0x95, 0xc6, 0x9d, 0x3f,
+    0x7d, 0xbd, 0x4b, 0x1d, 0x40, 0x35, 0x97, 0x6f, 0xd9, 0x0c, 0x51, 0xa7,
+    0xac, 0x5b, 0xe8, 0xa1, 0xa8, 0x9b, 0x4e, 0x3c, 0x88, 0x29, 0x23, 0xca,
+    0x83, 0x1a, 0xc4, 0x5c, 0xec, 0x13, 0x1a, 0x07, 0x5d, 0xf3, 0x58, 0xa6,
+    0x17, 0x1c, 0x09, 0xca, 0x5f, 0x14, 0x47, 0xf6, 0x94, 0x2f, 0xe8, 0x98,
+    0x31, 0x51, 0xbe, 0x32, 0xaa, 0x8c, 0xb0, 0x79, 0x88, 0xfa, 0xa3, 0x9c,
+    0xcc, 0xc1, 0xf6, 0x25, 0xa9, 0x5d, 0xa1, 0x46, 0xf1, 0x30, 0xd0, 0x41,
+    0xf9, 0x5e, 0xca, 0x28, 0x06, 0x3c, 0xce, 0xb2, 0x40, 0xe3, 0xaf, 0x5e,
+    0x53, 0x0e, 0xfc, 0x94, 0x9d, 0x6d, 0xc1, 0x90, 0x24, 0x00, 0x31, 0xcf,
+    0x8d, 0x4a, 0xce, 0x81, 0xac, 0xe0, 0x88, 0x2e, 0xf0, 0x13, 0xac, 0x3c,
+    0x48, 0xde, 0x0f, 0xdd, 0xc3, 0xcd, 0xa2, 0xc0, 0x5d, 0x67, 0x33, 0x2a,
+    0xf8, 0x93, 0x25, 0x95, 0x76, 0x5f, 0x0c, 0xfc, 0x88, 0x4d, 0x9d, 0x99,
+    0x69, 0x66, 0x89, 0xfe, 0x09, 0xb5, 0x78, 0xae, 0xa0, 0x22, 0x1e, 0x41,
+    0xdc, 0xad, 0x8a, 0xef, 0x89, 0x74, 0x96, 0xc5, 0x83, 0x08, 0xe4, 0xec,
+    0xb0, 0xaf, 0xd9, 0xdb, 0x83, 0x42, 0xea, 0x96, 0xf4, 0x3b, 0xa2, 0x9a,
+    0x73, 0x04, 0x99, 0x59, 0xfe, 0x21, 0x35, 0xdc, 0xb3, 0xe8, 0x81, 0x5a,
+    0xe5, 0x4e, 0x51, 0x9c, 0xc6, 0x5d, 0x81, 0xae, 0x00, 0x0a, 0xee, 0xbf,
+    0xa2, 0x4d, 0xdf, 0xec, 0xcd, 0x86, 0x62, 0x9b, 0xd3, 0xee, 0x58, 0x8e,
+    0x69, 0x0c, 0x7f, 0x83, 0xfc, 0xf1, 0x19, 0xde, 0x05, 0x81, 0x3d, 0xe0,
+    0x46, 0x95, 0xaf, 0x39, 0x13, 0xbf, 0xac, 0xa0, 0x71, 0x00, 0xeb, 0xb8,
+    0x92, 0xe7, 0x92, 0x86, 0x29, 0xf8, 0x78, 0x02, 0x19, 0xc5, 0x72, 0xe1,
+    0x8f, 0xce, 0x62, 0x2a, 0x7b, 0x0f, 0xef, 0xa1, 0x79, 0xbf, 0xf9, 0x51,
+    0x01, 0xc4, 0x3d, 0xbf, 0xbd, 0xcd, 0xf3, 0x62, 0x97, 0xf9, 0x68, 0x9c,
+    0xb8, 0x60, 0x6d, 0xb3, 0x75, 0xb3, 0x41, 0xff, 0xb2, 0x94, 0x67, 0x6f,
+    0x74, 0xbb, 0xaa, 0x3a, 0x41, 0x56, 0x0a, 0x16, 0x8c, 0xd9, 0xc5, 0xa6,
+    0x22, 0x0d, 0xb5, 0x1e, 0x31, 0xf2, 0x87, 0xe3, 0xed, 0x3d, 0x5a, 0x38,
+    0x59, 0x4f, 0x35, 0x99, 0xfe, 0x60, 0x94, 0xe2, 0x40, 0x90, 0xe3, 0x08,
+    0x16, 0x8a, 0x19, 0x65, 0x3e, 0x1e, 0x16, 0x30, 0xe5, 0xba, 0x5e, 0x84,
+    0xef, 0x76, 0x4a, 0x0e, 0x4e, 0x44, 0xd9, 0x3b, 0x6f, 0xb1, 0xe5, 0x89,
+    0xf0, 0x7b, 0x09, 0x02, 0x8e, 0x61, 0xe9, 0xfd, 0xcb, 0x8f, 0x24, 0x90,
+    0xde, 0x3c, 0x0d, 0xad, 0x1c, 0xa5, 0x28, 0xcf, 0x45, 0xf0, 0x12, 0x3e,
+    0x64, 0x7f, 0x55, 0xa4, 0x21, 0x54, 0xff, 0x15, 0x07, 0xfe, 0xd0, 0x98,
+    0x24, 0x0f, 0xf6, 0xe2, 0xa4, 0x51, 0x34, 0xdf, 0x14, 0x8e, 0x09, 0xaf,
+    0x51, 0xe9, 0xa0, 0xb5, 0x59, 0x98, 0x07, 0x93, 0xfe, 0xb9, 0x57, 0x30,
+    0x33, 0x68, 0xc7, 0xe9, 0x38, 0x61, 0xe1, 0x22, 0x3c, 0x1b, 0xac, 0x68,
+    0x75, 0x51, 0x34, 0xcc, 0x74, 0x35, 0x1b, 0xc0, 0x2c, 0xaa, 0xf1, 0xd5,
+    0xfe, 0x2e, 0x5f, 0x88, 0x59, 0x28, 0x5a, 0xfe, 0x70, 0x22, 0xb4, 0xfc,
+    0x73, 0xe2, 0x62, 0x07, 0xd2, 0x8f, 0xbc, 0x5d, 0x1f, 0x61, 0xbb, 0xf2,
+    0x2f, 0xc2, 0x21, 0x09, 0x58, 0x60, 0x22, 0x72, 0x92, 0xca, 0x04, 0xf8,
+    0x56, 0x4e, 0x76, 0xec, 0xc4, 0x03, 0x33, 0xe1, 0x4b, 0xaa, 0x2e, 0x71,
+    0x17, 0x2d, 0x71, 0xd3, 0x29, 0xf2, 0x78, 0x0f, 0xe7, 0xdf, 0x9f, 0xb1,
+    0x75, 0x96, 0x17, 0x5f, 0xc0, 0x77, 0x3d, 0x6d, 0x50, 0xd1, 0x50, 0x40,
+    0x1a, 0x17, 0xae, 0x93, 0xdd, 0x0f, 0x93, 0xa9, 0xb0, 0x9b, 0xc2, 0xab,
+    0x7d, 0xa2, 0x8a, 0xf0, 0xe9, 0xc2, 0x5d, 0xc8, 0x33, 0xe5, 0xd9, 0x51,
+    0xfc, 0x51, 0x5f, 0x26, 0x10, 0x15, 0x89, 0x12, 0x35, 0x42, 0xb3, 0x7a,
+    0x10, 0x98, 0x69, 0xfa, 0xa2, 0xa0, 0x86, 0xa7, 0x25, 0x7d, 0x51, 0xcf,
+    0xc3, 0xb3, 0x95, 0xfc, 0x96, 0x9f, 0x60, 0x42, 0x8c, 0x6c, 0x97, 0x18,
+    0x0c, 0xfb, 0x49, 0xb7, 0x61, 0x25, 0xb8, 0xb1, 0xc9, 0x87, 0xf3, 0xf0,
+    0xc5, 0xa1, 0x3d, 0x90, 0x24, 0xe5, 0xca, 0xe1, 0x0f, 0x6a, 0x76, 0x74,
+    0xd5, 0x6f, 0x0e, 0x07, 0xdf, 0x0c, 0xeb, 0x0a, 0xb9, 0xfe, 0xd2, 0xa0,
+    0xf5, 0x6d, 0x1d, 0xe1, 0xaa, 0x3a, 0xb8, 0x39, 0x30, 0x52, 0x8d, 0xe0,
+    0x4e, 0x4e, 0xa0, 0x0e, 0x85, 0x1a, 0xdd, 0x0f, 0x14, 0xff, 0x8a, 0x6c,
+    0x7b, 0x9c, 0xf2, 0x58, 0x6a, 0x62, 0x15, 0x39, 0x04, 0xf8, 0x39, 0xf4,
+    0xe2, 0xad, 0x12, 0xd7, 0x28, 0x27, 0xc5, 0x49, 0xdf, 0x18, 0x59, 0xc0,
+    0xa7, 0xcc, 0xe5, 0x56, 0x61, 0x99, 0xce, 0x31, 0x05, 0x0b, 0x06, 0x3a,
+    0xb0, 0x92, 0x19, 0x22, 0x67, 0x77, 0xba, 0x34, 0x97, 0xdf, 0x5f, 0x9b,
+    0x6e, 0xac, 0x44, 0xb6, 0xd1, 0x57, 0xac, 0xa1, 0x2b, 0x5e, 0xf1, 0x27,
+    0x58, 0xba, 0xfe, 0x05, 0xd7, 0x41, 0xa6, 0x88, 0xc6, 0xbc, 0x93, 0xff,
+    0x2a, 0x62, 0x0b, 0x35, 0x1b, 0xb9, 0xd9, 0x2d, 0x02, 0xc2, 0x41, 0xdc,
+    0x8c, 0x7b, 0x9e, 0xda, 0xfd, 0xb3, 0x36, 0x1f, 0xc4, 0x26, 0xcb, 0x75,
+    0xec, 0xcd, 0xc5, 0xe7, 0xb3, 0x1e, 0x2f, 0x30, 0x17, 0x22, 0x95, 0x7b,
+    0xdd, 0xfe, 0xa9, 0xe7, 0x63, 0x3b, 0xb0, 0xcc, 0x4d, 0x8a, 0x46, 0x70,
+    0x77, 0xbf, 0xe6, 0x2e, 0x3f, 0xd6, 0x1f, 0xe9, 0x86, 0xf2, 0x63, 0x09,
+    0x0b, 0xa0, 0xc4, 0xfa, 0x08, 0x65, 0x99, 0x5d, 0x79, 0x4c, 0x11, 0xe6,
+    0x3f, 0xd7, 0x94, 0xc3, 0x41, 0x0c, 0x47, 0xc0, 0x64, 0xe2, 0xdc, 0x88,
+    0x20, 0x50, 0x25, 0xc9, 0x4b, 0xae, 0x06, 0x24, 0x4c, 0xaf, 0x33, 0x26,
+    0x62, 0xe2, 0xf9, 0xaf, 0xcf, 0x48, 0xe1, 0x16, 0xaa, 0x64, 0x01, 0x70,
+    0xd8, 0xc3, 0xef, 0x01, 0x6a, 0x64, 0xf0, 0xf5, 0x4a, 0xd0, 0xdd, 0x21,
+    0xd5, 0x57, 0x28, 0x65, 0x3b, 0x04, 0x3e, 0xc9, 0x94, 0x59, 0x42, 0xac,
+    0x9b, 0xdf, 0x4e, 0x33, 0xae, 0xd1, 0xda, 0xfc, 0xf3, 0xe6, 0xa1, 0x4a,
+    0xb4, 0xa4, 0x24, 0x57, 0x5a, 0x34, 0x6f, 0x6f, 0x94, 0xe9, 0x88, 0x42,
+    0xc5, 0x0d, 0xdf, 0x42, 0x44, 0x08, 0x7b, 0x99, 0x69, 0x59, 0xb6, 0x54,
+    0x67, 0x7d, 0x83, 0xb8, 0xea, 0x53, 0x9b, 0x1c, 0xb2, 0xd7, 0x44, 0x20,
+    0x30, 0xb3, 0x72, 0x10, 0x86, 0x87, 0x82, 0x58, 0xb4, 0xf4, 0x08, 0xd1,
+    0xd9, 0x8a, 0x84, 0xcc, 0xb0, 0x3a, 0xf1, 0xde, 0x24, 0x16, 0x18, 0x7e,
+    0xd0, 0x92, 0xb8, 0x72, 0x15, 0x08, 0x0c, 0xac, 0xa1, 0x96, 0x24, 0xcf,
+    0x47, 0x31, 0x3b, 0xc7, 0x28, 0x11, 0xf0, 0x42, 0xe6, 0x40, 0x63, 0xa9,
+    0xeb, 0xff, 0x80, 0x58, 0x0f, 0xee, 0x4e, 0xc5, 0xc0, 0xe9, 0xb5, 0xc2,
+    0x18, 0x71, 0x97, 0xfe, 0x1a, 0x53, 0x93, 0xe4, 0x77, 0x92, 0x25, 0xa4,
+    0x27, 0x03, 0xf6, 0x64, 0xf1, 0x63, 0x37, 0x7b, 0xb7, 0x3a, 0xe2, 0xcb,
+    0x0c, 0x83, 0x0b, 0x52, 0x3f, 0xee, 0x41, 0x9a, 0x55, 0x8e, 0x85, 0x4a,
+    0x23, 0x64, 0xea, 0x68, 0xe8, 0x5e, 0xd7, 0xf3, 0x9e, 0xbc, 0x6d, 0x78,
+    0xba, 0xd2, 0xe5, 0xe8, 0x35, 0xfa, 0x74, 0x0f, 0x33, 0x2a, 0x0e, 0xcc,
+    0xb2, 0x01, 0xaf, 0x53, 0x04, 0x70, 0x8a, 0xdd, 0x9e, 0x95, 0xcb, 0x3a,
+    0x81, 0x25, 0x2f, 0x77, 0xb4, 0x31, 0xc7, 0x0b, 0x14, 0xc4, 0xd6, 0x20,
+    0xa7, 0x80, 0xb1, 0xd5, 0x3d, 0x90, 0x04, 0xaf, 0x59, 0x20, 0xac, 0x6c,
+    0x5e, 0xfc, 0xda, 0x7f, 0x9e, 0x70, 0x08, 0xe2, 0x5c, 0x02, 0x9c, 0x95,
+    0x7d, 0xf9, 0xab, 0x2c, 0x15, 0x90, 0xc6, 0xab, 0x49, 0x21, 0x74, 0xcb,
+    0x93, 0xb0, 0x44, 0x03, 0xfa, 0xc5, 0x35, 0x54, 0xb3, 0x4e, 0x10, 0x25,
+    0x25, 0x94, 0x7d, 0x45, 0x74, 0xb5, 0x58, 0x85, 0xac, 0xb2, 0xc2, 0xd7,
+    0xb5, 0xbe, 0xf0, 0xc8, 0x53, 0xdc, 0x62, 0xf8, 0x9b, 0x88, 0x98, 0xa7,
+    0xda, 0x5a, 0x83, 0x22, 0xe4, 0x26, 0x83, 0x45, 0x41, 0x6f, 0x42, 0x61,
+    0xcb, 0xc0, 0x89, 0x56, 0x2a, 0xef, 0x1f, 0xbb, 0xb2, 0xc9, 0xa1, 0xc8,
+    0x16, 0x2d, 0x43, 0xc1, 0x13, 0x29, 0x76, 0xfa, 0x64, 0x4e, 0xe0, 0x66,
+    0x5a, 0x9d, 0x35, 0x8f, 0x42, 0xd4, 0xe6, 0xea, 0x1d, 0xaf, 0x63, 0x73,
+    0xb3, 0xff, 0x62, 0xd3, 0xdb, 0x60, 0x01, 0x7b, 0xf9, 0x03, 0xf2, 0x89,
+    0x29, 0xe8, 0x48, 0xac, 0x2a, 0x71, 0x71, 0xdc, 0x80, 0xb1, 0x96, 0x5e,
+    0xdd, 0x23, 0xea, 0xac, 0x44, 0xbc, 0xf3, 0x70, 0xf4, 0x40, 0x92, 0x94,
+    0x8a, 0x89, 0x27, 0x02, 0xe7, 0x7f, 0x59, 0x27, 0x12, 0x11, 0xf1, 0x14,
+    0x2d, 0x1c, 0x35, 0x89, 0xd6, 0xca, 0xa7, 0xe5, 0xba, 0x3c, 0x2b, 0x91,
+    0x50, 0x2f, 0x87, 0x1f, 0x89, 0x12, 0x3e, 0x7e, 0x69, 0x47, 0x1e, 0x86,
+    0xaf, 0x4d, 0xe6, 0x27, 0x04, 0x11, 0x61, 0x15, 0xdd, 0x0f, 0xe0, 0xe6,
+    0x3f, 0x9f, 0x83, 0x13, 0x52, 0x41, 0x72, 0xba, 0x9e, 0xe2, 0x2e, 0x9c,
+    0x98, 0xf5, 0x16, 0x17, 0x2a, 0xa7, 0xe5, 0x74, 0x26, 0x93, 0x88, 0xda,
+    0x7f, 0x9b, 0x2e, 0x38, 0x4c, 0x73, 0x86, 0x98, 0xc6, 0xef, 0xb6, 0x34,
+    0x02, 0x8c, 0x70, 0xbe, 0x81, 0x02, 0x3a, 0xa0, 0xb7, 0x33, 0x40, 0x6a,
+    0x7b, 0x2c, 0xe6, 0xdc, 0x00, 0xb6, 0x86, 0x83, 0xbd, 0x8b, 0x75, 0xff,
+    0xaa, 0xa0, 0x4a, 0x14, 0xf2, 0xed, 0xd0, 0xa3, 0xe3, 0x46, 0x1f, 0x63,
+    0x04, 0xe6, 0xd5, 0x35, 0x14, 0xb2, 0xf4, 0x49, 0x06, 0x92, 0x94, 0x01,
+    0x29, 0x32, 0x35, 0x43, 0x98, 0xdd, 0xc9, 0x58, 0x16, 0x19, 0x38, 0x7f,
+    0xf1, 0x03, 0x0e, 0x9b, 0xfc, 0xc9, 0xaf, 0x4a, 0xee, 0x58, 0x66, 0xd0,
+    0x8b, 0x34, 0x49, 0xfe, 0x4b, 0x08, 0xf2, 0xbe, 0xdb, 0x6e, 0x9c, 0xe8,
+    0x1d, 0x99, 0xdd, 0xfc, 0x3b, 0x29, 0x95, 0x90, 0x58, 0xd7, 0x6f, 0x1a,
+    0x07, 0x2d, 0x18, 0xee, 0x05, 0x15, 0x23, 0x3b, 0xce, 0x1f, 0xdf, 0x97,
+    0x1c, 0x95, 0x29, 0xf2, 0x07, 0x7c, 0x5c, 0x3a, 0x3e, 0x1b, 0x4c, 0x0e,
+    0xde, 0x8e, 0x59, 0x72, 0x82, 0x00, 0xd7, 0x26, 0x4b, 0xb7, 0x2f, 0xb0,
+    0x8e, 0x19, 0x53, 0xdf, 0xf6, 0x58, 0xbe, 0x0d, 0xd1, 0x0c, 0x59, 0x2c,
+    0xf0, 0xe0, 0xb7, 0xdf, 0x82, 0x90, 0x11, 0x26, 0x02, 0x08, 0x3e, 0xb4,
+    0x50, 0x48, 0x75, 0x5e, 0x54, 0x29, 0xff, 0x2b, 0x70, 0xa4, 0x16, 0x10,
+    0xcc, 0x3e, 0x40, 0x3c, 0xf0, 0xda, 0x54, 0xe6, 0x36, 0x0c, 0x5a, 0xde,
+    0x12, 0x82, 0x4f, 0x1d, 0xa8, 0x58, 0x1c, 0xc3, 0x99, 0x6f, 0x1b, 0x53,
+    0x91, 0x3e, 0xb8, 0xbf, 0x3b, 0x37, 0x66, 0xa7, 0xff, 0xe6, 0x46, 0x60,
+    0x72, 0xc3, 0x6e, 0x56, 0xc0, 0x36, 0x66, 0x2e, 0x6d, 0xf8, 0x33, 0xfa,
+    0x23, 0xfa, 0xff, 0x55, 0xa2, 0x4b, 0xb6, 0xc1, 0x2b, 0x8d, 0xc1, 0x9f,
+    0x3c, 0xf2, 0xb2, 0x66, 0xd6, 0x66, 0x0f, 0x53, 0x75, 0x5f, 0x69, 0x7f,
+    0xc9, 0x33, 0xce, 0x3b, 0x86, 0x43, 0x0f, 0x92, 0xdc, 0x2d, 0xb6, 0xcc,
+    0x3a, 0x5d, 0xbb, 0xe8, 0xc5, 0x0c, 0x41, 0x44, 0x75, 0xb3, 0xdd, 0xf1,
+    0x34, 0x8b, 0xc1, 0x37, 0x1f, 0xfc, 0x18, 0x5a, 0x2d, 0x78, 0x13, 0x13,
+    0xff, 0x75, 0x70, 0x18, 0x86, 0x5a, 0x60, 0xc3, 0xd2, 0x9d, 0xeb, 0xe7,
+    0x59, 0xd8, 0x3b, 0xc9, 0x5d, 0xe7, 0x32, 0xbb, 0x43, 0x59, 0xc8, 0x99,
+    0xf4, 0xa3, 0x07, 0x8c, 0x0e, 0xa1, 0x99, 0x57, 0x6a, 0x5c, 0x7f, 0xcd,
+    0xa6, 0x63, 0x38, 0x7d, 0xcf, 0xb8, 0x27, 0xf1, 0xc5, 0x3d, 0x38, 0xf9,
+    0xc5, 0x6b, 0xba, 0x18, 0xb5, 0xb2, 0x08, 0x70, 0x92, 0xe6, 0xe1, 0xd9,
+    0x1b, 0xa5, 0xec, 0x83, 0xb2, 0x12, 0x5f, 0x73, 0x31, 0x08, 0xf2, 0x70,
+    0x8f, 0xb2, 0x40, 0xd6, 0xef, 0x19, 0x8f, 0x78, 0xa2, 0x05, 0xaa, 0x48,
+    0xad, 0x84, 0xb6, 0x0a, 0x19, 0x2e, 0x6f, 0x22, 0x9a, 0x3d, 0x8a, 0x80,
+    0x49, 0xfe, 0xff, 0xa0, 0xec, 0x99, 0xdb, 0x89, 0x38, 0x60, 0xf5, 0x56,
+    0x4d, 0x03, 0x20, 0x0c, 0x96, 0x04, 0xfc, 0x63, 0xbd, 0xa4, 0x59, 0xab,
+    0x1e, 0x43, 0x84, 0x04, 0xd8, 0x42, 0xe1, 0xc8, 0x03, 0xbd, 0x0e, 0x52,
+    0x36, 0xa1, 0x00, 0xfe, 0xc0, 0x42, 0xf9, 0x47, 0x1f, 0x98, 0xde, 0x39,
+    0x1e, 0xd0, 0x85, 0xdb, 0x70, 0x8e, 0x06, 0x39, 0xb0, 0x09, 0x2a, 0xb9,
+    0xb9, 0xa8, 0x50, 0x28, 0x1a, 0x26, 0x05, 0x7f, 0xdc, 0x56, 0xcf, 0x63,
+    0xf6, 0x0b, 0xfb, 0x46, 0x0f, 0x6d, 0x00, 0xec, 0x22, 0xa8, 0xe2, 0x21,
+    0x5e, 0xfd, 0x4c, 0xa2, 0xd7, 0x35, 0x37, 0xd5, 0xa7, 0xad, 0xf9, 0xf3,
+    0x03, 0xdf, 0xf1, 0x35, 0x63, 0x25, 0xb8, 0xba, 0x23, 0xb7, 0xd2, 0xc3,
+    0xaa, 0x4d, 0x59, 0x23, 0xc8, 0xf0, 0x64, 0x15, 0x96, 0xf5, 0xac, 0x7b,
+    0x7e, 0x95, 0x2d, 0xf3, 0xfe, 0x9b, 0xe9, 0x5c, 0x82, 0x61, 0xe9, 0xbc,
+    0x4f, 0x80, 0x07, 0x07, 0xb5, 0x85, 0xf8, 0x65, 0xac, 0xdf, 0xf5, 0x1b,
+    0x8c, 0x49, 0x7d, 0x96, 0xf6, 0xd5, 0xba, 0x6e, 0x3a, 0x3c, 0x18, 0x6c,
+    0x18, 0xa1, 0xaa, 0xfd, 0x9f, 0x56, 0x01, 0x4a, 0x96, 0xe3, 0xf7, 0x73,
+    0x35, 0x39, 0x62, 0xcb, 0x74, 0x8c, 0x4f, 0x4b, 0x59, 0xfc, 0x42, 0x1a,
+    0x7f, 0xe2, 0x12, 0x44, 0x26, 0xbb, 0x4e, 0xd5, 0xef, 0xda, 0x1d, 0xbe,
+    0xe5, 0x57, 0x94, 0x01, 0x49, 0xd7, 0xe7, 0xd6, 0x37, 0xf2, 0x01, 0xaa,
+    0xeb, 0x45, 0x52, 0x93, 0xec, 0x0f, 0xd2, 0xa1, 0x10, 0xa1, 0x63, 0x06,
+    0xdc, 0xb6, 0xf7, 0xb9, 0x27, 0x5f, 0x34, 0x66, 0xba, 0xfc, 0x49, 0x66,
+    0x75, 0x7c, 0xc1, 0xcf, 0xdc, 0xf2, 0x28, 0x5c, 0x62, 0x7e, 0x93, 0x99,
+    0xbf, 0x1c, 0x27, 0x50, 0x71, 0x96, 0x9b, 0xbc, 0xd6, 0xea, 0x12, 0x18,
+    0x26, 0x70, 0x76, 0x89, 0xa3, 0x05, 0x2b, 0x2f, 0x40, 0x59, 0x5c, 0x64,
+    0x6c, 0xad, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x02, 0x0a, 0x11, 0x1a, 0x21, 0x2b};
diff --git a/src/crypto/fipsmodule/mldsa/mldsa.cc.inc b/src/crypto/fipsmodule/mldsa/mldsa.cc.inc
index 0024010..e89d87c 100644
--- a/src/crypto/fipsmodule/mldsa/mldsa.cc.inc
+++ b/src/crypto/fipsmodule/mldsa/mldsa.cc.inc
@@ -30,6 +30,12 @@
 namespace mldsa {
 namespace {
 
+namespace fips {
+void ensure_keygen_self_test();
+void ensure_sign_self_test();
+void ensure_verify_self_test();
+}  // namespace fips
+
 constexpr int kDegree = 256;
 constexpr int kRhoBytes = 32;
 constexpr int kSigmaBytes = 64;
@@ -1397,7 +1403,7 @@
 // FIPS 204, Algorithm 6 (`ML-DSA.KeyGen_internal`). Returns 1 on success and 0
 // on failure.
 template <int K, int L>
-int mldsa_generate_key_external_entropy(
+int mldsa_generate_key_external_entropy_no_self_test(
     uint8_t out_encoded_public_key[public_key_bytes<K>()],
     struct private_key<K, L> *priv,
     const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
@@ -1461,6 +1467,16 @@
 }
 
 template <int K, int L>
+int mldsa_generate_key_external_entropy(
+    uint8_t out_encoded_public_key[public_key_bytes<K>()],
+    struct private_key<K, L> *priv,
+    const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
+  fips::ensure_keygen_self_test();
+  return mldsa_generate_key_external_entropy_no_self_test(
+      out_encoded_public_key, priv, entropy);
+}
+
+template <int K, int L>
 int mldsa_public_from_private(struct public_key<K> *pub,
                               const struct private_key<K, L> *priv) {
   // Intermediate values, allocated on the heap to allow use when there is a
@@ -1499,7 +1515,7 @@
 // FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`). Returns 1 on success and 0
 // on failure.
 template <int K, int L>
-int mldsa_sign_internal(
+int mldsa_sign_internal_no_self_test(
     uint8_t out_encoded_signature[signature_bytes<K>()],
     const struct private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
     const uint8_t *context_prefix, size_t context_prefix_len,
@@ -1605,6 +1621,11 @@
     if (constant_time_declassify_w(
             constant_time_ge_w(z_max, gamma1<K>() - beta<K>()) |
             constant_time_ge_w(r0_max, kGamma2 - beta<K>()))) {
+#if defined(BORINGSSL_FIPS_BREAK_TESTS)
+      // In order to show that our self-tests trigger both restart cases in
+      // this loop, printf-logging is added when built in break-test mode.
+      printf("MLDSA signature restart case 1.\n");
+#endif
       continue;
     }
 
@@ -1618,6 +1639,11 @@
     size_t h_ones = vector_count_ones(&values->sign.h);
     if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) |
                                    constant_time_lt_w(omega<K>(), h_ones))) {
+#if defined(BORINGSSL_FIPS_BREAK_TESTS)
+      // In order to show that our self-tests trigger both restart cases in
+      // this loop, printf-logging is added when built in break-test mode.
+      printf("MLDSA signature restart case 2.\n");
+#endif
       continue;
     }
 
@@ -1637,14 +1663,26 @@
   }
 }
 
+template <int K, int L>
+int mldsa_sign_internal(
+    uint8_t out_encoded_signature[signature_bytes<K>()],
+    const struct private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
+    const uint8_t *context_prefix, size_t context_prefix_len,
+    const uint8_t *context, size_t context_len,
+    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
+  fips::ensure_sign_self_test();
+  return mldsa_sign_internal_no_self_test(
+      out_encoded_signature, priv, msg, msg_len, context_prefix,
+      context_prefix_len, context, context_len, randomizer);
+}
+
 // FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`).
 template <int K, int L>
-int mldsa_verify_internal(const struct public_key<K> *pub,
-                          const uint8_t encoded_signature[signature_bytes<K>()],
-                          const uint8_t *msg, size_t msg_len,
-                          const uint8_t *context_prefix,
-                          size_t context_prefix_len, const uint8_t *context,
-                          size_t context_len) {
+int mldsa_verify_internal_no_self_test(
+    const struct public_key<K> *pub,
+    const uint8_t encoded_signature[signature_bytes<K>()], const uint8_t *msg,
+    size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len,
+    const uint8_t *context, size_t context_len) {
   // Intermediate values, allocated on the heap to allow use when there is a
   // limited amount of stack.
   struct values_st {
@@ -1712,6 +1750,18 @@
          OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * lambda_bytes<K>()) ==
              0;
 }
+template <int K, int L>
+int mldsa_verify_internal(const struct public_key<K> *pub,
+                          const uint8_t encoded_signature[signature_bytes<K>()],
+                          const uint8_t *msg, size_t msg_len,
+                          const uint8_t *context_prefix,
+                          size_t context_prefix_len, const uint8_t *context,
+                          size_t context_len) {
+  fips::ensure_verify_self_test();
+  return mldsa_verify_internal_no_self_test<K, L>(
+      pub, encoded_signature, msg, msg_len, context_prefix, context_prefix_len,
+      context, context_len);
+}
 
 struct private_key<6, 5> *private_key_from_external_65(
     const struct BCM_mldsa65_private_key *external) {
@@ -1724,19 +1774,19 @@
   return (struct private_key<6, 5> *)external;
 }
 
-struct public_key<6> *
-public_key_from_external_65(const struct BCM_mldsa65_public_key *external) {
-  static_assert(sizeof(struct BCM_mldsa65_public_key) ==
-                    sizeof(struct public_key<6>),
-                "MLDSA65 public key size incorrect");
-  static_assert(alignof(struct BCM_mldsa65_public_key) ==
-                    alignof(struct public_key<6>),
-                "MLDSA65 public key align incorrect");
+struct public_key<6> *public_key_from_external_65(
+    const struct BCM_mldsa65_public_key *external) {
+  static_assert(
+      sizeof(struct BCM_mldsa65_public_key) == sizeof(struct public_key<6>),
+      "MLDSA65 public key size incorrect");
+  static_assert(
+      alignof(struct BCM_mldsa65_public_key) == alignof(struct public_key<6>),
+      "MLDSA65 public key align incorrect");
   return (struct public_key<6> *)external;
 }
 
-struct private_key<8, 7> *
-private_key_from_external_87(const struct BCM_mldsa87_private_key *external) {
+struct private_key<8, 7> *private_key_from_external_87(
+    const struct BCM_mldsa87_private_key *external) {
   static_assert(sizeof(struct BCM_mldsa87_private_key) ==
                     sizeof(struct private_key<8, 7>),
                 "MLDSA87 private key size incorrect");
@@ -1746,17 +1796,177 @@
   return (struct private_key<8, 7> *)external;
 }
 
-struct public_key<8> *
-public_key_from_external_87(const struct BCM_mldsa87_public_key *external) {
-  static_assert(sizeof(struct BCM_mldsa87_public_key) ==
-                    sizeof(struct public_key<8>),
-                "MLDSA87 public key size incorrect");
-  static_assert(alignof(struct BCM_mldsa87_public_key) ==
-                    alignof(struct public_key<8>),
-                "MLDSA87 public key align incorrect");
+struct public_key<8> *public_key_from_external_87(
+    const struct BCM_mldsa87_public_key *external) {
+  static_assert(
+      sizeof(struct BCM_mldsa87_public_key) == sizeof(struct public_key<8>),
+      "MLDSA87 public key size incorrect");
+  static_assert(
+      alignof(struct BCM_mldsa87_public_key) == alignof(struct public_key<8>),
+      "MLDSA87 public key align incorrect");
   return (struct public_key<8> *)external;
 }
 
+namespace fips {
+
+#include "fips_known_values.inc"
+
+static int keygen_self_test() {
+  private_key<6, 5> priv;
+  uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
+  if (!mldsa_generate_key_external_entropy_no_self_test(pub_bytes, &priv,
+                                                        kGenerateKeyEntropy)) {
+    return 0;
+  }
+
+  uint8_t priv_bytes[BCM_MLDSA65_PRIVATE_KEY_BYTES];
+  CBB cbb;
+  CBB_init_fixed(&cbb, priv_bytes, sizeof(priv_bytes));
+  if (!mldsa_marshal_private_key(&cbb, &priv)) {
+    return 0;
+  }
+
+  static_assert(sizeof(pub_bytes) == sizeof(kExpectedPublicKey));
+  static_assert(sizeof(priv_bytes) == sizeof(kExpectedPrivateKey));
+  if (!BORINGSSL_check_test(kExpectedPublicKey, pub_bytes, sizeof(pub_bytes),
+                            "ML-DSA keygen public key") ||
+      !BORINGSSL_check_test(kExpectedPrivateKey, priv_bytes, sizeof(priv_bytes),
+                            "ML-DSA keygen private key")) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int sign_self_test() {
+  private_key<6, 5> priv;
+  uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
+  if (!mldsa_generate_key_external_entropy(pub_bytes, &priv, kSignEntropy)) {
+    return 0;
+  }
+
+  const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
+  uint8_t sig[BCM_MLDSA65_SIGNATURE_BYTES];
+
+  // This message triggers the first restart case for signing.
+  uint8_t message[4] = {0};
+  if (!mldsa_sign_internal_no_self_test(sig, &priv, message, sizeof(message),
+                                        nullptr, 0, nullptr, 0, randomizer)) {
+    return 0;
+  }
+  static_assert(sizeof(kExpectedCase1Signature) == sizeof(sig));
+  if (!BORINGSSL_check_test(kExpectedCase1Signature, sig, sizeof(sig),
+                            "ML-DSA sign case 1")) {
+    return 0;
+  }
+
+  // This message triggers the second restart case for signing.
+  message[0] = 123;
+  if (!mldsa_sign_internal_no_self_test(sig, &priv, message, sizeof(message),
+                                        nullptr, 0, nullptr, 0, randomizer)) {
+    return 0;
+  }
+  static_assert(sizeof(kExpectedCase2Signature) == sizeof(sig));
+  if (!BORINGSSL_check_test(kExpectedCase2Signature, sig, sizeof(sig),
+                            "ML-DSA sign case 2")) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int verify_self_test() {
+  struct values_st {
+    private_key<6, 5> priv;
+    public_key<6> pub;
+    uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
+  };
+  std::unique_ptr<values_st, DeleterFree<values_st>> values(
+      reinterpret_cast<struct values_st *>(OPENSSL_malloc(sizeof(values_st))));
+  if (!values) {
+    return 0;
+  }
+
+  if (!mldsa_generate_key_external_entropy(values->pub_bytes, &values->priv,
+                                           kSignEntropy)) {
+    return 0;
+  }
+
+  const uint8_t message[4] = {1, 0};
+  if (!mldsa_public_from_private(&values->pub, &values->priv) ||
+      !mldsa_verify_internal_no_self_test<6, 5>(
+          &values->pub, kExpectedVerifySignature, message, sizeof(message),
+          nullptr, 0, nullptr, 0)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+template <int K, int L>
+int check_key(private_key<K, L> *priv) {
+  uint8_t sig[signature_bytes<K>()];
+  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
+  mldsa::public_key<K> pub;
+  if (!mldsa_public_from_private(&pub, priv) ||
+      !mldsa_sign_internal_no_self_test(sig, priv, nullptr, 0, nullptr, 0,
+                                        nullptr, 0, randomizer)) {
+    return 0;
+  }
+
+  if (boringssl_fips_break_test("MLDSA_PWCT")) {
+    sig[0] ^= 1;
+  }
+
+  if (!mldsa_verify_internal_no_self_test<K, L>(&pub, sig, nullptr, 0, nullptr,
+                                                0, nullptr, 0)) {
+    return 0;
+  }
+  return 1;
+}
+
+#if defined(BORINGSSL_FIPS)
+
+DEFINE_STATIC_ONCE(g_mldsa_keygen_self_test_once)
+
+void ensure_keygen_self_test(void) {
+  CRYPTO_once(g_mldsa_keygen_self_test_once_bss_get(), []() {
+    if (!keygen_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_mldsa_sign_self_test_once)
+
+void ensure_sign_self_test(void) {
+  CRYPTO_once(g_mldsa_sign_self_test_once_bss_get(), []() {
+    if (!sign_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_mldsa_verify_self_test_once)
+
+void ensure_verify_self_test(void) {
+  CRYPTO_once(g_mldsa_verify_self_test_once_bss_get(), []() {
+    if (!verify_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+#else
+
+void ensure_keygen_self_test(void) {}
+void ensure_sign_self_test(void) {}
+void ensure_verify_self_test(void) {}
+
+#endif
+
+}  // namespace fips
+
 }  // namespace
 }  // namespace mldsa
 
@@ -1783,6 +1993,12 @@
       CBS_len(in) == 0);
 }
 
+bcm_status BCM_mldsa65_check_key_fips(
+    struct BCM_mldsa65_private_key *private_key) {
+  return bcm_as_approved_status(
+      mldsa::fips::check_key(mldsa::private_key_from_external_65(private_key)));
+}
+
 // Calls |MLDSA_generate_key_external_entropy| with random bytes from
 // |BCM_rand_bytes|.
 bcm_status BCM_mldsa65_generate_key(
@@ -1807,11 +2023,51 @@
     uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
     struct BCM_mldsa65_private_key *out_private_key,
     const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
-  return bcm_as_approved_status(mldsa_generate_key_external_entropy(
+  return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
       out_encoded_public_key,
       mldsa::private_key_from_external_65(out_private_key), entropy));
 }
 
+bcm_status BCM_mldsa65_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
+    uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
+    struct BCM_mldsa65_private_key *out_private_key) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  if (BCM_mldsa65_generate_key(out_encoded_public_key, out_seed,
+                               out_private_key) == bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa65_check_key_fips(out_private_key);
+}
+
+bcm_status BCM_mldsa65_generate_key_external_entropy_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
+    struct BCM_mldsa65_private_key *out_private_key,
+    const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  if (BCM_mldsa65_generate_key_external_entropy(out_encoded_public_key,
+                                                out_private_key, entropy) ==
+      bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa65_check_key_fips(out_private_key);
+}
+
+bcm_status BCM_mldsa65_private_key_from_seed_fips(
+    struct BCM_mldsa65_private_key *out_private_key,
+    const uint8_t seed[BCM_MLDSA_SEED_BYTES]) {
+  uint8_t public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES];
+  if (BCM_mldsa65_generate_key_external_entropy(public_key, out_private_key,
+                                                seed) == bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa65_check_key_fips(out_private_key);
+}
+
 bcm_status BCM_mldsa65_public_from_private(
     struct BCM_mldsa65_public_key *out_public_key,
     const struct BCM_mldsa65_private_key *private_key) {
@@ -1900,6 +2156,12 @@
       CBS_len(in) == 0);
 }
 
+bcm_status BCM_mldsa87_check_key_fips(
+    struct BCM_mldsa87_private_key *private_key) {
+  return bcm_as_approved_status(
+      mldsa::fips::check_key(mldsa::private_key_from_external_87(private_key)));
+}
+
 // Calls |MLDSA_generate_key_external_entropy| with random bytes from
 // |BCM_rand_bytes|.
 bcm_status BCM_mldsa87_generate_key(
@@ -1923,11 +2185,51 @@
     uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
     struct BCM_mldsa87_private_key *out_private_key,
     const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
-  return bcm_as_approved_status(mldsa_generate_key_external_entropy(
+  return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
       out_encoded_public_key,
       mldsa::private_key_from_external_87(out_private_key), entropy));
 }
 
+bcm_status BCM_mldsa87_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
+    uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
+    struct BCM_mldsa87_private_key *out_private_key) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  if (BCM_mldsa87_generate_key(out_encoded_public_key, out_seed,
+                               out_private_key) == bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa87_check_key_fips(out_private_key);
+}
+
+bcm_status BCM_mldsa87_generate_key_external_entropy_fips(
+    uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
+    struct BCM_mldsa87_private_key *out_private_key,
+    const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  if (BCM_mldsa87_generate_key_external_entropy(out_encoded_public_key,
+                                                out_private_key, entropy) ==
+      bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa87_check_key_fips(out_private_key);
+}
+
+bcm_status BCM_mldsa87_private_key_from_seed_fips(
+    struct BCM_mldsa87_private_key *out_private_key,
+    const uint8_t seed[BCM_MLDSA_SEED_BYTES]) {
+  uint8_t public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES];
+  if (BCM_mldsa87_generate_key_external_entropy(public_key, out_private_key,
+                                                seed) == bcm_status::failure) {
+    return bcm_status::failure;
+  }
+  return BCM_mldsa87_check_key_fips(out_private_key);
+}
+
 bcm_status BCM_mldsa87_public_from_private(
     struct BCM_mldsa87_public_key *out_public_key,
     const struct BCM_mldsa87_private_key *private_key) {
@@ -1991,3 +2293,8 @@
   return bcm_as_approved_status(mldsa_marshal_public_key(
       out, mldsa::public_key_from_external_87(public_key)));
 }
+
+int boringssl_self_test_mldsa() {
+  return mldsa::fips::keygen_self_test() && mldsa::fips::sign_self_test() &&
+         mldsa::fips::verify_self_test();
+}
diff --git a/src/crypto/fipsmodule/mlkem/fips_known_values.inc b/src/crypto/fipsmodule/mlkem/fips_known_values.inc
new file mode 100644
index 0000000..81c1b8e
--- /dev/null
+++ b/src/crypto/fipsmodule/mlkem/fips_known_values.inc
@@ -0,0 +1,411 @@
+const uint8_t kTestEntropy[BCM_MLKEM_SEED_BYTES] = {
+    0xc8, 0x77, 0x34, 0x04, 0xb3, 0xe5, 0x3e, 0x31, 0x7b, 0xab, 0x41,
+    0x08, 0xa8, 0x88, 0x9c, 0x90, 0xbe, 0xfb, 0x38, 0x0f, 0x63, 0x89,
+    0x70, 0xbc, 0xdc, 0x33, 0xeb, 0x2d, 0xe2, 0x99, 0x6b, 0x1a};
+
+const uint8_t kExpectedPublicKeyBytes[BCM_MLKEM768_PUBLIC_KEY_BYTES] = {
+    0xcb, 0x0b, 0x33, 0xa2, 0xac, 0xc4, 0x94, 0x56, 0x1a, 0x36, 0x1c, 0x0d,
+    0xa3, 0x57, 0x5b, 0x63, 0x6c, 0x0d, 0x1f, 0xe1, 0xa8, 0x36, 0xd5, 0x5d,
+    0x38, 0x5c, 0xac, 0xf4, 0x67, 0x39, 0x9a, 0x12, 0x5b, 0xef, 0xa1, 0x0a,
+    0x57, 0x76, 0x87, 0x83, 0xaa, 0xaf, 0x1d, 0x9c, 0xce, 0x2b, 0x78, 0x9b,
+    0x40, 0x82, 0x1e, 0x34, 0xb3, 0x55, 0x2d, 0xd0, 0x20, 0xcd, 0x5b, 0x46,
+    0x8d, 0xda, 0xb8, 0x83, 0xa8, 0xab, 0xfb, 0x36, 0x45, 0xcb, 0x40, 0xae,
+    0x69, 0x77, 0x03, 0x22, 0xa8, 0xb4, 0xaa, 0x17, 0x53, 0x90, 0x05, 0x6a,
+    0x69, 0xb9, 0xc5, 0x2d, 0xbc, 0x9a, 0x81, 0xf6, 0x2a, 0x3c, 0x57, 0x96,
+    0x8c, 0xb2, 0x72, 0xa7, 0xd4, 0x84, 0x77, 0xf9, 0x0b, 0x80, 0xe7, 0x1e,
+    0x75, 0x61, 0x0e, 0xf9, 0xb0, 0xcf, 0x4c, 0x03, 0xca, 0x30, 0x45, 0x50,
+    0x25, 0x82, 0x56, 0x02, 0xbb, 0x58, 0xab, 0x99, 0xc7, 0x8d, 0xd5, 0x37,
+    0x12, 0xc8, 0x36, 0x5b, 0x00, 0x5f, 0x91, 0xf6, 0x2d, 0x9b, 0x91, 0xc2,
+    0x3e, 0x75, 0x56, 0x83, 0xd2, 0xaa, 0xd4, 0x03, 0xcd, 0xe8, 0xe8, 0x3f,
+    0x09, 0xc1, 0x8e, 0x84, 0xb1, 0x75, 0x85, 0x06, 0xa7, 0x4a, 0x40, 0xc2,
+    0xc9, 0x90, 0xb0, 0x0f, 0x59, 0x84, 0xe5, 0xf7, 0xa8, 0xd8, 0x35, 0x33,
+    0xa5, 0x82, 0x4e, 0xf6, 0xb5, 0xaf, 0xd5, 0xaa, 0xbb, 0x52, 0x30, 0x0b,
+    0xb1, 0x67, 0x7b, 0xbb, 0xdc, 0x38, 0x58, 0xf4, 0x2f, 0xe4, 0xeb, 0x47,
+    0xf0, 0x49, 0x76, 0x45, 0x10, 0x02, 0x19, 0xa7, 0xc6, 0x1f, 0x8a, 0x71,
+    0xda, 0x51, 0x61, 0x79, 0xc4, 0x10, 0xeb, 0x3a, 0x11, 0xd9, 0x93, 0x1d,
+    0x83, 0x81, 0x48, 0x3d, 0x68, 0x35, 0xff, 0xe3, 0xa6, 0xa8, 0x40, 0x74,
+    0xdb, 0x7c, 0xb4, 0xb2, 0x05, 0x89, 0xc8, 0x09, 0x42, 0x27, 0x28, 0x55,
+    0x01, 0x57, 0xc9, 0xf9, 0xfa, 0x36, 0xd3, 0x5c, 0x51, 0x40, 0xca, 0x1e,
+    0x34, 0xc8, 0xb9, 0x27, 0xf1, 0x15, 0xc9, 0xa4, 0x18, 0x9c, 0xa8, 0x4c,
+    0x55, 0xf8, 0x4d, 0x90, 0xbc, 0x88, 0xd1, 0x46, 0x01, 0x80, 0x96, 0x54,
+    0x8d, 0x01, 0x6e, 0xe4, 0x26, 0x0c, 0x7a, 0x08, 0x3d, 0x7c, 0x26, 0x66,
+    0xb1, 0xd1, 0x15, 0xc7, 0xc0, 0x0b, 0x06, 0x92, 0x9c, 0x26, 0xa6, 0x6c,
+    0x3a, 0x46, 0x47, 0x15, 0x37, 0xb0, 0x0a, 0xc1, 0x5d, 0xe0, 0x51, 0xae,
+    0x17, 0x87, 0x2f, 0x75, 0x2c, 0x64, 0xd5, 0x39, 0x09, 0xe6, 0xd0, 0x7c,
+    0x3d, 0x79, 0x47, 0x78, 0x0a, 0x82, 0xc9, 0xba, 0x37, 0x07, 0x93, 0x94,
+    0xa4, 0x45, 0x7c, 0x07, 0x69, 0x24, 0x1d, 0xc9, 0x75, 0x41, 0x6b, 0xc1,
+    0x42, 0x28, 0x06, 0xe3, 0xfc, 0x7b, 0xd2, 0xf8, 0xbf, 0xe7, 0x5a, 0xc2,
+    0xc0, 0x81, 0x63, 0xf3, 0x84, 0x32, 0x31, 0x4a, 0x8d, 0x6b, 0xe3, 0x3e,
+    0x22, 0x67, 0x9a, 0x3a, 0x96, 0x09, 0xa6, 0xf9, 0x53, 0x40, 0x41, 0x2a,
+    0x04, 0xa7, 0xc5, 0x7b, 0x86, 0xcd, 0xed, 0xec, 0xae, 0xfd, 0xc7, 0x11,
+    0x48, 0x56, 0x77, 0x0b, 0xb7, 0xbb, 0xaf, 0xfb, 0x6c, 0x9e, 0xd6, 0x5c,
+    0xbc, 0xf7, 0x9a, 0x75, 0xb5, 0xb2, 0x20, 0xd9, 0x60, 0x90, 0x65, 0x02,
+    0xf9, 0x16, 0x34, 0xdf, 0x0b, 0x16, 0x2a, 0x97, 0x00, 0x5d, 0xc1, 0x65,
+    0xc3, 0xb9, 0x1f, 0x2e, 0x85, 0x97, 0xbd, 0xca, 0xaa, 0x1d, 0xf2, 0x4f,
+    0x74, 0xe5, 0x56, 0x94, 0xdc, 0x53, 0xbb, 0xc0, 0x75, 0x1c, 0x2b, 0x59,
+    0x6b, 0x50, 0x2c, 0x25, 0x4c, 0x78, 0xd7, 0x68, 0x40, 0x0b, 0x91, 0x7a,
+    0x93, 0x02, 0x83, 0x5e, 0x6c, 0x03, 0xc7, 0xc4, 0x24, 0x6f, 0x8b, 0xa4,
+    0x70, 0x37, 0x1f, 0xe5, 0x33, 0x59, 0xf6, 0xbb, 0x5f, 0xb8, 0x58, 0x50,
+    0x62, 0x16, 0x95, 0x2a, 0x88, 0xa3, 0xc6, 0x24, 0x94, 0x4b, 0xb0, 0x03,
+    0x8e, 0xe6, 0x50, 0xd1, 0x63, 0xa2, 0xab, 0x00, 0x16, 0xf4, 0x0a, 0x7d,
+    0xe6, 0xe0, 0xb9, 0x0c, 0xd8, 0x08, 0xae, 0xf6, 0x80, 0xb7, 0x48, 0xb8,
+    0x10, 0xd1, 0x77, 0x57, 0x48, 0x2a, 0xc1, 0xf1, 0x4e, 0x61, 0xb4, 0x06,
+    0x5a, 0xa1, 0xba, 0x32, 0x4a, 0x9a, 0xab, 0x8c, 0xa8, 0xe3, 0xa0, 0x68,
+    0x39, 0xa3, 0x25, 0x55, 0x48, 0xcd, 0x12, 0x98, 0x14, 0x1b, 0x39, 0x5b,
+    0xf4, 0x88, 0xbe, 0x5f, 0xac, 0xba, 0x18, 0x20, 0x74, 0x2c, 0xa1, 0x0b,
+    0xfc, 0xf1, 0x00, 0x85, 0x24, 0x27, 0x3d, 0x80, 0xb6, 0x30, 0x42, 0x7b,
+    0x74, 0xb0, 0xbf, 0x87, 0x51, 0x9b, 0xa8, 0x1c, 0x79, 0xbd, 0x50, 0x85,
+    0x66, 0xe1, 0x93, 0xdd, 0xc5, 0x5d, 0x5d, 0xd0, 0xbe, 0xcb, 0x90, 0x36,
+    0xf8, 0xc6, 0xc2, 0xea, 0xea, 0x40, 0xce, 0xa7, 0xb0, 0xae, 0xc5, 0x44,
+    0x3a, 0x27, 0xc5, 0x4a, 0xf0, 0x21, 0x4f, 0xf6, 0x63, 0xb1, 0x8c, 0x20,
+    0x76, 0x65, 0xb5, 0x79, 0x55, 0x10, 0xa5, 0xa7, 0x4b, 0x57, 0x96, 0xb3,
+    0x03, 0xe6, 0xa8, 0x93, 0xf5, 0xc5, 0xca, 0xe0, 0x1a, 0x23, 0x30, 0x6d,
+    0x09, 0x07, 0x81, 0x5e, 0x05, 0xc6, 0x1b, 0x7a, 0x0e, 0xde, 0xf3, 0x00,
+    0x91, 0xf3, 0xbb, 0x4b, 0xa6, 0x8e, 0x96, 0xc3, 0x3a, 0xc8, 0x72, 0x19,
+    0x23, 0x23, 0xc7, 0x94, 0x46, 0x75, 0xa2, 0xc5, 0x9e, 0xa3, 0x15, 0x86,
+    0xb4, 0xa7, 0x95, 0xda, 0x16, 0xae, 0x42, 0xe8, 0xcc, 0xf6, 0x41, 0xbc,
+    0x9c, 0xe8, 0x07, 0xc9, 0x05, 0x3c, 0x74, 0xb2, 0xad, 0x77, 0xc4, 0x08,
+    0x56, 0x78, 0xb8, 0x65, 0x2a, 0x33, 0x39, 0x82, 0x16, 0x3c, 0x2b, 0x73,
+    0x41, 0x2a, 0xbc, 0xc8, 0x36, 0x23, 0x2c, 0x23, 0x29, 0xce, 0x94, 0x8a,
+    0xba, 0x13, 0x3f, 0xfa, 0xcc, 0x6e, 0x17, 0x40, 0xb0, 0xb4, 0x9c, 0xae,
+    0xf9, 0x72, 0x40, 0xf7, 0x2a, 0xaf, 0x00, 0x17, 0x7e, 0x88, 0x44, 0x4e,
+    0x32, 0xa4, 0x80, 0x96, 0x53, 0x20, 0xe4, 0xaa, 0x18, 0x9c, 0x69, 0x63,
+    0xdb, 0x81, 0x73, 0x0e, 0x64, 0x40, 0x12, 0xc1, 0x26, 0x0e, 0xac, 0x4d,
+    0x38, 0xa6, 0x4c, 0x05, 0xeb, 0x42, 0x1f, 0x88, 0x6e, 0x6c, 0xa3, 0x98,
+    0x95, 0xc3, 0x5a, 0x31, 0xfc, 0x8a, 0x7c, 0xd6, 0xa5, 0x6c, 0x5a, 0xc9,
+    0xf5, 0xf2, 0xb0, 0xf7, 0x05, 0x8d, 0x3a, 0x0b, 0x3f, 0x4d, 0x1b, 0x0e,
+    0x38, 0x7b, 0x1c, 0xe5, 0xd0, 0x75, 0x40, 0x77, 0xc2, 0xe0, 0x8b, 0xa9,
+    0xfb, 0xa6, 0xa7, 0x13, 0xf0, 0xbc, 0x0c, 0x13, 0xb0, 0x70, 0x3a, 0x2f,
+    0x20, 0xe7, 0x38, 0xd8, 0x82, 0xa4, 0xc0, 0x06, 0x96, 0x95, 0x75, 0x5c,
+    0xbc, 0x68, 0xce, 0xee, 0xa6, 0x44, 0xbb, 0xf2, 0x62, 0x14, 0x43, 0x10,
+    0xe6, 0x0b, 0x5c, 0x66, 0x02, 0xbf, 0x38, 0xe9, 0x8f, 0x19, 0x69, 0x6c,
+    0x08, 0xfa, 0x93, 0x23, 0xf1, 0x35, 0x5f, 0x33, 0xcf, 0xe2, 0x32, 0x11,
+    0xda, 0x31, 0xbb, 0xd8, 0xf5, 0x7e, 0x55, 0xc3, 0x6a, 0xa3, 0x04, 0x8c,
+    0xef, 0x50, 0x67, 0x0f, 0xe9, 0xbb, 0x11, 0x6b, 0xca, 0x5a, 0x23, 0x15,
+    0xf7, 0x52, 0x8c, 0x69, 0xbb, 0x2d, 0x26, 0xd3, 0x78, 0x32, 0x33, 0x9b,
+    0x1d, 0x02, 0x7c, 0x22, 0x4b, 0x57, 0x19, 0xec, 0xcd, 0x16, 0x63, 0x5d,
+    0x1f, 0x0c, 0x67, 0xda, 0x6a, 0xc7, 0x2c, 0xf1, 0x0b, 0xcf, 0x92, 0x10,
+    0xcb, 0x78, 0x57, 0x67, 0x61, 0x0e, 0xb3, 0x55, 0xb0, 0x17, 0x32, 0x4e,
+    0x95, 0xf1, 0xcb, 0xb5, 0xdb, 0x5d, 0x8e, 0x38, 0x97, 0x28, 0x46, 0x1e,
+    0x37, 0x4b, 0x5c, 0x03, 0xf4, 0x84, 0x0c, 0xfc, 0x49, 0x3b, 0xd2, 0xc6,
+    0x97, 0xd4, 0x4f, 0xef, 0xe6, 0x5c, 0xb2, 0x96, 0x8e, 0xbc, 0x18, 0x9f,
+    0xec, 0x8a, 0x67, 0x53, 0xe8, 0x2a, 0x41, 0x5c, 0x6e, 0xfe, 0xca, 0x1a,
+    0xd0, 0x03, 0x4f, 0xe8, 0xd9, 0xb0, 0xe2, 0xa1, 0x6c, 0x32, 0xd5, 0x37,
+    0x68, 0x9c, 0x6b, 0x30, 0x87, 0xb4, 0x6e, 0xa8, 0xc5, 0x45, 0xe4, 0x74,
+    0x4a, 0x80, 0x02, 0x84, 0x78, 0x0e, 0x2c, 0x9c, 0x37, 0x07, 0x26, 0x31,
+    0x88, 0x0a, 0x89, 0xd2, 0xba, 0x8b, 0x09, 0xb2, 0x16, 0x7b, 0x23, 0xa8,
+    0x0c, 0x82, 0xc4, 0x22, 0xa2, 0x21, 0x2d, 0xa4, 0xa0, 0xeb, 0xe4, 0xa6,
+    0xd4, 0x16, 0xa0, 0xa7, 0x19, 0x8b, 0x8f, 0x87, 0x9b, 0x53, 0x6c, 0xba,
+    0x14, 0xa7, 0xc4, 0x64, 0x08, 0xb4, 0x68, 0xda, 0x85, 0xa6, 0x47, 0xbc,
+    0x58, 0x34, 0xcd, 0x60, 0x43, 0xad, 0x14, 0xd4, 0xca, 0xd7, 0xb1, 0x6c,
+    0xc0, 0x05, 0x68, 0xaf, 0xa7, 0x08, 0x9d, 0x6a, 0xb0, 0x70, 0x96, 0x81,
+    0xb8, 0x55, 0xbf, 0xa1, 0xcc, 0xb1, 0x37, 0xe0, 0x94, 0x42, 0x05, 0x0c,
+    0x83, 0xef, 0x6d, 0xf0, 0x4e, 0xba, 0xe6, 0x78, 0x49, 0xaf, 0x1f, 0x88,
+    0xf0, 0x18, 0x0c, 0x17, 0x66, 0x92, 0xd8, 0x50, 0x57, 0x3b, 0x8e, 0xc9,
+    0xd5, 0x8c, 0xfb, 0x9b, 0x78, 0x65, 0x01, 0x76};
+
+const uint8_t kExpectedPrivateKeyBytes[2400] = {
+    0xd8, 0xc9, 0x39, 0x7c, 0x31, 0x30, 0xd8, 0xec, 0xb4, 0x11, 0xa6, 0x8e,
+    0xfc, 0xc8, 0x9a, 0x55, 0x3c, 0xb7, 0xe6, 0x81, 0x7e, 0x02, 0x88, 0xbd,
+    0x06, 0x91, 0x60, 0x9b, 0xf5, 0x57, 0x6a, 0xf8, 0x73, 0x9e, 0x52, 0xa8,
+    0x03, 0xf0, 0x97, 0xb4, 0x22, 0xb7, 0x02, 0x23, 0xcd, 0x3e, 0xa1, 0x03,
+    0x20, 0x66, 0x6e, 0x20, 0x20, 0xcb, 0x42, 0xec, 0xb6, 0xc2, 0x14, 0x2c,
+    0xe7, 0xa8, 0x88, 0x3d, 0xd2, 0x26, 0x9c, 0xf7, 0xb3, 0x4f, 0x00, 0x27,
+    0x61, 0xc6, 0x10, 0xb2, 0x72, 0x34, 0x39, 0xf1, 0x79, 0x03, 0xcc, 0x06,
+    0xd2, 0xe4, 0x29, 0x57, 0x91, 0x2f, 0x0d, 0x45, 0x19, 0x30, 0x27, 0x47,
+    0xcc, 0xba, 0xbe, 0x19, 0x01, 0x1a, 0xbb, 0xd8, 0xcb, 0x74, 0xca, 0x4a,
+    0xfa, 0x32, 0x2f, 0xb8, 0xbb, 0x5c, 0x19, 0x2a, 0xbf, 0x31, 0x0a, 0x82,
+    0xf3, 0x29, 0x74, 0x30, 0xa4, 0x95, 0x4c, 0x42, 0x59, 0x8c, 0xb3, 0xcb,
+    0xfe, 0xa9, 0xb4, 0x2e, 0x60, 0x71, 0x64, 0x51, 0x6d, 0xf9, 0x73, 0x5b,
+    0xf5, 0x59, 0x9b, 0xf5, 0xd9, 0x9d, 0x3f, 0x86, 0x3a, 0x50, 0x6c, 0x23,
+    0x8c, 0x96, 0xc0, 0x5e, 0x7c, 0x48, 0x43, 0xec, 0x08, 0xf5, 0xf7, 0x7e,
+    0x6b, 0x54, 0x84, 0xb2, 0x6c, 0x52, 0xd5, 0x2b, 0x38, 0x85, 0xf4, 0x40,
+    0x36, 0x09, 0x2f, 0xe6, 0xd0, 0x9e, 0xe6, 0xb6, 0x96, 0x7a, 0xe1, 0xc3,
+    0xf7, 0xfa, 0x89, 0xc6, 0x75, 0x6f, 0x65, 0xea, 0x4a, 0x6d, 0x55, 0x33,
+    0xe2, 0xc6, 0x30, 0xfb, 0x7b, 0xbd, 0xcb, 0x33, 0x4d, 0xd6, 0x84, 0x1b,
+    0x28, 0x77, 0x60, 0xbf, 0x4b, 0x82, 0xd0, 0xb0, 0xc5, 0x88, 0x0c, 0x51,
+    0x00, 0x22, 0x5e, 0xd9, 0x41, 0x2e, 0x7e, 0x43, 0xa6, 0x9d, 0x34, 0x5d,
+    0x24, 0x80, 0xad, 0x7f, 0xd3, 0xae, 0xc7, 0x5a, 0x51, 0x74, 0x06, 0xc0,
+    0x6f, 0x04, 0xae, 0x9b, 0x79, 0x6e, 0x35, 0xfa, 0x0d, 0xf3, 0xda, 0xa4,
+    0xfa, 0x38, 0x4a, 0xee, 0xb3, 0xa4, 0x87, 0xa7, 0x27, 0xe2, 0x02, 0x2a,
+    0x29, 0x27, 0xcf, 0xca, 0x4a, 0x20, 0x01, 0x15, 0x3d, 0x12, 0xc7, 0xcc,
+    0x74, 0x99, 0x17, 0xa6, 0x7b, 0x04, 0xd7, 0xea, 0x64, 0x88, 0xa3, 0x54,
+    0xb5, 0xc2, 0xa3, 0xea, 0x69, 0x94, 0xb9, 0xc3, 0x45, 0xf8, 0x2b, 0x3c,
+    0xe5, 0xc1, 0x25, 0xf6, 0xc9, 0x82, 0xe3, 0x45, 0x25, 0xca, 0x71, 0x3d,
+    0x73, 0x10, 0x99, 0xa5, 0xb5, 0x79, 0xdc, 0x61, 0x8f, 0x04, 0x3c, 0x61,
+    0x6b, 0x90, 0x4d, 0x83, 0xa3, 0x0d, 0xb4, 0xba, 0xb7, 0x3b, 0x81, 0xca,
+    0xbb, 0x59, 0x16, 0x46, 0xf4, 0x75, 0x7c, 0xaa, 0x0f, 0x90, 0xec, 0x37,
+    0xa4, 0x50, 0xa8, 0x41, 0xb4, 0x33, 0xd2, 0xb7, 0x28, 0xe1, 0xda, 0x74,
+    0x36, 0x3a, 0xa6, 0x96, 0x76, 0x06, 0x67, 0xd3, 0x8e, 0xda, 0xd5, 0x29,
+    0x24, 0x1a, 0xbe, 0x82, 0x83, 0x6b, 0x3a, 0x90, 0xc1, 0x86, 0x34, 0x2d,
+    0xd8, 0xa3, 0xa5, 0x7e, 0xe6, 0xca, 0x3f, 0xc5, 0xbf, 0xba, 0x24, 0x14,
+    0xd2, 0xfc, 0x3f, 0x97, 0x8c, 0xca, 0x59, 0xa5, 0x52, 0xf1, 0x8c, 0x62,
+    0x8d, 0x8a, 0x7d, 0x1b, 0x35, 0x76, 0x79, 0x98, 0x39, 0x57, 0x53, 0x1f,
+    0x78, 0x82, 0x7d, 0xcd, 0x9c, 0xab, 0xb3, 0x12, 0x52, 0x86, 0x87, 0xbf,
+    0x01, 0x12, 0x58, 0x45, 0x37, 0x75, 0x1a, 0xe0, 0x03, 0xbd, 0x67, 0x4c,
+    0x76, 0xfa, 0x06, 0x59, 0xa2, 0x1f, 0x48, 0x73, 0x7f, 0x0c, 0x90, 0xc1,
+    0x82, 0xc0, 0x98, 0x2f, 0x6a, 0x1c, 0x6f, 0x6c, 0x98, 0x70, 0x16, 0x8e,
+    0x8c, 0x5b, 0x60, 0x92, 0x42, 0x59, 0xd6, 0xb2, 0x13, 0x7a, 0x11, 0xb6,
+    0x15, 0x1b, 0x07, 0x50, 0x52, 0x73, 0x86, 0xbc, 0x3a, 0xff, 0x66, 0x71,
+    0x57, 0xf8, 0x89, 0x7a, 0x3a, 0x95, 0xc5, 0xa1, 0x31, 0x48, 0x15, 0xc9,
+    0xe0, 0x4b, 0x41, 0xb6, 0x07, 0x5a, 0x70, 0x88, 0x11, 0xce, 0xdc, 0xa7,
+    0x84, 0x23, 0x85, 0x96, 0xd8, 0x20, 0x9f, 0x89, 0x42, 0xbc, 0x0b, 0xd0,
+    0xd9, 0x11, 0x9f, 0x2f, 0x71, 0x37, 0xa2, 0x10, 0x98, 0x95, 0xa7, 0x1f,
+    0x99, 0x48, 0x8e, 0x5b, 0x40, 0x65, 0x9f, 0x08, 0x4e, 0x04, 0x16, 0x35,
+    0xc8, 0x56, 0xa1, 0x02, 0xa1, 0xaf, 0x0e, 0x5b, 0xaf, 0x02, 0x66, 0x2e,
+    0xc8, 0xa5, 0x49, 0xe7, 0xa4, 0x6b, 0x03, 0xe2, 0x42, 0xb3, 0x37, 0x76,
+    0x2c, 0x89, 0x00, 0x76, 0x83, 0xb3, 0x93, 0xdc, 0x78, 0x56, 0xc9, 0x02,
+    0xf1, 0xd3, 0x92, 0xe5, 0x14, 0x36, 0xba, 0x37, 0x1d, 0x86, 0x87, 0x81,
+    0x5f, 0x30, 0x16, 0x7f, 0xdb, 0x76, 0xe2, 0x46, 0x3d, 0x32, 0xe8, 0x47,
+    0x35, 0x5b, 0x68, 0x39, 0x70, 0xa3, 0xc2, 0xb8, 0xb3, 0x6e, 0xd0, 0x22,
+    0x6b, 0x39, 0x9c, 0xd9, 0xa3, 0x93, 0x69, 0xbc, 0xcb, 0xe0, 0xbc, 0x82,
+    0x1b, 0xfb, 0x9f, 0x72, 0x17, 0x40, 0x72, 0xeb, 0xb2, 0x97, 0x31, 0x66,
+    0x18, 0x48, 0x9a, 0xe5, 0x3a, 0x2a, 0x41, 0x13, 0x3e, 0xfc, 0xfb, 0xb4,
+    0xb0, 0x96, 0x6e, 0x53, 0x37, 0x18, 0xbb, 0x26, 0x1d, 0xbe, 0x33, 0x0f,
+    0x06, 0x8b, 0x8c, 0xb1, 0xfc, 0x8c, 0x24, 0x19, 0x8d, 0x7d, 0x76, 0x52,
+    0x35, 0x75, 0x71, 0x36, 0x61, 0x7d, 0x75, 0x3a, 0x31, 0x9a, 0x16, 0x05,
+    0x2d, 0x51, 0x63, 0x6f, 0x07, 0x64, 0xfd, 0x80, 0x16, 0x2d, 0xa3, 0x3a,
+    0x15, 0xca, 0xaa, 0x76, 0xec, 0x2f, 0x91, 0x47, 0xb2, 0x29, 0x61, 0x04,
+    0x80, 0x20, 0x8d, 0x3c, 0x31, 0xa6, 0x4f, 0x8b, 0xc8, 0xc0, 0x71, 0xbb,
+    0x0a, 0xec, 0xbc, 0xdf, 0xdc, 0x91, 0x8c, 0xb9, 0x80, 0xb7, 0x67, 0xa9,
+    0x7f, 0x30, 0x18, 0x4e, 0xd3, 0x68, 0x27, 0x50, 0x15, 0xad, 0x8c, 0x6a,
+    0xab, 0xc9, 0xbe, 0xad, 0x41, 0x4b, 0xcd, 0x23, 0x73, 0x9f, 0x77, 0x58,
+    0xe3, 0xd8, 0x2e, 0x16, 0xcb, 0xa0, 0x17, 0x89, 0x51, 0x31, 0x53, 0x01,
+    0xa8, 0xf1, 0x9b, 0x61, 0xc3, 0x0a, 0x5b, 0x0c, 0x70, 0x36, 0x48, 0x1b,
+    0xae, 0x17, 0x51, 0x1f, 0xc7, 0x7b, 0xce, 0xd4, 0x45, 0xff, 0xea, 0xb0,
+    0x5f, 0x48, 0x07, 0x4f, 0x79, 0x26, 0x5c, 0xb6, 0xce, 0x4c, 0xc4, 0x02,
+    0xd1, 0x31, 0x88, 0xa9, 0xc0, 0x53, 0x6a, 0x42, 0x6f, 0x9c, 0x32, 0xaa,
+    0x86, 0xec, 0x25, 0xa7, 0x5b, 0x31, 0x68, 0xc9, 0xa9, 0xd8, 0x2c, 0x70,
+    0xa0, 0x02, 0x31, 0x52, 0x8a, 0x2c, 0xc0, 0x0a, 0xbe, 0x8c, 0x59, 0x6c,
+    0x72, 0x42, 0x21, 0xcb, 0x44, 0x07, 0x02, 0x27, 0xa0, 0x71, 0xa3, 0x7f,
+    0xe3, 0x97, 0x24, 0x70, 0x47, 0x4d, 0x10, 0xfc, 0x54, 0x83, 0xdc, 0x44,
+    0x09, 0x36, 0x23, 0x4a, 0x26, 0x95, 0x60, 0x96, 0xa4, 0x11, 0x1b, 0x18,
+    0x9d, 0x01, 0x9c, 0x8c, 0xd7, 0x37, 0x60, 0x08, 0x02, 0xef, 0xe3, 0x81,
+    0xf3, 0x48, 0x5c, 0x9c, 0xac, 0x4f, 0xb6, 0xc7, 0x66, 0xd6, 0xda, 0x25,
+    0x78, 0x4a, 0xca, 0x91, 0xf1, 0x16, 0x75, 0x69, 0x8b, 0x09, 0x63, 0x0d,
+    0x74, 0x49, 0x57, 0x33, 0xe1, 0x23, 0x87, 0xc5, 0x0e, 0x85, 0x27, 0x1e,
+    0x5a, 0xfa, 0x3f, 0xa8, 0x82, 0xbc, 0x49, 0xc7, 0x99, 0x15, 0xe1, 0x2f,
+    0x04, 0x36, 0x88, 0xd4, 0xa1, 0x9a, 0xe5, 0xb3, 0x70, 0x95, 0x85, 0x43,
+    0x76, 0xb9, 0x7d, 0x3b, 0x9c, 0x61, 0xf3, 0x30, 0x59, 0x4e, 0x2a, 0xc6,
+    0x3f, 0x52, 0x35, 0x81, 0x43, 0x61, 0x72, 0xc0, 0x89, 0x98, 0x67, 0x1e,
+    0x6f, 0xec, 0xc6, 0x2a, 0x9a, 0x14, 0x36, 0x34, 0x4c, 0x9f, 0xfb, 0x2e,
+    0xd1, 0xd2, 0x4e, 0x6b, 0xb9, 0xc9, 0x56, 0x74, 0xbe, 0xab, 0xa4, 0x7c,
+    0x48, 0x84, 0x07, 0xf6, 0x04, 0xb1, 0x89, 0x0b, 0x13, 0x79, 0x13, 0xb5,
+    0x31, 0xd6, 0x2c, 0x40, 0x47, 0xbd, 0xba, 0x37, 0xb1, 0x65, 0x7c, 0xb3,
+    0xa3, 0x45, 0x1e, 0x0f, 0x41, 0x62, 0x07, 0xf9, 0x1e, 0x25, 0xa5, 0x78,
+    0x47, 0xd2, 0xa6, 0x4b, 0x20, 0x7b, 0x9b, 0x39, 0x07, 0x09, 0xf3, 0x9e,
+    0x09, 0xfb, 0xac, 0x87, 0xb6, 0xb5, 0x9b, 0xd8, 0x09, 0xa3, 0xd6, 0x69,
+    0xb3, 0x3a, 0x87, 0x09, 0xb0, 0x19, 0xb3, 0xc1, 0x47, 0x8e, 0xd7, 0x3a,
+    0x6e, 0xb5, 0x48, 0x89, 0x56, 0x87, 0x60, 0xb1, 0xba, 0x52, 0xd5, 0x94,
+    0x22, 0x54, 0xbd, 0x7c, 0xf1, 0xa4, 0x54, 0xaa, 0x38, 0x5c, 0x76, 0xa8,
+    0x52, 0x19, 0x97, 0x9a, 0x71, 0x47, 0x6c, 0xa0, 0x39, 0xd1, 0x0b, 0xd0,
+    0xa6, 0xb3, 0x65, 0xdc, 0xbc, 0xa4, 0x4d, 0x62, 0x44, 0xb2, 0x47, 0x5e,
+    0x77, 0x77, 0x32, 0x2f, 0x78, 0xa6, 0x97, 0xdb, 0xb5, 0xba, 0x3b, 0x4a,
+    0xcb, 0x0b, 0x33, 0xa2, 0xac, 0xc4, 0x94, 0x56, 0x1a, 0x36, 0x1c, 0x0d,
+    0xa3, 0x57, 0x5b, 0x63, 0x6c, 0x0d, 0x1f, 0xe1, 0xa8, 0x36, 0xd5, 0x5d,
+    0x38, 0x5c, 0xac, 0xf4, 0x67, 0x39, 0x9a, 0x12, 0x5b, 0xef, 0xa1, 0x0a,
+    0x57, 0x76, 0x87, 0x83, 0xaa, 0xaf, 0x1d, 0x9c, 0xce, 0x2b, 0x78, 0x9b,
+    0x40, 0x82, 0x1e, 0x34, 0xb3, 0x55, 0x2d, 0xd0, 0x20, 0xcd, 0x5b, 0x46,
+    0x8d, 0xda, 0xb8, 0x83, 0xa8, 0xab, 0xfb, 0x36, 0x45, 0xcb, 0x40, 0xae,
+    0x69, 0x77, 0x03, 0x22, 0xa8, 0xb4, 0xaa, 0x17, 0x53, 0x90, 0x05, 0x6a,
+    0x69, 0xb9, 0xc5, 0x2d, 0xbc, 0x9a, 0x81, 0xf6, 0x2a, 0x3c, 0x57, 0x96,
+    0x8c, 0xb2, 0x72, 0xa7, 0xd4, 0x84, 0x77, 0xf9, 0x0b, 0x80, 0xe7, 0x1e,
+    0x75, 0x61, 0x0e, 0xf9, 0xb0, 0xcf, 0x4c, 0x03, 0xca, 0x30, 0x45, 0x50,
+    0x25, 0x82, 0x56, 0x02, 0xbb, 0x58, 0xab, 0x99, 0xc7, 0x8d, 0xd5, 0x37,
+    0x12, 0xc8, 0x36, 0x5b, 0x00, 0x5f, 0x91, 0xf6, 0x2d, 0x9b, 0x91, 0xc2,
+    0x3e, 0x75, 0x56, 0x83, 0xd2, 0xaa, 0xd4, 0x03, 0xcd, 0xe8, 0xe8, 0x3f,
+    0x09, 0xc1, 0x8e, 0x84, 0xb1, 0x75, 0x85, 0x06, 0xa7, 0x4a, 0x40, 0xc2,
+    0xc9, 0x90, 0xb0, 0x0f, 0x59, 0x84, 0xe5, 0xf7, 0xa8, 0xd8, 0x35, 0x33,
+    0xa5, 0x82, 0x4e, 0xf6, 0xb5, 0xaf, 0xd5, 0xaa, 0xbb, 0x52, 0x30, 0x0b,
+    0xb1, 0x67, 0x7b, 0xbb, 0xdc, 0x38, 0x58, 0xf4, 0x2f, 0xe4, 0xeb, 0x47,
+    0xf0, 0x49, 0x76, 0x45, 0x10, 0x02, 0x19, 0xa7, 0xc6, 0x1f, 0x8a, 0x71,
+    0xda, 0x51, 0x61, 0x79, 0xc4, 0x10, 0xeb, 0x3a, 0x11, 0xd9, 0x93, 0x1d,
+    0x83, 0x81, 0x48, 0x3d, 0x68, 0x35, 0xff, 0xe3, 0xa6, 0xa8, 0x40, 0x74,
+    0xdb, 0x7c, 0xb4, 0xb2, 0x05, 0x89, 0xc8, 0x09, 0x42, 0x27, 0x28, 0x55,
+    0x01, 0x57, 0xc9, 0xf9, 0xfa, 0x36, 0xd3, 0x5c, 0x51, 0x40, 0xca, 0x1e,
+    0x34, 0xc8, 0xb9, 0x27, 0xf1, 0x15, 0xc9, 0xa4, 0x18, 0x9c, 0xa8, 0x4c,
+    0x55, 0xf8, 0x4d, 0x90, 0xbc, 0x88, 0xd1, 0x46, 0x01, 0x80, 0x96, 0x54,
+    0x8d, 0x01, 0x6e, 0xe4, 0x26, 0x0c, 0x7a, 0x08, 0x3d, 0x7c, 0x26, 0x66,
+    0xb1, 0xd1, 0x15, 0xc7, 0xc0, 0x0b, 0x06, 0x92, 0x9c, 0x26, 0xa6, 0x6c,
+    0x3a, 0x46, 0x47, 0x15, 0x37, 0xb0, 0x0a, 0xc1, 0x5d, 0xe0, 0x51, 0xae,
+    0x17, 0x87, 0x2f, 0x75, 0x2c, 0x64, 0xd5, 0x39, 0x09, 0xe6, 0xd0, 0x7c,
+    0x3d, 0x79, 0x47, 0x78, 0x0a, 0x82, 0xc9, 0xba, 0x37, 0x07, 0x93, 0x94,
+    0xa4, 0x45, 0x7c, 0x07, 0x69, 0x24, 0x1d, 0xc9, 0x75, 0x41, 0x6b, 0xc1,
+    0x42, 0x28, 0x06, 0xe3, 0xfc, 0x7b, 0xd2, 0xf8, 0xbf, 0xe7, 0x5a, 0xc2,
+    0xc0, 0x81, 0x63, 0xf3, 0x84, 0x32, 0x31, 0x4a, 0x8d, 0x6b, 0xe3, 0x3e,
+    0x22, 0x67, 0x9a, 0x3a, 0x96, 0x09, 0xa6, 0xf9, 0x53, 0x40, 0x41, 0x2a,
+    0x04, 0xa7, 0xc5, 0x7b, 0x86, 0xcd, 0xed, 0xec, 0xae, 0xfd, 0xc7, 0x11,
+    0x48, 0x56, 0x77, 0x0b, 0xb7, 0xbb, 0xaf, 0xfb, 0x6c, 0x9e, 0xd6, 0x5c,
+    0xbc, 0xf7, 0x9a, 0x75, 0xb5, 0xb2, 0x20, 0xd9, 0x60, 0x90, 0x65, 0x02,
+    0xf9, 0x16, 0x34, 0xdf, 0x0b, 0x16, 0x2a, 0x97, 0x00, 0x5d, 0xc1, 0x65,
+    0xc3, 0xb9, 0x1f, 0x2e, 0x85, 0x97, 0xbd, 0xca, 0xaa, 0x1d, 0xf2, 0x4f,
+    0x74, 0xe5, 0x56, 0x94, 0xdc, 0x53, 0xbb, 0xc0, 0x75, 0x1c, 0x2b, 0x59,
+    0x6b, 0x50, 0x2c, 0x25, 0x4c, 0x78, 0xd7, 0x68, 0x40, 0x0b, 0x91, 0x7a,
+    0x93, 0x02, 0x83, 0x5e, 0x6c, 0x03, 0xc7, 0xc4, 0x24, 0x6f, 0x8b, 0xa4,
+    0x70, 0x37, 0x1f, 0xe5, 0x33, 0x59, 0xf6, 0xbb, 0x5f, 0xb8, 0x58, 0x50,
+    0x62, 0x16, 0x95, 0x2a, 0x88, 0xa3, 0xc6, 0x24, 0x94, 0x4b, 0xb0, 0x03,
+    0x8e, 0xe6, 0x50, 0xd1, 0x63, 0xa2, 0xab, 0x00, 0x16, 0xf4, 0x0a, 0x7d,
+    0xe6, 0xe0, 0xb9, 0x0c, 0xd8, 0x08, 0xae, 0xf6, 0x80, 0xb7, 0x48, 0xb8,
+    0x10, 0xd1, 0x77, 0x57, 0x48, 0x2a, 0xc1, 0xf1, 0x4e, 0x61, 0xb4, 0x06,
+    0x5a, 0xa1, 0xba, 0x32, 0x4a, 0x9a, 0xab, 0x8c, 0xa8, 0xe3, 0xa0, 0x68,
+    0x39, 0xa3, 0x25, 0x55, 0x48, 0xcd, 0x12, 0x98, 0x14, 0x1b, 0x39, 0x5b,
+    0xf4, 0x88, 0xbe, 0x5f, 0xac, 0xba, 0x18, 0x20, 0x74, 0x2c, 0xa1, 0x0b,
+    0xfc, 0xf1, 0x00, 0x85, 0x24, 0x27, 0x3d, 0x80, 0xb6, 0x30, 0x42, 0x7b,
+    0x74, 0xb0, 0xbf, 0x87, 0x51, 0x9b, 0xa8, 0x1c, 0x79, 0xbd, 0x50, 0x85,
+    0x66, 0xe1, 0x93, 0xdd, 0xc5, 0x5d, 0x5d, 0xd0, 0xbe, 0xcb, 0x90, 0x36,
+    0xf8, 0xc6, 0xc2, 0xea, 0xea, 0x40, 0xce, 0xa7, 0xb0, 0xae, 0xc5, 0x44,
+    0x3a, 0x27, 0xc5, 0x4a, 0xf0, 0x21, 0x4f, 0xf6, 0x63, 0xb1, 0x8c, 0x20,
+    0x76, 0x65, 0xb5, 0x79, 0x55, 0x10, 0xa5, 0xa7, 0x4b, 0x57, 0x96, 0xb3,
+    0x03, 0xe6, 0xa8, 0x93, 0xf5, 0xc5, 0xca, 0xe0, 0x1a, 0x23, 0x30, 0x6d,
+    0x09, 0x07, 0x81, 0x5e, 0x05, 0xc6, 0x1b, 0x7a, 0x0e, 0xde, 0xf3, 0x00,
+    0x91, 0xf3, 0xbb, 0x4b, 0xa6, 0x8e, 0x96, 0xc3, 0x3a, 0xc8, 0x72, 0x19,
+    0x23, 0x23, 0xc7, 0x94, 0x46, 0x75, 0xa2, 0xc5, 0x9e, 0xa3, 0x15, 0x86,
+    0xb4, 0xa7, 0x95, 0xda, 0x16, 0xae, 0x42, 0xe8, 0xcc, 0xf6, 0x41, 0xbc,
+    0x9c, 0xe8, 0x07, 0xc9, 0x05, 0x3c, 0x74, 0xb2, 0xad, 0x77, 0xc4, 0x08,
+    0x56, 0x78, 0xb8, 0x65, 0x2a, 0x33, 0x39, 0x82, 0x16, 0x3c, 0x2b, 0x73,
+    0x41, 0x2a, 0xbc, 0xc8, 0x36, 0x23, 0x2c, 0x23, 0x29, 0xce, 0x94, 0x8a,
+    0xba, 0x13, 0x3f, 0xfa, 0xcc, 0x6e, 0x17, 0x40, 0xb0, 0xb4, 0x9c, 0xae,
+    0xf9, 0x72, 0x40, 0xf7, 0x2a, 0xaf, 0x00, 0x17, 0x7e, 0x88, 0x44, 0x4e,
+    0x32, 0xa4, 0x80, 0x96, 0x53, 0x20, 0xe4, 0xaa, 0x18, 0x9c, 0x69, 0x63,
+    0xdb, 0x81, 0x73, 0x0e, 0x64, 0x40, 0x12, 0xc1, 0x26, 0x0e, 0xac, 0x4d,
+    0x38, 0xa6, 0x4c, 0x05, 0xeb, 0x42, 0x1f, 0x88, 0x6e, 0x6c, 0xa3, 0x98,
+    0x95, 0xc3, 0x5a, 0x31, 0xfc, 0x8a, 0x7c, 0xd6, 0xa5, 0x6c, 0x5a, 0xc9,
+    0xf5, 0xf2, 0xb0, 0xf7, 0x05, 0x8d, 0x3a, 0x0b, 0x3f, 0x4d, 0x1b, 0x0e,
+    0x38, 0x7b, 0x1c, 0xe5, 0xd0, 0x75, 0x40, 0x77, 0xc2, 0xe0, 0x8b, 0xa9,
+    0xfb, 0xa6, 0xa7, 0x13, 0xf0, 0xbc, 0x0c, 0x13, 0xb0, 0x70, 0x3a, 0x2f,
+    0x20, 0xe7, 0x38, 0xd8, 0x82, 0xa4, 0xc0, 0x06, 0x96, 0x95, 0x75, 0x5c,
+    0xbc, 0x68, 0xce, 0xee, 0xa6, 0x44, 0xbb, 0xf2, 0x62, 0x14, 0x43, 0x10,
+    0xe6, 0x0b, 0x5c, 0x66, 0x02, 0xbf, 0x38, 0xe9, 0x8f, 0x19, 0x69, 0x6c,
+    0x08, 0xfa, 0x93, 0x23, 0xf1, 0x35, 0x5f, 0x33, 0xcf, 0xe2, 0x32, 0x11,
+    0xda, 0x31, 0xbb, 0xd8, 0xf5, 0x7e, 0x55, 0xc3, 0x6a, 0xa3, 0x04, 0x8c,
+    0xef, 0x50, 0x67, 0x0f, 0xe9, 0xbb, 0x11, 0x6b, 0xca, 0x5a, 0x23, 0x15,
+    0xf7, 0x52, 0x8c, 0x69, 0xbb, 0x2d, 0x26, 0xd3, 0x78, 0x32, 0x33, 0x9b,
+    0x1d, 0x02, 0x7c, 0x22, 0x4b, 0x57, 0x19, 0xec, 0xcd, 0x16, 0x63, 0x5d,
+    0x1f, 0x0c, 0x67, 0xda, 0x6a, 0xc7, 0x2c, 0xf1, 0x0b, 0xcf, 0x92, 0x10,
+    0xcb, 0x78, 0x57, 0x67, 0x61, 0x0e, 0xb3, 0x55, 0xb0, 0x17, 0x32, 0x4e,
+    0x95, 0xf1, 0xcb, 0xb5, 0xdb, 0x5d, 0x8e, 0x38, 0x97, 0x28, 0x46, 0x1e,
+    0x37, 0x4b, 0x5c, 0x03, 0xf4, 0x84, 0x0c, 0xfc, 0x49, 0x3b, 0xd2, 0xc6,
+    0x97, 0xd4, 0x4f, 0xef, 0xe6, 0x5c, 0xb2, 0x96, 0x8e, 0xbc, 0x18, 0x9f,
+    0xec, 0x8a, 0x67, 0x53, 0xe8, 0x2a, 0x41, 0x5c, 0x6e, 0xfe, 0xca, 0x1a,
+    0xd0, 0x03, 0x4f, 0xe8, 0xd9, 0xb0, 0xe2, 0xa1, 0x6c, 0x32, 0xd5, 0x37,
+    0x68, 0x9c, 0x6b, 0x30, 0x87, 0xb4, 0x6e, 0xa8, 0xc5, 0x45, 0xe4, 0x74,
+    0x4a, 0x80, 0x02, 0x84, 0x78, 0x0e, 0x2c, 0x9c, 0x37, 0x07, 0x26, 0x31,
+    0x88, 0x0a, 0x89, 0xd2, 0xba, 0x8b, 0x09, 0xb2, 0x16, 0x7b, 0x23, 0xa8,
+    0x0c, 0x82, 0xc4, 0x22, 0xa2, 0x21, 0x2d, 0xa4, 0xa0, 0xeb, 0xe4, 0xa6,
+    0xd4, 0x16, 0xa0, 0xa7, 0x19, 0x8b, 0x8f, 0x87, 0x9b, 0x53, 0x6c, 0xba,
+    0x14, 0xa7, 0xc4, 0x64, 0x08, 0xb4, 0x68, 0xda, 0x85, 0xa6, 0x47, 0xbc,
+    0x58, 0x34, 0xcd, 0x60, 0x43, 0xad, 0x14, 0xd4, 0xca, 0xd7, 0xb1, 0x6c,
+    0xc0, 0x05, 0x68, 0xaf, 0xa7, 0x08, 0x9d, 0x6a, 0xb0, 0x70, 0x96, 0x81,
+    0xb8, 0x55, 0xbf, 0xa1, 0xcc, 0xb1, 0x37, 0xe0, 0x94, 0x42, 0x05, 0x0c,
+    0x83, 0xef, 0x6d, 0xf0, 0x4e, 0xba, 0xe6, 0x78, 0x49, 0xaf, 0x1f, 0x88,
+    0xf0, 0x18, 0x0c, 0x17, 0x66, 0x92, 0xd8, 0x50, 0x57, 0x3b, 0x8e, 0xc9,
+    0xd5, 0x8c, 0xfb, 0x9b, 0x78, 0x65, 0x01, 0x76, 0x7a, 0x0e, 0xf0, 0x7f,
+    0x2b, 0xc4, 0x48, 0x81, 0xc2, 0xb7, 0xc1, 0x6e, 0x4b, 0xc7, 0x33, 0xa3,
+    0x9b, 0xf1, 0xcf, 0x63, 0x77, 0x52, 0x07, 0xe1, 0x9f, 0xa9, 0x6b, 0xce,
+    0x02, 0xbf, 0x06, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+const uint8_t kExpectedCiphertext[BCM_MLKEM768_CIPHERTEXT_BYTES] = {
+    0x8c, 0xfa, 0xd2, 0x09, 0x06, 0x1b, 0xff, 0x23, 0x9f, 0x84, 0x61, 0xfd,
+    0x69, 0x7a, 0xa6, 0x2c, 0x57, 0x43, 0x64, 0x6b, 0x6b, 0x6b, 0xa3, 0xe1,
+    0xa9, 0x4f, 0x3e, 0x29, 0xff, 0x3d, 0xb1, 0x84, 0x51, 0x1d, 0x48, 0xe3,
+    0xf2, 0xf9, 0x5c, 0x9b, 0xf8, 0x05, 0xa1, 0x4c, 0xf4, 0x78, 0xce, 0xd8,
+    0xc8, 0x0a, 0xc9, 0x71, 0xa7, 0x50, 0x89, 0xde, 0x66, 0x11, 0x68, 0x2c,
+    0x70, 0x0f, 0xa3, 0x15, 0xa7, 0x8f, 0xa7, 0xd1, 0x49, 0x32, 0x2b, 0xe7,
+    0xe3, 0x63, 0xff, 0x6b, 0x8c, 0x77, 0xd8, 0x97, 0x6f, 0x6c, 0x80, 0xc2,
+    0x73, 0x7d, 0xe2, 0x39, 0x6f, 0x61, 0x4f, 0xa3, 0x85, 0x14, 0x8e, 0x68,
+    0x58, 0x18, 0xba, 0x1c, 0x19, 0x01, 0x4c, 0x06, 0x73, 0x58, 0x4a, 0x9d,
+    0xdd, 0x2e, 0x78, 0x82, 0x62, 0xbf, 0x15, 0x0c, 0x8e, 0xa7, 0xcf, 0xee,
+    0xd7, 0x9a, 0x42, 0x30, 0xf5, 0x44, 0xdc, 0x3f, 0xdc, 0x67, 0x5c, 0x06,
+    0xf0, 0xcf, 0x3b, 0x24, 0x9e, 0xfa, 0xe8, 0x4b, 0x3b, 0x00, 0x01, 0x7c,
+    0x4d, 0x50, 0xa8, 0xac, 0x30, 0x74, 0xf4, 0x73, 0x98, 0x5e, 0x09, 0x92,
+    0xbd, 0xe1, 0xc4, 0x3a, 0x9f, 0xd0, 0x62, 0xc8, 0x4e, 0x7f, 0xb0, 0xaa,
+    0xb3, 0x8c, 0xb5, 0xf9, 0x57, 0xe3, 0x90, 0x9a, 0x94, 0x0d, 0xdb, 0x9e,
+    0xf7, 0x78, 0xbf, 0x18, 0xd0, 0x02, 0x8e, 0x02, 0x04, 0xbe, 0xee, 0x87,
+    0x49, 0xb1, 0xfe, 0x28, 0xd2, 0xdb, 0xd0, 0x7a, 0x12, 0x50, 0xa3, 0xc6,
+    0x32, 0xd6, 0x06, 0xa6, 0xc5, 0xb0, 0xa8, 0xbe, 0x49, 0x8a, 0x8b, 0xfe,
+    0xf6, 0xb1, 0xe5, 0xb6, 0xf0, 0x61, 0xc6, 0x1f, 0xe7, 0xcb, 0x4d, 0x66,
+    0xdd, 0xe4, 0xd2, 0x2b, 0x73, 0xbd, 0x03, 0x79, 0x76, 0x05, 0x87, 0x58,
+    0x6f, 0x6f, 0x8f, 0x20, 0x4f, 0x1f, 0x81, 0xa9, 0x9c, 0x22, 0x8d, 0xbd,
+    0xef, 0x41, 0x5e, 0x39, 0x9e, 0x90, 0x4b, 0x63, 0x8b, 0x50, 0xac, 0x4f,
+    0x20, 0x08, 0x82, 0x53, 0x52, 0x86, 0xce, 0x55, 0xf5, 0x21, 0xd7, 0x8c,
+    0xdf, 0xf3, 0x54, 0x90, 0xed, 0x27, 0xa9, 0x95, 0xbb, 0xec, 0x7a, 0xe2,
+    0xeb, 0x80, 0x29, 0xca, 0xc9, 0x4b, 0x1a, 0xfe, 0xe8, 0x40, 0xcf, 0x70,
+    0x37, 0xb3, 0xb8, 0xb3, 0x04, 0xf6, 0xc3, 0x44, 0x1e, 0xf8, 0x40, 0x95,
+    0xf9, 0x92, 0x97, 0x63, 0xab, 0x35, 0x11, 0x7b, 0x2d, 0x9e, 0x5b, 0xeb,
+    0xfe, 0x80, 0xfe, 0xc3, 0xc6, 0xa4, 0x8c, 0xac, 0xd2, 0xa5, 0x0d, 0x11,
+    0xcd, 0xbc, 0xdd, 0x57, 0x9d, 0xf4, 0xbc, 0xdf, 0xbe, 0xa2, 0xfc, 0xcd,
+    0x2b, 0x83, 0x0e, 0x4e, 0x77, 0x44, 0x10, 0x93, 0xeb, 0xca, 0xec, 0xb6,
+    0x26, 0x48, 0x45, 0x08, 0x72, 0xd4, 0xfe, 0xa2, 0xe5, 0xc8, 0x12, 0x8f,
+    0x38, 0xcd, 0xd6, 0xaa, 0x97, 0xd4, 0xad, 0xb3, 0x0b, 0x19, 0x5b, 0x70,
+    0x50, 0xbf, 0x9d, 0x45, 0xd6, 0x0d, 0xf6, 0x72, 0x08, 0x0f, 0x98, 0xbd,
+    0x1f, 0x39, 0xea, 0x4c, 0x76, 0xa8, 0x6e, 0xc2, 0x24, 0xe3, 0x3d, 0xf4,
+    0x40, 0xe8, 0x68, 0xfe, 0xaf, 0xeb, 0xae, 0x65, 0x84, 0x86, 0x10, 0xb6,
+    0x58, 0x75, 0xb9, 0x22, 0x6d, 0x74, 0x5d, 0xa7, 0xc0, 0x17, 0x10, 0x0f,
+    0x36, 0x5f, 0x99, 0xf3, 0x60, 0x39, 0xeb, 0x6e, 0x04, 0x4d, 0x29, 0xc7,
+    0xec, 0x2a, 0x1d, 0x8f, 0x5c, 0x23, 0x84, 0xba, 0x65, 0xe9, 0xab, 0x32,
+    0xd4, 0x62, 0xd1, 0x53, 0xb8, 0x71, 0x40, 0x9a, 0xf0, 0x05, 0xdb, 0xa0,
+    0x5a, 0xca, 0xeb, 0xb0, 0xbf, 0xfe, 0x7e, 0x19, 0x32, 0x42, 0xef, 0xab,
+    0xf3, 0x49, 0x13, 0x50, 0x08, 0x98, 0xcd, 0xcf, 0x5a, 0x77, 0x5d, 0xe6,
+    0x3f, 0x9d, 0xa0, 0x21, 0x98, 0xcb, 0x78, 0x69, 0xd8, 0x22, 0xdb, 0xae,
+    0x87, 0x2c, 0x38, 0x0a, 0x96, 0xa2, 0x30, 0x8f, 0x37, 0xe4, 0xc5, 0x94,
+    0x57, 0x40, 0x30, 0xa0, 0x4e, 0x7c, 0xfe, 0x6f, 0x2e, 0x15, 0x88, 0x7b,
+    0xf2, 0x22, 0x9c, 0x95, 0x7e, 0xd6, 0x2d, 0x37, 0xd4, 0x13, 0x95, 0x31,
+    0xf6, 0xbb, 0xf4, 0xaf, 0x33, 0x42, 0xf0, 0x45, 0xb1, 0xa8, 0xb4, 0x09,
+    0x9a, 0x6d, 0x7a, 0xdb, 0xb0, 0xf2, 0x00, 0xdc, 0x77, 0x6a, 0x43, 0xf1,
+    0xbb, 0x56, 0xc5, 0x7c, 0xee, 0xa6, 0xd6, 0x10, 0xa0, 0x81, 0xca, 0x28,
+    0xab, 0x48, 0xb4, 0x72, 0xbc, 0xe6, 0xe2, 0x24, 0xef, 0x49, 0xdc, 0xb5,
+    0x1f, 0x83, 0xe7, 0xda, 0xdd, 0x73, 0x5c, 0x7b, 0x85, 0x4a, 0x15, 0x7b,
+    0xcb, 0xf1, 0x14, 0x6b, 0x32, 0xef, 0xce, 0xaf, 0x37, 0x04, 0xa4, 0x1e,
+    0xcb, 0x1b, 0x84, 0x1d, 0xdb, 0xbf, 0x2f, 0x88, 0x89, 0xf4, 0x5e, 0xb0,
+    0x32, 0x99, 0x81, 0x9c, 0x8a, 0xb0, 0xfd, 0x28, 0x6f, 0xc9, 0xe9, 0xaf,
+    0x60, 0x11, 0xa5, 0x8d, 0xa4, 0xfb, 0x93, 0x91, 0x7a, 0xa0, 0xd2, 0xcd,
+    0xda, 0x4d, 0xf3, 0xfe, 0xc8, 0x55, 0x4f, 0x26, 0x9d, 0x56, 0x87, 0x12,
+    0xfe, 0x93, 0x3e, 0x34, 0xf5, 0x3d, 0x4f, 0x6e, 0x26, 0x56, 0xf7, 0x80,
+    0xa2, 0xb9, 0x0f, 0xa1, 0xf8, 0x72, 0xb0, 0xaa, 0xec, 0xe2, 0x97, 0xd0,
+    0x3a, 0x6d, 0xe5, 0xe9, 0x12, 0x1b, 0x32, 0x0a, 0xdb, 0x52, 0x8f, 0x9d,
+    0xd0, 0xff, 0x67, 0xcc, 0x63, 0x41, 0x32, 0x2f, 0xe7, 0x0c, 0xb0, 0xa5,
+    0x73, 0xc5, 0xc3, 0x54, 0x75, 0x06, 0x8e, 0x36, 0x54, 0xea, 0x9c, 0x6b,
+    0x60, 0xee, 0x10, 0x06, 0xd2, 0xb3, 0x8c, 0xe3, 0x09, 0xfe, 0x1e, 0x47,
+    0xc3, 0xd5, 0x6c, 0x0d, 0x0c, 0x84, 0x5e, 0x4f, 0x01, 0xfa, 0xcf, 0xae,
+    0xc1, 0xac, 0xd9, 0xb0, 0x03, 0x74, 0x8e, 0xc5, 0x57, 0x51, 0x96, 0x23,
+    0x72, 0xc6, 0x81, 0x7f, 0xf1, 0x6c, 0x29, 0xea, 0x31, 0x2a, 0x23, 0xbb,
+    0x88, 0x6f, 0x01, 0xa2, 0x2f, 0x69, 0xd2, 0x1c, 0xe8, 0x1e, 0x63, 0x44,
+    0xd9, 0x90, 0x0b, 0x57, 0x78, 0xc6, 0xd1, 0xb3, 0xf6, 0x97, 0x99, 0xd8,
+    0x09, 0xe0, 0x9d, 0x69, 0x00, 0xa0, 0xd4, 0xe0, 0x80, 0xfd, 0xdf, 0x23,
+    0x3a, 0xf8, 0xc0, 0x97, 0xea, 0xb6, 0xbf, 0x87, 0x75, 0x40, 0x1e, 0x0d,
+    0x1e, 0x6c, 0x84, 0xa4, 0x7e, 0xbb, 0xa3, 0x02, 0x76, 0x76, 0xc8, 0x4e,
+    0x8b, 0x21, 0x3d, 0x27, 0xbc, 0x38, 0x0f, 0x79, 0xfb, 0xc5, 0xdd, 0x37,
+    0x67, 0xcb, 0x61, 0x5a, 0x12, 0x85, 0x31, 0x91, 0x3e, 0x7a, 0x4b, 0x6c,
+    0xfd, 0x4e, 0x54, 0x47, 0xfc, 0xc5, 0x2e, 0x34, 0xe4, 0xaa, 0x3d, 0xa2,
+    0xd3, 0x1d, 0x15, 0xbc, 0xea, 0xa7, 0xe3, 0xcd, 0xd6, 0x49, 0xee, 0x06,
+    0x11, 0x2b, 0xf1, 0x58, 0x81, 0xdd, 0x99, 0xe1, 0xbd, 0x63, 0xa0, 0xd7,
+    0xa0, 0x4b, 0x01, 0xab, 0xf3, 0x5c, 0x35, 0xf0, 0xb0, 0xdc, 0xd0, 0x87,
+    0x78, 0x02, 0xec, 0x99, 0x0e, 0xb2, 0x23, 0x8b, 0xb1, 0x44, 0x93, 0x65,
+    0xd5, 0x1c, 0x00, 0x7e, 0x98, 0xb3, 0x5e, 0xf9, 0xca, 0xbc, 0x26, 0x38,
+    0x18, 0x22, 0x14, 0x3c, 0xed, 0x8d, 0x54, 0xa4, 0x05, 0x00, 0x7f, 0xfb,
+    0xd5, 0x73, 0x77, 0xf4, 0x98, 0xa0, 0xf7, 0x60, 0xb4, 0x47, 0x10, 0x75,
+    0x30, 0x2d, 0xde, 0x9c, 0x3e, 0x08, 0x8f, 0xe5, 0xc9, 0x5a, 0xd9, 0x20,
+    0xf3, 0x97, 0xb5, 0xd1, 0xb3, 0x90, 0x23, 0x6f, 0x9f, 0x5e, 0xf1, 0x0f,
+    0x76, 0x18, 0xbf, 0x2b, 0x23, 0x8e, 0x45, 0x3f, 0xaf, 0x2b, 0x53, 0x78,
+    0x27, 0xa2, 0xf6, 0x07, 0x2b, 0x61, 0x24, 0x5b, 0xc7, 0x2e, 0x25, 0xf1,
+    0xb3, 0x4c, 0x50, 0xe8, 0x6d, 0xee, 0x56, 0x52, 0x37, 0xd0, 0x6e, 0xd6,
+    0xcb, 0xc8, 0x2a, 0xb1, 0xba, 0x49, 0xc7, 0x5a, 0x55, 0x3c, 0x6f, 0x16,
+    0x64, 0x08, 0xa6, 0x46, 0x09, 0x37, 0x86, 0x0b, 0xe7, 0x7e, 0x2d, 0xf4,
+    0x96, 0x80, 0x41, 0x77, 0x1a, 0xf9, 0xd2, 0xe0, 0xf3, 0x64, 0x0e, 0x3f,
+    0x3d, 0xe1, 0xec, 0x63, 0x40, 0x10, 0x15, 0xcf, 0x4c, 0xc9, 0x1c, 0x9b,
+    0x9f, 0xe8, 0x50, 0x27, 0xc2, 0x54, 0x44, 0x14, 0xb6, 0x2e, 0xe4, 0x53,
+    0xf2, 0x60, 0x8a, 0xb6, 0x1c, 0x14, 0xb6, 0x25, 0xf2, 0x44, 0x59, 0xb7,
+    0x67, 0x3b, 0x94, 0x88, 0x15, 0x70, 0x6f, 0xa8};
+
+const uint8_t kExpectedSharedSecret[BCM_MLKEM_SHARED_SECRET_BYTES] = {
+    0x7d, 0x9f, 0x1c, 0xb4, 0xae, 0x04, 0xd7, 0x5f, 0xa6, 0x57, 0x5a,
+    0xe0, 0xe4, 0x29, 0xb5, 0x73, 0xa9, 0x74, 0xb7, 0xa1, 0x25, 0xbd,
+    0xfb, 0x8a, 0x6e, 0x0f, 0x19, 0xba, 0xe1, 0x16, 0xae, 0x81};
+
+const uint8_t
+    kExpectedImplicitRejectionSharedSecret[BCM_MLKEM_SHARED_SECRET_BYTES] = {
+        0xa3, 0x19, 0x2a, 0x8c, 0x88, 0xfc, 0x99, 0x6d, 0x2d, 0xf9, 0x85,
+        0x8d, 0x2c, 0x55, 0x36, 0x39, 0x93, 0xf0, 0x49, 0x4d, 0x7e, 0xc0,
+        0xbe, 0x5a, 0x56, 0x7b, 0x8a, 0x42, 0x43, 0xa5, 0x74, 0x5d};
diff --git a/src/crypto/fipsmodule/mlkem/mlkem.cc.inc b/src/crypto/fipsmodule/mlkem/mlkem.cc.inc
index c543f3c..c3773cc 100644
--- a/src/crypto/fipsmodule/mlkem/mlkem.cc.inc
+++ b/src/crypto/fipsmodule/mlkem/mlkem.cc.inc
@@ -26,12 +26,19 @@
 
 #include "../../internal.h"
 #include "../bcm_interface.h"
+#include "../delocate.h"
 #include "../keccak/internal.h"
 
 
 namespace mlkem {
 namespace {
 
+namespace fips {
+void ensure_keygen_self_test();
+void ensure_encap_self_test();
+void ensure_decap_self_test();
+}  // namespace fips
+
 // See
 // https://csrc.nist.gov/pubs/fips/203/final
 
@@ -690,7 +697,7 @@
 }
 
 template <int RANK>
-void mlkem_generate_key_external_seed(
+void mlkem_generate_key_external_seed_no_self_test(
     uint8_t *out_encoded_public_key, private_key<RANK> *priv,
     const uint8_t seed[BCM_MLKEM_SEED_BYTES]) {
   uint8_t augmented_seed[33];
@@ -727,6 +734,15 @@
   OPENSSL_memcpy(priv->fo_failure_secret, seed + 32, 32);
 }
 
+template <int RANK>
+void mlkem_generate_key_external_seed(
+    uint8_t *out_encoded_public_key, private_key<RANK> *priv,
+    const uint8_t seed[BCM_MLKEM_SEED_BYTES]) {
+  fips::ensure_keygen_self_test();
+  mlkem_generate_key_external_seed_no_self_test(out_encoded_public_key, priv,
+                                                seed);
+}
+
 // Encrypts a message with given randomness to
 // the ciphertext in |out|. Without applying the Fujisaki-Okamoto transform this
 // would not result in a CCA secure scheme, since lattice schemes are vulnerable
@@ -768,9 +784,9 @@
 
 // See section 6.3
 template <int RANK>
-void mlkem_decap(uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
-                 const uint8_t *ciphertext,
-                 const struct private_key<RANK> *priv) {
+void mlkem_decap_no_self_test(
+    uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
+    const uint8_t *ciphertext, const struct private_key<RANK> *priv) {
   uint8_t decrypted[64];
   decrypt_cpa(decrypted, priv, ciphertext);
   OPENSSL_memcpy(decrypted + 32, priv->pub.public_key_hash,
@@ -794,6 +810,14 @@
   }
 }
 
+template <int RANK>
+void mlkem_decap(uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
+                 const uint8_t *ciphertext,
+                 const struct private_key<RANK> *priv) {
+  fips::ensure_decap_self_test();
+  mlkem_decap_no_self_test(out_shared_secret, ciphertext, priv);
+}
+
 // mlkem_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate
 // the value of |pub->public_key_hash|.
 template <int RANK>
@@ -863,8 +887,8 @@
   return (struct public_key<RANK768> *)external;
 }
 
-static struct public_key<RANK1024> *
-public_key_1024_from_external(const struct BCM_mlkem1024_public_key *external) {
+static struct public_key<RANK1024> *public_key_1024_from_external(
+    const struct BCM_mlkem1024_public_key *external) {
   static_assert(sizeof(struct BCM_mlkem1024_public_key) >=
                     sizeof(struct public_key<RANK1024>),
                 "MLKEM1024 public key is too small");
@@ -874,8 +898,8 @@
   return (struct public_key<RANK1024> *)external;
 }
 
-struct private_key<RANK768> *
-private_key_768_from_external(const struct BCM_mlkem768_private_key *external) {
+struct private_key<RANK768> *private_key_768_from_external(
+    const struct BCM_mlkem768_private_key *external) {
   static_assert(sizeof(struct BCM_mlkem768_private_key) >=
                     sizeof(struct private_key<RANK768>),
                 "MLKEM private key too small");
@@ -885,8 +909,7 @@
   return (struct private_key<RANK768> *)external;
 }
 
-struct private_key<RANK1024> *
-private_key_1024_from_external(
+struct private_key<RANK1024> *private_key_1024_from_external(
     const struct BCM_mlkem1024_private_key *external) {
   static_assert(sizeof(struct BCM_mlkem1024_private_key) >=
                     sizeof(struct private_key<RANK1024>),
@@ -897,9 +920,196 @@
   return (struct private_key<RANK1024> *)external;
 }
 
+// See section 6.2.
+template <int RANK>
+void mlkem_encap_external_entropy_no_self_test(
+    uint8_t *out_ciphertext,
+    uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
+    const struct mlkem::public_key<RANK> *pub,
+    const uint8_t entropy[BCM_MLKEM_ENCAP_ENTROPY]) {
+  uint8_t input[64];
+  OPENSSL_memcpy(input, entropy, BCM_MLKEM_ENCAP_ENTROPY);
+  OPENSSL_memcpy(input + BCM_MLKEM_ENCAP_ENTROPY, pub->public_key_hash,
+                 sizeof(input) - BCM_MLKEM_ENCAP_ENTROPY);
+  uint8_t key_and_randomness[64];
+  mlkem::hash_g(key_and_randomness, input, sizeof(input));
+  encrypt_cpa(out_ciphertext, pub, entropy, key_and_randomness + 32);
+  // The ciphertext is public.
+  CONSTTIME_DECLASSIFY(out_ciphertext, mlkem::ciphertext_size(RANK));
+  static_assert(BCM_MLKEM_SHARED_SECRET_BYTES == 32, "");
+  memcpy(out_shared_secret, key_and_randomness, 32);
+}
+
+template <int RANK>
+void mlkem_encap_external_entropy(
+    uint8_t *out_ciphertext,
+    uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
+    const struct mlkem::public_key<RANK> *pub,
+    const uint8_t entropy[BCM_MLKEM_ENCAP_ENTROPY]) {
+  fips::ensure_encap_self_test();
+  mlkem_encap_external_entropy_no_self_test(out_ciphertext, out_shared_secret,
+                                            pub, entropy);
+}
+
+namespace fips {
+
+#include "fips_known_values.inc"
+
+static int keygen_self_test() {
+  uint8_t pub_key[BCM_MLKEM768_PUBLIC_KEY_BYTES];
+  private_key<RANK768> priv;
+  static_assert(sizeof(kTestEntropy) >= BCM_MLKEM_SEED_BYTES);
+  mlkem_generate_key_external_seed_no_self_test(pub_key, &priv, kTestEntropy);
+  CBB cbb;
+  constexpr size_t kMarshaledPrivateKeySize = 2400;
+  uint8_t priv_bytes[kMarshaledPrivateKeySize];
+  CBB_init_fixed(&cbb, priv_bytes, sizeof(priv_bytes));
+  static_assert(sizeof(kExpectedPrivateKeyBytes) == kMarshaledPrivateKeySize);
+  static_assert(sizeof(kExpectedPublicKeyBytes) == sizeof(pub_key));
+  if (!mlkem_marshal_private_key(&cbb, &priv) ||
+      !BORINGSSL_check_test(kExpectedPrivateKeyBytes, priv_bytes,
+                            sizeof(priv_bytes), "ML-KEM keygen private key") ||
+      !BORINGSSL_check_test(kExpectedPublicKeyBytes, pub_key, sizeof(pub_key),
+                            "ML-KEM keygen public key")) {
+    return 0;
+  }
+  return 1;
+}
+
+static int encap_self_test() {
+  CBS cbs;
+  CBS_init(&cbs, kExpectedPublicKeyBytes, sizeof(kExpectedPublicKeyBytes));
+  public_key<RANK768> pub;
+  if (!mlkem_parse_public_key(&pub, &cbs)) {
+    return 0;
+  }
+  uint8_t ciphertext[BCM_MLKEM768_CIPHERTEXT_BYTES];
+  uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  static_assert(sizeof(kTestEntropy) >= BCM_MLKEM_ENCAP_ENTROPY);
+  mlkem_encap_external_entropy_no_self_test(ciphertext, shared_secret, &pub,
+                                            kTestEntropy);
+  if (!BORINGSSL_check_test(ciphertext, kExpectedCiphertext, sizeof(ciphertext),
+                            "ML-KEM encap ciphertext") ||
+      !BORINGSSL_check_test(kExpectedSharedSecret, shared_secret,
+                            sizeof(kExpectedSharedSecret),
+                            "ML-KEM encap shared secret")) {
+    return 0;
+  }
+  return 1;
+}
+
+static int decap_self_test() {
+  CBS cbs;
+  CBS_init(&cbs, kExpectedPrivateKeyBytes, sizeof(kExpectedPrivateKeyBytes));
+  private_key<RANK768> priv;
+  if (!mlkem_parse_private_key(&priv, &cbs)) {
+    return 0;
+  }
+  uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  mlkem_decap_no_self_test(shared_secret, kExpectedCiphertext, &priv);
+  static_assert(sizeof(kExpectedSharedSecret) == sizeof(shared_secret));
+  if (!BORINGSSL_check_test(kExpectedSharedSecret, shared_secret,
+                            sizeof(shared_secret),
+                            "ML-KEM decap shared secret")) {
+    return 0;
+  }
+
+  uint8_t implicit_rejection_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  static_assert(sizeof(kExpectedPrivateKeyBytes) >=
+                sizeof(kExpectedCiphertext));
+  mlkem_decap_no_self_test(implicit_rejection_shared_secret,
+                           kExpectedPrivateKeyBytes, &priv);
+  static_assert(sizeof(kExpectedImplicitRejectionSharedSecret) ==
+                sizeof(implicit_rejection_shared_secret));
+  if (!BORINGSSL_check_test(kExpectedImplicitRejectionSharedSecret,
+                            implicit_rejection_shared_secret,
+                            sizeof(implicit_rejection_shared_secret),
+                            "ML-KEM decap implicit rejection shared secret")) {
+    return 0;
+  }
+  return 1;
+}
+
+#if defined(BORINGSSL_FIPS)
+
+DEFINE_STATIC_ONCE(g_mlkem_keygen_self_test_once)
+
+void ensure_keygen_self_test(void) {
+  CRYPTO_once(g_mlkem_keygen_self_test_once_bss_get(), []() {
+    if (!keygen_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_mlkem_encap_self_test_once)
+
+void ensure_encap_self_test(void) {
+  CRYPTO_once(g_mlkem_encap_self_test_once_bss_get(), []() {
+    if (!encap_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_mlkem_decap_self_test_once)
+
+void ensure_decap_self_test(void) {
+  CRYPTO_once(g_mlkem_decap_self_test_once_bss_get(), []() {
+    if (!decap_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+#else
+
+void ensure_keygen_self_test(void) {}
+void ensure_encap_self_test(void) {}
+void ensure_decap_self_test(void) {}
+
+#endif
+}  // namespace fips
+
 }  // namespace
 }  // namespace mlkem
 
+bcm_status BCM_mlkem768_check_fips(
+    const struct BCM_mlkem768_private_key *private_key) {
+  mlkem::private_key<RANK768> *priv =
+      mlkem::private_key_768_from_external(private_key);
+
+  const uint8_t entropy[BCM_MLKEM_ENCAP_ENTROPY] = {1, 2, 3, 4};
+  uint8_t ciphertext[BCM_MLKEM768_CIPHERTEXT_BYTES];
+  uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  mlkem_encap_external_entropy_no_self_test(ciphertext, shared_secret,
+                                            &priv->pub, entropy);
+
+  if (boringssl_fips_break_test("MLKEM_PWCT")) {
+    shared_secret[0] ^= 1;
+  }
+
+  uint8_t shared_secret2[BCM_MLKEM_SHARED_SECRET_BYTES];
+  mlkem::mlkem_decap_no_self_test(shared_secret2, ciphertext, priv);
+  if (CRYPTO_memcmp(shared_secret, shared_secret2, sizeof(shared_secret)) !=
+      0) {
+    return bcm_status::failure;
+  }
+  return bcm_status::approved;
+}
+
+bcm_status BCM_mlkem768_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLKEM768_PUBLIC_KEY_BYTES],
+    uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
+    struct BCM_mlkem768_private_key *out_private_key) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  BCM_mlkem768_generate_key(out_encoded_public_key, optional_out_seed,
+                            out_private_key);
+  return BCM_mlkem768_check_fips(out_private_key);
+}
+
 bcm_infallible BCM_mlkem768_generate_key(
     uint8_t out_encoded_public_key[BCM_MLKEM768_PUBLIC_KEY_BYTES],
     uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
@@ -912,7 +1122,7 @@
   }
   BCM_mlkem768_generate_key_external_seed(out_encoded_public_key,
                                           out_private_key, seed);
-  return bcm_infallible::approved;
+  return bcm_infallible::not_approved;
 }
 
 bcm_status BCM_mlkem768_private_key_from_seed(
@@ -921,12 +1131,49 @@
   if (seed_len != BCM_MLKEM_SEED_BYTES) {
     return bcm_status::failure;
   }
+
   uint8_t public_key_bytes[BCM_MLKEM768_PUBLIC_KEY_BYTES];
   BCM_mlkem768_generate_key_external_seed(public_key_bytes, out_private_key,
                                           seed);
+  return bcm_status::not_approved;
+}
+
+bcm_status BCM_mlkem1024_check_fips(
+    const struct BCM_mlkem1024_private_key *private_key) {
+  mlkem::private_key<RANK1024> *priv =
+      mlkem::private_key_1024_from_external(private_key);
+
+  const uint8_t entropy[BCM_MLKEM_ENCAP_ENTROPY] = {1, 2, 3, 4};
+  uint8_t ciphertext[BCM_MLKEM1024_CIPHERTEXT_BYTES];
+  uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  mlkem_encap_external_entropy_no_self_test(ciphertext, shared_secret,
+                                            &priv->pub, entropy);
+
+  if (boringssl_fips_break_test("MLKEM_PWCT")) {
+    shared_secret[0] ^= 1;
+  }
+
+  uint8_t shared_secret2[BCM_MLKEM_SHARED_SECRET_BYTES];
+  mlkem::mlkem_decap_no_self_test(shared_secret2, ciphertext, priv);
+  if (CRYPTO_memcmp(shared_secret, shared_secret2, sizeof(shared_secret)) !=
+      0) {
+    return bcm_status::failure;
+  }
   return bcm_status::approved;
 }
 
+bcm_status BCM_mlkem1024_generate_key_fips(
+    uint8_t out_encoded_public_key[BCM_MLKEM1024_PUBLIC_KEY_BYTES],
+    uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
+    struct BCM_mlkem1024_private_key *out_private_key) {
+  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  BCM_mlkem1024_generate_key(out_encoded_public_key, optional_out_seed,
+                             out_private_key);
+  return BCM_mlkem1024_check_fips(out_private_key);
+}
+
 bcm_infallible BCM_mlkem1024_generate_key(
     uint8_t out_encoded_public_key[BCM_MLKEM1024_PUBLIC_KEY_BYTES],
     uint8_t optional_out_seed[BCM_MLKEM_SEED_BYTES],
@@ -939,7 +1186,7 @@
   }
   BCM_mlkem1024_generate_key_external_seed(out_encoded_public_key,
                                            out_private_key, seed);
-  return bcm_infallible::approved;
+  return bcm_infallible::not_approved;
 }
 
 bcm_status BCM_mlkem1024_private_key_from_seed(
@@ -951,7 +1198,7 @@
   uint8_t public_key_bytes[BCM_MLKEM1024_PUBLIC_KEY_BYTES];
   BCM_mlkem1024_generate_key_external_seed(public_key_bytes, out_private_key,
                                            seed);
-  return bcm_status::approved;
+  return bcm_status::not_approved;
 }
 
 bcm_infallible BCM_mlkem768_generate_key_external_seed(
@@ -1022,26 +1269,6 @@
   return bcm_infallible::approved;
 }
 
-// See section 6.2.
-template <int RANK>
-void mlkem_encap_external_entropy(
-    uint8_t *out_ciphertext,
-    uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
-    const struct mlkem::public_key<RANK> *pub,
-    const uint8_t entropy[BCM_MLKEM_ENCAP_ENTROPY]) {
-  uint8_t input[64];
-  OPENSSL_memcpy(input, entropy, BCM_MLKEM_ENCAP_ENTROPY);
-  OPENSSL_memcpy(input + BCM_MLKEM_ENCAP_ENTROPY, pub->public_key_hash,
-                 sizeof(input) - BCM_MLKEM_ENCAP_ENTROPY);
-  uint8_t key_and_randomness[64];
-  mlkem::hash_g(key_and_randomness, input, sizeof(input));
-  encrypt_cpa(out_ciphertext, pub, entropy, key_and_randomness + 32);
-  // The ciphertext is public.
-  CONSTTIME_DECLASSIFY(out_ciphertext, mlkem::ciphertext_size(RANK));
-  static_assert(BCM_MLKEM_SHARED_SECRET_BYTES == 32, "");
-  memcpy(out_shared_secret, key_and_randomness, 32);
-}
-
 bcm_infallible BCM_mlkem768_encap_external_entropy(
     uint8_t out_ciphertext[BCM_MLKEM768_CIPHERTEXT_BYTES],
     uint8_t out_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES],
@@ -1163,3 +1390,8 @@
   }
   return bcm_status::approved;
 }
+
+int boringssl_self_test_mlkem() {
+  return mlkem::fips::keygen_self_test() && mlkem::fips::encap_self_test() &&
+         mlkem::fips::decap_self_test();
+}
diff --git a/src/crypto/fipsmodule/rand/internal.h b/src/crypto/fipsmodule/rand/internal.h
index 7ffe617..e791edf 100644
--- a/src/crypto/fipsmodule/rand/internal.h
+++ b/src/crypto/fipsmodule/rand/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
-#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_RAND_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_RAND_INTERNAL_H
 
 #include <openssl/aes.h>
 #include <openssl/ctrdrbg.h>
@@ -81,4 +81,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_RAND_INTERNAL_H
diff --git a/src/crypto/fipsmodule/rand/rand.cc.inc b/src/crypto/fipsmodule/rand/rand.cc.inc
index 0200fa5..f531b44 100644
--- a/src/crypto/fipsmodule/rand/rand.cc.inc
+++ b/src/crypto/fipsmodule/rand/rand.cc.inc
@@ -140,7 +140,7 @@
 }
 
 #if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
-    !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+    !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 // rdrand should only be called if either |have_rdrand| or |have_fast_rdrand|
 // returned true.
 static int rdrand(uint8_t *buf, const size_t len) {
diff --git a/src/crypto/fipsmodule/rsa/internal.h b/src/crypto/fipsmodule/rsa/internal.h
index 6636104..94719ce 100644
--- a/src/crypto/fipsmodule/rsa/internal.h
+++ b/src/crypto/fipsmodule/rsa/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_RSA_INTERNAL_H
-#define OPENSSL_HEADER_RSA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_RSA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_RSA_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -167,4 +167,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_RSA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_RSA_INTERNAL_H
diff --git a/src/crypto/fipsmodule/rsa/padding.cc.inc b/src/crypto/fipsmodule/rsa/padding.cc.inc
index b671382..d86627f 100644
--- a/src/crypto/fipsmodule/rsa/padding.cc.inc
+++ b/src/crypto/fipsmodule/rsa/padding.cc.inc
@@ -121,8 +121,7 @@
 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);
+  bssl::ScopedEVP_MD_CTX ctx;
   FIPS_service_indicator_lock_state();
 
   size_t md_len = EVP_MD_size(md);
@@ -133,21 +132,21 @@
     counter[1] = (uint8_t)(i >> 16);
     counter[2] = (uint8_t)(i >> 8);
     counter[3] = (uint8_t)i;
-    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
-        !EVP_DigestUpdate(&ctx, seed, seed_len) ||
-        !EVP_DigestUpdate(&ctx, counter, sizeof(counter))) {
+    if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) ||
+        !EVP_DigestUpdate(ctx.get(), seed, seed_len) ||
+        !EVP_DigestUpdate(ctx.get(), counter, sizeof(counter))) {
       goto err;
     }
 
     if (md_len <= len) {
-      if (!EVP_DigestFinal_ex(&ctx, out, NULL)) {
+      if (!EVP_DigestFinal_ex(ctx.get(), out, nullptr)) {
         goto err;
       }
       out += md_len;
       len -= md_len;
     } else {
       uint8_t digest[EVP_MAX_MD_SIZE];
-      if (!EVP_DigestFinal_ex(&ctx, digest, NULL)) {
+      if (!EVP_DigestFinal_ex(ctx.get(), digest, nullptr)) {
         goto err;
       }
       OPENSSL_memcpy(out, digest, len);
@@ -158,7 +157,6 @@
   ret = 1;
 
 err:
-  EVP_MD_CTX_cleanup(&ctx);
   FIPS_service_indicator_unlock_state();
   return ret;
 }
@@ -175,8 +173,7 @@
   int ret = 0;
   uint8_t *DB = NULL;
   const uint8_t *H;
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
   unsigned MSBits;
   size_t emLen, maskedDBLen, salt_start;
   FIPS_service_indicator_lock_state();
@@ -247,11 +244,11 @@
     goto err;
   }
   uint8_t H_[EVP_MAX_MD_SIZE];
-  if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
-      !EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
-      !EVP_DigestUpdate(&ctx, mHash, hLen) ||
-      !EVP_DigestUpdate(&ctx, DB + salt_start, maskedDBLen - salt_start) ||
-      !EVP_DigestFinal_ex(&ctx, H_, NULL)) {
+  if (!EVP_DigestInit_ex(ctx.get(), Hash, NULL) ||
+      !EVP_DigestUpdate(ctx.get(), kPSSZeroes, sizeof(kPSSZeroes)) ||
+      !EVP_DigestUpdate(ctx.get(), mHash, hLen) ||
+      !EVP_DigestUpdate(ctx.get(), DB + salt_start, maskedDBLen - salt_start) ||
+      !EVP_DigestFinal_ex(ctx.get(), H_, NULL)) {
     goto err;
   }
   if (OPENSSL_memcmp(H_, H, hLen) != 0) {
@@ -263,7 +260,6 @@
 
 err:
   OPENSSL_free(DB);
-  EVP_MD_CTX_cleanup(&ctx);
   FIPS_service_indicator_unlock_state();
   return ret;
 }
@@ -272,7 +268,8 @@
                                    const unsigned char *mHash,
                                    const EVP_MD *Hash, const EVP_MD *mgf1Hash,
                                    int sLenRequested) {
-  int ret = 0, digest_ok;
+  int ret = 0;
+  bssl::ScopedEVP_MD_CTX ctx;
   size_t maskedDBLen, MSBits, emLen;
   size_t hLen;
   unsigned char *H, *salt = NULL, *p;
@@ -333,15 +330,11 @@
   maskedDBLen = emLen - hLen - 1;
   H = EM + maskedDBLen;
 
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  digest_ok = EVP_DigestInit_ex(&ctx, Hash, NULL) &&
-              EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) &&
-              EVP_DigestUpdate(&ctx, mHash, hLen) &&
-              EVP_DigestUpdate(&ctx, salt, sLen) &&
-              EVP_DigestFinal_ex(&ctx, H, NULL);
-  EVP_MD_CTX_cleanup(&ctx);
-  if (!digest_ok) {
+  if (!EVP_DigestInit_ex(ctx.get(), Hash, NULL) ||
+      !EVP_DigestUpdate(ctx.get(), kPSSZeroes, sizeof(kPSSZeroes)) ||
+      !EVP_DigestUpdate(ctx.get(), mHash, hLen) ||
+      !EVP_DigestUpdate(ctx.get(), salt, sLen) ||
+      !EVP_DigestFinal_ex(ctx.get(), H, NULL)) {
     goto err;
   }
 
diff --git a/src/crypto/fipsmodule/rsa/rsa.cc.inc b/src/crypto/fipsmodule/rsa/rsa.cc.inc
index 0240e8a..ebcd558 100644
--- a/src/crypto/fipsmodule/rsa/rsa.cc.inc
+++ b/src/crypto/fipsmodule/rsa/rsa.cc.inc
@@ -718,15 +718,15 @@
   // Note |bn_mul_consttime| and |bn_div_consttime| do not scale linearly, but
   // checking |ainv| is in range bounds the running time, assuming |m|'s bounds
   // were checked by the caller.
-  BN_CTX_start(ctx);
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
-  int ret = tmp != NULL && bn_mul_consttime(tmp, a, ainv, ctx) &&
-            bn_div_consttime(NULL, tmp, tmp, m, m_min_bits, ctx);
-  if (ret) {
-    *out_ok = constant_time_declassify_int(BN_is_one(tmp));
+  if (tmp == nullptr ||  //
+      !bn_mul_consttime(tmp, a, ainv, ctx) ||
+      !bn_div_consttime(NULL, tmp, tmp, m, m_min_bits, ctx)) {
+    return 0;
   }
-  BN_CTX_end(ctx);
-  return ret;
+  *out_ok = constant_time_declassify_int(BN_is_one(tmp));
+  return 1;
 }
 
 int RSA_check_key(const RSA *key) {
diff --git a/src/crypto/fipsmodule/rsa/rsa_impl.cc.inc b/src/crypto/fipsmodule/rsa/rsa_impl.cc.inc
index 79e2789..e5c34f1 100644
--- a/src/crypto/fipsmodule/rsa/rsa_impl.cc.inc
+++ b/src/crypto/fipsmodule/rsa/rsa_impl.cc.inc
@@ -31,6 +31,10 @@
 #include "internal.h"
 
 
+static_assert(OPENSSL_RSA_MAX_MODULUS_BITS <=
+                  BN_MONTGOMERY_MAX_WORDS * BN_BITS2,
+              "Max RSA size too big for Montgomery arithmetic");
+
 int rsa_check_public_key(const RSA *rsa) {
   if (rsa->n == NULL) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
@@ -442,8 +446,6 @@
   }
 
   const unsigned rsa_size = RSA_size(rsa);
-  BIGNUM *f, *result;
-
   if (max_out < rsa_size) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
     return 0;
@@ -454,18 +456,17 @@
     return 0;
   }
 
-  BN_CTX *ctx = BN_CTX_new();
-  if (ctx == NULL) {
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
     return 0;
   }
 
   int ret = 0;
-  uint8_t *buf = NULL;
-
-  BN_CTX_start(ctx);
-  f = BN_CTX_get(ctx);
-  result = BN_CTX_get(ctx);
-  if (f == NULL || result == NULL) {
+  uint8_t *buf = nullptr;
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *f = BN_CTX_get(ctx.get());
+  BIGNUM *result = BN_CTX_get(ctx.get());
+  if (f == nullptr || result == nullptr) {
     goto err;
   }
 
@@ -474,12 +475,12 @@
   } else {
     // Allocate a temporary buffer to hold the padded plaintext.
     buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(rsa_size));
-    if (buf == NULL) {
+    if (buf == nullptr) {
       goto err;
     }
   }
 
-  if (BN_bin2bn(in, in_len, f) == NULL) {
+  if (BN_bin2bn(in, in_len, f) == nullptr) {
     goto err;
   }
 
@@ -488,8 +489,9 @@
     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)) {
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx.get()) ||
+      !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx.get(),
+                       rsa->mont_n)) {
     goto err;
   }
 
@@ -518,8 +520,6 @@
   }
 
 err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(ctx);
   if (buf != out) {
     OPENSSL_free(buf);
   }
@@ -535,32 +535,28 @@
 
 int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
                                   size_t len) {
-  if (rsa->n == NULL || rsa->d == NULL) {
+  if (rsa->n == nullptr || rsa->d == nullptr) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
     return 0;
   }
 
-  BIGNUM *f, *result;
-  BN_CTX *ctx = NULL;
-  size_t blinding_index = 0;
-  BN_BLINDING *blinding = NULL;
-  int ret = 0, do_blinding;
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
-  BN_CTX_start(ctx);
-  f = BN_CTX_get(ctx);
-  result = BN_CTX_get(ctx);
-
-  if (f == NULL || result == NULL) {
+  size_t blinding_index = 0;
+  BN_BLINDING *blinding = nullptr;
+  int ret = 0, do_blinding;
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *f = BN_CTX_get(ctx.get());
+  BIGNUM *result = BN_CTX_get(ctx.get());
+  if (f == nullptr || result == nullptr) {
     goto err;
   }
 
   // The caller should have ensured this.
   assert(len == BN_num_bytes(rsa->n));
-  if (BN_bin2bn(in, len, f) == NULL) {
+  if (BN_bin2bn(in, len, f) == nullptr) {
     goto err;
   }
 
@@ -572,7 +568,7 @@
     goto err;
   }
 
-  if (!freeze_private_key(rsa, ctx)) {
+  if (!freeze_private_key(rsa, ctx.get())) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
     goto err;
   }
@@ -580,7 +576,7 @@
   do_blinding =
       (rsa->flags & (RSA_FLAG_NO_BLINDING | RSA_FLAG_NO_PUBLIC_EXPONENT)) == 0;
 
-  if (rsa->e == NULL && do_blinding) {
+  if (rsa->e == nullptr && do_blinding) {
     // We cannot do blinding or verification without |e|, and continuing without
     // those countermeasures is dangerous. However, the Java/Android RSA API
     // requires support for keys where only |d| and |n| (and not |e|) are known.
@@ -594,29 +590,29 @@
   }
 
   if (do_blinding) {
-    blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
-    if (blinding == NULL) {
+    blinding = rsa_blinding_get(rsa, &blinding_index, ctx.get());
+    if (blinding == nullptr) {
       OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
       goto err;
     }
-    if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) {
+    if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx.get())) {
       goto err;
     }
   }
 
-  if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL &&
-      rsa->dmq1 != NULL && rsa->iqmp != NULL &&
+  if (rsa->p != nullptr && rsa->q != nullptr && rsa->e != nullptr &&
+      rsa->dmp1 != nullptr && rsa->dmq1 != nullptr && rsa->iqmp != nullptr &&
       // Require that we can reduce |f| by |rsa->p| and |rsa->q| in constant
       // time, which requires primes be the same size, rounded to the Montgomery
       // coefficient. (See |mod_montgomery|.) This is not required by RFC 8017,
       // but it is true for keys generated by us and all common implementations.
       bn_less_than_montgomery_R(rsa->q, rsa->mont_p) &&
       bn_less_than_montgomery_R(rsa->p, rsa->mont_q)) {
-    if (!rsa_mod_exp_crt(result, f, rsa, ctx)) {
+    if (!rsa_mod_exp_crt(result, f, rsa, ctx.get())) {
       goto err;
     }
-  } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d_fixed, rsa->n, ctx,
-                                        rsa->mont_n)) {
+  } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d_fixed, rsa->n,
+                                        ctx.get(), rsa->mont_n)) {
     goto err;
   }
 
@@ -630,17 +626,19 @@
   //
   // This check is cheap assuming |e| is small, which we require in
   // |rsa_check_public_key|.
-  if (rsa->e != NULL) {
-    BIGNUM *vrfy = BN_CTX_get(ctx);
-    if (vrfy == NULL ||
-        !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) ||
+  if (rsa->e != nullptr) {
+    BIGNUM *vrfy = BN_CTX_get(ctx.get());
+    if (vrfy == nullptr ||
+        !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx.get(),
+                         rsa->mont_n) ||
         !constant_time_declassify_int(BN_equal_consttime(vrfy, f))) {
       OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
       goto err;
     }
   }
 
-  if (do_blinding && !BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
+  if (do_blinding &&
+      !BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx.get())) {
     goto err;
   }
 
@@ -659,11 +657,7 @@
   ret = 1;
 
 err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  if (blinding != NULL) {
+  if (blinding != nullptr) {
     rsa_blinding_release(rsa, blinding, blinding_index);
   }
 
@@ -713,23 +707,19 @@
   assert(rsa->dmq1 != NULL);
   assert(rsa->iqmp != NULL);
 
-  BIGNUM *r1, *m1;
-  int ret = 0;
-
-  BN_CTX_start(ctx);
-  r1 = BN_CTX_get(ctx);
-  m1 = BN_CTX_get(ctx);
-  BIGNUM *n, *p, *q;
+  bssl::BN_CTXScope scope(ctx);
+  BIGNUM *r1 = BN_CTX_get(ctx);
+  BIGNUM *m1 = BN_CTX_get(ctx);
   if (r1 == NULL || m1 == NULL) {
-    goto err;
+    return 0;
   }
 
   // Use the minimal-width versions of |n|, |p|, and |q|. Either works, but if
   // someone gives us non-minimal values, these will be slightly more efficient
   // on the non-Montgomery operations.
-  n = &rsa->mont_n->N;
-  p = &rsa->mont_p->N;
-  q = &rsa->mont_q->N;
+  BIGNUM *n = &rsa->mont_n->N;
+  BIGNUM *p = &rsa->mont_p->N;
+  BIGNUM *q = &rsa->mont_q->N;
 
   // This is a pre-condition for |mod_montgomery|. It was already checked by the
   // caller.
@@ -762,7 +752,7 @@
       // [0, n).
       !bn_mul_consttime(r0, r0, q, ctx) ||  //
       !bn_uadd_consttime(r0, r0, m1)) {
-    goto err;
+    return 0;
   }
 
   // The result should be bounded by |n|, but fixed-width operations may
@@ -772,14 +762,10 @@
   declassify_assert(BN_cmp(r0, n) < 0);
   bn_assert_fits_in_bytes(r0, BN_num_bytes(n));
   if (!bn_resize_words(r0, n->width)) {
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
 static int ensure_bignum(BIGNUM **out) {
@@ -910,11 +896,11 @@
   }
   int limit = BN_is_word(e, 3) ? bits * 8 : bits * 5;
 
-  int ret = 0, tries = 0, rand_tries = 0;
-  BN_CTX_start(ctx);
+  int tries = 0, rand_tries = 0;
+  bssl::BN_CTXScope scope(ctx);
   BIGNUM *tmp = BN_CTX_get(ctx);
   if (tmp == NULL) {
-    goto err;
+    return 0;
   }
 
   for (;;) {
@@ -923,13 +909,13 @@
     // bound checked below in steps 4.4 and 5.5).
     if (!BN_rand(out, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD) ||
         !BN_GENCB_call(cb, BN_GENCB_GENERATED, rand_tries++)) {
-      goto err;
+      return 0;
     }
 
     if (p != NULL) {
       // If |p| and |out| are too close, try again (step 5.4).
       if (!bn_abs_sub_consttime(tmp, out, p, ctx)) {
-        goto err;
+        return 0;
       }
       if (BN_cmp(tmp, pow2_bits_100) <= 0) {
         continue;
@@ -959,18 +945,17 @@
       int relatively_prime;
       if (!bn_usub_consttime(tmp, out, BN_value_one()) ||
           !bn_is_relatively_prime(&relatively_prime, tmp, e, ctx)) {
-        goto err;
+        return 0;
       }
       if (constant_time_declassify_int(relatively_prime)) {
         // Test |out| for primality (steps 4.5.1 and 5.6.1).
         int is_probable_prime;
         if (!BN_primality_test(&is_probable_prime, out,
                                BN_prime_checks_for_generation, ctx, 0, cb)) {
-          goto err;
+          return 0;
         }
         if (is_probable_prime) {
-          ret = 1;
-          goto err;
+          return 1;
         }
       }
     }
@@ -980,16 +965,12 @@
     tries++;
     if (tries >= limit) {
       OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
-      goto err;
+      return 0;
     }
     if (!BN_GENCB_call(cb, 2, tries)) {
-      goto err;
+      return 0;
     }
   }
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
 }
 
 // rsa_generate_key_impl generates an RSA key using a generalized version of
@@ -1025,29 +1006,31 @@
     return 0;
   }
 
-  int ret = 0;
-  int prime_bits = bits / 2;
-  BN_CTX *ctx = BN_CTX_new();
-  BIGNUM *totient, *pm1, *qm1, *sqrt2, *pow2_prime_bits_100, *pow2_prime_bits;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
   int sqrt2_bits;
-  if (ctx == NULL) {
-    goto bn_err;
-  }
-  BN_CTX_start(ctx);
-  totient = BN_CTX_get(ctx);
-  pm1 = BN_CTX_get(ctx);
-  qm1 = BN_CTX_get(ctx);
-  sqrt2 = BN_CTX_get(ctx);
-  pow2_prime_bits_100 = BN_CTX_get(ctx);
-  pow2_prime_bits = BN_CTX_get(ctx);
-  if (totient == NULL || pm1 == NULL || qm1 == NULL || sqrt2 == NULL ||
-      pow2_prime_bits_100 == NULL || pow2_prime_bits == NULL ||
-      !BN_set_bit(pow2_prime_bits_100, prime_bits - 100) ||
-      !BN_set_bit(pow2_prime_bits, prime_bits)) {
-    goto bn_err;
+  if (ctx == nullptr) {
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
 
-  // We need the RSA components non-NULL.
+  int prime_bits = bits / 2;
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *totient = BN_CTX_get(ctx.get());
+  BIGNUM *pm1 = BN_CTX_get(ctx.get());
+  BIGNUM *qm1 = BN_CTX_get(ctx.get());
+  BIGNUM *sqrt2 = BN_CTX_get(ctx.get());
+  BIGNUM *pow2_prime_bits_100 = BN_CTX_get(ctx.get());
+  BIGNUM *pow2_prime_bits = BN_CTX_get(ctx.get());
+  if (totient == nullptr || pm1 == nullptr || qm1 == nullptr ||
+      sqrt2 == nullptr || pow2_prime_bits_100 == nullptr ||
+      pow2_prime_bits == nullptr ||
+      !BN_set_bit(pow2_prime_bits_100, prime_bits - 100) ||
+      !BN_set_bit(pow2_prime_bits, prime_bits)) {
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
+  }
+
+  // We need the RSA components non-null.
   if (!ensure_bignum(&rsa->n) ||     //
       !ensure_bignum(&rsa->d) ||     //
       !ensure_bignum(&rsa->e) ||     //
@@ -1056,16 +1039,19 @@
       !ensure_bignum(&rsa->dmp1) ||  //
       !ensure_bignum(&rsa->dmq1) ||  //
       !ensure_bignum(&rsa->iqmp)) {
-    goto bn_err;
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
 
   if (!BN_copy(rsa->e, e_value)) {
-    goto bn_err;
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
 
   // Compute sqrt2 >= ⌊2^(prime_bits-1)×√2⌋.
   if (!bn_set_words(sqrt2, kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen)) {
-    goto bn_err;
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
   sqrt2_bits = kBoringSSLRSASqrtTwoLen * BN_BITS2;
   assert(sqrt2_bits == (int)BN_num_bits(sqrt2));
@@ -1073,14 +1059,16 @@
     // For key sizes up to 4096 (prime_bits = 2048), this is exactly
     // ⌊2^(prime_bits-1)×√2⌋.
     if (!BN_rshift(sqrt2, sqrt2, sqrt2_bits - prime_bits)) {
-      goto bn_err;
+      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+      return 0;
     }
   } else if (prime_bits > sqrt2_bits) {
     // For key sizes beyond 4096, this is approximate. We err towards retrying
     // to ensure our key is the right size and round up.
     if (!BN_add_word(sqrt2, 1) ||
         !BN_lshift(sqrt2, sqrt2, prime_bits - sqrt2_bits)) {
-      goto bn_err;
+      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+      return 0;
     }
   }
   assert(prime_bits == (int)BN_num_bits(sqrt2));
@@ -1091,13 +1079,14 @@
     //
     // Each call to |generate_prime| fails with probability p = 2^-21. The
     // probability that either call fails is 1 - (1-p)^2, which is around 2^-20.
-    if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, sqrt2,
-                        pow2_prime_bits_100, ctx, cb) ||
+    if (!generate_prime(rsa->p, prime_bits, rsa->e, nullptr, sqrt2,
+                        pow2_prime_bits_100, ctx.get(), cb) ||
         !BN_GENCB_call(cb, 3, 0) ||
         !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, sqrt2,
-                        pow2_prime_bits_100, ctx, cb) ||
+                        pow2_prime_bits_100, ctx.get(), cb) ||
         !BN_GENCB_call(cb, 3, 1)) {
-      goto bn_err;
+      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+      return 0;
     }
 
     if (BN_cmp(rsa->p, rsa->q) < 0) {
@@ -1116,9 +1105,11 @@
     int no_inverse;
     if (!bn_usub_consttime(pm1, rsa->p, BN_value_one()) ||
         !bn_usub_consttime(qm1, rsa->q, BN_value_one()) ||
-        !bn_lcm_consttime(totient, pm1, qm1, ctx) ||
-        !bn_mod_inverse_consttime(rsa->d, &no_inverse, rsa->e, totient, ctx)) {
-      goto bn_err;
+        !bn_lcm_consttime(totient, pm1, qm1, ctx.get()) ||
+        !bn_mod_inverse_consttime(rsa->d, &no_inverse, rsa->e, totient,
+                                  ctx.get())) {
+      OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+      return 0;
     }
 
     // Retry if |rsa->d| <= 2^|prime_bits|. See appendix B.3.1's guidance on
@@ -1129,12 +1120,15 @@
   assert(BN_num_bits(pm1) == (unsigned)prime_bits);
   assert(BN_num_bits(qm1) == (unsigned)prime_bits);
   if (  // Calculate n.
-      !bn_mul_consttime(rsa->n, rsa->p, rsa->q, ctx) ||
+      !bn_mul_consttime(rsa->n, rsa->p, rsa->q, ctx.get()) ||
       // Calculate d mod (p-1).
-      !bn_div_consttime(NULL, rsa->dmp1, rsa->d, pm1, prime_bits, ctx) ||
+      !bn_div_consttime(nullptr, rsa->dmp1, rsa->d, pm1, prime_bits,
+                        ctx.get()) ||
       // Calculate d mod (q-1)
-      !bn_div_consttime(NULL, rsa->dmq1, rsa->d, qm1, prime_bits, ctx)) {
-    goto bn_err;
+      !bn_div_consttime(nullptr, rsa->dmq1, rsa->d, qm1, prime_bits,
+                        ctx.get())) {
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
   bn_set_minimal_width(rsa->n);
 
@@ -1142,41 +1136,30 @@
   bn_declassify(rsa->n);
 
   // Calculate q^-1 mod p.
-  rsa->mont_p = BN_MONT_CTX_new_consttime(rsa->p, ctx);
-  if (rsa->mont_p == NULL ||  //
-      !bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, rsa->p, ctx,
+  rsa->mont_p = BN_MONT_CTX_new_consttime(rsa->p, ctx.get());
+  if (rsa->mont_p == nullptr ||  //
+      !bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, rsa->p, ctx.get(),
                                    rsa->mont_p)) {
-    goto bn_err;
+    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
+    return 0;
   }
 
   // Sanity-check that |rsa->n| has the specified size. This is implied by
   // |generate_prime|'s bounds.
   if (BN_num_bits(rsa->n) != (unsigned)bits) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
-    goto err;
+    return 0;
   }
 
   // The key generation process is complex and thus error-prone. It could be
   // disastrous to generate and then use a bad key so double-check that the key
   // makes sense. Also, while |rsa| is mutable, fill in the cached components.
-  if (!RSA_check_key(rsa) ||
-      !freeze_private_key(rsa, ctx)) {
+  if (!RSA_check_key(rsa) || !freeze_private_key(rsa, ctx.get())) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR);
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-bn_err:
-  if (!ret) {
-    OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
-  }
-err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  return ret;
+  return 1;
 }
 
 static void replace_bignum(BIGNUM **out, BIGNUM **in) {
diff --git a/src/crypto/fipsmodule/self_check/self_check.cc.inc b/src/crypto/fipsmodule/self_check/self_check.cc.inc
index 15a68b5..b64c64b 100644
--- a/src/crypto/fipsmodule/self_check/self_check.cc.inc
+++ b/src/crypto/fipsmodule/self_check/self_check.cc.inc
@@ -44,14 +44,6 @@
 #include "../tls/internal.h"
 
 
-// MSVC wants to put a NUL byte at the end of non-char arrays and so cannot
-// compile the real logic.
-#if defined(_MSC_VER)
-
-int BORINGSSL_self_test(void) { return 0; }
-
-#else
-
 static void hexdump(FILE *out, const void *in, size_t len) {
   const uint8_t *in8 = reinterpret_cast<const uint8_t *>(in);
   for (size_t i = 0; i < len; i++) {
@@ -59,8 +51,8 @@
   }
 }
 
-static int check_test(const void *expected, const void *actual,
-                      size_t expected_len, const char *name) {
+int BORINGSSL_check_test(const void *expected, const void *actual,
+                         size_t expected_len, const char *name) {
   if (OPENSSL_memcmp(actual, expected, expected_len) != 0) {
     FILE *err = CRYPTO_get_stderr();
     fprintf(err, "%s failed.\nExpected:   ", name);
@@ -74,6 +66,14 @@
   return 1;
 }
 
+// MSVC wants to put a NUL byte at the end of non-char arrays and so cannot
+// compile the real logic.
+#if defined(_MSC_VER)
+
+int BORINGSSL_self_test(void) { return 0; }
+
+#else
+
 static int set_bignum(BIGNUM **out, const uint8_t *in, size_t len) {
   *out = BN_bin2bn(in, len, NULL);
   return *out != NULL;
@@ -337,8 +337,8 @@
   unsigned sig_len;
   if (!rsa_sign_no_self_test(NID_sha256, kRSASignDigest, sizeof(kRSASignDigest),
                              output, &sig_len, rsa_key) ||
-      !check_test(kRSASignSignature, output, sizeof(kRSASignSignature),
-                  "RSA-sign KAT")) {
+      !BORINGSSL_check_test(kRSASignSignature, output,
+                            sizeof(kRSASignSignature), "RSA-sign KAT")) {
     fprintf(CRYPTO_get_stderr(), "RSA signing test failed.\n");
     goto err;
   }
@@ -429,8 +429,9 @@
           kECDSASignDigest, sizeof(kECDSASignDigest), ecdsa_sign_output,
           &ecdsa_sign_output_len, sizeof(ecdsa_sign_output), ec_key, ecdsa_k,
           sizeof(ecdsa_k)) ||
-      !check_test(kECDSASignSig, ecdsa_sign_output, sizeof(ecdsa_sign_output),
-                  "ECDSA-sign signature")) {
+      !BORINGSSL_check_test(kECDSASignSig, ecdsa_sign_output,
+                            sizeof(ecdsa_sign_output),
+                            "ECDSA-sign signature")) {
     fprintf(CRYPTO_get_stderr(), "ECDSA-sign KAT failed.\n");
     goto err;
   }
@@ -496,8 +497,8 @@
                                  ec_scalar, NULL) ||
       !EC_POINT_point2oct(ec_group, ec_point_out, POINT_CONVERSION_UNCOMPRESSED,
                           z_comp_result, sizeof(z_comp_result), NULL) ||
-      !check_test(kP256PointResult, z_comp_result, sizeof(z_comp_result),
-                  "Z Computation Result")) {
+      !BORINGSSL_check_test(kP256PointResult, z_comp_result,
+                            sizeof(z_comp_result), "Z Computation Result")) {
     fprintf(CRYPTO_get_stderr(), "Z-computation KAT failed.\n");
     goto err;
   }
@@ -576,7 +577,7 @@
   if (dh == NULL || ffdhe2048_value == NULL || sizeof(dh_out) != DH_size(dh) ||
       dh_compute_key_padded_no_self_test(dh_out, ffdhe2048_value, dh) !=
           sizeof(dh_out) ||
-      !check_test(kDHOutput, dh_out, sizeof(dh_out), "FFC DH")) {
+      !BORINGSSL_check_test(kDHOutput, dh_out, sizeof(dh_out), "FFC DH")) {
     fprintf(CRYPTO_get_stderr(), "FFDH failed.\n");
     goto err;
   }
@@ -655,8 +656,8 @@
 
   // SHA-256 KAT
   SHA256(kInput, sizeof(kInput), output);
-  return check_test(kPlaintextSHA256, output, sizeof(kPlaintextSHA256),
-                    "SHA-256 KAT");
+  return BORINGSSL_check_test(kPlaintextSHA256, output,
+                              sizeof(kPlaintextSHA256), "SHA-256 KAT");
 }
 
 int boringssl_self_test_sha512(void) {
@@ -676,8 +677,8 @@
 
   // SHA-512 KAT
   SHA512(kInput, sizeof(kInput), output);
-  return check_test(kPlaintextSHA512, output, sizeof(kPlaintextSHA512),
-                    "SHA-512 KAT");
+  return BORINGSSL_check_test(kPlaintextSHA512, output,
+                              sizeof(kPlaintextSHA512), "SHA-512 KAT");
 }
 
 int boringssl_self_test_hmac_sha256(void) {
@@ -696,8 +697,8 @@
   HMAC(EVP_sha256(), kInput, sizeof(kInput), kInput, sizeof(kInput), output,
        &output_len);
   return output_len == sizeof(kPlaintextHMACSHA256) &&
-         check_test(kPlaintextHMACSHA256, output, sizeof(kPlaintextHMACSHA256),
-                    "HMAC-SHA-256 KAT");
+         BORINGSSL_check_test(kPlaintextHMACSHA256, output,
+                              sizeof(kPlaintextHMACSHA256), "HMAC-SHA-256 KAT");
 }
 
 static int boringssl_self_test_fast(void) {
@@ -707,10 +708,6 @@
   };
   static const uint8_t kAESIV[16] = {0};
 
-  EVP_AEAD_CTX aead_ctx;
-  EVP_AEAD_CTX_zero(&aead_ctx);
-  int ret = 0;
-
   AES_KEY aes_key;
   uint8_t aes_iv[16];
   uint8_t output[256];
@@ -727,15 +724,17 @@
       0x50, 0x3a, 0xc5, 0x5e, 0x8e, 0x93, 0x40, 0xf2, 0x10, 0xd8,
   };
   memcpy(aes_iv, kAESIV, sizeof(kAESIV));
-  if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
-    fprintf(CRYPTO_get_stderr(), "AES_set_encrypt_key failed.\n");
-    goto err;
+  if (!bcm_success(
+          BCM_aes_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key))) {
+    fprintf(CRYPTO_get_stderr(), "BCM_aes_set_encrypt_key failed.\n");
+    return 0;
   }
   AES_cbc_encrypt(kAESCBCEncPlaintext, output, sizeof(kAESCBCEncPlaintext),
                   &aes_key, aes_iv, AES_ENCRYPT);
-  if (!check_test(kAESCBCEncCiphertext, output, sizeof(kAESCBCEncCiphertext),
-                  "AES-CBC-encrypt KAT")) {
-    goto err;
+  if (!BORINGSSL_check_test(kAESCBCEncCiphertext, output,
+                            sizeof(kAESCBCEncCiphertext),
+                            "AES-CBC-encrypt KAT")) {
+    return 0;
   }
 
   // AES-CBC Decryption KAT
@@ -750,24 +749,27 @@
       0xb2, 0x25, 0x6f, 0xa6, 0xd0, 0xd2, 0x0e, 0x6f, 0x19, 0xb5,
   };
   memcpy(aes_iv, kAESIV, sizeof(kAESIV));
-  if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
-    fprintf(CRYPTO_get_stderr(), "AES_set_decrypt_key failed.\n");
-    goto err;
+  if (!bcm_success(
+          BCM_aes_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key))) {
+    fprintf(CRYPTO_get_stderr(), "BCM_aes_set_decrypt_key failed.\n");
+    return 0;
   }
   AES_cbc_encrypt(kAESCBCDecCiphertext, output, sizeof(kAESCBCDecCiphertext),
                   &aes_key, aes_iv, AES_DECRYPT);
-  if (!check_test(kAESCBCDecPlaintext, output, sizeof(kAESCBCDecPlaintext),
-                  "AES-CBC-decrypt KAT")) {
-    goto err;
+  if (!BORINGSSL_check_test(kAESCBCDecPlaintext, output,
+                            sizeof(kAESCBCDecPlaintext),
+                            "AES-CBC-decrypt KAT")) {
+    return 0;
   }
 
   size_t out_len;
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
   OPENSSL_memset(nonce, 0, sizeof(nonce));
-  if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
+  bssl::ScopedEVP_AEAD_CTX aead_ctx;
+  if (!EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm(), kAESKey,
                          sizeof(kAESKey), 0, NULL)) {
     fprintf(CRYPTO_get_stderr(), "EVP_AEAD_CTX_init for AES-128-GCM failed.\n");
-    goto err;
+    return 0;
   }
 
   // AES-GCM Encryption KAT
@@ -782,14 +784,14 @@
       0x1c, 0x63, 0x2e, 0x97, 0x93, 0x0f, 0xfb, 0xed, 0xb5, 0x9e, 0x1c, 0x20,
       0xb2, 0xb0, 0x58, 0xda, 0x48, 0x07, 0x2d, 0xbd, 0x96, 0x0d, 0x34, 0xc6,
   };
-  if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kAESGCMEncPlaintext, sizeof(kAESGCMEncPlaintext), NULL,
                          0) ||
-      !check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext),
-                  "AES-GCM-encrypt KAT")) {
+      !BORINGSSL_check_test(kAESGCMCiphertext, output,
+                            sizeof(kAESGCMCiphertext), "AES-GCM-encrypt KAT")) {
     fprintf(CRYPTO_get_stderr(), "EVP_AEAD_CTX_seal for AES-128-GCM failed.\n");
-    goto err;
+    return 0;
   }
 
   // AES-GCM Decryption KAT
@@ -805,15 +807,16 @@
           0xa9, 0x99, 0x17, 0x6a, 0x45, 0x05, 0x5e, 0x99, 0x83, 0x56, 0x01,
           0xc0, 0x82, 0x40, 0x81, 0xd2, 0x48, 0x45, 0xf2, 0xcc, 0xc3,
       };
-  if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_open(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kAESGCMDecCiphertext, sizeof(kAESGCMDecCiphertext),
                          NULL, 0) ||
-      !check_test(kAESGCMDecPlaintext, output, sizeof(kAESGCMDecPlaintext),
-                  "AES-GCM-decrypt KAT")) {
+      !BORINGSSL_check_test(kAESGCMDecPlaintext, output,
+                            sizeof(kAESGCMDecPlaintext),
+                            "AES-GCM-decrypt KAT")) {
     fprintf(CRYPTO_get_stderr(),
             "AES-GCM-decrypt KAT failed because EVP_AEAD_CTX_open failed.\n");
-    goto err;
+    return 0;
   }
 
   // SHA-1 KAT
@@ -826,13 +829,14 @@
       0x09, 0x11, 0x6d, 0x1a, 0xfd, 0x0f, 0x1e, 0x11, 0xe3, 0xcb,
   };
   SHA1(kSHA1Input, sizeof(kSHA1Input), output);
-  if (!check_test(kSHA1Digest, output, sizeof(kSHA1Digest), "SHA-1 KAT")) {
-    goto err;
+  if (!BORINGSSL_check_test(kSHA1Digest, output, sizeof(kSHA1Digest),
+                            "SHA-1 KAT")) {
+    return 0;
   }
 
   if (!boringssl_self_test_sha256() || !boringssl_self_test_sha512() ||
       !boringssl_self_test_hmac_sha256()) {
-    goto err;
+    return 0;
   }
 
   // DBRG KAT
@@ -874,22 +878,23 @@
                      sizeof(kDRBGPersonalization)) ||
       !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGOutput), kDRBGAD,
                          sizeof(kDRBGAD)) ||
-      !check_test(kDRBGOutput, output, sizeof(kDRBGOutput),
-                  "DRBG Generate KAT") ||
+      !BORINGSSL_check_test(kDRBGOutput, output, sizeof(kDRBGOutput),
+                            "DRBG Generate KAT") ||
       !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) ||
       !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGReseedOutput), kDRBGAD,
                          sizeof(kDRBGAD)) ||
-      !check_test(kDRBGReseedOutput, output, sizeof(kDRBGReseedOutput),
-                  "DRBG-reseed KAT")) {
+      !BORINGSSL_check_test(kDRBGReseedOutput, output,
+                            sizeof(kDRBGReseedOutput), "DRBG-reseed KAT")) {
     fprintf(CRYPTO_get_stderr(), "CTR-DRBG failed.\n");
-    goto err;
+    return 0;
   }
   CTR_DRBG_clear(&drbg);
 
   CTR_DRBG_STATE kZeroDRBG;
   memset(&kZeroDRBG, 0, sizeof(kZeroDRBG));
-  if (!check_test(&kZeroDRBG, &drbg, sizeof(drbg), "DRBG Clear KAT")) {
-    goto err;
+  if (!BORINGSSL_check_test(&kZeroDRBG, &drbg, sizeof(drbg),
+                            "DRBG Clear KAT")) {
+    return 0;
   }
 
   // TLS KDF KAT
@@ -918,10 +923,10 @@
                        kTLS10Secret, sizeof(kTLS10Secret), kTLSLabel,
                        sizeof(kTLSLabel), kTLSSeed1, sizeof(kTLSSeed1),
                        kTLSSeed2, sizeof(kTLSSeed2)) ||
-      !check_test(kTLS10Output, tls10_output, sizeof(kTLS10Output),
-                  "TLS10-KDF KAT")) {
+      !BORINGSSL_check_test(kTLS10Output, tls10_output, sizeof(kTLS10Output),
+                            "TLS10-KDF KAT")) {
     fprintf(CRYPTO_get_stderr(), "TLS KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   static const uint8_t kTLS12Secret[32] = {
@@ -939,10 +944,10 @@
                        kTLS12Secret, sizeof(kTLS12Secret), kTLSLabel,
                        sizeof(kTLSLabel), kTLSSeed1, sizeof(kTLSSeed1),
                        kTLSSeed2, sizeof(kTLSSeed2)) ||
-      !check_test(kTLS12Output, tls12_output, sizeof(kTLS12Output),
-                  "TLS12-KDF KAT")) {
+      !BORINGSSL_check_test(kTLS12Output, tls12_output, sizeof(kTLS12Output),
+                            "TLS12-KDF KAT")) {
     fprintf(CRYPTO_get_stderr(), "TLS KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   // TLS v1.3: derives a dummy client-early-traffic secret.
@@ -978,11 +983,11 @@
           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")) {
+      !BORINGSSL_check_test(kTLS13ExpandLabelOutput, tls13_expand_label_output,
+                            sizeof(kTLS13ExpandLabelOutput),
+                            "CRYPTO_tls13_hkdf_expand_label")) {
     fprintf(CRYPTO_get_stderr(), "TLS13-KDF failed.\n");
-    goto err;
+    return 0;
   }
 
   // HKDF
@@ -1010,25 +1015,33 @@
   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")) {
+      !BORINGSSL_check_test(kHKDFOutput, hkdf_output, sizeof(kHKDFOutput),
+                            "HKDF")) {
     fprintf(CRYPTO_get_stderr(), "HKDF failed.\n");
-    goto err;
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  EVP_AEAD_CTX_cleanup(&aead_ctx);
-
-  return ret;
+  return 1;
 }
 
 int BORINGSSL_self_test(void) {
   if (!boringssl_self_test_fast() ||
-      // When requested to run self tests, also run the lazy tests.
-      !boringssl_self_test_rsa() ||  //
-      !boringssl_self_test_ecc() ||  //
-      !boringssl_self_test_ffdh()) {
+      // When requested to run self tests, also run some of the lazy tests.
+      !boringssl_self_test_rsa() ||    //
+      !boringssl_self_test_ecc() ||    //
+      !boringssl_self_test_ffdh() ||   //
+      !boringssl_self_test_mlkem() ||  //
+      !boringssl_self_test_mldsa()) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int BORINGSSL_self_test_all(void) {
+  if (!BORINGSSL_self_test() ||
+      // When requested to run all self tests, add in the really slow tests.
+      !boringssl_self_test_slhdsa()) {
     return 0;
   }
 
diff --git a/src/crypto/fipsmodule/service_indicator/internal.h b/src/crypto/fipsmodule/service_indicator/internal.h
index 182aefc..5b69172 100644
--- a/src/crypto/fipsmodule/service_indicator/internal.h
+++ b/src/crypto/fipsmodule/service_indicator/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_SERVICE_INDICATOR_INTERNAL_H
-#define OPENSSL_HEADER_SERVICE_INDICATOR_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_SERVICE_INDICATOR_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_SERVICE_INDICATOR_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/service_indicator.h>
@@ -86,4 +86,4 @@
 
 #endif  // BORINGSSL_FIPS
 
-#endif  // OPENSSL_HEADER_SERVICE_INDICATOR_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_SERVICE_INDICATOR_INTERNAL_H
diff --git a/src/crypto/fipsmodule/sha/asm/sha1-x86_64.pl b/src/crypto/fipsmodule/sha/asm/sha1-x86_64.pl
index 2dc24f2..30f1238 100755
--- a/src/crypto/fipsmodule/sha/asm/sha1-x86_64.pl
+++ b/src/crypto/fipsmodule/sha/asm/sha1-x86_64.pl
@@ -2057,45 +2057,9 @@
 
 ####################################################################
 
-sub sha1rnds4 {
-    if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) {
-      my @opcode=(0x0f,0x3a,0xcc);
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);		# ModR/M
-	my $c=$1;
-	push @opcode,$c=~/^0/?oct($c):$c;
-	return ".byte\t".join(',',@opcode);
-    } else {
-	return "sha1rnds4\t".@_[0];
-    }
-}
-
-sub sha1op38 {
-    my $instr = shift;
-    my %opcodelet = (
-		"sha1nexte" => 0xc8,
-  		"sha1msg1"  => 0xc9,
-		"sha1msg2"  => 0xca	);
-
-    if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x0f,0x38);
-      my $rex=0;
-	$rex|=0x04			if ($2>=8);
-	$rex|=0x01			if ($1>=8);
-	unshift @opcode,0x40|$rex	if ($rex);
-	push @opcode,$opcodelet{$instr};
-	push @opcode,0xc0|($1&7)|(($2&7)<<3);		# ModR/M
-	return ".byte\t".join(',',@opcode);
-    } else {
-	return $instr."\t".@_[0];
-    }
-}
-
 foreach (split("\n",$code)) {
 	s/\`([^\`]*)\`/eval $1/geo;
 
-	s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo	or
-	s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo;
-
 	print $_,"\n";
 }
 close STDOUT or die "error closing STDOUT: $!";
diff --git a/src/crypto/fipsmodule/sha/asm/sha512-x86_64.pl b/src/crypto/fipsmodule/sha/asm/sha512-x86_64.pl
index 3a31a16..6768bf3 100755
--- a/src/crypto/fipsmodule/sha/asm/sha512-x86_64.pl
+++ b/src/crypto/fipsmodule/sha/asm/sha512-x86_64.pl
@@ -2042,28 +2042,9 @@
 ___
 }
 
-sub sha256op38 {
-    my $instr = shift;
-    my %opcodelet = (
-		"sha256rnds2" => 0xcb,
-  		"sha256msg1"  => 0xcc,
-		"sha256msg2"  => 0xcd	);
-
-    if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-7]),\s*%xmm([0-7])/) {
-      my @opcode=(0x0f,0x38);
-	push @opcode,$opcodelet{$instr};
-	push @opcode,0xc0|($1&7)|(($2&7)<<3);		# ModR/M
-	return ".byte\t".join(',',@opcode);
-    } else {
-	return $instr."\t".@_[0];
-    }
-}
-
 foreach (split("\n",$code)) {
 	s/\`([^\`]*)\`/eval $1/geo;
 
-	s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo;
-
 	print $_,"\n";
 }
 close STDOUT or die "error closing STDOUT: $!";
diff --git a/src/crypto/fipsmodule/sha/internal.h b/src/crypto/fipsmodule/sha/internal.h
index 7a6007c..d68bf0d 100644
--- a/src/crypto/fipsmodule/sha/internal.h
+++ b/src/crypto/fipsmodule/sha/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_SHA_INTERNAL_H
-#define OPENSSL_HEADER_SHA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_SHA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_SHA_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -74,9 +74,7 @@
 
 #define SHA1_ASM_SSSE3
 inline int sha1_ssse3_capable(void) {
-  // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not
-  // say to.
-  return CRYPTO_is_SSSE3_capable() && CRYPTO_is_FXSR_capable();
+  return CRYPTO_is_SSSE3_capable();
 }
 void sha1_block_data_order_ssse3(uint32_t state[5], const uint8_t *data,
                                  size_t num);
@@ -86,19 +84,14 @@
   // AMD CPUs have slow SHLD/SHRD. See also the discussion in sha1-586.pl.
   //
   // TODO(crbug.com/42290564): Should we enable SHAEXT on 32-bit x86?
-  // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not
-  // say to.
-  return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu() &&
-         CRYPTO_is_FXSR_capable();
+  return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu();
 }
 void sha1_block_data_order_avx(uint32_t state[5], const uint8_t *data,
                                size_t num);
 
 #define SHA256_ASM_SSSE3
 inline int sha256_ssse3_capable(void) {
-  // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not
-  // say to.
-  return CRYPTO_is_SSSE3_capable() && CRYPTO_is_FXSR_capable();
+  return CRYPTO_is_SSSE3_capable();
 }
 void sha256_block_data_order_ssse3(uint32_t state[8], const uint8_t *data,
                                    size_t num);
@@ -108,19 +101,14 @@
   // AMD CPUs have slow SHLD/SHRD. See also the discussion in sha1-586.pl.
   //
   // TODO(crbug.com/42290564): Should we enable SHAEXT on 32-bit x86?
-  // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not
-  // say to.
-  return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu() &&
-         CRYPTO_is_FXSR_capable();
+  return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu();
 }
 void sha256_block_data_order_avx(uint32_t state[8], const uint8_t *data,
                                  size_t num);
 
 #define SHA512_ASM_SSSE3
 inline int sha512_ssse3_capable(void) {
-  // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not
-  // say to.
-  return CRYPTO_is_SSSE3_capable() && CRYPTO_is_FXSR_capable();
+  return CRYPTO_is_SSSE3_capable();
 }
 void sha512_block_data_order_ssse3(uint64_t state[8], const uint8_t *data,
                                    size_t num);
@@ -223,4 +211,4 @@
 }  // extern "C"
 #endif
 
-#endif  // OPENSSL_HEADER_SHA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_SHA_INTERNAL_H
diff --git a/src/crypto/fipsmodule/slhdsa/fips_known_values.inc b/src/crypto/fipsmodule/slhdsa/fips_known_values.inc
new file mode 100644
index 0000000..5bff695
--- /dev/null
+++ b/src/crypto/fipsmodule/slhdsa/fips_known_values.inc
@@ -0,0 +1,674 @@
+const uint8_t kExpectedPublicKey[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x6b, 0xd7, 0xe8, 0xe1, 0x98,
+    0xea, 0xf6, 0x2d, 0x57, 0x2f, 0x13, 0xfc, 0x79, 0xf2, 0x6f};
+
+const uint8_t kExpectedPrivateKey[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xbe, 0x6b, 0xd7, 0xe8, 0xe1, 0x98, 0xea,
+    0xf6, 0x2d, 0x57, 0x2f, 0x13, 0xfc, 0x79, 0xf2, 0x6f};
+
+const uint8_t kExpectedSignatureSHA256[32] = {
+    0x82, 0xd4, 0x09, 0x74, 0x4d, 0x97, 0xae, 0x30, 0x53, 0x18, 0x46,
+    0x9f, 0x7b, 0x85, 0x7b, 0x91, 0xd4, 0xe3, 0x33, 0x10, 0xb7, 0x09,
+    0xb5, 0x50, 0xa7, 0xc4, 0x8a, 0x46, 0x09, 0x4e, 0xc9, 0xd4};
+
+const uint8_t kExpectedSignature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES] = {
+    0x3f, 0xd6, 0x91, 0x93, 0xee, 0x97, 0x08, 0xbd, 0xea, 0x11, 0x0b, 0xa2,
+    0x9f, 0x23, 0x5f, 0xf2, 0xec, 0x98, 0x88, 0xd1, 0x27, 0x61, 0xf8, 0x4d,
+    0xc6, 0xe3, 0xf0, 0xd7, 0xeb, 0x48, 0xd0, 0x5c, 0xac, 0xf6, 0xe8, 0x7f,
+    0xb7, 0xe9, 0x58, 0xf2, 0x21, 0x47, 0x21, 0x64, 0x03, 0xf1, 0xcd, 0x17,
+    0xab, 0x8d, 0xfb, 0x3d, 0xf1, 0x60, 0xd8, 0xc5, 0xaa, 0x43, 0xcf, 0x56,
+    0x2d, 0x82, 0x61, 0x99, 0xcc, 0x72, 0x56, 0x12, 0x3f, 0x06, 0xdb, 0x84,
+    0x2d, 0xd8, 0x31, 0x7e, 0x60, 0x1e, 0x4d, 0x8c, 0xf2, 0x15, 0x57, 0xa3,
+    0x78, 0x90, 0x59, 0xbe, 0x6a, 0x7e, 0xc7, 0xc7, 0xe2, 0x6d, 0x6c, 0x81,
+    0xf1, 0xc7, 0xc0, 0x2a, 0x98, 0xdd, 0x64, 0x05, 0x86, 0x99, 0x1f, 0x09,
+    0x16, 0xef, 0xad, 0xd6, 0x13, 0x7a, 0xf7, 0x8c, 0x38, 0xd3, 0x2e, 0xde,
+    0x10, 0xd6, 0x6e, 0x38, 0x24, 0xa2, 0x24, 0x40, 0xf5, 0x7c, 0x63, 0x42,
+    0xf1, 0xab, 0x72, 0x01, 0xc4, 0x54, 0xf6, 0x66, 0x34, 0x32, 0x39, 0xbb,
+    0x35, 0x13, 0x45, 0xd1, 0xea, 0x6d, 0x87, 0xff, 0x8b, 0x4a, 0x65, 0x7f,
+    0x84, 0xbd, 0xb1, 0x03, 0xe1, 0xd7, 0x43, 0xea, 0xbe, 0xe3, 0x78, 0xa5,
+    0xc5, 0xf5, 0xf9, 0xb2, 0x00, 0xe3, 0x13, 0x06, 0x36, 0xf3, 0xe8, 0xee,
+    0x07, 0xf2, 0x03, 0x48, 0xfd, 0x51, 0x1b, 0xb5, 0x10, 0xaa, 0x1d, 0xa9,
+    0x99, 0xad, 0x10, 0xc4, 0x59, 0xbf, 0x66, 0xdd, 0x27, 0x8d, 0xd8, 0x6a,
+    0x53, 0xe5, 0x9d, 0x1a, 0xc1, 0x17, 0x36, 0x2e, 0x2e, 0xaf, 0xc0, 0xc8,
+    0x96, 0x89, 0xbc, 0x4e, 0x7c, 0xa5, 0xcc, 0xa9, 0x2a, 0x76, 0xc3, 0x1d,
+    0xa0, 0xa1, 0xa0, 0x27, 0xbf, 0x93, 0x21, 0xf0, 0x67, 0x7c, 0x10, 0x5f,
+    0x7f, 0x3c, 0x68, 0xbd, 0x7b, 0x2d, 0x0a, 0x4a, 0xde, 0x1b, 0xd4, 0xaa,
+    0x85, 0x5c, 0xa1, 0x56, 0x9e, 0x61, 0x6c, 0x97, 0x65, 0xae, 0xc4, 0x13,
+    0xa8, 0x1a, 0x82, 0x87, 0x66, 0x1b, 0x72, 0x27, 0x43, 0xca, 0xb8, 0xc6,
+    0x4e, 0xe9, 0xbe, 0x4a, 0x77, 0x66, 0xea, 0xf4, 0xa0, 0x71, 0x94, 0x52,
+    0xee, 0xc6, 0xef, 0x38, 0x7b, 0x24, 0x94, 0xc3, 0x7a, 0xc9, 0x35, 0x93,
+    0x5b, 0x19, 0xc5, 0x4d, 0xf1, 0x7d, 0xb0, 0xb9, 0x60, 0xaf, 0x1e, 0xa9,
+    0x24, 0x85, 0x92, 0x50, 0x78, 0x13, 0x1d, 0xb6, 0x6d, 0x4a, 0x4c, 0x1b,
+    0xa0, 0x51, 0x86, 0xc9, 0xb4, 0x79, 0xe5, 0x09, 0x4e, 0x61, 0xf4, 0x80,
+    0x07, 0x04, 0xd6, 0x44, 0x7b, 0xf6, 0xc0, 0x90, 0xc0, 0x46, 0xce, 0xa3,
+    0x92, 0x1a, 0xfd, 0x85, 0xd7, 0xbc, 0xd5, 0x60, 0x0d, 0xcb, 0xc3, 0x02,
+    0xbc, 0x82, 0x75, 0xe4, 0x1f, 0xc4, 0xce, 0x5f, 0x35, 0x6b, 0xdf, 0x31,
+    0x1e, 0x39, 0x18, 0xcd, 0x4c, 0xc7, 0xcc, 0x1e, 0x20, 0x19, 0x4a, 0x87,
+    0xf4, 0x07, 0xb3, 0x15, 0x02, 0xe4, 0x1a, 0x63, 0x1c, 0xa1, 0x3c, 0x0b,
+    0xae, 0x33, 0x2c, 0x9a, 0xc4, 0x23, 0x02, 0x44, 0x96, 0x14, 0x09, 0x64,
+    0xea, 0x84, 0x08, 0x52, 0xed, 0x26, 0x2c, 0x29, 0xc0, 0x56, 0x34, 0xaa,
+    0x20, 0xba, 0x44, 0x39, 0x8d, 0x3e, 0xce, 0xed, 0x6a, 0x3f, 0xca, 0xcd,
+    0xd3, 0xbe, 0xa0, 0xee, 0x49, 0xb4, 0xdc, 0x24, 0xa7, 0xe1, 0x7a, 0x89,
+    0x8f, 0x75, 0xb7, 0x19, 0x71, 0xc6, 0x5e, 0x14, 0x9c, 0xbc, 0xde, 0xd7,
+    0x52, 0xd9, 0x32, 0x6a, 0xd3, 0xd4, 0xc5, 0x5f, 0x39, 0xf0, 0xd4, 0xda,
+    0xe2, 0x50, 0xfc, 0x14, 0x73, 0xd2, 0xc2, 0x28, 0xd0, 0x84, 0x46, 0xed,
+    0xe9, 0x7c, 0x40, 0x16, 0xec, 0x72, 0xbf, 0x77, 0xef, 0xac, 0xe8, 0xce,
+    0xbf, 0x58, 0x65, 0x29, 0x9d, 0x0d, 0xe2, 0xc9, 0xbf, 0x19, 0xdd, 0x9b,
+    0x8c, 0xb9, 0x1c, 0x32, 0x24, 0x3b, 0xa5, 0x7a, 0x1f, 0x78, 0x85, 0x77,
+    0xb0, 0x6c, 0x42, 0xb8, 0xc0, 0x75, 0xf5, 0xc0, 0x45, 0xe3, 0x44, 0x7c,
+    0xbd, 0x75, 0x6c, 0x5b, 0xe4, 0x91, 0x72, 0x9a, 0x5f, 0xe7, 0x1e, 0xe9,
+    0xa0, 0x6f, 0x26, 0xbb, 0x31, 0x9d, 0xe4, 0xec, 0x32, 0xae, 0x8d, 0xae,
+    0x7d, 0x14, 0x33, 0x04, 0x19, 0x26, 0x42, 0x09, 0x91, 0x0c, 0x5f, 0xaa,
+    0x1a, 0x74, 0xfa, 0x31, 0x67, 0xad, 0x71, 0x49, 0xd8, 0xf3, 0xe7, 0x8c,
+    0x91, 0x38, 0x0e, 0x10, 0x5b, 0xe5, 0x1e, 0xd2, 0x9a, 0x0c, 0x4d, 0x7b,
+    0x60, 0xac, 0x6a, 0x94, 0x9d, 0x4f, 0x8c, 0xd0, 0x1d, 0x2f, 0xf7, 0x3d,
+    0x06, 0x46, 0xc8, 0xd6, 0x25, 0x86, 0xfe, 0x67, 0xf2, 0x01, 0xe1, 0x73,
+    0x02, 0xa1, 0xdd, 0xf2, 0x6d, 0xe6, 0x9d, 0xb9, 0x83, 0x21, 0x38, 0x74,
+    0x04, 0xec, 0xe3, 0x9e, 0x21, 0xc0, 0xed, 0x91, 0x47, 0x46, 0x44, 0x6e,
+    0xf7, 0x76, 0xe7, 0xad, 0xbe, 0xef, 0xfe, 0xcd, 0xda, 0x1d, 0x60, 0xc8,
+    0x5f, 0x92, 0xd7, 0x21, 0xb4, 0x3c, 0x11, 0x5d, 0x24, 0x50, 0x44, 0xb2,
+    0xf8, 0x59, 0x7e, 0xc4, 0x7a, 0x25, 0xea, 0x19, 0x4f, 0x1c, 0x8e, 0xb5,
+    0x0d, 0xd6, 0x7a, 0xe6, 0x0a, 0x11, 0x1f, 0x6b, 0x28, 0x9f, 0xc0, 0x02,
+    0xc6, 0x1b, 0xca, 0x06, 0xdd, 0x59, 0xa3, 0xe0, 0xd0, 0x25, 0x3e, 0x10,
+    0x0a, 0x49, 0x54, 0xdc, 0xe5, 0x07, 0x8b, 0xcc, 0xa6, 0x3d, 0x41, 0xe5,
+    0x00, 0x70, 0xf7, 0x13, 0xed, 0x63, 0x7a, 0x4b, 0x69, 0x21, 0xaa, 0xf2,
+    0xd5, 0xf7, 0xa4, 0x9c, 0x52, 0x51, 0xef, 0xb9, 0xef, 0xee, 0x3b, 0xa4,
+    0xdf, 0x16, 0x29, 0x08, 0x0f, 0x6f, 0xbd, 0x4e, 0x53, 0xa2, 0x5c, 0x75,
+    0x5f, 0x04, 0x5a, 0xdf, 0x48, 0xd6, 0xeb, 0xf9, 0x80, 0x85, 0xd3, 0x1d,
+    0x7f, 0x23, 0x01, 0x04, 0x8b, 0x78, 0xba, 0xba, 0xc3, 0x74, 0xbe, 0x7d,
+    0x5b, 0x3e, 0x65, 0x3d, 0xcd, 0x5d, 0x96, 0xe3, 0x40, 0x40, 0x7f, 0x50,
+    0xfe, 0xa0, 0x53, 0xa6, 0xd9, 0x71, 0x15, 0x33, 0x39, 0x24, 0x83, 0xee,
+    0x69, 0x6f, 0x3c, 0x0a, 0x5e, 0xdc, 0x83, 0xb9, 0x8a, 0x1f, 0x7f, 0x67,
+    0x39, 0xb2, 0x58, 0xe4, 0x48, 0xd0, 0xac, 0x75, 0xba, 0x57, 0x13, 0x37,
+    0xaa, 0x0b, 0xd5, 0x02, 0x89, 0x01, 0x5f, 0xe8, 0x75, 0xcc, 0x2d, 0x76,
+    0x05, 0xde, 0x57, 0xa2, 0xac, 0x48, 0x95, 0xce, 0xa7, 0x1d, 0xf6, 0xdb,
+    0x64, 0xff, 0xde, 0x85, 0x7e, 0x13, 0xb9, 0x58, 0x4f, 0xdd, 0xf0, 0xcb,
+    0x9a, 0x31, 0x7e, 0xc5, 0x61, 0x41, 0x97, 0x56, 0xe4, 0xfa, 0xb1, 0xcb,
+    0x1e, 0xb3, 0xfd, 0x9c, 0xfd, 0xfd, 0x81, 0x84, 0x78, 0xca, 0xbd, 0xf1,
+    0x17, 0xec, 0xcb, 0x49, 0xa7, 0x8e, 0xe8, 0xc6, 0xc5, 0x9c, 0x30, 0xf4,
+    0xc5, 0xac, 0x2a, 0x0e, 0x36, 0x72, 0x03, 0x7d, 0xf2, 0xac, 0xf9, 0x88,
+    0x84, 0xb6, 0xae, 0x16, 0x77, 0x96, 0x81, 0x7b, 0xfc, 0x17, 0x07, 0x8f,
+    0xc2, 0x74, 0xd9, 0xce, 0x57, 0xfc, 0x33, 0x53, 0xec, 0x85, 0x0e, 0x55,
+    0x2e, 0xe3, 0xad, 0x5b, 0xeb, 0x47, 0x8d, 0xf6, 0xb4, 0xb9, 0xc9, 0xb7,
+    0x9a, 0x63, 0x0e, 0xd9, 0x56, 0xa1, 0x2b, 0x05, 0x39, 0x02, 0xf8, 0x28,
+    0xdf, 0x67, 0xa7, 0xce, 0x57, 0xfd, 0xd1, 0xb4, 0x55, 0x26, 0x85, 0xe7,
+    0xd2, 0x5b, 0x90, 0x26, 0xe1, 0x25, 0x5e, 0x73, 0x12, 0xcc, 0x65, 0x8e,
+    0xdc, 0x1c, 0x64, 0xe9, 0x2e, 0x58, 0xde, 0x70, 0xc3, 0xc6, 0xc9, 0x75,
+    0x35, 0x0a, 0x0f, 0x60, 0x35, 0xb4, 0x9f, 0xcb, 0x52, 0x20, 0xc9, 0x36,
+    0xb2, 0x52, 0xbb, 0x35, 0x61, 0xf9, 0xf2, 0xc0, 0xd3, 0x50, 0x08, 0xf6,
+    0x73, 0x7d, 0xcb, 0x12, 0xd2, 0xd7, 0x4c, 0x56, 0x59, 0xb9, 0x74, 0xec,
+    0xee, 0x4c, 0x93, 0x1d, 0x9d, 0x73, 0x79, 0xe6, 0xa9, 0x2a, 0x98, 0x22,
+    0x77, 0x80, 0x84, 0x73, 0x78, 0xe2, 0x8a, 0xec, 0x1e, 0x08, 0x6f, 0x49,
+    0x64, 0xea, 0x79, 0x99, 0xb1, 0xec, 0x19, 0x6e, 0x65, 0xbd, 0xaa, 0x28,
+    0x81, 0x4a, 0xe7, 0x70, 0x44, 0xc6, 0xa1, 0xbc, 0xe3, 0x72, 0x8c, 0xa1,
+    0x13, 0x8a, 0x17, 0x16, 0xcc, 0xfb, 0x03, 0x20, 0x36, 0xb6, 0x6f, 0x4c,
+    0x52, 0xc4, 0xc6, 0x7e, 0x61, 0x08, 0x56, 0x27, 0xb0, 0xf9, 0x96, 0x44,
+    0xd9, 0x62, 0x4a, 0x29, 0xea, 0xf2, 0x33, 0x2b, 0x68, 0x45, 0xe0, 0x50,
+    0x97, 0x6a, 0x1c, 0x59, 0x89, 0x43, 0x60, 0xc2, 0x5f, 0x31, 0xfe, 0xc7,
+    0x00, 0xcb, 0x6a, 0xe0, 0xcb, 0x1b, 0x50, 0x43, 0x18, 0xd1, 0x67, 0xbc,
+    0x62, 0xcf, 0xb8, 0xe9, 0x77, 0x81, 0x1d, 0x12, 0x97, 0xa4, 0x87, 0xbe,
+    0xa2, 0x16, 0x08, 0xf6, 0x1f, 0x42, 0x40, 0x51, 0x65, 0xe3, 0x72, 0x21,
+    0xef, 0x72, 0xba, 0xff, 0xa7, 0xfa, 0x3b, 0xac, 0xd7, 0xc9, 0x60, 0xa1,
+    0x5e, 0xae, 0xa5, 0x19, 0x80, 0xfa, 0x5c, 0xd8, 0xf0, 0x1a, 0xf4, 0x0f,
+    0xb2, 0x5f, 0x57, 0x9a, 0xd2, 0x1b, 0x7c, 0xef, 0xb9, 0x24, 0xd0, 0x30,
+    0x0e, 0x92, 0xc9, 0x44, 0x05, 0xcf, 0x16, 0x31, 0xc4, 0x3e, 0xa2, 0x94,
+    0x1f, 0x69, 0xad, 0x0e, 0xcf, 0x7f, 0xce, 0x41, 0x9a, 0xaf, 0x89, 0xc6,
+    0xbd, 0x65, 0x8c, 0x65, 0xca, 0x36, 0xea, 0xd4, 0x78, 0x04, 0x1b, 0x62,
+    0x14, 0x2f, 0x37, 0xbe, 0x9b, 0xbe, 0xfd, 0xf4, 0x9d, 0x3c, 0x48, 0xe4,
+    0x46, 0x71, 0x0d, 0x07, 0x93, 0xfa, 0x86, 0x6c, 0xa7, 0xce, 0xe9, 0x6a,
+    0xf3, 0xa1, 0x72, 0x19, 0x0a, 0xc9, 0xb9, 0xc4, 0x3b, 0x76, 0x2f, 0x16,
+    0x82, 0x85, 0xbc, 0x4c, 0x46, 0x32, 0x37, 0xc7, 0x19, 0xc5, 0x24, 0xe1,
+    0x0f, 0xe2, 0x8f, 0x6d, 0x62, 0x6b, 0x6c, 0x9e, 0xc8, 0x15, 0x01, 0x93,
+    0x5b, 0x03, 0x44, 0x6e, 0xd0, 0xdc, 0xbd, 0x29, 0x2f, 0x2e, 0x89, 0x11,
+    0x24, 0x37, 0xfa, 0xff, 0x83, 0x51, 0x1b, 0x31, 0x5e, 0xc6, 0x71, 0x0b,
+    0xbf, 0x64, 0xb0, 0xca, 0x01, 0xfd, 0x49, 0x64, 0x05, 0xe2, 0xe7, 0x9e,
+    0x6e, 0xfe, 0xce, 0x98, 0x86, 0xef, 0x16, 0xec, 0x19, 0x66, 0xbe, 0x0d,
+    0x8a, 0x99, 0xbb, 0xbf, 0x39, 0xa8, 0x85, 0xeb, 0x14, 0x51, 0x2d, 0x18,
+    0xd5, 0x93, 0x6f, 0x78, 0x7a, 0x5e, 0xa1, 0xee, 0xc0, 0xc3, 0x93, 0x68,
+    0x04, 0x0c, 0xd4, 0xfe, 0x6a, 0xf7, 0x05, 0x78, 0xac, 0xcf, 0xee, 0x9f,
+    0x92, 0x53, 0x8d, 0xd4, 0x99, 0x75, 0x27, 0x7f, 0x79, 0x6c, 0x97, 0x52,
+    0x34, 0x08, 0x31, 0xad, 0x4a, 0x54, 0x34, 0xab, 0x33, 0x2e, 0x16, 0x54,
+    0xcd, 0x7a, 0x75, 0x96, 0x29, 0x72, 0x3f, 0x40, 0x2e, 0xa4, 0xc8, 0x1c,
+    0x67, 0xb6, 0x37, 0x15, 0x51, 0x64, 0x83, 0x69, 0xd7, 0x62, 0xcf, 0x8f,
+    0x34, 0x18, 0x46, 0x98, 0x5c, 0x8b, 0x61, 0x5f, 0x73, 0xe2, 0xc6, 0xe2,
+    0x86, 0x82, 0xf5, 0xee, 0x1e, 0x2d, 0xb2, 0x73, 0xb0, 0x1b, 0x69, 0xf1,
+    0x23, 0x47, 0x0d, 0xe6, 0x30, 0xe6, 0xed, 0x91, 0x69, 0x23, 0x23, 0xdd,
+    0x28, 0x64, 0x56, 0xce, 0x98, 0xa1, 0xfd, 0x93, 0x8b, 0xd3, 0xc0, 0xb7,
+    0xdd, 0xc8, 0x4a, 0x16, 0xe4, 0x75, 0xa3, 0xef, 0xba, 0x20, 0x92, 0x42,
+    0xa8, 0x1b, 0xbc, 0x54, 0x88, 0x3e, 0x1b, 0xf0, 0xa1, 0x1f, 0xeb, 0x5d,
+    0xcb, 0x49, 0x61, 0x19, 0xf3, 0x7f, 0x06, 0xe3, 0xd5, 0x29, 0xbc, 0x1a,
+    0x54, 0x53, 0xb6, 0xf3, 0x33, 0x50, 0x01, 0xf5, 0xb2, 0xcf, 0x1a, 0x2a,
+    0x17, 0x8f, 0xfa, 0x1f, 0x41, 0x47, 0x6d, 0x61, 0x60, 0x02, 0x19, 0x36,
+    0x06, 0xfb, 0x66, 0xfc, 0x42, 0xe3, 0x87, 0xc6, 0x14, 0x82, 0x2e, 0x15,
+    0xe6, 0x29, 0xbf, 0x44, 0x4d, 0xb4, 0x85, 0xa9, 0x6e, 0x81, 0x75, 0xb9,
+    0x09, 0x8d, 0xcc, 0x57, 0x13, 0x4c, 0x43, 0xca, 0x94, 0x00, 0x5b, 0xb5,
+    0x23, 0xbe, 0xf6, 0x3a, 0x1d, 0x42, 0x15, 0xa0, 0xea, 0x2e, 0x89, 0x78,
+    0x7f, 0xba, 0x6c, 0xe4, 0x27, 0x4c, 0xb6, 0x86, 0x73, 0x0e, 0x9c, 0x8c,
+    0xef, 0x14, 0xe4, 0x35, 0x43, 0x6d, 0x56, 0xcd, 0x4d, 0xab, 0x48, 0x96,
+    0x18, 0xb0, 0x4f, 0x03, 0xad, 0xec, 0x62, 0xd3, 0x34, 0x5a, 0xd0, 0xff,
+    0x14, 0xb1, 0xaf, 0x92, 0xc4, 0x20, 0xaf, 0x2d, 0x17, 0x5e, 0x22, 0x51,
+    0x5c, 0x66, 0x09, 0x20, 0x1f, 0x50, 0x0c, 0xbc, 0xe0, 0xf5, 0x6e, 0x85,
+    0x31, 0x48, 0x80, 0xef, 0xf6, 0xef, 0x7c, 0xf5, 0xf3, 0x0e, 0x6b, 0x8d,
+    0x0b, 0x94, 0x5d, 0xaa, 0x27, 0x81, 0xd3, 0x9b, 0x07, 0xe0, 0x22, 0x0a,
+    0xce, 0x9d, 0xa1, 0x79, 0x38, 0xe2, 0x6d, 0x58, 0xa7, 0xde, 0x9b, 0xb0,
+    0x25, 0x0e, 0x6b, 0x25, 0x1e, 0xac, 0x48, 0xb0, 0x34, 0x27, 0x42, 0x30,
+    0xf5, 0xdb, 0x35, 0x4d, 0xf3, 0x1f, 0xbc, 0x58, 0x2a, 0xeb, 0x86, 0x82,
+    0x6e, 0x9a, 0x0b, 0xf6, 0xdb, 0xa6, 0x18, 0x12, 0x42, 0x17, 0x5c, 0xb3,
+    0xe9, 0x49, 0x5f, 0x2a, 0xf9, 0x81, 0x35, 0x2f, 0x2b, 0x92, 0xaa, 0x0d,
+    0x6b, 0xa7, 0xe1, 0xed, 0x55, 0xa4, 0xf1, 0xef, 0xa4, 0x6b, 0x50, 0x85,
+    0xe3, 0xcd, 0x9a, 0xb2, 0xc7, 0xd9, 0xdd, 0x46, 0x6a, 0xfc, 0x2c, 0xed,
+    0xd8, 0xf9, 0x4d, 0x8a, 0xb4, 0x30, 0xa0, 0xd0, 0x08, 0xf8, 0xf0, 0x61,
+    0xc5, 0x39, 0xa2, 0xfd, 0x78, 0x65, 0x41, 0x5a, 0x52, 0x06, 0xfe, 0x50,
+    0x74, 0xe2, 0x80, 0xb2, 0x22, 0x2d, 0x96, 0xbf, 0xd2, 0x4f, 0xc9, 0x00,
+    0x36, 0x58, 0xa7, 0x67, 0x7d, 0xfc, 0xc0, 0xae, 0x34, 0x69, 0xe3, 0x16,
+    0xbe, 0x59, 0x9e, 0x01, 0x9e, 0x39, 0x0b, 0x3d, 0x16, 0x80, 0x8b, 0xfb,
+    0xe0, 0x58, 0x81, 0xcd, 0xd1, 0x2c, 0x66, 0x9a, 0xe5, 0x0b, 0x4a, 0xec,
+    0xb7, 0x45, 0x7f, 0x98, 0xf2, 0xfb, 0xbe, 0x2b, 0xc8, 0xdd, 0x48, 0x95,
+    0x22, 0xde, 0x8e, 0xb8, 0xb8, 0x4c, 0x09, 0xe8, 0x9e, 0x34, 0x4b, 0xab,
+    0xe3, 0xa1, 0x19, 0x56, 0xb6, 0x08, 0x67, 0x29, 0x47, 0xba, 0x84, 0xe5,
+    0x5c, 0x7d, 0x81, 0x7c, 0x8e, 0x48, 0x0a, 0xce, 0x9f, 0x61, 0xfd, 0x26,
+    0x94, 0xe1, 0x35, 0x43, 0x60, 0xe4, 0x5c, 0x11, 0x26, 0x47, 0xab, 0x1b,
+    0x0e, 0x24, 0x8b, 0x25, 0x51, 0x6e, 0x21, 0x39, 0x36, 0xa6, 0x46, 0x4c,
+    0x93, 0x8d, 0xf8, 0xb1, 0xd6, 0x28, 0xdd, 0x21, 0x43, 0xf0, 0xa2, 0x5d,
+    0x2f, 0xbe, 0x67, 0xe3, 0x89, 0x7a, 0xe5, 0xa2, 0x22, 0x3f, 0xf7, 0x0a,
+    0xcd, 0xc4, 0xcc, 0xde, 0x81, 0xf1, 0x03, 0xa6, 0xac, 0x29, 0xa3, 0xbe,
+    0xdc, 0x3a, 0x84, 0x81, 0x98, 0x33, 0x97, 0xa5, 0xe2, 0x93, 0x98, 0xbd,
+    0x28, 0x7c, 0x78, 0xed, 0xdb, 0x30, 0x26, 0x11, 0x87, 0x32, 0x6f, 0xeb,
+    0xb0, 0x36, 0x05, 0xcf, 0xe3, 0x28, 0xfc, 0x3e, 0x71, 0xd3, 0x7c, 0x8e,
+    0xcd, 0xa9, 0xb4, 0x8b, 0x6e, 0x45, 0xdb, 0xc2, 0x48, 0xdf, 0x7f, 0xb8,
+    0x8a, 0x5b, 0x43, 0xc0, 0x41, 0x25, 0xe7, 0x0a, 0xe5, 0x02, 0x56, 0x21,
+    0xa1, 0x71, 0xa5, 0xee, 0x13, 0x9f, 0xd7, 0x6b, 0xdb, 0xfa, 0x28, 0x43,
+    0x58, 0x76, 0x2a, 0x32, 0x89, 0x9b, 0x11, 0x7c, 0xc8, 0xe5, 0x71, 0xe6,
+    0x2e, 0x08, 0xe1, 0x7a, 0xe5, 0x96, 0x30, 0x61, 0xb1, 0xd9, 0x0a, 0xe5,
+    0x39, 0x60, 0xaa, 0xf9, 0x3f, 0x7f, 0x88, 0xc7, 0x23, 0xa9, 0x02, 0xe1,
+    0xbd, 0xa9, 0xcd, 0xb7, 0xee, 0x6c, 0x67, 0xc7, 0x1b, 0xe0, 0xe1, 0x22,
+    0x08, 0xbe, 0xdb, 0xf6, 0x2b, 0x0d, 0x61, 0xc7, 0x62, 0x5c, 0x5a, 0x9c,
+    0xb0, 0xd0, 0x6a, 0x7f, 0xd4, 0x4b, 0x43, 0x4e, 0x93, 0x69, 0xf6, 0x43,
+    0xc7, 0xbd, 0x78, 0xfe, 0xf3, 0x2f, 0xc8, 0x1f, 0x6c, 0xf0, 0x13, 0x9d,
+    0xff, 0x46, 0xfc, 0xe9, 0x09, 0xe3, 0xaf, 0x47, 0x83, 0x71, 0x99, 0x74,
+    0xa1, 0xce, 0xa8, 0x35, 0x18, 0x29, 0xa4, 0xbd, 0x4a, 0x84, 0x55, 0x05,
+    0x29, 0x53, 0x2f, 0xa5, 0xad, 0xa7, 0xf2, 0x1c, 0x45, 0x13, 0xa3, 0xb0,
+    0xa9, 0x11, 0x80, 0xd6, 0x22, 0xff, 0x64, 0x3e, 0x39, 0xa0, 0x15, 0x58,
+    0x7f, 0x08, 0x99, 0x08, 0xff, 0x8e, 0x5f, 0x73, 0x98, 0x17, 0x3d, 0x5e,
+    0xe6, 0xcd, 0x2d, 0xdf, 0xd1, 0x32, 0x2b, 0x8c, 0x08, 0xa6, 0xdb, 0x51,
+    0x2a, 0x5f, 0xac, 0xad, 0x7a, 0x9b, 0x4c, 0x82, 0x25, 0xad, 0x33, 0x7f,
+    0x30, 0xc7, 0x48, 0xbd, 0xb4, 0xf5, 0x0d, 0x22, 0xd3, 0xf8, 0x47, 0x58,
+    0xd3, 0x17, 0x65, 0x81, 0xe4, 0x07, 0xa0, 0x32, 0x7e, 0xee, 0x30, 0xe9,
+    0x17, 0xaa, 0xa0, 0x0b, 0xd7, 0x97, 0x25, 0xa7, 0xdb, 0xfe, 0xab, 0xd2,
+    0x3c, 0x9b, 0x6b, 0xdf, 0xa6, 0x87, 0xa3, 0xc0, 0x59, 0xb4, 0x08, 0x11,
+    0xd4, 0x94, 0x49, 0x83, 0x70, 0x5f, 0x5b, 0x2d, 0x09, 0xd8, 0x53, 0x25,
+    0xb6, 0xd9, 0x91, 0x32, 0xd3, 0x94, 0x79, 0xbb, 0x4d, 0xf7, 0xb6, 0x92,
+    0xd3, 0xf4, 0x08, 0x50, 0xda, 0x7d, 0x91, 0x69, 0xad, 0xc3, 0x59, 0x4d,
+    0xc0, 0x1c, 0x14, 0xf2, 0x95, 0xd3, 0xea, 0xa8, 0x85, 0xa3, 0x93, 0x62,
+    0x73, 0x68, 0x4c, 0x36, 0x49, 0x35, 0x88, 0xf0, 0xe1, 0xc8, 0x29, 0xab,
+    0x59, 0x4f, 0xef, 0x2c, 0x4c, 0x07, 0xbd, 0xf3, 0x05, 0x24, 0x41, 0x46,
+    0x92, 0x66, 0x66, 0x79, 0x92, 0x32, 0x87, 0xcb, 0x90, 0x11, 0x2d, 0x54,
+    0xda, 0x6d, 0x64, 0x72, 0xae, 0x7d, 0x19, 0x50, 0x61, 0x46, 0xd9, 0x58,
+    0x2d, 0x28, 0x0d, 0x33, 0x7b, 0x17, 0x01, 0x61, 0x44, 0x77, 0x7e, 0x06,
+    0x2b, 0x41, 0x88, 0xe6, 0x92, 0x9c, 0x69, 0xa8, 0x89, 0x9f, 0x4a, 0xa4,
+    0x6f, 0x31, 0xa5, 0x68, 0xff, 0xdb, 0xb6, 0xe3, 0x0c, 0x3f, 0xc6, 0x24,
+    0x5e, 0xfc, 0x0e, 0x31, 0x32, 0x64, 0xec, 0x3f, 0xe7, 0x7a, 0x29, 0x16,
+    0x8f, 0xed, 0x6a, 0xb7, 0x96, 0x77, 0x29, 0xa3, 0xfe, 0x1e, 0x6b, 0x54,
+    0x91, 0xe9, 0xbb, 0x38, 0x65, 0x70, 0x8c, 0x4e, 0x50, 0x39, 0x5e, 0x63,
+    0xe4, 0x49, 0x33, 0x61, 0xb9, 0x92, 0x92, 0x51, 0xe9, 0x31, 0xf6, 0x5c,
+    0x21, 0x1a, 0x53, 0xbf, 0x4a, 0xe1, 0xbc, 0x1f, 0x61, 0x66, 0x3d, 0x83,
+    0x8c, 0x27, 0x17, 0x53, 0xbd, 0xf4, 0x3d, 0x13, 0xe3, 0xfe, 0x58, 0x60,
+    0x12, 0x78, 0x3b, 0xb1, 0xd7, 0x94, 0x87, 0xe2, 0x3e, 0xc2, 0x16, 0x43,
+    0x4e, 0xc8, 0xce, 0x43, 0xbc, 0x4a, 0xe4, 0xba, 0xd6, 0xfa, 0xfa, 0x7e,
+    0x13, 0xd3, 0x28, 0x8f, 0xd2, 0x2b, 0x0b, 0x93, 0x8d, 0x42, 0xe8, 0xd2,
+    0x50, 0x34, 0x31, 0xd8, 0xb3, 0xa7, 0x1c, 0x93, 0x3d, 0x80, 0x8f, 0x3f,
+    0xee, 0x7d, 0x3c, 0xd1, 0xcc, 0x2a, 0x99, 0x39, 0xfd, 0x8f, 0xed, 0x8e,
+    0x85, 0x51, 0x20, 0x04, 0xa7, 0xd7, 0x34, 0x83, 0x20, 0x7c, 0x91, 0x20,
+    0x96, 0xe6, 0x88, 0xd6, 0x29, 0x99, 0xff, 0x18, 0xa9, 0x3b, 0x3e, 0x41,
+    0x42, 0x80, 0x14, 0x3b, 0xf2, 0xc4, 0x24, 0x4e, 0x18, 0x04, 0xa0, 0xfb,
+    0x17, 0x00, 0x2b, 0xf7, 0x44, 0x22, 0x4b, 0x7c, 0x38, 0xb6, 0x66, 0x4c,
+    0x56, 0x85, 0xb2, 0x82, 0x92, 0xe8, 0x7b, 0x76, 0x33, 0x59, 0xe8, 0x09,
+    0xd1, 0xef, 0xa0, 0x1b, 0x5b, 0xc2, 0xb1, 0x01, 0x6d, 0x7f, 0xbb, 0x37,
+    0x72, 0x3f, 0xcd, 0x20, 0x6f, 0x2d, 0x9c, 0xfc, 0xfc, 0x1c, 0x2c, 0x24,
+    0x3f, 0x30, 0xcd, 0xf5, 0x91, 0x0a, 0x09, 0xa5, 0xeb, 0x97, 0xb0, 0xc4,
+    0x2c, 0xa3, 0x95, 0x57, 0xea, 0x59, 0x15, 0xc7, 0x81, 0xdf, 0x64, 0x99,
+    0x1b, 0x20, 0x8d, 0xe0, 0x29, 0x7c, 0x23, 0x16, 0x3c, 0x8e, 0x2e, 0x0b,
+    0xff, 0x02, 0xdc, 0x6f, 0x24, 0x1e, 0xfc, 0xac, 0x0f, 0x16, 0x38, 0xde,
+    0x5c, 0x9c, 0x5f, 0x48, 0x13, 0xfb, 0xac, 0xbd, 0x99, 0x5e, 0x7e, 0xe0,
+    0xcc, 0x3c, 0x21, 0x17, 0xfa, 0x67, 0x53, 0x31, 0xb3, 0x99, 0x98, 0x05,
+    0x2d, 0xa1, 0xb2, 0x72, 0xf6, 0xe0, 0x73, 0xb5, 0x6e, 0xc7, 0xa0, 0x7f,
+    0xfa, 0x75, 0x89, 0x20, 0x4c, 0x84, 0xa1, 0x2b, 0x39, 0x4a, 0xd1, 0xf5,
+    0x36, 0xfa, 0x5f, 0xb2, 0x7e, 0x75, 0x1b, 0x21, 0xae, 0x30, 0x83, 0x14,
+    0x3d, 0xf6, 0x4c, 0x3a, 0xd8, 0x1e, 0x05, 0xed, 0x93, 0xbf, 0xd3, 0xb2,
+    0x46, 0x23, 0x43, 0x3d, 0x78, 0xf9, 0x94, 0x78, 0xae, 0x20, 0x8b, 0x49,
+    0x8c, 0xac, 0x8f, 0x41, 0xe4, 0x5d, 0x96, 0x25, 0xd6, 0xd9, 0xde, 0x8b,
+    0x6a, 0xcd, 0x37, 0x22, 0x1b, 0xd7, 0xca, 0x8a, 0xa3, 0x79, 0x7b, 0x3d,
+    0x3e, 0x2d, 0xe3, 0x09, 0xa4, 0xbf, 0x9a, 0x48, 0x63, 0xa5, 0x88, 0xbf,
+    0xb6, 0xfb, 0x7b, 0xcc, 0x29, 0xd2, 0x2f, 0xdc, 0x36, 0xab, 0xd6, 0x46,
+    0xae, 0xf7, 0xca, 0xa9, 0xb4, 0x14, 0xae, 0xfe, 0x12, 0x62, 0xb9, 0xce,
+    0x4b, 0x99, 0xf8, 0xa5, 0x59, 0x81, 0x83, 0x68, 0x48, 0x44, 0x75, 0xab,
+    0xb2, 0x12, 0x89, 0x1c, 0xe7, 0x3d, 0x9b, 0x19, 0xa2, 0x6c, 0xa5, 0x62,
+    0x48, 0xed, 0x1c, 0xba, 0x89, 0x61, 0xe4, 0x24, 0x8a, 0xd8, 0x87, 0xb7,
+    0x64, 0xc8, 0x09, 0x20, 0x83, 0x50, 0x2b, 0xe7, 0xb9, 0x8c, 0x99, 0x05,
+    0x18, 0xd3, 0xf5, 0x19, 0xec, 0x75, 0x83, 0x4c, 0x80, 0x20, 0x2b, 0x6a,
+    0xa0, 0x75, 0x6b, 0x62, 0xd1, 0x02, 0x06, 0x16, 0x66, 0x9e, 0x5a, 0x13,
+    0xfe, 0x1d, 0xf4, 0x95, 0xff, 0xc2, 0xd7, 0x94, 0xda, 0x70, 0x57, 0xc2,
+    0x1d, 0xe8, 0x70, 0x13, 0x13, 0x95, 0x58, 0xdb, 0x0f, 0x1e, 0xab, 0x40,
+    0xbc, 0x14, 0xe5, 0xdd, 0x8b, 0xf5, 0x42, 0x21, 0xb4, 0x86, 0xf9, 0x18,
+    0x2b, 0xd4, 0x92, 0x39, 0xff, 0x11, 0x87, 0xa5, 0xe6, 0x64, 0xbc, 0x44,
+    0xa0, 0x41, 0x38, 0xed, 0xce, 0x3b, 0xce, 0x8c, 0x56, 0xad, 0xa2, 0xd5,
+    0xf2, 0x1c, 0x3b, 0xcb, 0x49, 0x27, 0x99, 0xab, 0xb1, 0x4a, 0x1b, 0x24,
+    0x8f, 0xb0, 0x17, 0xc0, 0x9d, 0xb3, 0x25, 0xac, 0xa8, 0x71, 0x78, 0x2b,
+    0xd3, 0xa0, 0xc9, 0x76, 0xc5, 0x5b, 0x2d, 0xfc, 0x20, 0x5c, 0x48, 0x0f,
+    0xfe, 0x19, 0x0b, 0x21, 0xed, 0xf3, 0xed, 0x19, 0xa1, 0xba, 0x27, 0xc3,
+    0x91, 0xa1, 0xf4, 0x98, 0x62, 0x14, 0xcf, 0x4a, 0x13, 0x1a, 0x35, 0xda,
+    0x09, 0xfe, 0x34, 0x6a, 0x47, 0x2a, 0x47, 0x7e, 0x99, 0x52, 0x03, 0x8b,
+    0x47, 0xc6, 0x37, 0x2f, 0xb6, 0xc8, 0x80, 0x7a, 0x14, 0x41, 0x7d, 0x10,
+    0x93, 0x48, 0xad, 0x95, 0xb5, 0xbb, 0x72, 0xd0, 0x36, 0xfb, 0x07, 0xfa,
+    0x42, 0x2c, 0x5b, 0x0a, 0xea, 0xe4, 0xea, 0x67, 0x05, 0x1c, 0x73, 0x20,
+    0xc5, 0xe6, 0x86, 0x87, 0xac, 0xe1, 0xcb, 0x67, 0xae, 0x01, 0x71, 0x05,
+    0x1e, 0xe5, 0x13, 0x1a, 0x9e, 0xa8, 0xbc, 0xd0, 0x66, 0x83, 0x30, 0x33,
+    0xcb, 0xf8, 0x01, 0x61, 0x60, 0xe3, 0xfc, 0x55, 0x7f, 0x3b, 0xd0, 0x51,
+    0x2e, 0x82, 0xb6, 0x11, 0x25, 0xe1, 0x50, 0x77, 0x02, 0x7d, 0x6c, 0x16,
+    0x37, 0x02, 0xa6, 0x9f, 0x8c, 0xdd, 0x50, 0xdc, 0x95, 0xb6, 0x4a, 0xc9,
+    0x97, 0xee, 0x0a, 0x11, 0x3c, 0x81, 0xbd, 0x08, 0x23, 0xda, 0xbe, 0xa7,
+    0x39, 0x8c, 0x24, 0x68, 0x2b, 0x68, 0x7b, 0x9e, 0x1a, 0xf1, 0xb7, 0x58,
+    0x2f, 0x2a, 0x3f, 0x90, 0xd8, 0x9a, 0xad, 0x92, 0xae, 0x2b, 0xb2, 0x41,
+    0x46, 0x2d, 0x80, 0xac, 0x84, 0x61, 0xe4, 0x7f, 0xb0, 0x59, 0xa6, 0x3e,
+    0x4d, 0x61, 0x8a, 0xb7, 0x6b, 0xaa, 0xb4, 0x86, 0x63, 0xd2, 0xf3, 0x12,
+    0xac, 0xe5, 0x97, 0x88, 0xaf, 0x29, 0xdd, 0x7c, 0xa3, 0xcd, 0x8d, 0x9f,
+    0x53, 0x22, 0xaf, 0x62, 0xad, 0xf9, 0x96, 0x10, 0x8d, 0x98, 0x99, 0x9a,
+    0x39, 0x10, 0x1a, 0x09, 0xad, 0x50, 0x52, 0x73, 0xb5, 0xfd, 0xde, 0xe4,
+    0xf6, 0xe9, 0x96, 0x65, 0xc8, 0x42, 0xf0, 0xf8, 0x31, 0x5a, 0xe5, 0x6d,
+    0x3b, 0x66, 0x02, 0xc4, 0x76, 0x45, 0xd8, 0xce, 0x97, 0xb9, 0xdd, 0x3b,
+    0x00, 0x8a, 0xda, 0x7b, 0x23, 0x7d, 0xc2, 0x4e, 0x18, 0xa9, 0xa0, 0x89,
+    0x3a, 0x19, 0xfd, 0xff, 0xcb, 0x3e, 0xd6, 0x8d, 0xcb, 0x40, 0xa7, 0x9f,
+    0x3b, 0xe9, 0x9c, 0xe9, 0x4f, 0x91, 0x5a, 0xa0, 0x24, 0x44, 0x4a, 0x37,
+    0x2b, 0xd5, 0x2c, 0x39, 0x8c, 0xe6, 0x1a, 0xcc, 0x23, 0x28, 0x88, 0xca,
+    0xfc, 0x77, 0xbd, 0xbf, 0x71, 0x2b, 0x0b, 0x2a, 0xb9, 0x36, 0x6a, 0x71,
+    0x88, 0x1e, 0x50, 0x76, 0x4c, 0xba, 0xe4, 0x43, 0xd0, 0xf1, 0x08, 0x5f,
+    0xe3, 0xb4, 0x18, 0x3e, 0x6c, 0x9d, 0xcd, 0xb7, 0xf4, 0xb7, 0x54, 0xdd,
+    0x71, 0xe0, 0xd3, 0xcb, 0x30, 0x3d, 0x74, 0x7c, 0x8a, 0x22, 0xd4, 0x38,
+    0x9c, 0x63, 0x24, 0x37, 0x26, 0x0c, 0x32, 0xaa, 0x7b, 0xaa, 0x54, 0x49,
+    0x98, 0xc4, 0x5a, 0x4e, 0xb3, 0x9b, 0xa8, 0x8e, 0xb6, 0x61, 0x0c, 0xf6,
+    0xe8, 0x1c, 0x1e, 0xb2, 0x4c, 0xd6, 0x2c, 0x03, 0x2d, 0x87, 0xc8, 0x23,
+    0x85, 0xfa, 0x06, 0x4e, 0x60, 0x23, 0x88, 0x9b, 0x8c, 0xad, 0x74, 0x99,
+    0x95, 0x5d, 0x9b, 0x79, 0x40, 0xad, 0x1e, 0x9c, 0xa3, 0xcf, 0xa4, 0x5e,
+    0xf4, 0xc0, 0x2e, 0xe1, 0x1b, 0x22, 0xc3, 0x9d, 0xb0, 0xc7, 0x80, 0xc5,
+    0x00, 0x8b, 0xd8, 0x45, 0x01, 0x27, 0xf2, 0x1c, 0x25, 0x9d, 0x73, 0xa3,
+    0xf4, 0x1c, 0x19, 0x1d, 0xc4, 0x46, 0xb3, 0x12, 0x9b, 0xdb, 0xa0, 0x31,
+    0x46, 0xb6, 0xf2, 0xaa, 0x27, 0xae, 0x80, 0x51, 0xac, 0x2c, 0xca, 0x1a,
+    0x60, 0xaa, 0x1a, 0x57, 0xb9, 0x88, 0x2f, 0xbd, 0x60, 0x48, 0xa0, 0xe6,
+    0xf3, 0xce, 0x3b, 0x48, 0x80, 0xe4, 0x3a, 0x82, 0x49, 0xcf, 0x68, 0x54,
+    0x48, 0xd3, 0xab, 0x70, 0xd8, 0x0a, 0x8c, 0x75, 0x66, 0x9b, 0x8b, 0x71,
+    0x65, 0xbf, 0x1b, 0x7c, 0xcf, 0x51, 0x67, 0xce, 0x3c, 0x16, 0x3b, 0x1c,
+    0xe8, 0x77, 0x33, 0x49, 0x4d, 0x15, 0x04, 0x2b, 0xfc, 0x3a, 0xcf, 0x97,
+    0x38, 0x97, 0x65, 0x77, 0x23, 0x95, 0xc4, 0x24, 0x7e, 0x44, 0x60, 0x04,
+    0x46, 0xa1, 0x41, 0x9a, 0x1a, 0x22, 0xbc, 0x4f, 0x10, 0xad, 0x52, 0xc1,
+    0xf2, 0xbf, 0xe8, 0xd6, 0x44, 0x65, 0xed, 0x66, 0x93, 0x77, 0x64, 0xa1,
+    0xcf, 0x25, 0xb6, 0x53, 0x32, 0x5a, 0x89, 0xf4, 0xe3, 0x47, 0x7f, 0xeb,
+    0x60, 0x68, 0x12, 0x50, 0x47, 0x32, 0x72, 0x31, 0x61, 0x26, 0xf9, 0x20,
+    0x52, 0x9c, 0xa6, 0x95, 0x66, 0xb7, 0x28, 0x7b, 0xc7, 0x9b, 0xe0, 0xc6,
+    0x19, 0x06, 0x3d, 0xe0, 0x29, 0x59, 0xe6, 0xc1, 0x21, 0x26, 0x5c, 0x72,
+    0x98, 0x05, 0xde, 0x5b, 0xae, 0x5a, 0x5c, 0x40, 0xf8, 0x31, 0x9b, 0x5e,
+    0xa8, 0x18, 0x75, 0x1e, 0xb4, 0x22, 0x4a, 0xda, 0x41, 0xa8, 0x1e, 0xec,
+    0x6a, 0x39, 0x8c, 0xfa, 0x6f, 0xa9, 0xdc, 0xa5, 0x8f, 0xc5, 0x67, 0x8a,
+    0x68, 0xde, 0xee, 0xc4, 0x0a, 0xcd, 0x34, 0x6b, 0xf7, 0x57, 0x5f, 0x19,
+    0x8c, 0x98, 0xdd, 0xec, 0x4f, 0xd2, 0x28, 0x48, 0x4d, 0x34, 0x86, 0x6a,
+    0x2f, 0x5a, 0x36, 0x80, 0x5d, 0x22, 0x68, 0xd2, 0x3e, 0x39, 0x2a, 0x0d,
+    0xeb, 0xbf, 0x91, 0x83, 0x80, 0x60, 0xa8, 0x44, 0x67, 0x21, 0x89, 0xca,
+    0x8a, 0x52, 0xcd, 0x7e, 0xcf, 0xa5, 0x99, 0xd0, 0x72, 0xa9, 0x62, 0x7b,
+    0xfa, 0x38, 0x36, 0x20, 0xe1, 0x19, 0xb5, 0x6d, 0x68, 0x9a, 0x44, 0x7e,
+    0x7b, 0x1d, 0x46, 0x11, 0x49, 0x26, 0x9e, 0xbd, 0x06, 0xb2, 0x01, 0x53,
+    0x02, 0xf2, 0x47, 0xe6, 0x57, 0x74, 0x09, 0x13, 0x39, 0x38, 0x02, 0x34,
+    0x2a, 0x3b, 0x8d, 0xc0, 0x68, 0x2d, 0x2c, 0x7c, 0x1e, 0x38, 0x80, 0xdb,
+    0x0a, 0xbf, 0xf7, 0x31, 0x35, 0xec, 0xbb, 0xaa, 0xc9, 0xaa, 0x0e, 0x9c,
+    0x33, 0x8e, 0x7f, 0x85, 0x1f, 0x69, 0x9f, 0xf2, 0x48, 0x5d, 0x51, 0x51,
+    0xde, 0x33, 0x87, 0x8f, 0x09, 0x02, 0x9e, 0xb7, 0x42, 0xa5, 0x32, 0x1a,
+    0xe8, 0xf7, 0xa3, 0x8e, 0xfc, 0x5c, 0xcc, 0x8b, 0x8c, 0xc4, 0x44, 0x66,
+    0xca, 0x28, 0xe4, 0x54, 0xc2, 0xfa, 0x9f, 0x69, 0xd8, 0xfe, 0x1e, 0x37,
+    0x6b, 0x34, 0x04, 0x94, 0xfe, 0x47, 0xa4, 0x6d, 0x45, 0x28, 0x19, 0xa2,
+    0xd8, 0x42, 0x89, 0xc7, 0xa0, 0x05, 0x34, 0x3c, 0x9f, 0xb3, 0x0d, 0xa2,
+    0x56, 0xb3, 0x45, 0xc4, 0x8c, 0x0b, 0x60, 0xcf, 0x58, 0x40, 0xa0, 0x21,
+    0x49, 0x3a, 0xac, 0xee, 0x6b, 0xc8, 0x98, 0x1c, 0x7c, 0xf9, 0x9d, 0xac,
+    0x7c, 0x9c, 0xc8, 0xd5, 0xcf, 0xf9, 0x2a, 0x83, 0xec, 0x50, 0x0e, 0xf2,
+    0x4d, 0x73, 0x05, 0xf2, 0x0f, 0xea, 0xca, 0x45, 0x2b, 0x97, 0x75, 0xbd,
+    0x53, 0x63, 0x36, 0x68, 0x9b, 0x14, 0x5c, 0xe0, 0x75, 0xd3, 0xb9, 0xe3,
+    0x25, 0x04, 0x75, 0x7a, 0xe7, 0xb7, 0xa5, 0x44, 0x14, 0x0d, 0xc4, 0x4f,
+    0xab, 0x86, 0x94, 0xdf, 0x50, 0x76, 0x73, 0xd7, 0x8d, 0x21, 0x2c, 0x77,
+    0x51, 0x16, 0xb2, 0x4a, 0x5f, 0xcb, 0x45, 0x6c, 0x19, 0x7a, 0x3b, 0x61,
+    0xbb, 0x98, 0xe4, 0xd3, 0x4a, 0x33, 0x1d, 0x88, 0x4c, 0x65, 0x1d, 0xdb,
+    0x86, 0xd0, 0x14, 0x2f, 0x3e, 0x27, 0x37, 0x1e, 0xbc, 0x88, 0x84, 0x23,
+    0x07, 0xe1, 0xc4, 0xaa, 0x5b, 0xde, 0x03, 0x86, 0x77, 0xfd, 0x53, 0x73,
+    0xd0, 0x70, 0xa2, 0xf9, 0xc6, 0x6c, 0xcb, 0x60, 0xd7, 0xe3, 0xa5, 0xd8,
+    0x34, 0xf8, 0x35, 0x7d, 0xe1, 0xaf, 0x8b, 0x0c, 0x04, 0x42, 0x70, 0x06,
+    0x32, 0xb5, 0x7e, 0x9e, 0xec, 0xda, 0xef, 0xd3, 0xd6, 0x3d, 0xd0, 0x6a,
+    0xcb, 0x7b, 0xed, 0xde, 0xb9, 0x0c, 0xf3, 0xb1, 0x88, 0x35, 0x4a, 0x79,
+    0x2c, 0x88, 0x63, 0xbc, 0xb7, 0x1a, 0x3e, 0xee, 0x61, 0xc5, 0x1f, 0x1b,
+    0x94, 0xbb, 0xc1, 0x6b, 0x61, 0xfa, 0x43, 0x27, 0x9b, 0x39, 0x5d, 0x0f,
+    0xb8, 0x0d, 0x25, 0xa7, 0xcc, 0x1c, 0x99, 0x36, 0xa0, 0x07, 0x71, 0xa9,
+    0x39, 0x73, 0x3a, 0x5a, 0x12, 0x99, 0xa6, 0x32, 0x30, 0xa5, 0x85, 0x84,
+    0xa4, 0xe8, 0x98, 0xb4, 0xd1, 0xd1, 0x5d, 0x39, 0xeb, 0x24, 0xde, 0xf2,
+    0xb4, 0xc2, 0x09, 0x90, 0x1a, 0x1b, 0x61, 0x58, 0x51, 0x11, 0x75, 0x7a,
+    0x37, 0x0f, 0x69, 0x07, 0x6d, 0xfa, 0x14, 0x08, 0x84, 0xce, 0x4e, 0xa4,
+    0x91, 0x96, 0x64, 0xfe, 0x1b, 0x4d, 0xa4, 0x52, 0x4e, 0xa8, 0x25, 0xa8,
+    0x70, 0x25, 0xb0, 0x60, 0xed, 0xbe, 0x65, 0x3f, 0x8a, 0xf5, 0x95, 0x5a,
+    0xf7, 0xda, 0xe2, 0xd7, 0xc2, 0xcf, 0x3b, 0xdc, 0x44, 0xf6, 0xe7, 0x68,
+    0x10, 0x50, 0x29, 0xbe, 0x48, 0x55, 0xcc, 0xac, 0xaf, 0x12, 0xa9, 0x61,
+    0x89, 0x89, 0xc9, 0xca, 0xef, 0x37, 0x35, 0x49, 0x0c, 0xc2, 0xb6, 0x36,
+    0xbf, 0x6e, 0x24, 0x80, 0x5c, 0x0c, 0x78, 0x33, 0x64, 0xfe, 0x5b, 0xf3,
+    0x75, 0x36, 0x65, 0x28, 0xeb, 0x20, 0xb4, 0xb0, 0x61, 0xcd, 0x7a, 0x0b,
+    0x24, 0x1e, 0x46, 0x1d, 0x10, 0xb1, 0x25, 0x6e, 0x3a, 0x25, 0x86, 0xf6,
+    0xad, 0x1c, 0x43, 0x0c, 0xf9, 0xcf, 0x42, 0xe0, 0x67, 0x2b, 0x36, 0x51,
+    0x66, 0xbb, 0xf7, 0xea, 0x41, 0x69, 0x6e, 0xb8, 0xb7, 0x0e, 0xfc, 0xfd,
+    0xaa, 0x1a, 0x95, 0x43, 0x08, 0x4b, 0xb8, 0xfc, 0x3b, 0x99, 0xeb, 0xa0,
+    0x7c, 0x8d, 0xbd, 0x69, 0x49, 0xd3, 0xdd, 0x0f, 0x8e, 0xbe, 0x34, 0xd2,
+    0x27, 0x87, 0x64, 0x79, 0x0d, 0xa6, 0xf2, 0xe5, 0x2f, 0xe3, 0xad, 0x2f,
+    0x21, 0xd6, 0x36, 0x58, 0x2c, 0x6e, 0x6a, 0x43, 0x6b, 0xc7, 0x3d, 0x8b,
+    0x8d, 0x24, 0xf0, 0xcb, 0x33, 0xdf, 0xf1, 0xd2, 0xeb, 0xcb, 0x5d, 0x00,
+    0xb1, 0x63, 0x08, 0x77, 0x9d, 0xfc, 0xa1, 0x58, 0x7d, 0xe4, 0xb7, 0x95,
+    0xc5, 0x99, 0x08, 0x6f, 0xf9, 0xc9, 0x50, 0x4f, 0x8c, 0xa8, 0xc0, 0xe6,
+    0xc4, 0xff, 0x00, 0xcd, 0x6f, 0xbe, 0xa3, 0xb6, 0x66, 0x63, 0x5d, 0x4b,
+    0x60, 0x4b, 0x1b, 0x3e, 0xc6, 0x70, 0x65, 0xe4, 0x8e, 0x48, 0xb2, 0x68,
+    0xdc, 0xd1, 0xac, 0x78, 0x46, 0x3d, 0x32, 0x58, 0x00, 0xfb, 0x28, 0x95,
+    0x7a, 0xf7, 0x11, 0x33, 0x5a, 0x5b, 0xb8, 0xfa, 0xe0, 0xa1, 0x84, 0x33,
+    0x64, 0x36, 0x37, 0xd4, 0x64, 0x9e, 0xc1, 0x05, 0xca, 0x87, 0x1d, 0xee,
+    0xc0, 0x4f, 0xf4, 0xd4, 0x81, 0x78, 0x54, 0x09, 0x93, 0x56, 0xc0, 0xb6,
+    0x7e, 0x26, 0xc3, 0xed, 0xec, 0xdb, 0x24, 0x2c, 0x80, 0xee, 0x0a, 0x57,
+    0x6c, 0xa9, 0x85, 0x1d, 0x44, 0xdd, 0x61, 0xb6, 0xfc, 0xdb, 0xd1, 0x00,
+    0xd0, 0x5f, 0xbb, 0x43, 0xcf, 0x32, 0x41, 0x2a, 0xef, 0xe8, 0x57, 0x89,
+    0x6d, 0xf0, 0x55, 0x8c, 0x54, 0x61, 0xee, 0x8a, 0xf7, 0x1d, 0x90, 0x51,
+    0x0f, 0x4e, 0x56, 0xd6, 0x9d, 0x71, 0x77, 0x3c, 0xe5, 0x28, 0xee, 0xc1,
+    0xd6, 0x8f, 0xef, 0xbd, 0x2c, 0x83, 0xb8, 0xce, 0x24, 0xa4, 0x41, 0x90,
+    0x14, 0x59, 0xd2, 0xfc, 0xc3, 0x0e, 0x5d, 0xa9, 0x22, 0x3b, 0xd3, 0xa4,
+    0x30, 0x19, 0x05, 0x64, 0x61, 0x1e, 0x86, 0xec, 0x89, 0x19, 0x75, 0xaf,
+    0x80, 0xe3, 0xd7, 0xfb, 0x0a, 0x91, 0xe2, 0xb7, 0xd1, 0x6f, 0xe4, 0xcc,
+    0x88, 0x92, 0x48, 0xed, 0x1e, 0x3b, 0xec, 0xa3, 0x9d, 0xeb, 0x9e, 0x78,
+    0xb1, 0xa9, 0x34, 0xc1, 0xb6, 0x9b, 0xfc, 0x1e, 0x2d, 0xef, 0xb1, 0x16,
+    0x49, 0xd9, 0x60, 0xde, 0xd0, 0xf5, 0x69, 0x12, 0x4d, 0xa1, 0xf7, 0xb4,
+    0x58, 0x3d, 0x9e, 0xb7, 0x93, 0xce, 0x37, 0x33, 0xc1, 0x82, 0x00, 0x74,
+    0x20, 0xfb, 0x3f, 0x48, 0xb1, 0x52, 0x43, 0x0c, 0x5c, 0x96, 0x82, 0x84,
+    0x4b, 0xe3, 0x8e, 0x1a, 0xe4, 0x64, 0x39, 0x6d, 0x98, 0x1c, 0x65, 0x11,
+    0xb2, 0x06, 0xc1, 0xae, 0x01, 0x68, 0xd6, 0xfe, 0x57, 0xe7, 0x53, 0xd7,
+    0xb1, 0x9f, 0xf9, 0xc8, 0x14, 0x17, 0x85, 0x5c, 0x41, 0x2b, 0x30, 0x60,
+    0xbe, 0xfb, 0x61, 0x6b, 0xd9, 0x04, 0x24, 0xa3, 0xec, 0x84, 0x29, 0x20,
+    0x6a, 0x70, 0x85, 0x1c, 0xf7, 0xe1, 0xce, 0x37, 0x14, 0x13, 0x6c, 0xfe,
+    0xe5, 0x48, 0x6a, 0x33, 0xb9, 0xb9, 0xa2, 0x31, 0x5f, 0xec, 0x3f, 0x8b,
+    0x16, 0x63, 0xb1, 0x2a, 0xb3, 0x6b, 0x07, 0x9a, 0x72, 0x62, 0xd2, 0x02,
+    0xef, 0x4c, 0x77, 0x82, 0x1b, 0xaa, 0xbf, 0xc4, 0xe2, 0x21, 0x2f, 0xc9,
+    0x31, 0x3d, 0x92, 0xf4, 0x73, 0x02, 0xa2, 0x47, 0x90, 0xed, 0xcb, 0xb2,
+    0xb9, 0xcd, 0xbf, 0xab, 0x7f, 0x6a, 0xe8, 0xc5, 0x19, 0x9a, 0x6a, 0x02,
+    0x98, 0x36, 0xfb, 0xe1, 0xae, 0xac, 0x6b, 0xca, 0x93, 0x59, 0xf1, 0x04,
+    0x9e, 0xd8, 0x78, 0x1e, 0x6d, 0x85, 0x3e, 0x2a, 0xe8, 0x79, 0x12, 0x67,
+    0x27, 0xb4, 0x9b, 0x66, 0xf7, 0xe2, 0x01, 0xf4, 0x98, 0xbe, 0xb0, 0x74,
+    0x6d, 0x91, 0xf8, 0x3c, 0x18, 0x7e, 0xc6, 0x84, 0x10, 0x51, 0xda, 0x14,
+    0x69, 0xc0, 0xac, 0xa4, 0xe3, 0xd8, 0x97, 0x73, 0xfe, 0xeb, 0xe0, 0xae,
+    0x51, 0xc4, 0x22, 0xa5, 0x91, 0x6f, 0x87, 0x38, 0x39, 0x9e, 0x97, 0x3a,
+    0xeb, 0x91, 0xa9, 0xbb, 0xf9, 0xa4, 0xca, 0x3e, 0xef, 0x17, 0x58, 0x79,
+    0x45, 0x77, 0x2b, 0xe7, 0x50, 0x92, 0x85, 0x90, 0x12, 0xc5, 0xc3, 0xe3,
+    0xcd, 0xc4, 0xbe, 0xbf, 0x6f, 0x47, 0x25, 0x88, 0xcd, 0x6c, 0xcc, 0xee,
+    0x9e, 0x61, 0x1b, 0x78, 0x0d, 0xd7, 0xaa, 0x77, 0x1b, 0x05, 0x91, 0xe7,
+    0x28, 0x09, 0xfc, 0x66, 0xe5, 0x7e, 0x28, 0xb3, 0x1d, 0x29, 0x33, 0x09,
+    0xdd, 0x15, 0x28, 0x17, 0x40, 0xa2, 0xef, 0xf4, 0xb9, 0x98, 0x2d, 0xc4,
+    0x22, 0x9b, 0x1e, 0xc1, 0xef, 0x49, 0x5f, 0xe7, 0xb9, 0xf2, 0x5b, 0x74,
+    0x6c, 0xd0, 0x11, 0xca, 0x5a, 0x3c, 0xa5, 0x78, 0xe7, 0xd2, 0xd7, 0x05,
+    0x86, 0x06, 0x7d, 0xe9, 0x13, 0x6f, 0xcd, 0x12, 0x26, 0x51, 0x9c, 0xf8,
+    0xcb, 0x5f, 0x38, 0x89, 0x32, 0xbb, 0xaa, 0x8c, 0xb9, 0xac, 0x67, 0x19,
+    0xee, 0xf8, 0x9f, 0x8b, 0x89, 0xca, 0xbc, 0x89, 0x13, 0xd3, 0x7e, 0x2b,
+    0xa7, 0xb0, 0x8c, 0x5f, 0x4e, 0x89, 0xad, 0x75, 0xc7, 0xc1, 0xf1, 0xd3,
+    0xa1, 0x0d, 0xc1, 0xbc, 0x7f, 0x60, 0xcf, 0x83, 0x5f, 0x27, 0x43, 0xe1,
+    0x2f, 0x45, 0x0c, 0x01, 0x65, 0x73, 0x31, 0x34, 0x63, 0x52, 0x44, 0x0e,
+    0x2a, 0x6c, 0x10, 0x29, 0xf4, 0xad, 0x51, 0x07, 0x58, 0x41, 0xc6, 0x74,
+    0xac, 0x8c, 0xfc, 0x01, 0xba, 0x80, 0xb9, 0x2d, 0x02, 0xc6, 0x96, 0x1d,
+    0xcf, 0x6d, 0xad, 0xb2, 0xc1, 0x8f, 0xec, 0x6d, 0xdd, 0xb6, 0x70, 0x4c,
+    0x99, 0x33, 0x16, 0xb2, 0x60, 0x34, 0xc3, 0xaa, 0x15, 0x09, 0xf2, 0x62,
+    0xf2, 0x95, 0x80, 0xf2, 0xc1, 0xca, 0x6d, 0x20, 0x67, 0x79, 0x7a, 0x29,
+    0xfa, 0xbb, 0x19, 0xd8, 0xd8, 0x20, 0xa7, 0x56, 0x84, 0xce, 0x96, 0x2c,
+    0x92, 0x0d, 0xf7, 0x00, 0x66, 0xc5, 0x8e, 0x05, 0x59, 0x3e, 0xf7, 0xa9,
+    0x14, 0x6b, 0x50, 0xaf, 0x83, 0xfd, 0x7b, 0x58, 0x5c, 0x2c, 0x6b, 0x7f,
+    0x84, 0x60, 0x53, 0xbb, 0x02, 0x3e, 0xad, 0x6c, 0x58, 0xe4, 0x0f, 0x7b,
+    0x77, 0x54, 0xd8, 0x11, 0x35, 0x5d, 0x98, 0x63, 0x51, 0x0c, 0x3f, 0x16,
+    0x3f, 0x8a, 0x1e, 0xf3, 0x58, 0x59, 0xb1, 0x32, 0x98, 0x10, 0xda, 0x94,
+    0x61, 0x81, 0x78, 0xf4, 0xec, 0x3b, 0x88, 0xc6, 0x47, 0xb1, 0xad, 0x01,
+    0xe6, 0xdb, 0x70, 0xa8, 0x13, 0x59, 0xbb, 0x67, 0x10, 0xeb, 0x7c, 0x5c,
+    0xba, 0x5d, 0xba, 0xdf, 0x81, 0xf0, 0xe9, 0x80, 0x75, 0xe4, 0x61, 0xb0,
+    0x72, 0xcf, 0x3b, 0x7a, 0xeb, 0xf0, 0xc1, 0xdf, 0xb9, 0xcc, 0x6f, 0x07,
+    0x75, 0xce, 0x22, 0xc8, 0x90, 0x3f, 0x90, 0xc9, 0xf3, 0x68, 0x91, 0xc8,
+    0xf2, 0x51, 0x2e, 0x72, 0x54, 0x40, 0x76, 0xdb, 0x9c, 0x75, 0x70, 0x5b,
+    0x5f, 0xd4, 0x5a, 0x45, 0x81, 0x89, 0x4a, 0xd8, 0x76, 0x22, 0x3e, 0xba,
+    0xaf, 0x80, 0xee, 0xe6, 0x8e, 0xd1, 0x14, 0xad, 0x24, 0x6f, 0x54, 0x71,
+    0x7d, 0x9f, 0x94, 0x25, 0x19, 0x39, 0xcc, 0x11, 0x11, 0x1a, 0x15, 0xcb,
+    0xc7, 0x02, 0xcd, 0x82, 0xf5, 0x7c, 0xbf, 0x11, 0x32, 0xd2, 0x33, 0xc6,
+    0xee, 0x05, 0x02, 0x46, 0x9d, 0xe6, 0xaf, 0xdd, 0xde, 0x94, 0xac, 0x35,
+    0xf1, 0x4f, 0x21, 0xbe, 0xab, 0x05, 0x78, 0xae, 0xd4, 0x6c, 0x64, 0x10,
+    0x71, 0xc4, 0x64, 0x11, 0x5d, 0x06, 0xc7, 0xdf, 0xfd, 0x1b, 0x90, 0x81,
+    0x75, 0xd2, 0xee, 0x2f, 0x8e, 0x5a, 0xe2, 0xc6, 0x12, 0x95, 0xda, 0xfb,
+    0xf1, 0xea, 0xf2, 0xfc, 0xcc, 0x09, 0x8b, 0xd3, 0x0d, 0x76, 0x20, 0xb1,
+    0xe6, 0x62, 0xe4, 0xee, 0xfe, 0x1e, 0x45, 0x70, 0x25, 0x91, 0x61, 0x3a,
+    0xb5, 0xd5, 0x86, 0xa3, 0xb6, 0x96, 0x9c, 0xc0, 0xa3, 0x61, 0x77, 0x30,
+    0xc4, 0x83, 0x1b, 0xeb, 0xa6, 0x46, 0x5c, 0xe7, 0xb6, 0x2b, 0xb2, 0xf6,
+    0xce, 0xd8, 0xb0, 0xad, 0xff, 0x8d, 0x70, 0x19, 0x3d, 0x37, 0x6a, 0x77,
+    0xc6, 0xac, 0x91, 0x20, 0xdd, 0x8c, 0x4a, 0x9f, 0x99, 0x3e, 0x9f, 0x57,
+    0x7e, 0x81, 0x84, 0xd3, 0x4c, 0x56, 0x2e, 0xa4, 0xff, 0xa7, 0xa5, 0x25,
+    0x86, 0xbf, 0x80, 0x04, 0x6e, 0x8f, 0xe8, 0xf9, 0x1f, 0x38, 0x60, 0xf6,
+    0x2c, 0xae, 0x7f, 0xe0, 0xe5, 0x9f, 0x5e, 0x21, 0x08, 0xbb, 0xe1, 0x41,
+    0x42, 0xc2, 0xa5, 0xd9, 0xfd, 0x73, 0x82, 0x86, 0xfa, 0x86, 0xe6, 0x91,
+    0x53, 0x6f, 0x99, 0x21, 0x29, 0x09, 0xb9, 0xfe, 0x91, 0x20, 0x99, 0xd8,
+    0xf1, 0xe9, 0xfc, 0x63, 0x2f, 0x51, 0x52, 0x7d, 0x3f, 0xe6, 0x88, 0xbd,
+    0x31, 0xdf, 0x74, 0xa0, 0xb8, 0x5d, 0xf0, 0x9d, 0x07, 0x20, 0xd3, 0x26,
+    0x7b, 0x80, 0xbd, 0x07, 0x6d, 0x32, 0xbb, 0x62, 0xd2, 0xec, 0x35, 0x3f,
+    0x7e, 0x5c, 0x10, 0xd0, 0x94, 0xd9, 0x14, 0x09, 0xee, 0xdc, 0x6f, 0xcd,
+    0xbb, 0x57, 0x1b, 0xed, 0x9a, 0x29, 0xfe, 0x34, 0x83, 0x3e, 0x08, 0x82,
+    0xc1, 0xa1, 0xae, 0x8d, 0xc6, 0x7c, 0xa2, 0x5f, 0x49, 0x1e, 0x9a, 0x55,
+    0xfc, 0x88, 0x21, 0x45, 0xde, 0xd1, 0x7e, 0x4c, 0xe0, 0x38, 0x9c, 0xea,
+    0xd7, 0x18, 0x0a, 0xba, 0x80, 0x23, 0xd6, 0x3e, 0x2e, 0xe1, 0x3e, 0x34,
+    0x83, 0x7b, 0x69, 0x42, 0xfc, 0xf6, 0xf0, 0x17, 0xc1, 0xac, 0x7f, 0x86,
+    0xc1, 0x86, 0x81, 0x8c, 0x01, 0xe7, 0x70, 0x02, 0x55, 0x7a, 0x72, 0xf2,
+    0xee, 0x4c, 0x96, 0xb9, 0xa1, 0xb9, 0x50, 0x67, 0x95, 0x74, 0x42, 0xd1,
+    0x16, 0x79, 0x90, 0xb2, 0x85, 0x78, 0x5b, 0x91, 0xf8, 0x59, 0x19, 0xe7,
+    0x6e, 0xb6, 0xc6, 0xff, 0xe0, 0x27, 0x2a, 0x39, 0x82, 0x91, 0xf2, 0x5b,
+    0xb4, 0x4c, 0x56, 0x22, 0x46, 0x06, 0x09, 0xf3, 0x6e, 0x2e, 0x69, 0x3b,
+    0x58, 0x7f, 0xb9, 0x8e, 0x40, 0x59, 0x51, 0xb0, 0x2f, 0x4c, 0x0d, 0x7b,
+    0x01, 0x9f, 0x0a, 0xf3, 0xdd, 0x38, 0xb3, 0xc9, 0x49, 0x15, 0xea, 0xaf,
+    0x6a, 0xf0, 0x2a, 0xe7, 0x3d, 0x23, 0xb2, 0xe7, 0xf7, 0x5d, 0xb9, 0xa0,
+    0x40, 0xd0, 0x4b, 0xcd, 0x95, 0xca, 0x54, 0xba, 0x25, 0x82, 0x11, 0xb8,
+    0x45, 0x76, 0x4c, 0xa9, 0x6f, 0x46, 0x1e, 0xf0, 0xcb, 0xcb, 0x89, 0x92,
+    0x2c, 0x5f, 0xdf, 0xbb, 0x80, 0xcb, 0x30, 0x5b, 0xbe, 0x29, 0x21, 0x23,
+    0x2f, 0x87, 0xa0, 0x1e, 0xe8, 0xe4, 0x29, 0x8c, 0x77, 0x78, 0x10, 0xb1,
+    0x2c, 0x35, 0x10, 0xa0, 0x17, 0x8c, 0x12, 0x57, 0x2e, 0xca, 0xae, 0xa7,
+    0x56, 0x21, 0xde, 0x74, 0x17, 0xf9, 0xa4, 0xdd, 0x38, 0x9c, 0xb9, 0x0f,
+    0x2a, 0xa7, 0x33, 0xb7, 0x22, 0xb3, 0x2b, 0xd9, 0xcd, 0x88, 0x3e, 0x86,
+    0x85, 0x38, 0xae, 0xb5, 0x88, 0x8d, 0xa4, 0x8f, 0x99, 0x1e, 0x2f, 0x4a,
+    0x8c, 0xfe, 0x58, 0x7f, 0xb4, 0x6e, 0xf2, 0x4f, 0x9e, 0x9f, 0x36, 0xec,
+    0xf2, 0x5b, 0xd3, 0xa2, 0x76, 0xf5, 0xa2, 0x2f, 0xbb, 0x42, 0x1d, 0x9c,
+    0xa5, 0xb9, 0x20, 0xb7, 0xcc, 0xdb, 0xd9, 0x5c, 0xe0, 0x69, 0x10, 0xbb,
+    0xae, 0xa3, 0xb4, 0x69, 0x86, 0xa0, 0x7e, 0xfa, 0xb5, 0x6d, 0xf2, 0xac,
+    0x3c, 0x96, 0xe5, 0xb6, 0x07, 0xe5, 0x8a, 0x97, 0xb8, 0x90, 0xcb, 0x5a,
+    0x23, 0x75, 0x56, 0xba, 0xf1, 0xbb, 0xf6, 0x10, 0x69, 0xc1, 0xf2, 0x57,
+    0xec, 0xab, 0x8b, 0xbe, 0x19, 0x0f, 0x72, 0x79, 0x46, 0xcc, 0xcb, 0xac,
+    0xab, 0xbe, 0x94, 0xae, 0xa4, 0x52, 0x43, 0xf4, 0x74, 0x05, 0x95, 0x33,
+    0x97, 0xd5, 0x7c, 0x41, 0x92, 0xef, 0x33, 0x02, 0x64, 0x57, 0x8e, 0x14,
+    0x05, 0x2c, 0xf4, 0x14, 0xc6, 0x62, 0x16, 0xa5, 0xc6, 0xe1, 0x38, 0x19,
+    0x01, 0x9f, 0xd2, 0x68, 0x18, 0x20, 0xaf, 0x81, 0xd1, 0x62, 0xd8, 0x32,
+    0x7a, 0x0e, 0x75, 0x85, 0x47, 0x43, 0xc2, 0xee, 0x8d, 0x96, 0xc7, 0xae,
+    0x00, 0xc3, 0x29, 0xc5, 0xf5, 0xf4, 0xca, 0xdd, 0x05, 0x1b, 0xfd, 0x82,
+    0x26, 0xa0, 0x67, 0xa0, 0x9f, 0xcb, 0x37, 0xe9, 0xe3, 0x3f, 0x79, 0x71,
+    0x80, 0x7f, 0x12, 0xc2, 0xe8, 0x54, 0x60, 0x8b, 0x8b, 0xb9, 0x19, 0xe7,
+    0x81, 0x70, 0x28, 0xd5, 0xf2, 0xb6, 0x3e, 0xb1, 0xc7, 0x66, 0x44, 0x4f,
+    0xe3, 0xa8, 0xe1, 0xa1, 0x97, 0x9a, 0xea, 0x60, 0x6c, 0x1b, 0xdd, 0x93,
+    0xd5, 0x76, 0x0e, 0xe8, 0xce, 0x8f, 0x75, 0x3f, 0x08, 0x55, 0x03, 0x55,
+    0x2e, 0xd6, 0x93, 0xb8, 0x4a, 0xe4, 0xef, 0x18, 0xbc, 0x7d, 0x7e, 0x4a,
+    0xae, 0x90, 0x5d, 0xd6, 0x53, 0x72, 0xff, 0x5b, 0xaa, 0x8b, 0x3b, 0x22,
+    0xb4, 0x8d, 0x1c, 0xdc, 0x8d, 0x4d, 0x2b, 0xd6, 0x4a, 0x33, 0xaf, 0xa6,
+    0x5c, 0xb3, 0x02, 0xfe, 0x57, 0x6e, 0x1f, 0xe8, 0x39, 0x0e, 0x62, 0x68,
+    0x93, 0xa9, 0x7b, 0x64, 0x40, 0x2c, 0xc6, 0xea, 0xd6, 0x26, 0xf0, 0x0e,
+    0x40, 0xdd, 0xf2, 0x6e, 0x6a, 0x2b, 0x9e, 0x0e, 0xd7, 0x03, 0xdf, 0x4c,
+    0x00, 0x8a, 0x6a, 0xf4, 0x14, 0x4c, 0x5a, 0x61, 0x23, 0x93, 0x12, 0xeb,
+    0x97, 0xe9, 0xfb, 0x6b, 0x63, 0xc4, 0x08, 0x54, 0xac, 0x01, 0xd0, 0xe8,
+    0xb4, 0x6e, 0xee, 0x58, 0x3c, 0x4b, 0x89, 0xfa, 0xd8, 0x6e, 0x4f, 0x5c,
+    0xb3, 0xdb, 0x51, 0x20, 0x63, 0x96, 0xa8, 0xef, 0x68, 0xbe, 0xbf, 0x0a,
+    0x69, 0x71, 0x33, 0x2a, 0x57, 0x0c, 0x20, 0x21, 0x5f, 0xe5, 0x45, 0x4d,
+    0xa0, 0x95, 0xd2, 0xb9, 0xe8, 0xc3, 0xbf, 0x6c, 0x77, 0xb8, 0xd8, 0x28,
+    0x2b, 0xce, 0x68, 0x2c, 0xb5, 0x7b, 0xdd, 0x31, 0xae, 0xd8, 0xa4, 0xee,
+    0x66, 0x7b, 0x3c, 0xc6, 0x6d, 0x58, 0xf3, 0xc2, 0xee, 0xff, 0x95, 0x98,
+    0x2b, 0xff, 0x1a, 0x52, 0xc1, 0xca, 0xb2, 0xbe, 0x87, 0x79, 0x9b, 0xe1,
+    0x19, 0x5c, 0xa5, 0x6c, 0x20, 0x8b, 0x2d, 0xa5, 0x46, 0x9d, 0xa7, 0x8a,
+    0xa5, 0x2e, 0xb0, 0xe1, 0x54, 0x1d, 0x74, 0xb8, 0x2e, 0x55, 0x99, 0x74,
+    0x7a, 0xe1, 0xe0, 0x81, 0xce, 0x64, 0x85, 0xb2, 0x5a, 0x1e, 0x57, 0xdc,
+    0x60, 0xf0, 0xfe, 0x0f, 0xe2, 0x72, 0x96, 0xab, 0x68, 0x6d, 0xcb, 0x5a,
+    0x1a, 0x32, 0xf0, 0x77, 0xda, 0x54, 0x36, 0x3d, 0x26, 0x12, 0x23, 0x23,
+    0xcf, 0x01, 0xf3, 0x49, 0xe4, 0x68, 0x1f, 0x5b, 0x95, 0x50, 0x04, 0xb5,
+    0x67, 0x49, 0xf5, 0x31, 0x0b, 0xb1, 0x2c, 0xf2, 0xb6, 0x26, 0xb4, 0x5d,
+    0x27, 0x9f, 0x3d, 0x7d, 0x2f, 0xf0, 0x06, 0xd4, 0x95, 0xdc, 0x38, 0x0f,
+    0xdb, 0xa8, 0xc8, 0x23, 0x9f, 0xe6, 0x6c, 0x4d, 0xe7, 0xdc, 0xeb, 0x30,
+    0xdf, 0xc1, 0xfa, 0xeb, 0xa0, 0xa0, 0x08, 0x0f, 0xdc, 0xad, 0xf6, 0xe3,
+    0xb3, 0x62, 0x62, 0x5b, 0xe4, 0xf7, 0x14, 0xda, 0x07, 0x2f, 0x75, 0x35,
+    0xe4, 0xaf, 0x7c, 0xda, 0x8e, 0x2a, 0xf1, 0x62, 0x60, 0x8d, 0x63, 0xe3,
+    0x9a, 0x98, 0x6a, 0xbe, 0x9b, 0xfb, 0x51, 0xd9, 0x40, 0x8f, 0xf5, 0x5c,
+    0xb5, 0x32, 0xc0, 0xfd, 0x9e, 0xce, 0xa3, 0x64, 0xe5, 0x38, 0xf9, 0xd6,
+    0xef, 0x85, 0x25, 0x70, 0xb8, 0x38, 0xc5, 0x12, 0xb9, 0x5d, 0xd5, 0x57,
+    0xf0, 0x29, 0x76, 0xa0, 0x1d, 0xc7, 0x9b, 0xf2, 0xf8, 0xe8, 0xb3, 0xea,
+    0x10, 0x28, 0x3d, 0xf2, 0x71, 0xa8, 0x2d, 0x12, 0xfa, 0x6a, 0x74, 0x61,
+    0x05, 0x16, 0x98, 0x63, 0xcc, 0x70, 0x78, 0xdb, 0xe6, 0x39, 0x45, 0x83,
+    0xd2, 0x16, 0x6d, 0x8e, 0xf5, 0x0e, 0xbc, 0x13, 0xf5, 0x37, 0x0c, 0xb4,
+    0x86, 0x10, 0x0b, 0x07, 0xb6, 0xc6, 0x59, 0xbe, 0xfa, 0x70, 0xc9, 0x6a,
+    0x29, 0xa7, 0xbe, 0x94, 0x0d, 0xde, 0xb8, 0x01, 0x87, 0xb2, 0xa0, 0xcf,
+    0xa0, 0xb7, 0x2d, 0x4d, 0x26, 0x69, 0x15, 0x34, 0x23, 0x52, 0x4a, 0x82,
+    0xce, 0xd7, 0xe2, 0x7a, 0xd3, 0x4c, 0x4c, 0x57, 0x37, 0xb3, 0xc9, 0xc4,
+    0x4f, 0xec, 0xad, 0xd2, 0x1b, 0x95, 0xef, 0xa8, 0x1f, 0x43, 0xb6, 0x4f,
+    0x66, 0x5a, 0xad, 0xf2, 0x64, 0x13, 0x4b, 0x0f, 0x0a, 0x02, 0x00, 0x2a,
+    0x11, 0xb8, 0x53, 0x09, 0xaa, 0x08, 0x2f, 0x8c, 0x30, 0x68, 0x8e, 0x9c,
+    0xd1, 0xb8, 0x0c, 0xf5, 0xd0, 0xb6, 0x8e, 0x1c, 0xdb, 0x2e, 0x0e, 0xaa,
+    0x86, 0xcc, 0x86, 0x16, 0x3b, 0x8f, 0xe0, 0xa3, 0xb0, 0x36, 0x50, 0x25,
+    0x11, 0x16, 0xd2, 0xc4, 0xc7, 0x2b, 0xbf, 0xa5, 0x25, 0xc5, 0xcb, 0x6e,
+    0xd3, 0x8b, 0xca, 0x24, 0xec, 0x69, 0x1a, 0x75, 0x38, 0x3f, 0x60, 0x9b,
+    0x17, 0xf6, 0x9c, 0x9a, 0xc1, 0xb2, 0xeb, 0xac, 0x20, 0x43, 0x73, 0x5f,
+    0x6d, 0x6a, 0x53, 0xcf, 0x4a, 0xfd, 0x42, 0xa7, 0x2d, 0x98, 0xb0, 0x53,
+    0x44, 0xad, 0xe2, 0x28, 0xf9, 0x61, 0xc3, 0x94, 0xef, 0x7e, 0x70, 0x3c,
+    0x09, 0xf5, 0xd0, 0x30, 0x10, 0xc9, 0x15, 0xb2, 0x99, 0xbc, 0xb9, 0xbb,
+    0x58, 0x72, 0x4d, 0x12, 0x80, 0x87, 0x8b, 0xd2, 0x3f, 0xf2, 0xa3, 0xc8,
+    0x92, 0xde, 0xb1, 0xf8, 0xf4, 0x2c, 0x3b, 0x1a, 0x37, 0x10, 0xb9, 0xea,
+    0x32, 0xc9, 0x34, 0xac, 0x3e, 0x6d, 0xb6, 0xd2, 0x7f, 0x02, 0x27, 0xfa,
+    0x36, 0xca, 0x29, 0x18, 0x35, 0x7a, 0x3d, 0x75, 0x36, 0x38, 0x98, 0x8f,
+    0x96, 0xa4, 0xaf, 0x17, 0x22, 0x2e, 0xdb, 0xaf, 0xbe, 0xd4, 0x1b, 0x42,
+    0x92, 0x37, 0x1b, 0x85, 0x97, 0xd6, 0x98, 0xf6, 0x20, 0xfb, 0x9f, 0xbd,
+    0xee, 0x7b, 0xd5, 0xb2, 0xed, 0x26, 0xfd, 0xc3, 0xd7, 0x36, 0x93, 0xb5,
+    0xeb, 0xe9, 0xe2, 0xd9, 0xcc, 0x5c, 0x15, 0xf1, 0x63, 0xa2, 0xc8, 0x21,
+    0xff, 0x3e, 0x06, 0x2e, 0x09, 0xe5, 0x2c, 0x57, 0xfe, 0x66, 0x36, 0x26,
+    0x00, 0xd2, 0x2f, 0xe1, 0x4b, 0xfb, 0x55, 0x38, 0xfa, 0x29, 0xff, 0x3d,
+    0x12, 0x28, 0xf8, 0xd8, 0xc0, 0x19, 0x55, 0xd3, 0xc6, 0xde, 0xb6, 0xa4,
+    0xf7, 0x1a, 0x8c, 0xd3, 0x2b, 0x32, 0xc3, 0x45, 0x69, 0xd0, 0xc2, 0xf3,
+    0x44, 0x07, 0x9a, 0x30, 0x3a, 0x68, 0xab, 0xdb, 0xa3, 0x05, 0x90, 0x57,
+    0xef, 0x93, 0x8a, 0x09, 0x3a, 0xdc, 0xc1, 0x14, 0x00, 0x00, 0x3f, 0xd3,
+    0x11, 0x16, 0x07, 0x89, 0xe8, 0x62, 0x63, 0x5a, 0x12, 0xba, 0x69, 0x56,
+    0x66, 0x7e, 0xa8, 0xac, 0x65, 0xe4, 0xd3, 0xa3, 0xfa, 0x14, 0x63, 0xac,
+    0x4b, 0x6e, 0xa5, 0x3d, 0x2e, 0xd7, 0xfa, 0xe0, 0xcf, 0x2f, 0x02, 0x80,
+    0x6a, 0xfa, 0x35, 0xfe, 0xac, 0x29, 0x99, 0xa6, 0x07, 0xec, 0x54, 0xcb,
+    0x0f, 0x16, 0x84, 0x6e, 0x65, 0x99, 0x52, 0x7c, 0xd7, 0x02, 0xa1, 0xdc,
+    0xa8, 0x0d, 0x79, 0x4e, 0x1d, 0x87, 0x6f, 0xad, 0xe2, 0xb3, 0xed, 0x92,
+    0xea, 0xe1, 0xcb, 0xa2, 0x50, 0xf0, 0x52, 0x53, 0x00, 0xaf, 0x02, 0xab,
+    0xb3, 0xda, 0xed, 0xa8, 0x68, 0xc7, 0xf4, 0xb6, 0xa6, 0x7e, 0x43, 0x9c,
+    0x4b, 0x18, 0x23, 0x3d, 0x02, 0x5a, 0xc9, 0x1b, 0x55, 0xda, 0x93, 0xc7,
+    0x8d, 0x4d, 0xdd, 0xd3, 0xb2, 0x48, 0xf9, 0x6b, 0x98, 0x98, 0x12, 0x2a,
+    0x59, 0x19, 0x7f, 0xfb, 0xc8, 0x2e, 0x08, 0x21, 0xc3, 0x49, 0x9c, 0x86,
+    0xf4, 0xf8, 0x32, 0x82, 0x97, 0x49, 0x58, 0x1c, 0x3a, 0x22, 0xd3, 0x24,
+    0x13, 0xf2, 0xc7, 0xa5, 0x71, 0x76, 0x40, 0x4c, 0x4a, 0x21, 0x04, 0x18,
+    0x8c, 0xcc, 0x15, 0x37, 0xa9, 0xf6, 0x3b, 0x79, 0xe5, 0xc3, 0x7a, 0xba,
+    0x2a, 0x5c, 0xc1, 0x35, 0x14, 0x5b, 0xd1, 0x13, 0x66, 0xaf, 0xe3, 0xc8,
+    0xb9, 0x50, 0x82, 0x26, 0x5d, 0x6b, 0xc7, 0x72, 0x19, 0x4b, 0x7c, 0xa9,
+    0xd6, 0xa3, 0xf8, 0x5a, 0xd6, 0x0e, 0xc6, 0x4e, 0xa0, 0x5a, 0xe5, 0x59,
+    0x84, 0x6b, 0x42, 0x2d, 0x2d, 0x4d, 0x52, 0x62, 0x36, 0x11, 0x05, 0x3f,
+    0xc8, 0x0b, 0xcf, 0x53, 0xd7, 0x5e, 0xb7, 0x18, 0x9e, 0xa4, 0xe0, 0xba,
+    0xe2, 0x48, 0xb8, 0x9d, 0x97, 0x88, 0xa0, 0xd8, 0x47, 0x97, 0x82, 0x3b,
+    0x08, 0x0b, 0x8b, 0x89, 0x6c, 0xaf, 0x95, 0xf2, 0xd7, 0x08, 0x1c, 0x9d,
+    0x98, 0x0c, 0x20, 0x37, 0x3e, 0xc8, 0x18, 0xd3, 0x53, 0x9c, 0x4f, 0x4d,
+    0x14, 0xd1, 0xac, 0xf9, 0x54, 0xf1, 0x54, 0x66, 0x39, 0x24, 0x22, 0x1a,
+    0xfb, 0xf7, 0x2a, 0x1d, 0x13, 0x09, 0x58, 0x31, 0x4a, 0x0f, 0xac, 0x67,
+    0xa6, 0xbe, 0xe8, 0x36, 0x1b, 0xd6, 0x05, 0xb3, 0x9a, 0xbb, 0x37, 0xb9,
+    0xf5, 0x48, 0xe5, 0x89, 0x0c, 0x89, 0xbb, 0x02, 0x26, 0x86, 0x1d, 0x82,
+    0xb9, 0xe7, 0xd7, 0x8e, 0x50, 0x19, 0xfc, 0xac, 0x6f, 0x65, 0xb5, 0xb2,
+    0x21, 0xf7, 0xd4, 0x76, 0x92, 0x6e, 0x6f, 0x56, 0x01, 0x94, 0x01, 0xab,
+    0x9e, 0x89, 0x05, 0x77, 0xa9, 0x65, 0x12, 0x2c, 0x62, 0xb2, 0xb1, 0xcc,
+    0xac, 0x46, 0x02, 0x9f, 0x09, 0x7d, 0xa2, 0xac, 0x9e, 0x40, 0x83, 0x2a,
+    0xd7, 0x9e, 0xc3, 0x7c, 0xa4, 0x8c, 0xa6, 0x01, 0xe3, 0x61, 0xc0, 0x09,
+    0xb9, 0xdb, 0x8a, 0xfc, 0x11, 0x03, 0xa2, 0xbb, 0x1b, 0x13, 0x59, 0x9e,
+    0xb6, 0x9b, 0x4b, 0xe8, 0x30, 0x4e, 0x6b, 0x8d, 0xd7, 0x04, 0x20, 0x3d,
+    0x82, 0x53, 0xfb, 0x75, 0x6f, 0x43, 0xdf, 0x05, 0x44, 0xb1, 0x7a, 0x94,
+    0x83, 0x9d, 0x55, 0x3d, 0x65, 0xa4, 0xdf, 0x78, 0x4a, 0xf1, 0x15, 0xb3,
+    0x6b, 0x4a, 0x23, 0xfa, 0xcf, 0x52, 0xc6, 0xa4, 0x3c, 0x98, 0x54, 0xc6,
+    0x3b, 0x5f, 0x90, 0x83, 0x67, 0x70, 0xbe, 0x5d, 0x93, 0x24, 0x32, 0xb2,
+    0xbc, 0x56, 0x81, 0x89, 0x91, 0x8d, 0xf9, 0x17, 0x56, 0x2d, 0xd4, 0xec,
+    0x0d, 0x17, 0xd9, 0x35, 0x05, 0x46, 0x29, 0x60, 0xf0, 0x6f, 0x3a, 0x9d,
+    0x20, 0x5d, 0xee, 0x3c, 0x30, 0x72, 0xee, 0x39, 0xbc, 0x2b, 0xf8, 0xcb,
+    0x94, 0xff, 0x65, 0x8e, 0x1c, 0x51, 0xfa, 0x1e, 0xd9, 0xb9, 0xc2, 0xcb,
+    0x29, 0x4b, 0x45, 0x67, 0x70, 0x7c, 0x38, 0xf1, 0xd8, 0xd1, 0xba, 0xa9,
+    0xae, 0x1f, 0xff, 0x80, 0x76, 0x8b, 0x5b, 0xe0, 0x2c, 0xcd, 0xe5, 0x9f,
+    0x39, 0x38, 0x62, 0x91, 0x62, 0x40, 0x37, 0xf9, 0x87, 0x65, 0xc9, 0x62,
+    0x53, 0xe9, 0xbf, 0xb0, 0x22, 0x72, 0x9e, 0x85, 0xf8, 0xa3, 0x9e, 0xa8,
+    0x71, 0x46, 0xef, 0xd5, 0xec, 0x5d, 0xa0, 0x47, 0x58, 0x96, 0xc7, 0x53,
+    0xdf, 0x69, 0x9e, 0xc5, 0xb0, 0x6c, 0x34, 0x6a, 0x85, 0xb3, 0xa2, 0xa2,
+    0x6d, 0x04, 0x0c, 0xd0, 0x31, 0xdd, 0x0c, 0x78, 0x69, 0x9e, 0x4b, 0x79,
+    0xde, 0xb6, 0x1d, 0x86, 0x83, 0x04, 0x98, 0x54, 0x97, 0x04, 0xae, 0xa2,
+    0xc1, 0xd9, 0xe5, 0x3d, 0xda, 0x98, 0x02, 0xb5, 0xad, 0x67, 0x0b, 0x7c,
+    0xb3, 0x6d, 0x0a, 0x40, 0xbe, 0xf2, 0x3a, 0x63, 0x1a, 0x34, 0x64, 0xbe,
+    0x76, 0x83, 0x82, 0x39, 0xfa, 0xb6, 0x6f, 0xc1, 0x9a, 0x9f, 0xb1, 0x5c,
+    0x8c, 0x86, 0x39, 0xf5, 0xcf, 0x78, 0x5e, 0x9e, 0x07, 0x17, 0xcb, 0x69,
+    0x74, 0x19, 0x4a, 0x48, 0x48, 0x50, 0xda, 0xae, 0xfa, 0xa2, 0xd4, 0xb8,
+    0x11, 0x00, 0x1a, 0x22, 0x69, 0x9c, 0x83, 0xf8, 0x00, 0x17, 0x65, 0xf9,
+    0x18, 0xc9, 0xef, 0x99, 0x0f, 0x91, 0x4b, 0x90, 0x4d, 0xb5, 0x8c, 0x20,
+    0x76, 0x7a, 0x2b, 0x7c, 0x21, 0xf6, 0x2e, 0x45, 0x32, 0xd3, 0x53, 0x80,
+    0xd0, 0xfc, 0xb1, 0xd2, 0x1c, 0x27, 0x33, 0x75, 0x4c, 0x6a, 0xaa, 0xfb,
+    0x68, 0x7b, 0x10, 0x6c, 0x93, 0xca, 0x2f, 0xa6, 0x50, 0x9c, 0x55, 0x63,
+    0x65, 0x4f, 0xd9, 0xcf, 0xee, 0x88, 0x8c, 0xf5, 0x96, 0x9a, 0x72, 0x52,
+    0x2e, 0xe5, 0xc0, 0xdf, 0xbc, 0x95, 0x68, 0x82, 0x97, 0xe8, 0x4f, 0xe2,
+    0x4c, 0x3a, 0x8c, 0xe5, 0xe4, 0x36, 0xd9, 0x7d, 0xd0, 0xd1, 0xce, 0xd6,
+    0xd4, 0x50, 0xd3, 0xee, 0x77, 0x14, 0x3e, 0x14, 0x1a, 0x47, 0x1d, 0xa7,
+    0x3b, 0x30, 0x1f, 0x99, 0x6b, 0x1e, 0x93, 0x27, 0xbd, 0x62, 0x09, 0x27,
+    0xbc, 0x9f, 0xcd, 0x94, 0x3b, 0x97, 0x89, 0x23, 0xc3, 0x56, 0xde, 0x87,
+    0x92, 0xa8, 0xc9, 0x3e, 0x37, 0x6a, 0x14, 0xf2, 0x84, 0x79, 0x23, 0x1d,
+    0xc0, 0x8f, 0x25, 0xc0, 0xc1, 0x0a, 0x22, 0x45, 0x5f, 0xf4, 0x4e, 0xbf,
+    0x3f, 0x71, 0x88, 0x9b, 0x36, 0x20, 0x5b, 0x96, 0xc0, 0x20, 0xba, 0x15,
+    0x8d, 0x7d, 0xef, 0x96, 0x1f, 0x79, 0xb5, 0x8c, 0x4c, 0x51, 0xd9, 0x38,
+    0x35, 0x57, 0x24, 0x73, 0xbe, 0x21, 0xb1, 0xf7, 0x23, 0x89, 0x3c, 0x13,
+    0x13, 0xd9, 0x70, 0x12, 0x8c, 0x41, 0x18, 0xab, 0xb9, 0xb0, 0x9e, 0x11,
+    0x4e, 0x1d, 0xb6, 0x99, 0xd2, 0xb2, 0x9f, 0x14, 0x5b, 0x15, 0xfd, 0xc8,
+    0x2f, 0xfb, 0xac, 0x10, 0xcc, 0x37, 0x92, 0xd9, 0x54, 0xab, 0x83, 0x0c,
+    0xc8, 0xad, 0x4d, 0xe0, 0x33, 0x41, 0x1e, 0xd8, 0xce, 0xff, 0x44, 0x87,
+    0x64, 0x04, 0x30, 0x33, 0x55, 0x3f, 0x1b, 0xe2, 0x3b, 0x42, 0x2b, 0x3c,
+    0x52, 0x28, 0xbd, 0x35, 0x44, 0xa1, 0xc9, 0xa4, 0x27, 0x23, 0x52, 0xe9,
+    0x74, 0xbc, 0x70, 0x1a, 0x54, 0x65, 0x1c, 0x02, 0xeb, 0xa0, 0x41, 0x8e,
+    0x3f, 0x14, 0x92, 0x04, 0x44, 0x1d, 0x30, 0x1e, 0x33, 0x31, 0x17, 0x4f,
+    0xed, 0xbc, 0xc5, 0xa1, 0x8f, 0xc7, 0x54, 0x72, 0xee, 0x93, 0x7e, 0x0a,
+    0x57, 0x00, 0xdd, 0x93, 0xc5, 0xe5, 0xc7, 0xa1, 0x37, 0x7f, 0x66, 0x07,
+    0xa8, 0x94, 0x90, 0x61, 0xd5, 0x08, 0x9d, 0xd7, 0xce, 0x1f, 0x76, 0xff,
+    0x6e, 0xaa, 0x50, 0x93, 0x36, 0xda, 0x34, 0xf9, 0x85, 0x7f, 0x0f, 0x87,
+    0x90, 0x93, 0x9e, 0x54, 0x5d, 0x48, 0xe7, 0xa3, 0x66, 0xb6, 0xb8, 0xd1,
+    0x09, 0x69, 0x55, 0x93, 0xcb, 0x70, 0x2d, 0xea, 0xe6, 0x6c, 0xe5, 0x54,
+    0x08, 0x7d, 0x26, 0x38, 0x1c, 0x8c, 0x1d, 0xc1, 0xfd, 0x54, 0xa3, 0x3e,
+    0x5a, 0x1f, 0x7a, 0xb9, 0x17, 0xec, 0x14, 0x1a, 0xba, 0x73, 0x97, 0x34,
+    0x04, 0x03, 0xc9, 0x90, 0xfc, 0x21, 0xcc, 0xb5, 0xec, 0x9b, 0x25, 0x81,
+    0x96, 0x5c, 0xc5, 0x00, 0xa8, 0xdd, 0x32, 0x5b, 0xdc, 0xd1, 0x23, 0xdb,
+    0xc2, 0x0c, 0xed, 0x22, 0xb2, 0xd5, 0x49, 0xae, 0xb1, 0x10, 0x10, 0xb8,
+    0xdf, 0xb0, 0xf8, 0x51, 0xee, 0x6f, 0x23, 0x85, 0xb8, 0xe7, 0x45, 0x17,
+    0x21, 0x32, 0x17, 0x66, 0x73, 0x31, 0x09, 0x02, 0xa6, 0x82, 0x30, 0x7f,
+    0x9d, 0xc4, 0x54, 0x41, 0x83, 0x5e, 0xc2, 0x42, 0xff, 0x0f, 0x85, 0x40,
+    0xe6, 0x86, 0x6c, 0x31, 0x9c, 0xbb, 0x86, 0xa9, 0xde, 0xf6, 0xda, 0x34,
+    0x1b, 0x22, 0x4b, 0xba, 0x65, 0x31, 0x4f, 0xbb, 0x28, 0x58, 0x9d, 0x96,
+    0x73, 0x5f, 0x5c, 0x16, 0x42, 0x15, 0x47, 0x3e, 0xa0, 0xf5, 0xf1, 0x0d,
+    0xbe, 0x51, 0x21, 0x64, 0x8d, 0xf1, 0x93, 0x21, 0x62, 0x2c, 0x34, 0x25,
+    0x99, 0x64, 0xe2, 0x70, 0xb4, 0x34, 0x17, 0x6f, 0x92, 0x38, 0x31, 0x20,
+    0x45, 0x6d, 0x84, 0x5e, 0xe4, 0xd0, 0x3f, 0x78, 0xab, 0xa9, 0x8f, 0x33,
+    0xa3, 0xc7, 0x74, 0x6f, 0x33, 0x38, 0x17, 0xe8, 0xa9, 0x55, 0xa7, 0x5a,
+    0x51, 0xf1, 0x94, 0xe2, 0xa7, 0x25, 0x06, 0x6d, 0x1c, 0x2b, 0xf8, 0x1c,
+    0xcf, 0xff, 0xab, 0xc0, 0xdc, 0x64, 0xc5, 0x77, 0xcb, 0x3c, 0x8a, 0xac,
+    0x4d, 0x07, 0xc5, 0x4f, 0x7d, 0x64, 0xee, 0x20, 0x30, 0xa9, 0x08, 0x88,
+    0xf1, 0x6c, 0x53, 0x4f, 0x60, 0xe0, 0x46, 0x1e, 0x2d, 0xf9, 0x59, 0xfd,
+    0xd6, 0x52, 0x09, 0x56, 0x19, 0x5c, 0x14, 0x47, 0xd2, 0x9c, 0x8f, 0x59,
+    0x64, 0xde, 0x15, 0xeb, 0xec, 0x60, 0xc4, 0x9f, 0xbc, 0xd3, 0xde, 0x37,
+    0x0a, 0xc0, 0x68, 0xcb, 0xc5, 0x2f, 0x91, 0xf1, 0xb4, 0x33, 0x82, 0x9d,
+    0x1e, 0x33, 0x2e, 0x9d, 0xfe, 0x9a, 0x5f, 0x8a, 0xa9, 0x19, 0x9e, 0x5b,
+    0xdb, 0x2c, 0x9a, 0xcf, 0x99, 0x58, 0x7f, 0x00, 0xdd, 0x85, 0x96, 0xff,
+    0x3e, 0xd0, 0x0a, 0xd2, 0xa3, 0xc5, 0x93, 0xba, 0xa3, 0x8a, 0x6e, 0x9a,
+    0x36, 0xa9, 0x85, 0x89, 0x8a, 0x96, 0x5b, 0x94, 0x0e, 0xc3, 0x02, 0xe2,
+    0x5d, 0x62, 0x8b, 0x2c, 0x55, 0x47, 0xfb, 0x50, 0xde, 0x18, 0x01, 0x03,
+    0xe4, 0xfb, 0xf7, 0x42, 0x22, 0xfb, 0xd4, 0xfd};
diff --git a/src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc b/src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc
index 40bf75b..b3e5644 100644
--- a/src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc
+++ b/src/crypto/fipsmodule/slhdsa/slhdsa.cc.inc
@@ -29,15 +29,23 @@
 #include "thash.h"
 
 
+namespace {
+
+namespace fips {
+void ensure_keygen_self_test();
+void ensure_sign_self_test();
+void ensure_verify_self_test();
+}  // namespace fips
+
 // The OBJECT IDENTIFIER header is also included in these values, per the spec.
-static const uint8_t kSHA256OID[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
-                                     0x65, 0x03, 0x04, 0x02, 0x01};
-static const uint8_t kSHA384OID[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
-                                     0x65, 0x03, 0x04, 0x02, 0x02};
+const uint8_t kSHA256OID[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+                              0x65, 0x03, 0x04, 0x02, 0x01};
+const uint8_t kSHA384OID[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+                              0x65, 0x03, 0x04, 0x02, 0x02};
 #define MAX_OID_LENGTH 11
 #define MAX_CONTEXT_LENGTH 255
 
-bcm_infallible BCM_slhdsa_sha2_128s_generate_key_from_seed(
+bcm_infallible generate_key_from_seed_no_self_test(
     uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
     uint8_t out_secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
     const uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N]) {
@@ -57,30 +65,33 @@
   OPENSSL_memcpy(out_secret_key + 3 * BCM_SLHDSA_SHA2_128S_N,
                  out_public_key + BCM_SLHDSA_SHA2_128S_N,
                  BCM_SLHDSA_SHA2_128S_N);
-  return bcm_infallible::approved;
-}
 
-bcm_infallible BCM_slhdsa_sha2_128s_generate_key(
-    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
-    uint8_t out_private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]) {
-  uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N];
-  RAND_bytes(seed, 3 * BCM_SLHDSA_SHA2_128S_N);
-  BCM_slhdsa_sha2_128s_generate_key_from_seed(out_public_key, out_private_key,
-                                              seed);
-  return bcm_infallible::approved;
-}
+  // FIPS 140-3 IG 10.3.A comment 1 says of the pair-wise consistency test for
+  // SLH-DSA:
+  //
+  // "For key pairs generated for use with approved algorithms in SP 800-208 and
+  // FIPS 205, the PCT (described by the tester in TE10.35.02) may be limited to
+  // confirming the same key identifier (I in the case of LMS, SEED in the case
+  // of XMSS and PK.SEED for SLH-DSA) is shared by the resulting public and
+  // private key following generation."
+  //
+  // Since this is cheap, we always do this.
 
-bcm_infallible BCM_slhdsa_sha2_128s_public_from_private(
-    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
-    const uint8_t private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]) {
-  OPENSSL_memcpy(out_public_key, private_key + 2 * BCM_SLHDSA_SHA2_128S_N,
-                 BCM_SLHDSA_SHA2_128S_N * 2);
-  return bcm_infallible::approved;
+  if (boringssl_fips_break_test("SLHDSA_PWCT")) {
+    out_public_key[0] ^= 1;
+  }
+  if (OPENSSL_memcmp(out_public_key,
+                     out_secret_key + 2 * BCM_SLHDSA_SHA2_128S_N,
+                     BCM_SLHDSA_SHA2_128S_N) != 0) {
+    abort();
+  }
+
+  return bcm_infallible::not_approved;
 }
 
 // Note that this overreads by a byte. This is fine in the context that it's
 // used.
-static uint64_t load_tree_index(const uint8_t in[8]) {
+uint64_t load_tree_index(const uint8_t in[8]) {
   static_assert(SLHDSA_SHA2_128S_TREE_BYTES == 7,
                 "This code needs to be updated");
   uint64_t index = CRYPTO_load_u64_be(in);
@@ -90,7 +101,7 @@
 }
 
 // Implements Algorithm 22: slh_sign function (Section 10.2.1, page 39)
-bcm_infallible BCM_slhdsa_sha2_128s_sign_internal(
+bcm_infallible sign_internal_no_self_test(
     uint8_t out_signature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES],
     const uint8_t secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
     const uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN], const uint8_t *context,
@@ -139,6 +150,189 @@
   return bcm_infallible::approved;
 }
 
+bcm_status verify_internal(
+    const uint8_t *signature, size_t signature_len,
+    const uint8_t public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    const uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN], const uint8_t *context,
+    size_t context_len, const uint8_t *msg, size_t msg_len) {
+  if (signature_len != BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES) {
+    return bcm_status::failure;
+  }
+  const uint8_t *pk_seed = public_key;
+  const uint8_t *pk_root = public_key + BCM_SLHDSA_SHA2_128S_N;
+
+  const uint8_t *r = signature;
+  const uint8_t *sig_fors = signature + BCM_SLHDSA_SHA2_128S_N;
+  const uint8_t *sig_ht = sig_fors + SLHDSA_SHA2_128S_FORS_BYTES;
+
+  uint8_t digest[SLHDSA_SHA2_128S_DIGEST_SIZE];
+  slhdsa_thash_hmsg(digest, r, pk_seed, pk_root, header, context, context_len,
+                    msg, msg_len);
+
+  uint8_t fors_digest[SLHDSA_SHA2_128S_FORS_MSG_BYTES];
+  OPENSSL_memcpy(fors_digest, digest, SLHDSA_SHA2_128S_FORS_MSG_BYTES);
+
+  const uint64_t idx_tree =
+      load_tree_index(digest + SLHDSA_SHA2_128S_FORS_MSG_BYTES);
+  uint32_t idx_leaf = CRYPTO_load_u16_be(
+      digest + SLHDSA_SHA2_128S_FORS_MSG_BYTES + SLHDSA_SHA2_128S_TREE_BYTES);
+  idx_leaf &= (~(uint32_t)0) >> (32 - SLHDSA_SHA2_128S_LEAF_BITS);
+
+  uint8_t addr[32] = {0};
+  slhdsa_set_tree_addr(addr, idx_tree);
+  slhdsa_set_type(addr, SLHDSA_SHA2_128S_ADDR_TYPE_FORSTREE);
+  slhdsa_set_keypair_addr(addr, idx_leaf);
+
+  uint8_t pk_fors[BCM_SLHDSA_SHA2_128S_N];
+  slhdsa_fors_pk_from_sig(pk_fors, sig_fors, fors_digest, pk_seed, addr);
+
+  if (!slhdsa_ht_verify(sig_ht, pk_fors, idx_tree, idx_leaf, pk_root,
+                        pk_seed)) {
+    return bcm_status::failure;
+  }
+
+  return bcm_status::approved;
+}
+
+namespace fips {
+
+#include "fips_known_values.inc"
+
+static int keygen_self_test() {
+  uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N] = {0};
+  uint8_t pub[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES];
+  uint8_t priv[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES];
+  generate_key_from_seed_no_self_test(pub, priv, seed);
+
+  static_assert(sizeof(kExpectedPublicKey) == sizeof(pub));
+  static_assert(sizeof(kExpectedPrivateKey) == sizeof(priv));
+  if (!BORINGSSL_check_test(kExpectedPublicKey, pub, sizeof(pub),
+                            "SLH-DSA public key") ||
+      !BORINGSSL_check_test(kExpectedPrivateKey, priv, sizeof(priv),
+                            "SLH-DSA private key")) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int sign_self_test() {
+  uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN] = {0};
+  uint8_t entropy[BCM_SLHDSA_SHA2_128S_N] = {0};
+  uint8_t sig[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES];
+  sign_internal_no_self_test(sig, kExpectedPrivateKey, header, nullptr, 0,
+                             nullptr, 0, entropy);
+  uint8_t digest[32];
+  SHA256(sig, sizeof(sig), digest);
+
+  static_assert(sizeof(kExpectedSignatureSHA256) == sizeof(digest));
+  if (!BORINGSSL_check_test(kExpectedSignatureSHA256, digest, sizeof(digest),
+                            "SLH-DSA signature")) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int verify_self_test() {
+  uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN] = {0};
+  return verify_internal(kExpectedSignature, sizeof(kExpectedSignature),
+                         kExpectedPublicKey, header, nullptr, 0, nullptr,
+                         0) == bcm_status::approved;
+}
+
+#if defined(BORINGSSL_FIPS)
+
+DEFINE_STATIC_ONCE(g_slhdsa_keygen_self_test_once)
+
+void ensure_keygen_self_test(void) {
+  CRYPTO_once(g_slhdsa_keygen_self_test_once_bss_get(), []() {
+    if (!keygen_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_slhdsa_sign_self_test_once)
+
+void ensure_sign_self_test(void) {
+  CRYPTO_once(g_slhdsa_sign_self_test_once_bss_get(), []() {
+    if (!sign_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+DEFINE_STATIC_ONCE(g_slhdsa_verify_self_test_once)
+
+void ensure_verify_self_test(void) {
+  CRYPTO_once(g_slhdsa_verify_self_test_once_bss_get(), []() {
+    if (!verify_self_test()) {
+      BORINGSSL_FIPS_abort();
+    }
+  });
+}
+
+#else
+
+void ensure_keygen_self_test(void) {}
+void ensure_sign_self_test(void) {}
+void ensure_verify_self_test(void) {}
+
+#endif
+
+}  // namespace fips
+
+}  // namespace
+
+bcm_infallible BCM_slhdsa_sha2_128s_generate_key_from_seed(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
+    const uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N]) {
+  fips::ensure_keygen_self_test();
+  return generate_key_from_seed_no_self_test(out_public_key, out_secret_key,
+                                             seed);
+}
+
+bcm_status BCM_slhdsa_sha2_128s_generate_key_from_seed_fips(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
+    const uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N]) {
+  if (out_public_key == nullptr || out_secret_key == nullptr) {
+    return bcm_status::failure;
+  }
+  BCM_slhdsa_sha2_128s_generate_key_from_seed(out_public_key, out_secret_key,
+                                              seed);
+  return bcm_status::approved;
+}
+
+bcm_infallible BCM_slhdsa_sha2_128s_generate_key(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]) {
+  uint8_t seed[3 * BCM_SLHDSA_SHA2_128S_N];
+  RAND_bytes(seed, 3 * BCM_SLHDSA_SHA2_128S_N);
+  return BCM_slhdsa_sha2_128s_generate_key_from_seed(out_public_key,
+                                                     out_private_key, seed);
+}
+
+bcm_status BCM_slhdsa_sha2_128s_generate_key_fips(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    uint8_t out_private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]) {
+  if (out_public_key == nullptr || out_private_key == nullptr) {
+    return bcm_status::failure;
+  }
+  BCM_slhdsa_sha2_128s_generate_key(out_public_key, out_private_key);
+  return bcm_status::approved;
+}
+
+bcm_infallible BCM_slhdsa_sha2_128s_public_from_private(
+    uint8_t out_public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
+    const uint8_t private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES]) {
+  OPENSSL_memcpy(out_public_key, private_key + 2 * BCM_SLHDSA_SHA2_128S_N,
+                 BCM_SLHDSA_SHA2_128S_N * 2);
+  return bcm_infallible::approved;
+}
+
 bcm_status BCM_slhdsa_sha2_128s_sign(
     uint8_t out_signature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES],
     const uint8_t private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
@@ -208,6 +402,16 @@
   return 1;
 }
 
+bcm_infallible BCM_slhdsa_sha2_128s_sign_internal(
+    uint8_t out_signature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES],
+    const uint8_t secret_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES],
+    const uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN], const uint8_t *context,
+    size_t context_len, const uint8_t *msg, size_t msg_len,
+    const uint8_t entropy[BCM_SLHDSA_SHA2_128S_N]) {
+  fips::ensure_sign_self_test();
+  return sign_internal_no_self_test(out_signature, secret_key, header, context,
+                                    context_len, msg, msg_len, entropy);
+}
 
 bcm_status BCM_slhdsa_sha2_128s_prehash_sign(
     uint8_t out_signature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES],
@@ -289,41 +493,12 @@
     const uint8_t public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES],
     const uint8_t header[BCM_SLHDSA_M_PRIME_HEADER_LEN], const uint8_t *context,
     size_t context_len, const uint8_t *msg, size_t msg_len) {
-  if (signature_len != BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES) {
-    return bcm_status::failure;
-  }
-  const uint8_t *pk_seed = public_key;
-  const uint8_t *pk_root = public_key + BCM_SLHDSA_SHA2_128S_N;
+  fips::ensure_verify_self_test();
+  return verify_internal(signature, signature_len, public_key, header, context,
+                         context_len, msg, msg_len);
+}
 
-  const uint8_t *r = signature;
-  const uint8_t *sig_fors = signature + BCM_SLHDSA_SHA2_128S_N;
-  const uint8_t *sig_ht = sig_fors + SLHDSA_SHA2_128S_FORS_BYTES;
-
-  uint8_t digest[SLHDSA_SHA2_128S_DIGEST_SIZE];
-  slhdsa_thash_hmsg(digest, r, pk_seed, pk_root, header, context, context_len,
-                    msg, msg_len);
-
-  uint8_t fors_digest[SLHDSA_SHA2_128S_FORS_MSG_BYTES];
-  OPENSSL_memcpy(fors_digest, digest, SLHDSA_SHA2_128S_FORS_MSG_BYTES);
-
-  const uint64_t idx_tree =
-      load_tree_index(digest + SLHDSA_SHA2_128S_FORS_MSG_BYTES);
-  uint32_t idx_leaf = CRYPTO_load_u16_be(
-      digest + SLHDSA_SHA2_128S_FORS_MSG_BYTES + SLHDSA_SHA2_128S_TREE_BYTES);
-  idx_leaf &= (~(uint32_t)0) >> (32 - SLHDSA_SHA2_128S_LEAF_BITS);
-
-  uint8_t addr[32] = {0};
-  slhdsa_set_tree_addr(addr, idx_tree);
-  slhdsa_set_type(addr, SLHDSA_SHA2_128S_ADDR_TYPE_FORSTREE);
-  slhdsa_set_keypair_addr(addr, idx_leaf);
-
-  uint8_t pk_fors[BCM_SLHDSA_SHA2_128S_N];
-  slhdsa_fors_pk_from_sig(pk_fors, sig_fors, fors_digest, pk_seed, addr);
-
-  if (!slhdsa_ht_verify(sig_ht, pk_fors, idx_tree, idx_leaf, pk_root,
-                        pk_seed)) {
-    return bcm_status::failure;
-  }
-
-  return bcm_status::approved;
+int boringssl_self_test_slhdsa() {
+  return fips::keygen_self_test() && fips::sign_self_test() &&
+         fips::verify_self_test();
 }
diff --git a/src/crypto/fuzzer_mode.cc b/src/crypto/fuzzer_mode.cc
new file mode 100644
index 0000000..e741552
--- /dev/null
+++ b/src/crypto/fuzzer_mode.cc
@@ -0,0 +1,30 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/crypto.h>
+
+#include "internal.h"
+
+
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+static CRYPTO_atomic_u32 fuzzer_mode_enabled = 0;
+
+int CRYPTO_fuzzer_mode_enabled(void) {
+  return CRYPTO_atomic_load_u32(&fuzzer_mode_enabled);
+}
+
+void CRYPTO_set_fuzzer_mode(int enabled) {
+  CRYPTO_atomic_store_u32(&fuzzer_mode_enabled, !!enabled);
+}
+#endif  // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
diff --git a/src/crypto/hrss/asm/poly_rq_mul.S b/src/crypto/hrss/asm/poly_rq_mul.S
index 2b99d0e..abbc4e3 100644
--- a/src/crypto/hrss/asm/poly_rq_mul.S
+++ b/src/crypto/hrss/asm/poly_rq_mul.S
@@ -8475,6 +8475,7 @@
 vpaddw 2752(%r8), %ymm11, %ymm11
 vpand mask_mod8192(%rip), %ymm11, %ymm11
 vmovdqu %ymm11, 1320(%rdi)
+vzeroupper
 pop %r12
 .cfi_restore r12
 pop %rbp
diff --git a/src/crypto/hrss/internal.h b/src/crypto/hrss/internal.h
index 44066cf..ab7ebc8 100644
--- a/src/crypto/hrss/internal.h
+++ b/src/crypto/hrss/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_HRSS_INTERNAL_H
-#define OPENSSL_HEADER_HRSS_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_HRSS_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_HRSS_INTERNAL_H
 
 #include <openssl/base.h>
 #include "../internal.h"
@@ -65,4 +65,4 @@
 }  // extern "C"
 #endif
 
-#endif  // !OPENSSL_HEADER_HRSS_INTERNAL_H
+#endif  // !OPENSSL_HEADER_CRYPTO_HRSS_INTERNAL_H
diff --git a/src/crypto/impl_dispatch_test.cc b/src/crypto/impl_dispatch_test.cc
index 7172a3c..070cc91 100644
--- a/src/crypto/impl_dispatch_test.cc
+++ b/src/crypto/impl_dispatch_test.cc
@@ -38,8 +38,8 @@
     ssse3_ = CRYPTO_is_SSSE3_capable();
     vaes_ = CRYPTO_is_VAES_capable() && CRYPTO_is_VPCLMULQDQ_capable() &&
             CRYPTO_is_AVX2_capable();
-    avx10_ = CRYPTO_is_AVX512BW_capable() && CRYPTO_is_AVX512VL_capable() &&
-             CRYPTO_is_BMI2_capable();
+    avx512_ = CRYPTO_is_AVX512BW_capable() && CRYPTO_is_AVX512VL_capable() &&
+              CRYPTO_is_BMI2_capable();
     avoid_zmm_ = CRYPTO_cpu_avoid_zmm_registers();
     is_x86_64_ =
 #if defined(OPENSSL_X86_64)
@@ -81,7 +81,7 @@
   bool ssse3_ = false;
   bool is_x86_64_ = false;
   bool vaes_ = false;
-  bool avx10_ = false;
+  bool avx512_ = false;
   bool avoid_zmm_ = false;
 #endif
 };
@@ -95,8 +95,8 @@
 constexpr size_t kFlag_aes_hw_set_encrypt_key = 3;
 constexpr size_t kFlag_vpaes_encrypt = 4;
 constexpr size_t kFlag_vpaes_set_encrypt_key = 5;
-constexpr size_t kFlag_aes_gcm_enc_update_vaes_avx10_512 = 7;
-constexpr size_t kFlag_aes_gcm_enc_update_vaes_avx2 = 8;
+constexpr size_t kFlag_aes_gcm_enc_update_vaes_avx2 = 6;
+constexpr size_t kFlag_aes_gcm_enc_update_vaes_avx512 = 7;
 
 TEST_F(ImplDispatchTest, AEAD_AES_GCM) {
   AssertFunctionsHit(
@@ -108,10 +108,10 @@
            is_x86_64_ && aesni_ && avx_movbe_ && !vaes_},
           {kFlag_vpaes_encrypt, ssse3_ && !aesni_},
           {kFlag_vpaes_set_encrypt_key, ssse3_ && !aesni_},
-          {kFlag_aes_gcm_enc_update_vaes_avx10_512,
-           is_x86_64_ && vaes_ && avx10_ && !avoid_zmm_},
           {kFlag_aes_gcm_enc_update_vaes_avx2,
-           is_x86_64_ && vaes_ && !(avx10_ && !avoid_zmm_)},
+           is_x86_64_ && vaes_ && !(avx512_ && !avoid_zmm_)},
+          {kFlag_aes_gcm_enc_update_vaes_avx512,
+           is_x86_64_ && vaes_ && avx512_ && !avoid_zmm_},
       },
       [] {
         const uint8_t kZeros[16] = {0};
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 4b14217..2f8c746 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -21,6 +21,7 @@
 #include <openssl/thread.h>
 
 #include <assert.h>
+#include <stdlib.h>
 #include <string.h>
 
 #if defined(BORINGSSL_CONSTANT_TIME_VALIDATION)
@@ -47,9 +48,7 @@
 #endif
 
 #if defined(OPENSSL_WINDOWS_THREADS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #if defined(__cplusplus)
@@ -104,12 +103,6 @@
 
 #define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
 
-#if defined(__clang__) && __clang_major__ >= 5
-#if __has_attribute(fallthrough)
-#define OPENSSL_CAN_USE_ATTR_FALLTHROUGH
-#endif
-#endif
-
 // GCC-like compilers indicate SSE2 with |__SSE2__|. MSVC leaves the caller to
 // know that x86_64 has SSE2, and uses _M_IX86_FP to indicate SSE2 on x86.
 // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
@@ -610,8 +603,7 @@
 typedef struct crypto_mutex_st {
   char padding;  // Empty structs have different sizes in C and C++.
 } CRYPTO_MUTEX;
-#define CRYPTO_MUTEX_INIT \
-  { 0 }
+#define CRYPTO_MUTEX_INIT {0}
 #elif defined(OPENSSL_WINDOWS_THREADS)
 typedef SRWLOCK CRYPTO_MUTEX;
 #define CRYPTO_MUTEX_INIT SRWLOCK_INIT
@@ -676,7 +668,7 @@
 
 BSSL_NAMESPACE_END
 
-}       // extern "C++"
+}  // extern "C++"
 #endif  // defined(__cplusplus)
 
 
@@ -740,10 +732,9 @@
   uint8_t num_reserved;
 } CRYPTO_EX_DATA_CLASS;
 
-#define CRYPTO_EX_DATA_CLASS_INIT \
-  { CRYPTO_MUTEX_INIT, NULL, NULL, {}, 0 }
+#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_MUTEX_INIT, NULL, NULL, {}, 0}
 #define CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA \
-  { CRYPTO_MUTEX_INIT, NULL, NULL, {}, 1 }
+  {CRYPTO_MUTEX_INIT, NULL, NULL, {}, 1}
 
 // CRYPTO_get_ex_new_index_ex allocates a new index for |ex_data_class|. Each
 // class of object should provide a wrapper function that uses the correct
@@ -785,9 +776,6 @@
   return __builtin_bswap64(x);
 }
 #elif defined(_MSC_VER)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
-#include <stdlib.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #pragma intrinsic(_byteswap_uint64, _byteswap_ulong, _byteswap_ushort)
 static inline uint16_t CRYPTO_bswap2(uint16_t x) { return _byteswap_ushort(x); }
 
@@ -842,7 +830,7 @@
   return memchr(s, c, n);
 }
 
-}      // extern "C++"
+}  // extern "C++"
 #else  // __cplusplus
 
 static inline void *OPENSSL_memchr(const void *s, int c, size_t n) {
@@ -1048,6 +1036,12 @@
 
 #endif  // FIPS
 
+// BORINGSSL_check_test memcmp's two values of equal length. It returns 1 on
+// success and, on failure, it prints an error message that includes the
+// hexdumps the two values and returns 0.
+int BORINGSSL_check_test(const void *expected, const void *actual,
+                         size_t expected_len, const char *name);
+
 // boringssl_self_test_sha256 performs a SHA-256 KAT.
 int boringssl_self_test_sha256(void);
 
@@ -1057,6 +1051,15 @@
 // boringssl_self_test_hmac_sha256 performs an HMAC-SHA-256 KAT.
 int boringssl_self_test_hmac_sha256(void);
 
+// boringssl_self_test_mlkem performs the ML-KEM KATs.
+OPENSSL_EXPORT int boringssl_self_test_mlkem(void);
+
+// boringssl_self_test_mldsa performs the ML-DSA KATs.
+OPENSSL_EXPORT int boringssl_self_test_mldsa(void);
+
+// boringssl_self_test_slhdsa performs the SLH-DSA KATs.
+OPENSSL_EXPORT int boringssl_self_test_slhdsa(void);
+
 #if defined(BORINGSSL_FIPS_COUNTERS)
 void boringssl_fips_inc_counter(enum fips_counter_t counter);
 #else
@@ -1105,14 +1108,6 @@
 
 // See Intel manual, volume 2A, table 3-11.
 
-inline int CRYPTO_is_FXSR_capable(void) {
-#if defined(__FXSR__)
-  return 1;
-#else
-  return (OPENSSL_get_ia32cap(0) & (1u << 24)) != 0;
-#endif
-}
-
 inline int CRYPTO_is_intel_cpu(void) {
   // The reserved bit 30 is used to indicate an Intel CPU.
   return (OPENSSL_get_ia32cap(0) & (1u << 30)) != 0;
@@ -1399,6 +1394,7 @@
 
 #endif  // OPENSSL_ARM || OPENSSL_AARCH64
 
+
 #if defined(BORINGSSL_DISPATCH_TEST)
 // Runtime CPU dispatch testing support
 
@@ -1410,12 +1406,12 @@
 //   3: aes_hw_set_encrypt_key
 //   4: vpaes_encrypt
 //   5: vpaes_set_encrypt_key
-//   6: aes_gcm_enc_update_vaes_avx10_256 [reserved]
-//   7: aes_gcm_enc_update_vaes_avx10_512
-//   8: aes_gcm_enc_update_vaes_avx2
-extern uint8_t BORINGSSL_function_hit[9];
+//   6: aes_gcm_enc_update_vaes_avx2
+//   7: aes_gcm_enc_update_vaes_avx512
+extern uint8_t BORINGSSL_function_hit[8];
 #endif  // BORINGSSL_DISPATCH_TEST
 
+
 // OPENSSL_vasprintf_internal is just like |vasprintf(3)|. If |system_malloc| is
 // 0, memory will be allocated with |OPENSSL_malloc| and must be freed with
 // |OPENSSL_free|. Otherwise the system |malloc| function is used and the memory
@@ -1424,6 +1420,19 @@
                                               va_list args, int system_malloc)
     OPENSSL_PRINTF_FORMAT_FUNC(2, 0);
 
+
+// Fuzzer mode.
+
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+// CRYPTO_fuzzer_mode_enabled returns whether fuzzer mode is enabled. See
+// |CRYPTO_set_fuzzer_mode|. In non-fuzzer builds, this function statically
+// returns zero so the codepaths will be deleted by the optimizer.
+int CRYPTO_fuzzer_mode_enabled(void);
+#else
+inline int CRYPTO_fuzzer_mode_enabled(void) { return 0; }
+#endif
+
+
 #if defined(__cplusplus)
 }  // extern C
 #endif
diff --git a/src/crypto/lhash/internal.h b/src/crypto/lhash/internal.h
index 9208d58..cb09dfa 100644
--- a/src/crypto/lhash/internal.h
+++ b/src/crypto/lhash/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_LHASH_INTERNAL_H
-#define OPENSSL_HEADER_LHASH_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H
 
 #include <openssl/lhash.h>
 
@@ -218,4 +218,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_LHASH_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H
diff --git a/src/crypto/md5/internal.h b/src/crypto/md5/internal.h
index 501b389..5d38e3e 100644
--- a/src/crypto/md5/internal.h
+++ b/src/crypto/md5/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_MD5_INTERNAL_H
-#define OPENSSL_HEADER_MD5_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_MD5_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_MD5_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -34,4 +34,4 @@
 }  // extern "C"
 #endif
 
-#endif  // OPENSSL_HEADER_MD5_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_MD5_INTERNAL_H
diff --git a/src/crypto/mem.cc b/src/crypto/mem.cc
index aed60a8..83a1af7 100644
--- a/src/crypto/mem.cc
+++ b/src/crypto/mem.cc
@@ -24,9 +24,7 @@
 #include <openssl/err.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #if defined(BORINGSSL_MALLOC_FAILURE_TESTING)
diff --git a/src/crypto/mldsa/mldsa_test.cc b/src/crypto/mldsa/mldsa_test.cc
index 6d66fc6..112b444 100644
--- a/src/crypto/mldsa/mldsa_test.cc
+++ b/src/crypto/mldsa/mldsa_test.cc
@@ -515,7 +515,6 @@
   }
 }
 
-
 TEST(MLDSATest, WycheproofVerifyTests65) {
   FileTestGTest(
       "third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt",
@@ -532,4 +531,34 @@
           BCM_mldsa87_parse_public_key, BCM_mldsa87_verify>);
 }
 
+TEST(MLDSATest, Self) { ASSERT_TRUE(boringssl_self_test_mldsa()); }
+
+TEST(MLDSATest, PWCT) {
+  uint8_t seed[BCM_MLDSA_SEED_BYTES];
+
+  auto pub65 = std::make_unique<uint8_t[]>(BCM_MLDSA65_PUBLIC_KEY_BYTES);
+  auto priv65 = std::make_unique<BCM_mldsa65_private_key>();
+  ASSERT_EQ(BCM_mldsa65_generate_key_fips(pub65.get(), seed, priv65.get()),
+            bcm_status::approved);
+
+  auto pub87 = std::make_unique<uint8_t[]>(BCM_MLDSA87_PUBLIC_KEY_BYTES);
+  auto priv87 = std::make_unique<BCM_mldsa87_private_key>();
+  ASSERT_EQ(BCM_mldsa87_generate_key_fips(pub87.get(), seed, priv87.get()),
+            bcm_status::approved);
+}
+
+TEST(MLDSATest, NullptrArgumentsToCreate) {
+  // For FIPS reasons, this should fail rather than crash.
+  ASSERT_EQ(BCM_mldsa65_generate_key_fips(nullptr, nullptr, nullptr),
+            bcm_status::failure);
+  ASSERT_EQ(BCM_mldsa87_generate_key_fips(nullptr, nullptr, nullptr),
+            bcm_status::failure);
+  ASSERT_EQ(
+      BCM_mldsa65_generate_key_external_entropy_fips(nullptr, nullptr, nullptr),
+      bcm_status::failure);
+  ASSERT_EQ(
+      BCM_mldsa87_generate_key_external_entropy_fips(nullptr, nullptr, nullptr),
+      bcm_status::failure);
+}
+
 }  // namespace
diff --git a/src/crypto/mlkem/mlkem_test.cc b/src/crypto/mlkem/mlkem_test.cc
index 0d8baaa..5b4d686 100644
--- a/src/crypto/mlkem/mlkem_test.cc
+++ b/src/crypto/mlkem/mlkem_test.cc
@@ -527,4 +527,29 @@
       0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5};
   EXPECT_EQ(Bytes(result), Bytes(kExpected));
 }
+
+TEST(MLKEMTest, Self) { ASSERT_TRUE(boringssl_self_test_mlkem()); }
+
+TEST(MLKEMTest, PWCT) {
+  auto pub768 = std::make_unique<uint8_t[]>(BCM_MLKEM768_PUBLIC_KEY_BYTES);
+  auto priv768 = std::make_unique<BCM_mlkem768_private_key>();
+  ASSERT_EQ(
+      BCM_mlkem768_generate_key_fips(pub768.get(), nullptr, priv768.get()),
+      bcm_status::approved);
+
+  auto pub1024 = std::make_unique<uint8_t[]>(BCM_MLKEM1024_PUBLIC_KEY_BYTES);
+  auto priv1024 = std::make_unique<BCM_mlkem1024_private_key>();
+  ASSERT_EQ(
+      BCM_mlkem1024_generate_key_fips(pub1024.get(), nullptr, priv1024.get()),
+      bcm_status::approved);
+}
+
+TEST(MLKEMTest, NullptrArgumentsToCreate) {
+  // For FIPS reasons, this should fail rather than crash.
+  ASSERT_EQ(BCM_mlkem768_generate_key_fips(nullptr, nullptr, nullptr),
+            bcm_status::failure);
+  ASSERT_EQ(BCM_mlkem1024_generate_key_fips(nullptr, nullptr, nullptr),
+            bcm_status::failure);
+}
+
 }  // namespace
diff --git a/src/crypto/obj/obj.cc b/src/crypto/obj/obj.cc
index ffc12ff..9fa26bb 100644
--- a/src/crypto/obj/obj.cc
+++ b/src/crypto/obj/obj.cc
@@ -278,14 +278,8 @@
 
 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
-  CBB oid;
-
-  if (obj == NULL || !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, obj->data, obj->length) || !CBB_flush(out)) {
-    return 0;
-  }
-
-  return 1;
+  return obj != NULL &&
+         CBB_add_asn1_element(out, CBS_ASN1_OBJECT, obj->data, obj->length);
 }
 
 const ASN1_OBJECT *OBJ_get_undef(void) {
diff --git a/src/crypto/pem/internal.h b/src/crypto/pem/internal.h
index bda89a6..3178c11 100644
--- a/src/crypto/pem/internal.h
+++ b/src/crypto/pem/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_PEM_INTERNAL_H
-#define OPENSSL_HEADER_PEM_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_PEM_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_PEM_INTERNAL_H
 
 #include <openssl/pem.h>
 
@@ -41,4 +41,4 @@
 }  // extern "C"
 #endif
 
-#endif  // OPENSSL_HEADER_PEM_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_PEM_INTERNAL_H
diff --git a/src/crypto/pem/pem_lib.cc b/src/crypto/pem/pem_lib.cc
index 854af77..7679aa0 100644
--- a/src/crypto/pem/pem_lib.cc
+++ b/src/crypto/pem/pem_lib.cc
@@ -239,7 +239,7 @@
 int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
                        const EVP_CIPHER *enc, const unsigned char *pass,
                        int pass_len, pem_password_cb *callback, void *u) {
-  EVP_CIPHER_CTX ctx;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
   int dsize = 0, i, j, ret = 0;
   unsigned char *p, *data = NULL;
   const char *objstr = NULL;
@@ -305,16 +305,14 @@
     PEM_dek_info(buf, objstr, iv_len, (char *)iv);
     // k=strlen(buf);
 
-    EVP_CIPHER_CTX_init(&ctx);
     ret = 1;
-    if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) ||
-        !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
-        !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) {
+    if (!EVP_EncryptInit_ex(ctx.get(), enc, NULL, key, iv) ||
+        !EVP_EncryptUpdate(ctx.get(), data, &j, data, i) ||
+        !EVP_EncryptFinal_ex(ctx.get(), &(data[j]), &i)) {
       ret = 0;
     } else {
       i += j;
     }
-    EVP_CIPHER_CTX_cleanup(&ctx);
     if (ret == 0) {
       goto err;
     }
@@ -329,7 +327,6 @@
 err:
   OPENSSL_cleanse(key, sizeof(key));
   OPENSSL_cleanse(iv, sizeof(iv));
-  OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
   OPENSSL_cleanse(buf, PEM_BUFSIZE);
   OPENSSL_free(data);
   return ret;
@@ -339,7 +336,7 @@
                   long *plen, pem_password_cb *callback, void *u) {
   int i = 0, j, o, pass_len;
   long len;
-  EVP_CIPHER_CTX ctx;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
   unsigned char key[EVP_MAX_KEY_LENGTH];
   char buf[PEM_BUFSIZE];
 
@@ -365,15 +362,13 @@
   }
 
   j = (int)len;
-  EVP_CIPHER_CTX_init(&ctx);
-  o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, cipher->iv);
+  o = EVP_DecryptInit_ex(ctx.get(), cipher->cipher, NULL, key, cipher->iv);
   if (o) {
-    o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
+    o = EVP_DecryptUpdate(ctx.get(), data, &i, data, j);
   }
   if (o) {
-    o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
+    o = EVP_DecryptFinal_ex(ctx.get(), &(data[i]), &j);
   }
-  EVP_CIPHER_CTX_cleanup(&ctx);
   OPENSSL_cleanse((char *)buf, sizeof(buf));
   OPENSSL_cleanse((char *)key, sizeof(key));
   if (!o) {
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index a0bade3..0955c86 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -127,7 +127,7 @@
 	    if ($self->{op} =~ /^(movz)x?([bw]).*/) {	# movz is pain...
 		$self->{op} = $1;
 		$self->{sz} = $2;
-	    } elsif ($self->{op} =~ /call|jmp/) {
+	    } elsif ($self->{op} =~ /call|jmp|^rdrand$/) {
 		$self->{sz} = "";
 	    } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn
 		$self->{sz} = "";
@@ -1319,198 +1319,6 @@
     }
 }
 
-# Upon initial x86_64 introduction SSE>2 extensions were not introduced
-# yet. In order not to be bothered by tracing exact assembler versions,
-# but at the same time to provide a bare security minimum of AES-NI, we
-# hard-code some instructions. Extensions past AES-NI on the other hand
-# are traced by examining assembler version in individual perlasm
-# modules...
-
-my %regrm = (	"%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
-		"%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7	);
-
-sub rex {
- my $opcode=shift;
- my ($dst,$src,$rex)=@_;
-
-   $rex|=0x04 if($dst>=8);
-   $rex|=0x01 if($src>=8);
-   push @$opcode,($rex|0x40) if ($rex);
-}
-
-my $movq = sub {	# elderly gas can't handle inter-register movq
-  my $arg = shift;
-  my @opcode=(0x66);
-    if ($arg =~ /%xmm([0-9]+),\s*%r(\w+)/) {
-	my ($src,$dst)=($1,$2);
-	if ($dst !~ /[0-9]+/)	{ $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,$src,$dst,0x8);
-	push @opcode,0x0f,0x7e;
-	push @opcode,0xc0|(($src&7)<<3)|($dst&7);	# ModR/M
-	@opcode;
-    } elsif ($arg =~ /%r(\w+),\s*%xmm([0-9]+)/) {
-	my ($src,$dst)=($2,$1);
-	if ($dst !~ /[0-9]+/)	{ $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,$src,$dst,0x8);
-	push @opcode,0x0f,0x6e;
-	push @opcode,0xc0|(($src&7)<<3)|($dst&7);	# ModR/M
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $pextrd = sub {
-    if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*(%\w+)/) {
-      my @opcode=(0x66);
-	my $imm=$1;
-	my $src=$2;
-	my $dst=$3;
-	if ($dst =~ /%r([0-9]+)d/)	{ $dst = $1; }
-	elsif ($dst =~ /%e/)		{ $dst = $regrm{$dst}; }
-	rex(\@opcode,$src,$dst);
-	push @opcode,0x0f,0x3a,0x16;
-	push @opcode,0xc0|(($src&7)<<3)|($dst&7);	# ModR/M
-	push @opcode,$imm;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $pinsrd = sub {
-    if (shift =~ /\$([0-9]+),\s*(%\w+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x66);
-	my $imm=$1;
-	my $src=$2;
-	my $dst=$3;
-	if ($src =~ /%r([0-9]+)/)	{ $src = $1; }
-	elsif ($src =~ /%e/)		{ $src = $regrm{$src}; }
-	rex(\@opcode,$dst,$src);
-	push @opcode,0x0f,0x3a,0x22;
-	push @opcode,0xc0|(($dst&7)<<3)|($src&7);	# ModR/M
-	push @opcode,$imm;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $pshufb = sub {
-    if (shift =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x66);
-	rex(\@opcode,$2,$1);
-	push @opcode,0x0f,0x38,0x00;
-	push @opcode,0xc0|($1&7)|(($2&7)<<3);		# ModR/M
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $palignr = sub {
-    if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x66);
-	rex(\@opcode,$3,$2);
-	push @opcode,0x0f,0x3a,0x0f;
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);		# ModR/M
-	push @opcode,$1;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $pclmulqdq = sub {
-    if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x66);
-	rex(\@opcode,$3,$2);
-	push @opcode,0x0f,0x3a,0x44;
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);		# ModR/M
-	my $c=$1;
-	push @opcode,$c=~/^0/?oct($c):$c;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $rdrand = sub {
-    if (shift =~ /%[er](\w+)/) {
-      my @opcode=();
-      my $dst=$1;
-	if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,0,$dst,8);
-	push @opcode,0x0f,0xc7,0xf0|($dst&7);
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $rdseed = sub {
-    if (shift =~ /%[er](\w+)/) {
-      my @opcode=();
-      my $dst=$1;
-	if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,0,$dst,8);
-	push @opcode,0x0f,0xc7,0xf8|($dst&7);
-	@opcode;
-    } else {
-	();
-    }
-};
-
-# Not all AVX-capable assemblers recognize AMD XOP extension. Since we
-# are using only two instructions hand-code them in order to be excused
-# from chasing assembler versions...
-
-sub rxb {
- my $opcode=shift;
- my ($dst,$src1,$src2,$rxb)=@_;
-
-   $rxb|=0x7<<5;
-   $rxb&=~(0x04<<5) if($dst>=8);
-   $rxb&=~(0x01<<5) if($src1>=8);
-   $rxb&=~(0x02<<5) if($src2>=8);
-   push @$opcode,$rxb;
-}
-
-my $vprotd = sub {
-    if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x8f);
-	rxb(\@opcode,$3,$2,-1,0x08);
-	push @opcode,0x78,0xc2;
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);		# ModR/M
-	my $c=$1;
-	push @opcode,$c=~/^0/?oct($c):$c;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-my $vprotq = sub {
-    if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
-      my @opcode=(0x8f);
-	rxb(\@opcode,$3,$2,-1,0x08);
-	push @opcode,0x78,0xc3;
-	push @opcode,0xc0|($2&7)|(($3&7)<<3);		# ModR/M
-	my $c=$1;
-	push @opcode,$c=~/^0/?oct($c):$c;
-	@opcode;
-    } else {
-	();
-    }
-};
-
-# Intel Control-flow Enforcement Technology extension. All functions and
-# indirect branch targets will have to start with this instruction...
-
-my $endbranch = sub {
-    (0xf3,0x0f,0x1e,0xfa);
-};
-
 ########################################################################
 
 {
diff --git a/src/crypto/pkcs7/internal.h b/src/crypto/pkcs7/internal.h
index 7505e33..e6cc8b5 100644
--- a/src/crypto/pkcs7/internal.h
+++ b/src/crypto/pkcs7/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_PKCS7_INTERNAL_H
-#define OPENSSL_HEADER_PKCS7_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_PKCS7_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_PKCS7_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -36,6 +36,8 @@
 // doing so it makes callbacks to let the caller fill in parts of the structure.
 // All callbacks are ignored if NULL and return one on success or zero on error.
 //
+//   signed_data_version: version number of the SignedData structure. In PKCS#7,
+//       it is always 1. In CMS, it depends on the features used.
 //   digest_algos_cb: may write AlgorithmIdentifiers into the given CBB, which
 //       is a SET of digest algorithms.
 //   cert_crl_cb: may write the |certificates| or |crls| fields.
@@ -44,15 +46,27 @@
 //       (See https://datatracker.ietf.org/doc/html/rfc2315#section-9.1)
 //
 // pkcs7_add_signed_data returns one on success or zero on error.
-int pkcs7_add_signed_data(CBB *out,
-                          int (*digest_algos_cb)(CBB *out, const void *arg),
-                          int (*cert_crl_cb)(CBB *out, const void *arg),
-                          int (*signer_infos_cb)(CBB *out, const void *arg),
-                          const void *arg);
+int pkcs7_add_signed_data(CBB *out, uint64_t signed_data_version,
+                          int (*digest_algos_cb)(CBB *out, void *arg),
+                          int (*cert_crl_cb)(CBB *out, void *arg),
+                          int (*signer_infos_cb)(CBB *out, void *arg),
+                          void *arg);
+
+// pkcs7_add_external_signature writes a PKCS#7 or CMS SignedData structure to
+// |out|, containing an external (i.e. the contents are not included) signature,
+// using |sign_cert| and |key| to sign the contents of |data| with |md|. If
+// |use_key_id| is true (CMS-only), the SignerInfo specifies the signer with key
+// identifier. Otherwise, it uses issuer and serial number (PKCS#7 or CMS v1).
+// The SignedData will have no embedded certificates and no attributes.
+//
+// Note: CMS v1 and PKCS#7 v1.5 are not completely compatible, but they overlap
+// in all cases implemented by this function.
+int pkcs7_add_external_signature(CBB *out, X509 *sign_cert, EVP_PKEY *key,
+                                 const EVP_MD *md, BIO *data, bool use_key_id);
 
 
 #if defined(__cplusplus)
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_PKCS7_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_PKCS7_INTERNAL_H
diff --git a/src/crypto/pkcs7/pkcs7.cc b/src/crypto/pkcs7/pkcs7.cc
index 4d6c05f..aa92cc1 100644
--- a/src/crypto/pkcs7/pkcs7.cc
+++ b/src/crypto/pkcs7/pkcs7.cc
@@ -130,7 +130,7 @@
   return ret;
 }
 
-static int pkcs7_bundle_raw_certificates_cb(CBB *out, const void *arg) {
+static int pkcs7_bundle_raw_certificates_cb(CBB *out, void *arg) {
   const STACK_OF(CRYPTO_BUFFER) *certs =
       reinterpret_cast<const STACK_OF(CRYPTO_BUFFER) *>(arg);
   CBB certificates;
@@ -155,37 +155,39 @@
 
 int PKCS7_bundle_raw_certificates(CBB *out,
                                   const STACK_OF(CRYPTO_BUFFER) *certs) {
-  return pkcs7_add_signed_data(out, /*digest_algos_cb=*/NULL,
+  return pkcs7_add_signed_data(out, /*signed_data_version=*/1,
+                               /*digest_algos_cb=*/nullptr,
                                pkcs7_bundle_raw_certificates_cb,
-                               /*signer_infos_cb=*/NULL, certs);
+                               /*signer_infos_cb=*/nullptr,
+                               const_cast<STACK_OF(CRYPTO_BUFFER) *>(certs));
 }
 
-int pkcs7_add_signed_data(CBB *out,
-                          int (*digest_algos_cb)(CBB *out, const void *arg),
-                          int (*cert_crl_cb)(CBB *out, const void *arg),
-                          int (*signer_infos_cb)(CBB *out, const void *arg),
-                          const void *arg) {
-  CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set,
-      content_info, signer_infos;
+int pkcs7_add_signed_data(CBB *out, uint64_t signed_data_version,
+                          int (*digest_algos_cb)(CBB *out, void *arg),
+                          int (*cert_crl_cb)(CBB *out, void *arg),
+                          int (*signer_infos_cb)(CBB *out, void *arg),
+                          void *arg) {
+  CBB outer_seq, wrapped_seq, seq, digest_algos_set, content_info, signer_infos;
 
   // See https://tools.ietf.org/html/rfc2315#section-7
   if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) ||
+      !CBB_add_asn1_element(&outer_seq, CBS_ASN1_OBJECT, kPKCS7SignedData,
+                            sizeof(kPKCS7SignedData)) ||
       !CBB_add_asn1(&outer_seq, &wrapped_seq,
                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
       // See https://tools.ietf.org/html/rfc2315#section-9.1
       !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) ||
-      !CBB_add_u8(&version_bytes, 1) ||
+      !CBB_add_asn1_uint64(&seq, signed_data_version) ||
       !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
       (digest_algos_cb != NULL && !digest_algos_cb(&digest_algos_set, arg)) ||
+      !CBB_flush_asn1_set_of(&digest_algos_set) ||
       !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
+      !CBB_add_asn1_element(&content_info, CBS_ASN1_OBJECT, kPKCS7Data,
+                            sizeof(kPKCS7Data)) ||
       (cert_crl_cb != NULL && !cert_crl_cb(&seq, arg)) ||
       !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
-      (signer_infos_cb != NULL && !signer_infos_cb(&signer_infos, arg))) {
+      (signer_infos_cb != NULL && !signer_infos_cb(&signer_infos, arg)) ||
+      !CBB_flush_asn1_set_of(&signer_infos)) {
     return 0;
   }
 
diff --git a/src/crypto/pkcs7/pkcs7_test.cc b/src/crypto/pkcs7/pkcs7_test.cc
index 168a7c2..89987a8 100644
--- a/src/crypto/pkcs7/pkcs7_test.cc
+++ b/src/crypto/pkcs7/pkcs7_test.cc
@@ -19,403 +19,17 @@
 #include <openssl/mem.h>
 #include <openssl/pem.h>
 #include <openssl/pkcs7.h>
+#include <openssl/span.h>
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
+#include <string>
+
 #include "../internal.h"
+#include "../test/test_data.h"
 #include "../test/test_util.h"
 
 
-// kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
-// using the Chrome UI.
-static const uint8_t kPKCS7NSS[] = {
-    0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
-    0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80,
-    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00,
-    0x00, 0xa0, 0x82, 0x0b, 0x1e, 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02,
-    0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30,
-    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
-    0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
-    0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55,
-    0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
-    0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
-    0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
-    0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e,
-    0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30,
-    0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30,
-    0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09,
-    0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30,
-    0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54,
-    0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30,
-    0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54,
-    0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
-    0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
-    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
-    0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda,
-    0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b,
-    0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1,
-    0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08,
-    0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d,
-    0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6,
-    0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83,
-    0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d,
-    0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16,
-    0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2,
-    0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35,
-    0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b,
-    0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19,
-    0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde,
-    0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe,
-    0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00,
-    0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d,
-    0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e,
-    0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26,
-    0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52,
-    0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84,
-    0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71,
-    0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51,
-    0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
-    0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
-    0x04, 0x16, 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab,
-    0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e,
-    0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
-    0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c,
-    0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06,
-    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
-    0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d,
-    0x54, 0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78,
-    0x2a, 0x62, 0x94, 0xa2, 0x27, 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47,
-    0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b,
-    0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64,
-    0x76, 0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71,
-    0xd8, 0xc7, 0x3d, 0x37, 0xd2, 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde,
-    0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f,
-    0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11,
-    0x51, 0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea,
-    0x5e, 0x4f, 0x74, 0xf7, 0x05, 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15,
-    0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69,
-    0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a,
-    0xb5, 0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7,
-    0x83, 0xad, 0xdb, 0xf5, 0x27, 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd,
-    0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6,
-    0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c,
-    0x4d, 0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7,
-    0x1d, 0x76, 0x13, 0xa9, 0xd5, 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5,
-    0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4,
-    0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34,
-    0xed, 0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33, 0x30, 0x82, 0x03,
-    0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08,
-    0x3e, 0xa3, 0xe4, 0x78, 0x99, 0x38, 0x13, 0x9d, 0x30, 0x0d, 0x06, 0x09,
-    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
-    0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
-    0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
-    0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31,
-    0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f,
-    0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
-    0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20,
-    0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x36,
-    0x31, 0x32, 0x32, 0x31, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31,
-    0x30, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x69,
-    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
-    0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a,
-    0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
-    0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75,
-    0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13,
-    0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f,
-    0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, 0x16, 0x06,
-    0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x67,
-    0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30,
-    0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08,
-    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
-    0xb2, 0x68, 0x6e, 0x3f, 0x03, 0x9e, 0x43, 0x85, 0x16, 0xb7, 0x89, 0x0b,
-    0x16, 0x2a, 0xbe, 0x26, 0x36, 0xdd, 0x68, 0x0a, 0x53, 0x4e, 0x20, 0x40,
-    0xf8, 0xd1, 0xdd, 0x63, 0xcb, 0x46, 0x73, 0x09, 0x96, 0x36, 0xde, 0x2c,
-    0x45, 0x71, 0x2e, 0x8a, 0x79, 0xeb, 0x40, 0x2f, 0x65, 0x83, 0x81, 0xdb,
-    0x37, 0x03, 0x84, 0xa1, 0x9a, 0xd0, 0x22, 0x3b, 0x73, 0x38, 0x45, 0xd3,
-    0xd5, 0x91, 0xb2, 0x52, 0xa3, 0x82, 0x01, 0x4f, 0x30, 0x82, 0x01, 0x4b,
-    0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06,
-    0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b,
-    0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x1a, 0x06, 0x03, 0x55,
-    0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6d, 0x61, 0x69, 0x6c,
-    0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
-    0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
-    0x30, 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
-    0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
-    0x05, 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
-    0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-    0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72,
-    0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
-    0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c,
-    0x69, 0x65, 0x6e, 0x74, 0x73, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-    0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d,
-    0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xc6, 0xb0,
-    0x4a, 0x46, 0x61, 0x83, 0xff, 0x91, 0x46, 0x45, 0x35, 0xa7, 0x0f, 0xd0,
-    0x5b, 0xe9, 0xdd, 0x94, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-    0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55,
-    0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16,
-    0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a,
-    0xba, 0x5a, 0x81, 0x2f, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
-    0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
-    0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f,
-    0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f,
-    0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
-    0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
-    0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
-    0x01, 0x01, 0x00, 0x7f, 0x41, 0xf5, 0x57, 0x18, 0x3c, 0x75, 0xf5, 0x23,
-    0x66, 0xc3, 0xf0, 0xf2, 0x3e, 0x70, 0x34, 0x56, 0xca, 0x78, 0xec, 0xc7,
-    0x81, 0x58, 0x0d, 0xdf, 0xf0, 0xfd, 0x86, 0xe6, 0xe6, 0x50, 0x3d, 0xf6,
-    0x09, 0x9a, 0x4d, 0xca, 0x60, 0x37, 0x9a, 0xd4, 0xca, 0x51, 0x7c, 0xf0,
-    0x66, 0x23, 0xea, 0x5e, 0x6a, 0x6f, 0x7b, 0xa6, 0x7a, 0x38, 0x97, 0x42,
-    0x58, 0x1a, 0x1b, 0x42, 0xae, 0x28, 0xde, 0x18, 0x7f, 0xcc, 0x76, 0x18,
-    0x58, 0x05, 0xbf, 0xea, 0xef, 0x14, 0xad, 0x34, 0xe5, 0x5f, 0x25, 0xab,
-    0xa1, 0x5f, 0x78, 0x5b, 0x6f, 0xe6, 0x69, 0xd8, 0x74, 0x8c, 0x19, 0x59,
-    0xb0, 0x1a, 0xfb, 0x8e, 0xdf, 0x61, 0xac, 0xeb, 0x2b, 0x0a, 0x1c, 0xab,
-    0x30, 0x0d, 0x64, 0x25, 0x78, 0xdf, 0x81, 0x71, 0xe3, 0xbd, 0xde, 0x9c,
-    0x3f, 0xdd, 0xe9, 0xf8, 0xb6, 0x98, 0x2d, 0x13, 0xa3, 0x7b, 0x14, 0x6f,
-    0xe3, 0x8b, 0xfc, 0x4e, 0x31, 0x26, 0xba, 0x10, 0xb4, 0x12, 0xe9, 0xc9,
-    0x49, 0x60, 0xf0, 0xaa, 0x1f, 0x44, 0x68, 0x19, 0xd2, 0xb3, 0xc8, 0x46,
-    0x22, 0x6b, 0xe1, 0x21, 0x77, 0xfd, 0x72, 0x33, 0x13, 0x21, 0x27, 0x81,
-    0xe4, 0x7a, 0xc9, 0xe4, 0x1c, 0x05, 0x04, 0x73, 0x13, 0xda, 0x47, 0xfe,
-    0x59, 0x41, 0x9c, 0x11, 0xc5, 0xf6, 0xb5, 0xd0, 0x01, 0xcb, 0x40, 0x19,
-    0xf5, 0xfe, 0xb3, 0x3c, 0x1f, 0x61, 0x8f, 0x4d, 0xdb, 0x81, 0x2a, 0x8a,
-    0xed, 0xb8, 0x53, 0xc7, 0x19, 0x6b, 0xfa, 0x8b, 0xfc, 0xe3, 0x2e, 0x12,
-    0x4e, 0xbd, 0xc5, 0x44, 0x9d, 0x1c, 0x7f, 0x3b, 0x09, 0x51, 0xd7, 0x0a,
-    0x0f, 0x22, 0x0a, 0xfd, 0x8c, 0x90, 0x14, 0xed, 0x10, 0xcb, 0x50, 0xcf,
-    0xa5, 0x45, 0xce, 0xb0, 0x21, 0x28, 0xcb, 0xd6, 0xf5, 0x6e, 0xb2, 0x3e,
-    0xfa, 0x35, 0x0c, 0x3d, 0x09, 0x0d, 0x81, 0x30, 0x82, 0x04, 0x04, 0x30,
-    0x82, 0x02, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a,
-    0x69, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-    0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06,
-    0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
-    0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06,
-    0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
-    0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41,
-    0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x30, 0x35, 0x31, 0x35,
-    0x31, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30,
-    0x34, 0x31, 0x35, 0x31, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x49, 0x31, 0x0b,
-    0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
-    0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f,
-    0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23,
-    0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
-    0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41,
-    0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 0x30,
-    0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
-    0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9c, 0x2a, 0x04, 0x77,
-    0x5c, 0xd8, 0x50, 0x91, 0x3a, 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48,
-    0xbc, 0x89, 0x3f, 0xf1, 0x19, 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f,
-    0xc5, 0xf1, 0x89, 0xce, 0x21, 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32,
-    0x44, 0x89, 0xa0, 0x74, 0x0b, 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62,
-    0x95, 0xee, 0xeb, 0x59, 0x5f, 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e,
-    0x94, 0x3f, 0xbc, 0x5b, 0x48, 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb,
-    0x91, 0xe9, 0x15, 0xc4, 0xcf, 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f,
-    0x54, 0xde, 0x7d, 0xbe, 0xa0, 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f,
-    0x28, 0x30, 0x03, 0x40, 0xda, 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a,
-    0x3c, 0xa7, 0x37, 0x06, 0x8e, 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24,
-    0xde, 0xe6, 0xf9, 0xfc, 0x31, 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e,
-    0x4a, 0xaf, 0x42, 0xd2, 0xcb, 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53,
-    0xdd, 0x15, 0x4b, 0x8b, 0x1f, 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8,
-    0x3e, 0x63, 0x2b, 0x84, 0x35, 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46,
-    0x22, 0xf8, 0x53, 0x95, 0xbe, 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec,
-    0xba, 0x97, 0x20, 0x11, 0xc7, 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61,
-    0x7a, 0x95, 0x25, 0x8c, 0x4e, 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca,
-    0x14, 0xfc, 0xce, 0x22, 0x6a, 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97,
-    0x03, 0x7e, 0xc0, 0xb1, 0xde, 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e,
-    0x71, 0xb7, 0xde, 0xf4, 0x25, 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d,
-    0xfb, 0x0e, 0x11, 0x79, 0x89, 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69,
-    0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30,
-    0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
-    0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11,
-    0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03,
-    0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
-    0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba,
-    0x5a, 0x81, 0x2f, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
-    0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
-    0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
-    0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x33,
-    0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74,
-    0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f,
-    0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72,
-    0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e,
-    0x63, 0x72, 0x6c, 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
-    0x07, 0x01, 0x01, 0x04, 0x31, 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b,
-    0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74,
-    0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
-    0x2d, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
-    0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d,
-    0x20, 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01,
-    0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
-    0x01, 0x01, 0x00, 0x36, 0xd7, 0x06, 0x80, 0x11, 0x27, 0xad, 0x2a, 0x14,
-    0x9b, 0x38, 0x77, 0xb3, 0x23, 0xa0, 0x75, 0x58, 0xbb, 0xb1, 0x7e, 0x83,
-    0x42, 0xba, 0x72, 0xda, 0x1e, 0xd8, 0x8e, 0x36, 0x06, 0x97, 0xe0, 0xf0,
-    0x95, 0x3b, 0x37, 0xfd, 0x1b, 0x42, 0x58, 0xfe, 0x22, 0xc8, 0x6b, 0xbd,
-    0x38, 0x5e, 0xd1, 0x3b, 0x25, 0x6e, 0x12, 0xeb, 0x5e, 0x67, 0x76, 0x46,
-    0x40, 0x90, 0xda, 0x14, 0xc8, 0x78, 0x0d, 0xed, 0x95, 0x66, 0xda, 0x8e,
-    0x86, 0x6f, 0x80, 0xa1, 0xba, 0x56, 0x32, 0x95, 0x86, 0xdc, 0xdc, 0x6a,
-    0xca, 0x04, 0x8c, 0x5b, 0x7f, 0xf6, 0xbf, 0xcc, 0x6f, 0x85, 0x03, 0x58,
-    0xc3, 0x68, 0x51, 0x13, 0xcd, 0xfd, 0xc8, 0xf7, 0x79, 0x3d, 0x99, 0x35,
-    0xf0, 0x56, 0xa3, 0xbd, 0xe0, 0x59, 0xed, 0x4f, 0x44, 0x09, 0xa3, 0x9e,
-    0x38, 0x7a, 0xf6, 0x46, 0xd1, 0x1d, 0x12, 0x9d, 0x4f, 0xbe, 0xd0, 0x40,
-    0xfc, 0x55, 0xfe, 0x06, 0x5e, 0x3c, 0xda, 0x1c, 0x56, 0xbd, 0x96, 0x51,
-    0x7b, 0x6f, 0x57, 0x2a, 0xdb, 0xa2, 0xaa, 0x96, 0xdc, 0x8c, 0x74, 0xc2,
-    0x95, 0xbe, 0xf0, 0x6e, 0x95, 0x13, 0xff, 0x17, 0xf0, 0x3c, 0xac, 0xb2,
-    0x10, 0x8d, 0xcc, 0x73, 0xfb, 0xe8, 0x8f, 0x02, 0xc6, 0xf0, 0xfb, 0x33,
-    0xb3, 0x95, 0x3b, 0xe3, 0xc2, 0xcb, 0x68, 0x58, 0x73, 0xdb, 0xa8, 0x24,
-    0x62, 0x3b, 0x06, 0x35, 0x9d, 0x0d, 0xa9, 0x33, 0xbd, 0x78, 0x03, 0x90,
-    0x2e, 0x4c, 0x78, 0x5d, 0x50, 0x3a, 0x81, 0xd4, 0xee, 0xa0, 0xc8, 0x70,
-    0x38, 0xdc, 0xb2, 0xf9, 0x67, 0xfa, 0x87, 0x40, 0x5d, 0x61, 0xc0, 0x51,
-    0x8f, 0x6b, 0x83, 0x6b, 0xcd, 0x05, 0x3a, 0xca, 0xe1, 0xa7, 0x05, 0x78,
-    0xfc, 0xca, 0xda, 0x94, 0xd0, 0x2c, 0x08, 0x3d, 0x7e, 0x16, 0x79, 0xc8,
-    0xa0, 0x50, 0x20, 0x24, 0x54, 0x33, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00,
-};
-
-// kPKCS7Windows is the Equifax root certificate, as exported by Windows 7.
-static const uint8_t kPKCS7Windows[] = {
-    0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-    0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02,
-    0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-    0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02,
-    0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
-    0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-    0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06,
-    0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
-    0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63,
-    0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d,
-    0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75,
-    0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73,
-    0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30,
-    0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
-    0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
-    0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-    0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
-    0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53,
-    0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26,
-    0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75,
-    0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
-    0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41,
-    0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
-    0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
-    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17,
-    0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a,
-    0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4,
-    0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45,
-    0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9,
-    0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a,
-    0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9,
-    0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f,
-    0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb,
-    0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef,
-    0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe,
-    0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64,
-    0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
-    0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55,
-    0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
-    0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
-    0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf,
-    0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06,
-    0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52,
-    0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a,
-    0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-    0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75,
-    0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9,
-    0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc,
-    0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4,
-    0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65,
-    0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47,
-    0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7,
-    0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56,
-    0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e,
-    0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe,
-    0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59,
-    0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00,
-};
-
-// kOpenSSLCRL is the Equifax CRL, converted to PKCS#7 form by:
-//   openssl crl2pkcs7 -inform DER -in secureca.crl
-static const uint8_t kOpenSSLCRL[] = {
-    0x30, 0x82, 0x03, 0x85, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-    0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x02,
-    0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-    0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x00, 0xa1, 0x82, 0x03, 0x58, 0x30,
-    0x82, 0x03, 0x54, 0x30, 0x82, 0x02, 0xbd, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e,
-    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
-    0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07,
-    0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06,
-    0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
-    0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72,
-    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74,
-    0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x32,
-    0x32, 0x37, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31,
-    0x35, 0x30, 0x33, 0x30, 0x39, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30, 0x5a,
-    0x30, 0x82, 0x02, 0x3c, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x58, 0xe4, 0x17,
-    0x0d, 0x31, 0x34, 0x30, 0x34, 0x32, 0x37, 0x30, 0x38, 0x31, 0x39, 0x32,
-    0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x76, 0x19, 0x17, 0x0d, 0x31,
-    0x34, 0x30, 0x36, 0x31, 0x38, 0x31, 0x35, 0x30, 0x30, 0x30, 0x33, 0x5a,
-    0x30, 0x14, 0x02, 0x03, 0x0f, 0x9a, 0xfb, 0x17, 0x0d, 0x31, 0x34, 0x30,
-    0x34, 0x32, 0x39, 0x31, 0x38, 0x30, 0x39, 0x31, 0x37, 0x5a, 0x30, 0x14,
-    0x02, 0x03, 0x14, 0x8b, 0xc0, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x30,
-    0x39, 0x31, 0x39, 0x34, 0x36, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03,
-    0x14, 0xe4, 0x9c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x31, 0x36, 0x32,
-    0x33, 0x33, 0x39, 0x33, 0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x86,
-    0x07, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x31, 0x31, 0x35, 0x35,
-    0x30, 0x35, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xe2, 0x29, 0x17,
-    0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, 0x38, 0x35, 0x35, 0x31,
-    0x35, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0d, 0x42, 0x66, 0x17, 0x0d, 0x31,
-    0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x35, 0x33, 0x5a,
-    0x30, 0x14, 0x02, 0x03, 0x03, 0x1e, 0x33, 0x17, 0x0d, 0x30, 0x32, 0x30,
-    0x35, 0x31, 0x35, 0x31, 0x33, 0x30, 0x36, 0x31, 0x31, 0x5a, 0x30, 0x14,
-    0x02, 0x03, 0x12, 0xe2, 0x23, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30,
-    0x36, 0x32, 0x30, 0x34, 0x30, 0x32, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03,
-    0x13, 0x9c, 0xab, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x37, 0x32, 0x39, 0x31,
-    0x36, 0x34, 0x34, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x12, 0xc6,
-    0x0a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x30, 0x36, 0x32, 0x32, 0x32,
-    0x31, 0x33, 0x39, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x03, 0x25, 0x85, 0x17,
-    0x0d, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31, 0x38, 0x31, 0x31, 0x35,
-    0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0x86, 0xe6, 0x17, 0x0d, 0x31,
-    0x34, 0x30, 0x37, 0x32, 0x35, 0x30, 0x32, 0x30, 0x30, 0x33, 0x38, 0x5a,
-    0x30, 0x14, 0x02, 0x03, 0x13, 0x9c, 0xa1, 0x17, 0x0d, 0x31, 0x30, 0x30,
-    0x37, 0x32, 0x39, 0x31, 0x36, 0x34, 0x37, 0x33, 0x32, 0x5a, 0x30, 0x14,
-    0x02, 0x03, 0x15, 0x4d, 0x5c, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x33,
-    0x30, 0x30, 0x30, 0x30, 0x34, 0x34, 0x32, 0x5a, 0x30, 0x14, 0x02, 0x03,
-    0x0f, 0xfa, 0x2d, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31,
-    0x38, 0x35, 0x30, 0x31, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x13, 0x75,
-    0x55, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x31, 0x31, 0x38, 0x30, 0x32, 0x32,
-    0x31, 0x33, 0x33, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0f, 0x56, 0x96, 0x17,
-    0x0d, 0x31, 0x34, 0x30, 0x36, 0x32, 0x34, 0x31, 0x32, 0x33, 0x31, 0x30,
-    0x32, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x0b, 0x80, 0x8a, 0x17, 0x0d, 0x31,
-    0x32, 0x30, 0x36, 0x32, 0x37, 0x31, 0x37, 0x31, 0x30, 0x32, 0x35, 0x5a,
-    0x30, 0x14, 0x02, 0x03, 0x0f, 0x94, 0x16, 0x17, 0x0d, 0x31, 0x30, 0x30,
-    0x33, 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x33, 0x31, 0x5a, 0x30, 0x14,
-    0x02, 0x03, 0x14, 0x16, 0xb3, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31,
-    0x38, 0x31, 0x34, 0x33, 0x32, 0x35, 0x36, 0x5a, 0x30, 0x14, 0x02, 0x03,
-    0x0a, 0xe1, 0x85, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x32, 0x37, 0x31,
-    0x37, 0x31, 0x30, 0x31, 0x37, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x14, 0xcc,
-    0x3e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x31, 0x31, 0x32, 0x35,
-    0x35, 0x33, 0x31, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x10, 0x5b, 0xcb, 0x17,
-    0x0d, 0x31, 0x30, 0x30, 0x37, 0x33, 0x30, 0x32, 0x31, 0x33, 0x31, 0x32,
-    0x30, 0x5a, 0x30, 0x14, 0x02, 0x03, 0x15, 0x6a, 0x1f, 0x17, 0x0d, 0x31,
-    0x34, 0x30, 0x32, 0x32, 0x36, 0x31, 0x32, 0x33, 0x35, 0x31, 0x39, 0x5a,
-    0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
-    0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1d, 0x5c, 0x27, 0x07, 0x11,
-    0x03, 0xf2, 0x00, 0xbd, 0xf4, 0x46, 0x3e, 0x71, 0xfd, 0x10, 0x84, 0x83,
-    0xd9, 0xd2, 0xd2, 0x19, 0xa0, 0x20, 0xf7, 0x1a, 0x43, 0x3d, 0xac, 0xda,
-    0x33, 0xfc, 0xb7, 0x42, 0x60, 0x1a, 0xa4, 0xa8, 0xb2, 0x07, 0x5c, 0x51,
-    0x16, 0xc0, 0x42, 0x80, 0x0a, 0x0f, 0xf0, 0x47, 0x5b, 0x4b, 0x78, 0x90,
-    0xaf, 0xc7, 0xac, 0x48, 0xf8, 0xca, 0x3c, 0x13, 0x5e, 0xf6, 0xd1, 0x88,
-    0xae, 0x55, 0xa3, 0x0c, 0x8a, 0x62, 0x47, 0x29, 0xf8, 0x72, 0xb8, 0x24,
-    0x17, 0xaf, 0xb2, 0x06, 0x1e, 0xa7, 0x72, 0x76, 0xab, 0x96, 0x1d, 0xe0,
-    0x7c, 0xd4, 0x0c, 0x42, 0x82, 0x3d, 0x4a, 0x8e, 0x15, 0x77, 0x2f, 0x3c,
-    0x2a, 0x8c, 0x3a, 0x04, 0x10, 0x55, 0xdc, 0xbb, 0xba, 0xb1, 0x91, 0xee,
-    0x7b, 0xe7, 0x23, 0xc5, 0x71, 0x13, 0xae, 0x6b, 0x21, 0x35, 0xd3, 0x64,
-    0xf0, 0x00, 0x54, 0x31, 0x00,
-};
-
 // kPEMCert is the result of exporting the mail.google.com certificate from
 // Chrome and then running it through:
 //   openssl pkcs7 -inform DER -in mail.google.com -outform PEM
@@ -470,7 +84,7 @@
     "fNQMQoI9So4Vdy88Kow6BBBV3Lu6sZHue+cjxXETrmshNdNk8ABUMQA=\n"
     "-----END PKCS7-----\n";
 
-static void TestCertReparse(const uint8_t *der_bytes, size_t der_len) {
+static void TestCertReparse(bssl::Span<const uint8_t> der) {
   bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
   ASSERT_TRUE(certs);
   bssl::UniquePtr<STACK_OF(X509)> certs2(sk_X509_new_null());
@@ -478,13 +92,12 @@
   uint8_t *result_data, *result2_data;
   size_t result_len, result2_len;
 
-  CBS pkcs7;
-  CBS_init(&pkcs7, der_bytes, der_len);
+  CBS pkcs7 = der;
   ASSERT_TRUE(PKCS7_get_certificates(certs.get(), &pkcs7));
   EXPECT_EQ(0u, CBS_len(&pkcs7));
 
   bssl::ScopedCBB cbb;
-  ASSERT_TRUE(CBB_init(cbb.get(), der_len));
+  ASSERT_TRUE(CBB_init(cbb.get(), der.size()));
   ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), certs.get()));
   ASSERT_TRUE(CBB_finish(cbb.get(), &result_data, &result_len));
   bssl::UniquePtr<uint8_t> free_result_data(result_data);
@@ -503,7 +116,7 @@
     ASSERT_EQ(0, X509_cmp(a, b));
   }
 
-  ASSERT_TRUE(CBB_init(cbb.get(), der_len));
+  ASSERT_TRUE(CBB_init(cbb.get(), der.size()));
   ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), certs2.get()));
   ASSERT_TRUE(CBB_finish(cbb.get(), &result2_data, &result2_len));
   bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
@@ -511,10 +124,10 @@
   EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
 
   // Parse with the legacy API instead.
-  const uint8_t *ptr = der_bytes;
-  bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
+  const uint8_t *ptr = der.data();
+  bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der.size()));
   ASSERT_TRUE(pkcs7_obj);
-  EXPECT_EQ(ptr, der_bytes + der_len);
+  EXPECT_EQ(ptr, der.data() + der.size());
 
   ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
   const STACK_OF(X509) *certs3 = pkcs7_obj->d.sign->cert;
@@ -531,7 +144,7 @@
   int result3_len = i2d_PKCS7(pkcs7_obj.get(), &result3_data);
   ASSERT_GT(result3_len, 0);
   bssl::UniquePtr<uint8_t> free_result3_data(result3_data);
-  EXPECT_EQ(Bytes(der_bytes, der_len), Bytes(result3_data, result3_len));
+  EXPECT_EQ(Bytes(der), Bytes(result3_data, result3_len));
 
   // Make a new object with the legacy API.
   pkcs7_obj.reset(
@@ -555,7 +168,7 @@
   EXPECT_EQ(Bytes(result_data, result_len), Bytes(result4_data, result4_len));
 }
 
-static void TestCRLReparse(const uint8_t *der_bytes, size_t der_len) {
+static void TestCRLReparse(bssl::Span<const uint8_t> der) {
   bssl::UniquePtr<STACK_OF(X509_CRL)> crls(sk_X509_CRL_new_null());
   ASSERT_TRUE(crls);
   bssl::UniquePtr<STACK_OF(X509_CRL)> crls2(sk_X509_CRL_new_null());
@@ -563,13 +176,12 @@
   uint8_t *result_data, *result2_data;
   size_t result_len, result2_len;
 
-  CBS pkcs7;
-  CBS_init(&pkcs7, der_bytes, der_len);
+  CBS pkcs7 = der;
   ASSERT_TRUE(PKCS7_get_CRLs(crls.get(), &pkcs7));
   EXPECT_EQ(0u, CBS_len(&pkcs7));
 
   bssl::ScopedCBB cbb;
-  ASSERT_TRUE(CBB_init(cbb.get(), der_len));
+  ASSERT_TRUE(CBB_init(cbb.get(), der.size()));
   ASSERT_TRUE(PKCS7_bundle_CRLs(cbb.get(), crls.get()));
   ASSERT_TRUE(CBB_finish(cbb.get(), &result_data, &result_len));
   bssl::UniquePtr<uint8_t> free_result_data(result_data);
@@ -588,7 +200,7 @@
     ASSERT_EQ(0, X509_CRL_cmp(a, b));
   }
 
-  ASSERT_TRUE(CBB_init(cbb.get(), der_len));
+  ASSERT_TRUE(CBB_init(cbb.get(), der.size()));
   ASSERT_TRUE(PKCS7_bundle_CRLs(cbb.get(), crls2.get()));
   ASSERT_TRUE(CBB_finish(cbb.get(), &result2_data, &result2_len));
   bssl::UniquePtr<uint8_t> free_result2_data(result2_data);
@@ -596,10 +208,10 @@
   EXPECT_EQ(Bytes(result_data, result_len), Bytes(result2_data, result2_len));
 
   // Parse with the legacy API instead.
-  const uint8_t *ptr = der_bytes;
-  bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der_len));
+  const uint8_t *ptr = der.data();
+  bssl::UniquePtr<PKCS7> pkcs7_obj(d2i_PKCS7(nullptr, &ptr, der.size()));
   ASSERT_TRUE(pkcs7_obj);
-  EXPECT_EQ(ptr, der_bytes + der_len);
+  EXPECT_EQ(ptr, der.data() + der.size());
 
   ASSERT_TRUE(PKCS7_type_is_signed(pkcs7_obj.get()));
   const STACK_OF(X509_CRL) *crls3 = pkcs7_obj->d.sign->crl;
@@ -646,15 +258,23 @@
 }
 
 TEST(PKCS7Test, CertReparseNSS) {
-  TestCertReparse(kPKCS7NSS, sizeof(kPKCS7NSS));
+  // nss.p7c contains the certificate chain of mail.google.com, as saved by NSS
+  // using the Chrome UI.
+  TestCertReparse(
+      bssl::StringAsBytes(GetTestData("crypto/pkcs7/test/nss.p7c")));
 }
 
 TEST(PKCS7Test, CertReparseWindows) {
-  TestCertReparse(kPKCS7Windows, sizeof(kPKCS7Windows));
+  // windows.p7c is the Equifax root certificate, as exported by Windows 7.
+  TestCertReparse(
+      bssl::StringAsBytes(GetTestData("crypto/pkcs7/test/windows.p7c")));
 }
 
 TEST(PKCS7Test, CrlReparse) {
-  TestCRLReparse(kOpenSSLCRL, sizeof(kOpenSSLCRL));
+  // openssl_crl.p7c is the Equifax CRL, converted to PKCS#7 form by:
+  //   openssl crl2pkcs7 -inform DER -in secureca.crl
+  TestCRLReparse(
+      bssl::StringAsBytes(GetTestData("crypto/pkcs7/test/openssl_crl.p7c")));
 }
 
 TEST(PKCS7Test, PEMCerts) {
@@ -667,9 +287,9 @@
 
 // Test that we output certificates in the canonical DER order.
 TEST(PKCS7Test, SortCerts) {
-  // kPKCS7NSS contains three certificates in the canonical DER order.
-  CBS pkcs7;
-  CBS_init(&pkcs7, kPKCS7NSS, sizeof(kPKCS7NSS));
+  // nss.p7c contains three certificates in the canonical DER order.
+  std::string nss_p7c = GetTestData("crypto/pkcs7/test/nss.p7c");
+  CBS pkcs7 = bssl::StringAsBytes(nss_p7c);
   bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
   ASSERT_TRUE(certs);
   ASSERT_TRUE(PKCS7_get_certificates(certs.get(), &pkcs7));
@@ -687,7 +307,7 @@
     ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert2)));
     ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert3)));
     bssl::ScopedCBB cbb;
-    ASSERT_TRUE(CBB_init(cbb.get(), sizeof(kPKCS7NSS)));
+    ASSERT_TRUE(CBB_init(cbb.get(), nss_p7c.size()));
     ASSERT_TRUE(PKCS7_bundle_certificates(cbb.get(), new_certs.get()));
 
     // The bundle should be sorted back to the original order.
@@ -712,9 +332,9 @@
 // Test that we output certificates in the canonical DER order, using the
 // CRYPTO_BUFFER version of the parse and bundle functions.
 TEST(PKCS7Test, SortCertsRaw) {
-  // kPKCS7NSS contains three certificates in the canonical DER order.
-  CBS pkcs7;
-  CBS_init(&pkcs7, kPKCS7NSS, sizeof(kPKCS7NSS));
+  // nss.p7c contains three certificates in the canonical DER order.
+  std::string nss_p7c = GetTestData("crypto/pkcs7/test/nss.p7c");
+  CBS pkcs7 = bssl::StringAsBytes(nss_p7c);
   bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> certs(sk_CRYPTO_BUFFER_new_null());
   ASSERT_TRUE(certs);
   ASSERT_TRUE(PKCS7_get_raw_certificates(certs.get(), &pkcs7, nullptr));
@@ -734,7 +354,7 @@
     ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert2)));
     ASSERT_TRUE(bssl::PushToStack(new_certs.get(), bssl::UpRef(new_cert3)));
     bssl::ScopedCBB cbb;
-    ASSERT_TRUE(CBB_init(cbb.get(), sizeof(kPKCS7NSS)));
+    ASSERT_TRUE(CBB_init(cbb.get(), nss_p7c.size()));
     ASSERT_TRUE(PKCS7_bundle_raw_certificates(cbb.get(), new_certs.get()));
 
     // The bundle should be sorted back to the original order.
@@ -830,108 +450,20 @@
 TEST(PKCS7Test, KernelModuleSigning) {
   // Sign a message with the same call that the Linux kernel's sign-file.c
   // makes.
-  static const char kCert[] = R"(
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgIURVkPzF/4dwy7419Qk75uhIuyf0EwDQYJKoZIhvcNAQEL
-BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
-GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA5MjExOTIyMTJaFw0yMjA5
-MjExOTIyMTJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
-HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQC1+MOn+BopcEVR4QMvjXdAxGkWFllXyQFDToL+qOiP
-RU1yN7C8KCtkbOAFttJIO4O/i0iZ7KqYbnmB6YUA/ONAcakocnrdoESgRJcVMeAx
-Dk/11OtMF5yIfeOOO/TUeVNmAUaT63gFbKy/adpqhzJtOv9BBl5VcYNGGSE+0wtb
-mjpmNsxunEQR1KLDc97fGYHeRfKoSyrCIEE8IaAEpKGR2Sku3v9Jwh7RpjupgiUA
-kH6pJk7VMZm5vl2wFjYvfysgjeN5ZtsxFDMaPYZStpxMxpNd5C9DsO2Ljp5NMpGf
-NGmG4ZqiaQg8z2cIM6ESmN1zDJdUh5IXed1fOxBZD/poUFH0wDRFWnvzlaPmjJEF
-rYLMK8svnE5nEQp9vu93ISFBx7cofs+niMaUXPEqaRSqruifN2M1it3kOf/8YZl1
-vurs+VtHD6nOJo6bd11+37aBidIB/BaWnzLrDmSTcPFa1tkTHwoLqc9+jThTq9jZ
-6w3lAMPpsoenyD19UmQB589+4kNp2SIO/TtzVQCGgQPXE2jDCl6G9aIPMkfvpPZK
-4THVil3WQRCFYnYdDO4HQXo2ZuC4RiqgY5ygfeoL+fa9k383lgxxAHQLS7xsbaVB
-40RmfdbdevgPYIwZNNO78ddRmMdSv6IknSW9gydGzY//btY+t1SWcBZWzn1Ewq8g
-2QIDAQABo1MwUTAdBgNVHQ4EFgQUotZD9ajEvnQYVezIWzcW4pzvMcUwHwYDVR0j
-BBgwFoAUotZD9ajEvnQYVezIWzcW4pzvMcUwDwYDVR0TAQH/BAUwAwEB/zANBgkq
-hkiG9w0BAQsFAAOCAgEAqCe42PIWoyLDx9bR+5cSp99N5xo5lLiSLtWx2emDbZB2
-AunqKYeEgIV+TWNF2w1SZ/ckFgV7SlL2Yl73N/veSNRfNAnpjLksGDFpdJb7YXrx
-cUvxdy1mr8oau6J7PC9JGjBTBrnhqwCQX1FtcAxODKll2Lsfuj6+bdC3rCK7KBEo
-ENamMJZIeo8lRP9qFF2xwCEzZjRv2zvB6O5o9045aTUcdCrwUfKE2sqY6EXRzFTC
-waK0HRCd1FLv9omhz/Ug5PMHP4d6MZfnAbFm+AzAhnpkrk/9TJYSOoNTNLWsuqhp
-dN0rKqiFWv1zIwfknXvTh1P1Ap+G5jffAca0zWUH1oKjE7ZZioSsaZ6gySnD8+WQ
-TPbOYtG+n0mhCH1TrU8Dqi3rd8g5IbC8loYLRH94QtodOnevD4Qo9Orfrsr8hGOW
-ABespanZArhoQ03DAtpNhtHm2NWJQF2uHNqcTrkq0omqZBTbMD1GKMBujoNooAUu
-w51U9r+RycPJTFqEGHb0nd7EjoyXEXtuX1Ld5fTZjQ9SszmQKQ8w3lHqRGNlkSiO
-e3IOOq2ruXmq1jykxpmi82IcTRUE8TZBfL/yz0nxpHKAYC1VwMezrkgZDGz4npxf
-1z2+qd58xU6/jsf7/+3xdPFubeEJujdbCkWQsQC5Rzm48zDWGq/pyzFji44K3TA=
------END CERTIFICATE-----
-)";
-
-  static const char kKey[] = R"(
------BEGIN PRIVATE KEY-----
-MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQC1+MOn+BopcEVR
-4QMvjXdAxGkWFllXyQFDToL+qOiPRU1yN7C8KCtkbOAFttJIO4O/i0iZ7KqYbnmB
-6YUA/ONAcakocnrdoESgRJcVMeAxDk/11OtMF5yIfeOOO/TUeVNmAUaT63gFbKy/
-adpqhzJtOv9BBl5VcYNGGSE+0wtbmjpmNsxunEQR1KLDc97fGYHeRfKoSyrCIEE8
-IaAEpKGR2Sku3v9Jwh7RpjupgiUAkH6pJk7VMZm5vl2wFjYvfysgjeN5ZtsxFDMa
-PYZStpxMxpNd5C9DsO2Ljp5NMpGfNGmG4ZqiaQg8z2cIM6ESmN1zDJdUh5IXed1f
-OxBZD/poUFH0wDRFWnvzlaPmjJEFrYLMK8svnE5nEQp9vu93ISFBx7cofs+niMaU
-XPEqaRSqruifN2M1it3kOf/8YZl1vurs+VtHD6nOJo6bd11+37aBidIB/BaWnzLr
-DmSTcPFa1tkTHwoLqc9+jThTq9jZ6w3lAMPpsoenyD19UmQB589+4kNp2SIO/Ttz
-VQCGgQPXE2jDCl6G9aIPMkfvpPZK4THVil3WQRCFYnYdDO4HQXo2ZuC4RiqgY5yg
-feoL+fa9k383lgxxAHQLS7xsbaVB40RmfdbdevgPYIwZNNO78ddRmMdSv6IknSW9
-gydGzY//btY+t1SWcBZWzn1Ewq8g2QIDAQABAoICAFQ/liZAIaypxA5ChP0RG/Mq
-fBSzyC1ybFlDEjbg8LrUNST6T6LtXhmipp0+pWC33SljTPumrNzh2POir+djLbt6
-Y/zL88KEHwGsf95aNxe/Lpn8N+wEyn4O+rmxXIq6mTgSwyBc1jZ8uAXu9iZ37YrQ
-07jBQA+C/GoJ3HB/uTRx1TPZjxBu3Lz8m1auYLMd1hiYfd4Y3vT9hfZXAwTjS8KA
-riZ7K+p0K1yY/+pczNDUFTAvAjSGQEvUrP+HaRLYZ5ks1/IvArBYT8iIT5Yf4YFS
-NowzxwYp9fC02OmYzf7Nf0XpUXR7+EpfI66SaLJ5f51yaOXD1olz7F/YsprpYN7+
-oQd7EKar1bY3ROM6naUZtsIoEblg6B0mkyHWQgZ9wZRbcN7Zmuc/tIpLat7se+MP
-xQeAcH4Yhgnd2G6EELpmJBcyJ0Ss3atpI1eenU+ly++L4XbDQH9norKQ1PEDXYbV
-XMAV5uIsplBL7hGIa6/u/cRMM5eN3TJchtzIHFhq9+ENMvjTOfo0bflcYR+tNxGD
-6agWlD/Apedaapu/3Xp7ekyCiy/YTIwgT4U3rprYplzFM5HbzYtZ9ThxUm+CmnYj
-ZSCKiLoaQq+11/M9zH1Je0uJP5aK0CxOii2LVRXZYaQfbDtiHNWUSM7uPIZMnDgE
-IPTpl9CEfk7U3pgiUlg5AoIBAQDjUeikACPaRuewIjLqwTT2/j+ZO+/dCG4atFZa
-W+gdZ1NVDCdowQPBZWg6bqejRr1MvORg2L83kqZDQjaT9y59qxsFhXCy26xKp7aP
-Z4pEvUQmQnnf3RYHk3EBtOHyyMetTaghTGzL3MlPGo3uGbCiYtVoPKXZXGWeiOFN
-s9RNDh/7m6harB2bmX2cK+QPdJ1roVBXQDLkjh2mvLnC5vrsw81GWSkbWQpYmnVi
-YdLhytM+UTYjTrSugtrKk9e2KOFf2uR8PVaPeINEM4uubxW5YUy6gwF8ePtWYAtZ
-Skw3kdBdShhGzHORSY3NsRTJZL6AUdkhHYFTl/rlfj1WXsdnAoIBAQDM7i0u2T+E
-HmroTGiQAIRUEwUZQFDRkcEnM75jpkQT39jXF+zmhjzS1slJF2x0E0jUBV0juVWh
-mz1kHjTMV0j3/mvCeVv0iTcdIbHYRtTwmOjzkwTsZGh6T7okYck3KexRjpyhPpcX
-hOHOPJKS/muG0ZuaJjTEbJOzrSPU0rt0ppL7nOwd5jIOoGAciWiP17G1Lyyitrv4
-mKBK6mFQQWjAgEGy3jvBocbUo7Qo8Aucm6Y4eF1fUyC/X07RBzERHS4TuM+AQlDN
-T+LgTgcwTjE+Nzow2WMwCIbhVQqFRScuWqcJ6NQ6S/dV0R+aGJ90Ey+DtiZ9N9uV
-j0omAGvM8u2/AoIBADXF94FsIw8MfNw2itLrl2riJAtMmWYxC1K33EGNwi/KdHUG
-5f+qwQerxGcmK/O81STk/iVGwJ0VzMzWSfDgpRfHNSIuOcWln3EdkVsFBDlUiF2A
-ljH1q7NpFm9v6Y80HcAKQb52xLnI5boXrwFnBFi1hoQc7KKpb8R73sgxxQPhVoF/
-hejFFE/tlEAwRce+L0r5ovaw0hks4SjDNjI7z5nYi6ObjdTRUFg7WY9HUspk32m7
-blIV2Tn67GTFal7F9uJk9m3JWMOhn3OvudguoPX0ZWEtgll+iP4axDSAFd2DWcXn
-tCxzStdQjgHdZOxrL4FNW06xGxm6Nvi4zyuySfsCggEAOuIpC3ATBxRyZYMm/FGZ
-tEquyV2omz8FQA1nJFzu7MMCHHPcdzSVH4Pl3GGloQi1gW51H8GuMDxZ/H2NcDWY
-WuG49u1GFdKjinRXFKztnKBjNzHEVWRYfOSRuMh8N6SNKbYPnWlNos1k0IypFSGT
-pe5uhnF58gK8wgD67bkLce43B6NEWSb+tSMx2qFE8SfqAQSoD6zv//NjA4OrKJNS
-1RVFS279vpqMdib/qk+nFn3G2i0Dr1NEcpihHgCyAZff2Hze6pyjeQr+RrNE74VY
-MudNiiG8lV2t2+tClZ6ULoaPvpIvAP04+WiYav+uOX0VxwO8tXgqWSQOCzNNxlr7
-IwKCAQA7odNjE6Sc2qiecrOu13kEi3gT0heshIyZ0XhePrS1vgHfCouIRvNMw4FT
-45ZZUFDSdOxhrew5GuMeLvo2YILBjmkX3UqTojQMbur7FcGH8/P0Sm0f20Vc06oS
-sQF5Ji4LSyf6t9oQKePjFIGoIc6pf6BXJZYP4rBnzQzUQjH2yzDYDY3TuV7bFJJU
-DcSTGM6nP0fRMmgBtB14o7A6Gsy6X/N2ElgbvWT8YhmUC6H8DIzmZwHRKaG6C6g5
-eEjuAYenYNM4jxeteC1neUDIdGxH/BA7JrAqcGaN9GT+R47YIfiS2WrEssD1Pi5h
-hJTbHtjEDJ7BHLC/CNUhXbpyyu1y
------END PRIVATE KEY-----
-)";
-
+  std::string cert_pem = GetTestData("crypto/pkcs7/test/sign_cert.pem");
+  std::string key_pem = GetTestData("crypto/pkcs7/test/sign_key.pem");
   bssl::UniquePtr<BIO> cert_bio(
-      BIO_new_mem_buf(const_cast<char *>(kCert), sizeof(kCert) - 1));
+      BIO_new_mem_buf(cert_pem.data(), cert_pem.size()));
   bssl::UniquePtr<X509> cert(
       PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr));
 
-  bssl::UniquePtr<BIO> key_bio(
-      BIO_new_mem_buf(const_cast<char *>(kKey), sizeof(kKey) - 1));
+  bssl::UniquePtr<BIO> key_bio(BIO_new_mem_buf(key_pem.data(), key_pem.size()));
   bssl::UniquePtr<EVP_PKEY> key(
       PEM_read_bio_PrivateKey(key_bio.get(), nullptr, nullptr, nullptr));
 
   static const char kSignedData[] = "signed data";
-  bssl::UniquePtr<BIO> data_bio(BIO_new_mem_buf(const_cast<char *>(kSignedData),
-                                                sizeof(kSignedData) - 1));
+  bssl::UniquePtr<BIO> data_bio(
+      BIO_new_mem_buf(kSignedData, sizeof(kSignedData) - 1));
 
   bssl::UniquePtr<PKCS7> pkcs7(
       PKCS7_sign(cert.get(), key.get(), /*certs=*/nullptr, data_bio.get(),
@@ -944,69 +476,8 @@
   bssl::UniquePtr<uint8_t> pkcs7_storage(pkcs7_bytes);
 
   // RSA signatures are deterministic so the output should not change.
-  static const uint8_t kExpectedOutput[] = {
-      0x30, 0x82, 0x02, 0xbc, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-      0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xad, 0x30, 0x82, 0x02, 0xa9, 0x02,
-      0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
-      0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
-      0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, 0x86, 0x30, 0x82,
-      0x02, 0x82, 0x02, 0x01, 0x01, 0x30, 0x5d, 0x30, 0x45, 0x31, 0x0b, 0x30,
-      0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-      0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d,
-      0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-      0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
-      0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-      0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x02, 0x14, 0x45, 0x59, 0x0f, 0xcc,
-      0x5f, 0xf8, 0x77, 0x0c, 0xbb, 0xe3, 0x5f, 0x50, 0x93, 0xbe, 0x6e, 0x84,
-      0x8b, 0xb2, 0x7f, 0x41, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
-      0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
-      0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00,
-      0x54, 0xd4, 0x7c, 0xdc, 0x19, 0x86, 0xa1, 0xb2, 0xbe, 0xe3, 0xa4, 0x5e,
-      0xad, 0x16, 0x6f, 0x7c, 0xf9, 0xa6, 0x40, 0x90, 0xb8, 0x78, 0x85, 0xf1,
-      0x02, 0x59, 0xe5, 0x9f, 0x83, 0xfb, 0x20, 0xcf, 0x29, 0x52, 0xb6, 0x35,
-      0x5c, 0xf9, 0xef, 0x4e, 0xc5, 0xd3, 0xa6, 0x45, 0x6e, 0xfa, 0x0a, 0xa7,
-      0x53, 0xc8, 0xf4, 0xf9, 0xd6, 0xc5, 0xd8, 0xd8, 0x04, 0x3d, 0xb4, 0x15,
-      0xa7, 0x7a, 0x53, 0xdd, 0x27, 0xfa, 0x58, 0x2e, 0x5e, 0xc4, 0xcd, 0x45,
-      0xaa, 0xc2, 0x7b, 0xf9, 0x3d, 0xd7, 0x22, 0x20, 0x90, 0xbb, 0xa5, 0x62,
-      0xd5, 0xaa, 0x39, 0x8f, 0xc1, 0x00, 0xef, 0x4b, 0x03, 0x2c, 0x32, 0xc0,
-      0xad, 0x27, 0xb6, 0xfe, 0x86, 0xe5, 0x9d, 0xf0, 0xbe, 0xb1, 0x0d, 0xa4,
-      0xa3, 0x40, 0xe0, 0xaa, 0x0a, 0x13, 0x6e, 0x61, 0x9a, 0x3b, 0xae, 0x78,
-      0xd4, 0x6f, 0x2d, 0x1d, 0x40, 0x4b, 0xe3, 0x5f, 0xf8, 0xe8, 0x21, 0x89,
-      0x35, 0x73, 0x6d, 0x7e, 0x41, 0xc6, 0x0f, 0x0c, 0x01, 0x64, 0x61, 0xa8,
-      0x37, 0xef, 0x2b, 0x95, 0xb7, 0x34, 0xac, 0xc7, 0xdb, 0x66, 0x87, 0x45,
-      0xb4, 0x0f, 0x60, 0x01, 0x07, 0x29, 0x74, 0x32, 0x0b, 0xae, 0xbc, 0x08,
-      0x88, 0x15, 0xc3, 0x79, 0x4a, 0x1c, 0x5a, 0x9c, 0xc2, 0xfb, 0x4f, 0xd3,
-      0x17, 0xc2, 0x40, 0x71, 0x37, 0xea, 0xa6, 0x1e, 0xf0, 0x5b, 0xa5, 0xd7,
-      0x9b, 0x9e, 0x57, 0x44, 0x74, 0xc5, 0xd5, 0x5f, 0xba, 0xbc, 0xd7, 0xe1,
-      0xae, 0xd0, 0xd3, 0xb5, 0x10, 0xc6, 0x8b, 0xb1, 0x83, 0x7c, 0xaa, 0x3a,
-      0xbb, 0xe8, 0x7f, 0x56, 0xc4, 0x3b, 0x9d, 0x45, 0x09, 0x9b, 0x34, 0xc9,
-      0xfb, 0x5a, 0xa1, 0xab, 0xd0, 0x07, 0x79, 0x43, 0x58, 0x44, 0xd7, 0x40,
-      0xc4, 0xa7, 0xd3, 0xe9, 0x18, 0xb9, 0x78, 0x1d, 0x93, 0x0b, 0xc1, 0xdb,
-      0xc3, 0xae, 0xc9, 0xe8, 0x2c, 0xa7, 0x8c, 0x7e, 0x31, 0x1e, 0xec, 0x1c,
-      0xab, 0x83, 0xa0, 0x5d, 0x0e, 0xc3, 0x6a, 0x7c, 0x97, 0x09, 0xcf, 0x00,
-      0xa9, 0x66, 0xda, 0x21, 0x85, 0xaa, 0x47, 0xd8, 0xea, 0x8f, 0x72, 0x54,
-      0x03, 0x6c, 0xbc, 0x4b, 0xf9, 0x92, 0xae, 0x82, 0x75, 0x33, 0x10, 0x4d,
-      0x65, 0x4d, 0x0e, 0x73, 0x5d, 0x6f, 0x09, 0xee, 0x56, 0x78, 0x87, 0x0b,
-      0xa3, 0xaa, 0xc2, 0x5f, 0x49, 0x73, 0x0d, 0x78, 0xfa, 0x40, 0xc1, 0x25,
-      0x2f, 0x5d, 0x8a, 0xe1, 0xbf, 0x38, 0x2c, 0xd0, 0x26, 0xbd, 0xf5, 0x6e,
-      0x02, 0x01, 0x2e, 0x9e, 0x27, 0x64, 0x4b, 0x61, 0x8c, 0x68, 0x6e, 0x09,
-      0xfe, 0x0b, 0xf8, 0x36, 0x4e, 0x84, 0xb7, 0x76, 0xcb, 0x41, 0xf0, 0x40,
-      0x72, 0xc9, 0x74, 0x64, 0x5f, 0xbe, 0x9e, 0xfe, 0x9e, 0xce, 0x89, 0x84,
-      0x68, 0x81, 0x57, 0x2a, 0xdb, 0xd6, 0x01, 0xa8, 0x1b, 0x6e, 0x5d, 0xc4,
-      0x65, 0xbd, 0x0d, 0x98, 0x54, 0xa3, 0x18, 0x23, 0x09, 0x4a, 0x8d, 0x6c,
-      0xc6, 0x2e, 0xfe, 0x7a, 0xa9, 0x11, 0x92, 0x8b, 0xd0, 0xc1, 0xe7, 0x76,
-      0x71, 0xec, 0x34, 0xfc, 0xc8, 0x2a, 0x5e, 0x38, 0x52, 0xe6, 0xc8, 0xa5,
-      0x1d, 0x0b, 0xce, 0xf5, 0xc0, 0xe5, 0x0b, 0x88, 0xa9, 0x55, 0x88, 0x6c,
-      0xfa, 0xea, 0xaa, 0x39, 0x66, 0xdd, 0x80, 0x52, 0xe0, 0x7e, 0x45, 0x8e,
-      0x51, 0x2c, 0x36, 0x07, 0xd7, 0x2b, 0xf1, 0x46, 0x00, 0x66, 0xb2, 0x5a,
-      0x39, 0xbe, 0xf7, 0x26, 0x15, 0xbc, 0x55, 0xdb, 0xe9, 0x01, 0xdd, 0x54,
-      0x27, 0x2b, 0xfe, 0x86, 0x52, 0xef, 0xc6, 0x27, 0xa3, 0xf7, 0x55, 0x55,
-      0xb8, 0xe2, 0x1f, 0xcb, 0x32, 0xd8, 0xba, 0xd6, 0x69, 0xde, 0x8d, 0xa7,
-      0xfa, 0xad, 0xf6, 0x2a, 0xc0, 0x6f, 0x86, 0x50, 0x27, 0x5a, 0xe2, 0xe3,
-      0xf6, 0xb9, 0x01, 0xec, 0x01, 0x37, 0x84, 0x01,
-  };
-  EXPECT_EQ(Bytes(pkcs7_bytes, pkcs7_len),
-            Bytes(kExpectedOutput, sizeof(kExpectedOutput)));
+  std::string expected = GetTestData("crypto/pkcs7/test/sign_sha256.p7s");
+  EXPECT_EQ(Bytes(pkcs7_bytes, pkcs7_len), Bytes(expected));
 
   // Other option combinations should fail.
   EXPECT_FALSE(
diff --git a/src/crypto/pkcs7/pkcs7_x509.cc b/src/crypto/pkcs7/pkcs7_x509.cc
index 8484c38..8933f61 100644
--- a/src/crypto/pkcs7/pkcs7_x509.cc
+++ b/src/crypto/pkcs7/pkcs7_x509.cc
@@ -17,8 +17,12 @@
 #include <assert.h>
 #include <limits.h>
 
+#include <openssl/asn1.h>
 #include <openssl/bytestring.h>
+#include <openssl/cms.h>
+#include <openssl/digest.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 #include <openssl/pem.h>
@@ -26,6 +30,8 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
+#include "../asn1/internal.h"
+#include "../x509/internal.h"
 #include "../internal.h"
 #include "internal.h"
 
@@ -168,8 +174,8 @@
   return ret;
 }
 
-static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) {
-  const STACK_OF(X509) *certs = reinterpret_cast<const STACK_OF(X509) *>(arg);
+static int pkcs7_bundle_certificates_cb(CBB *out, void *arg) {
+  auto *certs = static_cast<const STACK_OF(X509) *>(arg);
   size_t i;
   CBB certificates;
 
@@ -195,14 +201,14 @@
 }
 
 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
-  return pkcs7_add_signed_data(out, /*digest_algos_cb=*/NULL,
-                               pkcs7_bundle_certificates_cb,
-                               /*signer_infos_cb=*/NULL, certs);
+  return pkcs7_add_signed_data(
+      out, /*signed_data_version=*/1,
+      /*digest_algos_cb=*/nullptr, pkcs7_bundle_certificates_cb,
+      /*signer_infos_cb=*/nullptr, const_cast<STACK_OF(X509) *>(certs));
 }
 
-static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
-  const STACK_OF(X509_CRL) *crls =
-      reinterpret_cast<const STACK_OF(X509_CRL) *>(arg);
+static int pkcs7_bundle_crls_cb(CBB *out, void *arg) {
+  auto *crls = static_cast<const STACK_OF(X509_CRL) *>(arg);
   size_t i;
   CBB crl_data;
 
@@ -228,9 +234,10 @@
 }
 
 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
-  return pkcs7_add_signed_data(out, /*digest_algos_cb=*/NULL,
-                               pkcs7_bundle_crls_cb,
-                               /*signer_infos_cb=*/NULL, crls);
+  return pkcs7_add_signed_data(
+      out, /*signed_data_version=*/1,
+      /*digest_algos_cb=*/nullptr, pkcs7_bundle_crls_cb,
+      /*signer_infos_cb=*/nullptr, const_cast<STACK_OF(X509_CRL) *>(crls));
 }
 
 static PKCS7 *pkcs7_new(CBS *cbs) {
@@ -363,164 +370,155 @@
 int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
 int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }
 
-// write_sha256_ai writes an AlgorithmIdentifier for SHA-256 to
-// |digest_algos_set|.
-static int write_sha256_ai(CBB *digest_algos_set, const void *arg) {
-  CBB seq;
-  return CBB_add_asn1(digest_algos_set, &seq, CBS_ASN1_SEQUENCE) &&
-         OBJ_nid2cbb(&seq, NID_sha256) &&  //
-         // https://datatracker.ietf.org/doc/html/rfc5754#section-2
-         // "Implementations MUST generate SHA2 AlgorithmIdentifiers with absent
-         //  parameters."
-         CBB_flush(digest_algos_set);
-}
-
-// sign_sha256 writes at most |max_out_sig| bytes of the signature of |data| by
-// |pkey| to |out_sig| and sets |*out_sig_len| to the number of bytes written.
-// It returns one on success or zero on error.
-static int sign_sha256(uint8_t *out_sig, size_t *out_sig_len,
-                       size_t max_out_sig, EVP_PKEY *pkey, BIO *data) {
-  static const size_t kBufSize = 4096;
-  uint8_t *buffer = reinterpret_cast<uint8_t *>(OPENSSL_malloc(kBufSize));
-  if (!buffer) {
-    return 0;
-  }
-
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-
-  int ret = 0;
-  if (!EVP_DigestSignInit(&ctx, NULL, EVP_sha256(), NULL, pkey)) {
-    goto out;
-  }
-
+static bool digest_sign_update(EVP_MD_CTX *ctx, BIO *data) {
   for (;;) {
-    const int n = BIO_read(data, buffer, kBufSize);
+    uint8_t buf[4096];
+    const int n = BIO_read(data, buf, sizeof(buf));
     if (n == 0) {
-      break;
-    } else if (n < 0 || !EVP_DigestSignUpdate(&ctx, buffer, n)) {
-      goto out;
+      return true;
+    } else if (n < 0 || !EVP_DigestSignUpdate(ctx, buf, n)) {
+      return false;
     }
   }
-
-  *out_sig_len = max_out_sig;
-  if (!EVP_DigestSignFinal(&ctx, out_sig, out_sig_len)) {
-    goto out;
-  }
-
-  ret = 1;
-
-out:
-  EVP_MD_CTX_cleanup(&ctx);
-  OPENSSL_free(buffer);
-  return ret;
 }
 
 namespace {
 struct signer_info_data {
-  const X509 *sign_cert;
-  uint8_t *signature;
-  size_t signature_len;
+  X509 *sign_cert = nullptr;
+  bssl::ScopedEVP_MD_CTX sign_ctx;
+  bool use_key_id = false;
 };
 }  // namespace
 
+static int write_signer_digest_algos(CBB *digest_algos_set, void *arg) {
+  auto *si_data = static_cast<struct signer_info_data *>(arg);
+  // https://www.rfc-editor.org/rfc/rfc5754.html#section-2
+  // "Implementations MUST generate SHA2 AlgorithmIdentifiers with absent
+  //  parameters."
+  return EVP_marshal_digest_algorithm_no_params(
+      digest_algos_set, EVP_MD_CTX_get0_md(si_data->sign_ctx.get()));
+}
+
 // write_signer_info writes the SignerInfo structure from
-// https://datatracker.ietf.org/doc/html/rfc2315#section-9.2 to |out|. It
-// returns one on success or zero on error.
-static int write_signer_info(CBB *out, const void *arg) {
-  const struct signer_info_data *const si_data =
-      reinterpret_cast<const struct signer_info_data *>(arg);
+// https://www.rfc-editor.org/rfc/rfc2315.html#section-9.2 and
+// https://www.rfc-editor.org/rfc/rfc5652.html#section-5.3 to |out|. It returns
+// one on success or zero on error.
+static int write_signer_info(CBB *out, void *arg) {
+  auto *si_data = static_cast<struct signer_info_data *>(arg);
 
-  int ret = 0;
-  uint8_t *subject_bytes = NULL;
-  uint8_t *serial_bytes = NULL;
-
-  const int subject_len =
-      i2d_X509_NAME(X509_get_subject_name(si_data->sign_cert), &subject_bytes);
-  const int serial_len = i2d_ASN1_INTEGER(
-      (ASN1_INTEGER *)X509_get0_serialNumber(si_data->sign_cert),
-      &serial_bytes);
-
-  CBB seq, issuer_and_serial, signing_algo, null, signature;
-  if (subject_len < 0 || serial_len < 0 ||
-      !CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
-      // version
-      !CBB_add_asn1_uint64(&seq, 1) ||
-      !CBB_add_asn1(&seq, &issuer_and_serial, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_bytes(&issuer_and_serial, subject_bytes, subject_len) ||
-      !CBB_add_bytes(&issuer_and_serial, serial_bytes, serial_len) ||
-      !write_sha256_ai(&seq, NULL) ||
-      !CBB_add_asn1(&seq, &signing_algo, CBS_ASN1_SEQUENCE) ||
-      !OBJ_nid2cbb(&signing_algo, NID_rsaEncryption) ||
-      !CBB_add_asn1(&signing_algo, &null, CBS_ASN1_NULL) ||
-      !CBB_add_asn1(&seq, &signature, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&signature, si_data->signature, si_data->signature_len) ||
-      !CBB_flush(out)) {
-    goto out;
+  uint64_t version = si_data->use_key_id ? 3u : 1u;
+  CBB seq, child, signing_algo, null, signature;
+  if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&seq, version)) {
+    return 0;
   }
 
-  ret = 1;
+  // Output the SignerIdentifier.
+  if (si_data->use_key_id) {
+    const ASN1_OCTET_STRING *skid =
+        X509_get0_subject_key_id(si_data->sign_cert);
+    if (skid == nullptr) {
+      OPENSSL_PUT_ERROR(CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
+      return 0;
+    }
+    // subjectKeyIdentifier is implicitly-tagged.
+    if (!CBB_add_asn1_element(&seq, CBS_ASN1_CONTEXT_SPECIFIC | 0,
+                              ASN1_STRING_get0_data(skid),
+                              ASN1_STRING_length(skid))) {
+      return 0;
+    }
+  } else {
+    if (!CBB_add_asn1(&seq, &child, CBS_ASN1_SEQUENCE) ||
+        !x509_marshal_name(&child, X509_get_subject_name(si_data->sign_cert)) ||
+        !asn1_marshal_integer(&child,
+                              X509_get0_serialNumber(si_data->sign_cert),
+                              /*tag=*/0)) {
+      return 0;
+    }
+  }
 
-out:
-  OPENSSL_free(subject_bytes);
-  OPENSSL_free(serial_bytes);
-  return ret;
+  // Output the digest and signature algorithm. This cannot use X.509 signature
+  // algorithms because CMS incorrectly decomposes signature algorithms into a
+  // combination of digesting and "encrypting" the digest, then uses the plain
+  // rsaEncryption OID instead of the hash-specific RSA OIDs. For now, we only
+  // support RSA.
+  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(si_data->sign_ctx->pctx);
+  if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
+    OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+  if (!EVP_marshal_digest_algorithm_no_params(
+          &seq, EVP_MD_CTX_get0_md(si_data->sign_ctx.get())) ||
+      !CBB_add_asn1(&seq, &signing_algo, CBS_ASN1_SEQUENCE) ||
+      !OBJ_nid2cbb(&signing_algo, NID_rsaEncryption) ||
+      !CBB_add_asn1(&signing_algo, &null, CBS_ASN1_NULL)) {
+    return 0;
+  }
+
+  // Output the signature.
+  uint8_t *ptr;
+  size_t sig_len;
+  if (!EVP_DigestSignFinal(si_data->sign_ctx.get(), nullptr, &sig_len) ||
+      !CBB_add_asn1(&seq, &signature, CBS_ASN1_OCTETSTRING) ||
+      !CBB_reserve(&signature, &ptr, sig_len) ||
+      !EVP_DigestSignFinal(si_data->sign_ctx.get(), ptr, &sig_len) ||
+      !CBB_did_write(&signature, sig_len) ||  //
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int pkcs7_add_external_signature(CBB *out, X509 *sign_cert, EVP_PKEY *key,
+                                 const EVP_MD *md, BIO *data, bool use_key_id) {
+  signer_info_data si_data;
+  si_data.use_key_id = use_key_id;
+  si_data.sign_cert = sign_cert;
+
+  // Set up the signature.
+  if (!EVP_DigestSignInit(si_data.sign_ctx.get(), nullptr, md, nullptr, key) ||
+      !digest_sign_update(si_data.sign_ctx.get(), data)) {
+    return 0;
+  }
+
+  // See RFC 5652, Section 5.1. When no certificates are present, the version
+  // comes from the highest SignerInfo version, which will be 3 (CMS) for a key
+  // ID, and 1 (CMS or PKCS#7) for issuer and serial.
+  uint64_t signed_data_version = use_key_id ? 3u : 1u;
+  return pkcs7_add_signed_data(
+      out, signed_data_version, write_signer_digest_algos,
+      /*cert_crl_cb=*/nullptr, write_signer_info, &si_data);
 }
 
 PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                   BIO *data, int flags) {
-  CBB cbb;
-  if (!CBB_init(&cbb, 2048)) {
-    return NULL;
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 2048)) {
+    return nullptr;
   }
 
-  uint8_t *der = NULL;
-  size_t len;
-  PKCS7 *ret = NULL;
-
-  if (sign_cert == NULL && pkey == NULL && flags == PKCS7_DETACHED) {
+  if (sign_cert == nullptr && pkey == nullptr && flags == PKCS7_DETACHED) {
     // Caller just wants to bundle certificates.
-    if (!PKCS7_bundle_certificates(&cbb, certs)) {
-      goto out;
+    if (!PKCS7_bundle_certificates(cbb.get(), certs)) {
+      return nullptr;
     }
-  } else if (sign_cert != NULL && pkey != NULL && certs == NULL &&
-             data != NULL &&
+  } else if (sign_cert != nullptr && pkey != nullptr && certs == nullptr &&
+             data != nullptr &&
              flags == (PKCS7_NOATTR | PKCS7_BINARY | PKCS7_NOCERTS |
-                       PKCS7_DETACHED) &&
-             EVP_PKEY_id(pkey) == NID_rsaEncryption) {
-    // sign-file.c from the Linux kernel.
-    const size_t signature_max_len = EVP_PKEY_size(pkey);
-    struct signer_info_data si_data = {
-        /*sign_cert=*/sign_cert,
-        /*signature=*/
-        reinterpret_cast<uint8_t *>(OPENSSL_malloc(signature_max_len)),
-        /*signature_len=*/0,
-    };
-
-    if (!si_data.signature ||
-        !sign_sha256(si_data.signature, &si_data.signature_len,
-                     signature_max_len, pkey, data) ||
-        !pkcs7_add_signed_data(&cbb, write_sha256_ai, /*cert_crl_cb=*/NULL,
-                               write_signer_info, &si_data)) {
-      OPENSSL_free(si_data.signature);
-      goto out;
+                       PKCS7_DETACHED)) {
+    // In OpenSSL, this API signs with some default hash. That default has been
+    // SHA-256 since 2015.
+    if (!pkcs7_add_external_signature(cbb.get(), sign_cert, pkey, EVP_sha256(),
+                                      data, /*use_key_id=*/false)) {
+      return nullptr;
     }
-    OPENSSL_free(si_data.signature);
   } else {
     OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-    goto out;
-  }
-
-  if (!CBB_finish(&cbb, &der, &len)) {
-    goto out;
+    return nullptr;
   }
 
   CBS cbs;
-  CBS_init(&cbs, der, len);
-  ret = pkcs7_new(&cbs);
-
-out:
-  CBB_cleanup(&cbb);
-  OPENSSL_free(der);
-  return ret;
+  CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
+  return pkcs7_new(&cbs);
 }
diff --git a/src/crypto/pkcs7/test/nss.p7c b/src/crypto/pkcs7/test/nss.p7c
new file mode 100644
index 0000000..1be5f1d
--- /dev/null
+++ b/src/crypto/pkcs7/test/nss.p7c
Binary files differ
diff --git a/src/crypto/pkcs7/test/openssl_crl.p7c b/src/crypto/pkcs7/test/openssl_crl.p7c
new file mode 100644
index 0000000..03c3c7f
--- /dev/null
+++ b/src/crypto/pkcs7/test/openssl_crl.p7c
Binary files differ
diff --git a/src/crypto/pkcs7/test/sign_cert.pem b/src/crypto/pkcs7/test/sign_cert.pem
new file mode 100644
index 0000000..09d0e33
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIURVkPzF/4dwy7419Qk75uhIuyf0EwDQYJKoZIhvcNAQEL
+BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA5MjExOTIyMTJaFw0yMjA5
+MjExOTIyMTJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
+HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQC1+MOn+BopcEVR4QMvjXdAxGkWFllXyQFDToL+qOiP
+RU1yN7C8KCtkbOAFttJIO4O/i0iZ7KqYbnmB6YUA/ONAcakocnrdoESgRJcVMeAx
+Dk/11OtMF5yIfeOOO/TUeVNmAUaT63gFbKy/adpqhzJtOv9BBl5VcYNGGSE+0wtb
+mjpmNsxunEQR1KLDc97fGYHeRfKoSyrCIEE8IaAEpKGR2Sku3v9Jwh7RpjupgiUA
+kH6pJk7VMZm5vl2wFjYvfysgjeN5ZtsxFDMaPYZStpxMxpNd5C9DsO2Ljp5NMpGf
+NGmG4ZqiaQg8z2cIM6ESmN1zDJdUh5IXed1fOxBZD/poUFH0wDRFWnvzlaPmjJEF
+rYLMK8svnE5nEQp9vu93ISFBx7cofs+niMaUXPEqaRSqruifN2M1it3kOf/8YZl1
+vurs+VtHD6nOJo6bd11+37aBidIB/BaWnzLrDmSTcPFa1tkTHwoLqc9+jThTq9jZ
+6w3lAMPpsoenyD19UmQB589+4kNp2SIO/TtzVQCGgQPXE2jDCl6G9aIPMkfvpPZK
+4THVil3WQRCFYnYdDO4HQXo2ZuC4RiqgY5ygfeoL+fa9k383lgxxAHQLS7xsbaVB
+40RmfdbdevgPYIwZNNO78ddRmMdSv6IknSW9gydGzY//btY+t1SWcBZWzn1Ewq8g
+2QIDAQABo1MwUTAdBgNVHQ4EFgQUotZD9ajEvnQYVezIWzcW4pzvMcUwHwYDVR0j
+BBgwFoAUotZD9ajEvnQYVezIWzcW4pzvMcUwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEAqCe42PIWoyLDx9bR+5cSp99N5xo5lLiSLtWx2emDbZB2
+AunqKYeEgIV+TWNF2w1SZ/ckFgV7SlL2Yl73N/veSNRfNAnpjLksGDFpdJb7YXrx
+cUvxdy1mr8oau6J7PC9JGjBTBrnhqwCQX1FtcAxODKll2Lsfuj6+bdC3rCK7KBEo
+ENamMJZIeo8lRP9qFF2xwCEzZjRv2zvB6O5o9045aTUcdCrwUfKE2sqY6EXRzFTC
+waK0HRCd1FLv9omhz/Ug5PMHP4d6MZfnAbFm+AzAhnpkrk/9TJYSOoNTNLWsuqhp
+dN0rKqiFWv1zIwfknXvTh1P1Ap+G5jffAca0zWUH1oKjE7ZZioSsaZ6gySnD8+WQ
+TPbOYtG+n0mhCH1TrU8Dqi3rd8g5IbC8loYLRH94QtodOnevD4Qo9Orfrsr8hGOW
+ABespanZArhoQ03DAtpNhtHm2NWJQF2uHNqcTrkq0omqZBTbMD1GKMBujoNooAUu
+w51U9r+RycPJTFqEGHb0nd7EjoyXEXtuX1Ld5fTZjQ9SszmQKQ8w3lHqRGNlkSiO
+e3IOOq2ruXmq1jykxpmi82IcTRUE8TZBfL/yz0nxpHKAYC1VwMezrkgZDGz4npxf
+1z2+qd58xU6/jsf7/+3xdPFubeEJujdbCkWQsQC5Rzm48zDWGq/pyzFji44K3TA=
+-----END CERTIFICATE-----
diff --git a/src/crypto/pkcs7/test/sign_key.pem b/src/crypto/pkcs7/test/sign_key.pem
new file mode 100644
index 0000000..97c6aaf
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQC1+MOn+BopcEVR
+4QMvjXdAxGkWFllXyQFDToL+qOiPRU1yN7C8KCtkbOAFttJIO4O/i0iZ7KqYbnmB
+6YUA/ONAcakocnrdoESgRJcVMeAxDk/11OtMF5yIfeOOO/TUeVNmAUaT63gFbKy/
+adpqhzJtOv9BBl5VcYNGGSE+0wtbmjpmNsxunEQR1KLDc97fGYHeRfKoSyrCIEE8
+IaAEpKGR2Sku3v9Jwh7RpjupgiUAkH6pJk7VMZm5vl2wFjYvfysgjeN5ZtsxFDMa
+PYZStpxMxpNd5C9DsO2Ljp5NMpGfNGmG4ZqiaQg8z2cIM6ESmN1zDJdUh5IXed1f
+OxBZD/poUFH0wDRFWnvzlaPmjJEFrYLMK8svnE5nEQp9vu93ISFBx7cofs+niMaU
+XPEqaRSqruifN2M1it3kOf/8YZl1vurs+VtHD6nOJo6bd11+37aBidIB/BaWnzLr
+DmSTcPFa1tkTHwoLqc9+jThTq9jZ6w3lAMPpsoenyD19UmQB589+4kNp2SIO/Ttz
+VQCGgQPXE2jDCl6G9aIPMkfvpPZK4THVil3WQRCFYnYdDO4HQXo2ZuC4RiqgY5yg
+feoL+fa9k383lgxxAHQLS7xsbaVB40RmfdbdevgPYIwZNNO78ddRmMdSv6IknSW9
+gydGzY//btY+t1SWcBZWzn1Ewq8g2QIDAQABAoICAFQ/liZAIaypxA5ChP0RG/Mq
+fBSzyC1ybFlDEjbg8LrUNST6T6LtXhmipp0+pWC33SljTPumrNzh2POir+djLbt6
+Y/zL88KEHwGsf95aNxe/Lpn8N+wEyn4O+rmxXIq6mTgSwyBc1jZ8uAXu9iZ37YrQ
+07jBQA+C/GoJ3HB/uTRx1TPZjxBu3Lz8m1auYLMd1hiYfd4Y3vT9hfZXAwTjS8KA
+riZ7K+p0K1yY/+pczNDUFTAvAjSGQEvUrP+HaRLYZ5ks1/IvArBYT8iIT5Yf4YFS
+NowzxwYp9fC02OmYzf7Nf0XpUXR7+EpfI66SaLJ5f51yaOXD1olz7F/YsprpYN7+
+oQd7EKar1bY3ROM6naUZtsIoEblg6B0mkyHWQgZ9wZRbcN7Zmuc/tIpLat7se+MP
+xQeAcH4Yhgnd2G6EELpmJBcyJ0Ss3atpI1eenU+ly++L4XbDQH9norKQ1PEDXYbV
+XMAV5uIsplBL7hGIa6/u/cRMM5eN3TJchtzIHFhq9+ENMvjTOfo0bflcYR+tNxGD
+6agWlD/Apedaapu/3Xp7ekyCiy/YTIwgT4U3rprYplzFM5HbzYtZ9ThxUm+CmnYj
+ZSCKiLoaQq+11/M9zH1Je0uJP5aK0CxOii2LVRXZYaQfbDtiHNWUSM7uPIZMnDgE
+IPTpl9CEfk7U3pgiUlg5AoIBAQDjUeikACPaRuewIjLqwTT2/j+ZO+/dCG4atFZa
+W+gdZ1NVDCdowQPBZWg6bqejRr1MvORg2L83kqZDQjaT9y59qxsFhXCy26xKp7aP
+Z4pEvUQmQnnf3RYHk3EBtOHyyMetTaghTGzL3MlPGo3uGbCiYtVoPKXZXGWeiOFN
+s9RNDh/7m6harB2bmX2cK+QPdJ1roVBXQDLkjh2mvLnC5vrsw81GWSkbWQpYmnVi
+YdLhytM+UTYjTrSugtrKk9e2KOFf2uR8PVaPeINEM4uubxW5YUy6gwF8ePtWYAtZ
+Skw3kdBdShhGzHORSY3NsRTJZL6AUdkhHYFTl/rlfj1WXsdnAoIBAQDM7i0u2T+E
+HmroTGiQAIRUEwUZQFDRkcEnM75jpkQT39jXF+zmhjzS1slJF2x0E0jUBV0juVWh
+mz1kHjTMV0j3/mvCeVv0iTcdIbHYRtTwmOjzkwTsZGh6T7okYck3KexRjpyhPpcX
+hOHOPJKS/muG0ZuaJjTEbJOzrSPU0rt0ppL7nOwd5jIOoGAciWiP17G1Lyyitrv4
+mKBK6mFQQWjAgEGy3jvBocbUo7Qo8Aucm6Y4eF1fUyC/X07RBzERHS4TuM+AQlDN
+T+LgTgcwTjE+Nzow2WMwCIbhVQqFRScuWqcJ6NQ6S/dV0R+aGJ90Ey+DtiZ9N9uV
+j0omAGvM8u2/AoIBADXF94FsIw8MfNw2itLrl2riJAtMmWYxC1K33EGNwi/KdHUG
+5f+qwQerxGcmK/O81STk/iVGwJ0VzMzWSfDgpRfHNSIuOcWln3EdkVsFBDlUiF2A
+ljH1q7NpFm9v6Y80HcAKQb52xLnI5boXrwFnBFi1hoQc7KKpb8R73sgxxQPhVoF/
+hejFFE/tlEAwRce+L0r5ovaw0hks4SjDNjI7z5nYi6ObjdTRUFg7WY9HUspk32m7
+blIV2Tn67GTFal7F9uJk9m3JWMOhn3OvudguoPX0ZWEtgll+iP4axDSAFd2DWcXn
+tCxzStdQjgHdZOxrL4FNW06xGxm6Nvi4zyuySfsCggEAOuIpC3ATBxRyZYMm/FGZ
+tEquyV2omz8FQA1nJFzu7MMCHHPcdzSVH4Pl3GGloQi1gW51H8GuMDxZ/H2NcDWY
+WuG49u1GFdKjinRXFKztnKBjNzHEVWRYfOSRuMh8N6SNKbYPnWlNos1k0IypFSGT
+pe5uhnF58gK8wgD67bkLce43B6NEWSb+tSMx2qFE8SfqAQSoD6zv//NjA4OrKJNS
+1RVFS279vpqMdib/qk+nFn3G2i0Dr1NEcpihHgCyAZff2Hze6pyjeQr+RrNE74VY
+MudNiiG8lV2t2+tClZ6ULoaPvpIvAP04+WiYav+uOX0VxwO8tXgqWSQOCzNNxlr7
+IwKCAQA7odNjE6Sc2qiecrOu13kEi3gT0heshIyZ0XhePrS1vgHfCouIRvNMw4FT
+45ZZUFDSdOxhrew5GuMeLvo2YILBjmkX3UqTojQMbur7FcGH8/P0Sm0f20Vc06oS
+sQF5Ji4LSyf6t9oQKePjFIGoIc6pf6BXJZYP4rBnzQzUQjH2yzDYDY3TuV7bFJJU
+DcSTGM6nP0fRMmgBtB14o7A6Gsy6X/N2ElgbvWT8YhmUC6H8DIzmZwHRKaG6C6g5
+eEjuAYenYNM4jxeteC1neUDIdGxH/BA7JrAqcGaN9GT+R47YIfiS2WrEssD1Pi5h
+hJTbHtjEDJ7BHLC/CNUhXbpyyu1y
+-----END PRIVATE KEY-----
diff --git a/src/crypto/pkcs7/test/sign_sha1.p7s b/src/crypto/pkcs7/test/sign_sha1.p7s
new file mode 100644
index 0000000..58438a0
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_sha1.p7s
Binary files differ
diff --git a/src/crypto/pkcs7/test/sign_sha1_key_id.p7s b/src/crypto/pkcs7/test/sign_sha1_key_id.p7s
new file mode 100644
index 0000000..e304a97
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_sha1_key_id.p7s
Binary files differ
diff --git a/src/crypto/pkcs7/test/sign_sha256.p7s b/src/crypto/pkcs7/test/sign_sha256.p7s
new file mode 100644
index 0000000..10a2c64
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_sha256.p7s
Binary files differ
diff --git a/src/crypto/pkcs7/test/sign_sha256_key_id.p7s b/src/crypto/pkcs7/test/sign_sha256_key_id.p7s
new file mode 100644
index 0000000..9cb8746
--- /dev/null
+++ b/src/crypto/pkcs7/test/sign_sha256_key_id.p7s
Binary files differ
diff --git a/src/crypto/pkcs7/test/windows.p7c b/src/crypto/pkcs7/test/windows.p7c
new file mode 100644
index 0000000..e602f95
--- /dev/null
+++ b/src/crypto/pkcs7/test/windows.p7c
Binary files differ
diff --git a/src/crypto/pkcs8/internal.h b/src/crypto/pkcs8/internal.h
index 0c72947..06f17a6 100644
--- a/src/crypto/pkcs8/internal.h
+++ b/src/crypto/pkcs8/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_PKCS8_INTERNAL_H
-#define OPENSSL_HEADER_PKCS8_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_PKCS8_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_PKCS8_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/stack.h>
@@ -51,11 +51,13 @@
                    size_t out_len, uint8_t *out, const EVP_MD *md);
 
 // pkcs12_pbe_encrypt_init configures |ctx| for encrypting with a PBES1 scheme
-// defined in PKCS#12. It writes the corresponding AlgorithmIdentifier to |out|.
-int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg,
-                            uint32_t iterations, const char *pass,
-                            size_t pass_len, const uint8_t *salt,
-                            size_t salt_len);
+// defined in PKCS#12, or a PBES2 scheme defined in PKCS#5. The algorithm is
+// determined as in |PKCS8_encrypt|. It writes the corresponding
+// AlgorithmIdentifier to |out|.
+int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg_nid,
+                            const EVP_CIPHER *alg_cipher, uint32_t iterations,
+                            const char *pass, size_t pass_len,
+                            const uint8_t *salt, size_t salt_len);
 
 struct pbe_suite {
   int pbe_nid;
@@ -74,6 +76,10 @@
 
 #define PKCS5_SALT_LEN 8
 
+// pkcs5_pbe2_nid_to_cipher returns the |EVP_CIPHER| for |nid| if |nid| is
+// supported with PKCS#5 PBES2, and nullptr otherwise.
+const EVP_CIPHER *pkcs5_pbe2_nid_to_cipher(int nid);
+
 int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
                             const char *pass, size_t pass_len, CBS *param);
 
@@ -94,4 +100,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_PKCS8_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_PKCS8_INTERNAL_H
diff --git a/src/crypto/pkcs8/p5_pbev2.cc b/src/crypto/pkcs8/p5_pbev2.cc
index bd0868b..bac897e 100644
--- a/src/crypto/pkcs8/p5_pbev2.cc
+++ b/src/crypto/pkcs8/p5_pbev2.cc
@@ -78,23 +78,20 @@
 };
 
 static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
-    if (CBS_mem_equal(cbs, kCipherOIDs[i].oid, kCipherOIDs[i].oid_len)) {
-      return kCipherOIDs[i].cipher_func();
+  for (const auto &cipher : kCipherOIDs) {
+    if (CBS_mem_equal(cbs, cipher.oid, cipher.oid_len)) {
+      return cipher.cipher_func();
     }
   }
 
-  return NULL;
+  return nullptr;
 }
 
 static int add_cipher_oid(CBB *out, int nid) {
-  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
-    if (kCipherOIDs[i].nid == nid) {
-      CBB child;
-      return CBB_add_asn1(out, &child, CBS_ASN1_OBJECT) &&
-             CBB_add_bytes(&child, kCipherOIDs[i].oid,
-                           kCipherOIDs[i].oid_len) &&
-             CBB_flush(out);
+  for (const auto &cipher : kCipherOIDs) {
+    if (cipher.nid == nid) {
+      return CBB_add_asn1_element(out, CBS_ASN1_OBJECT, cipher.oid,
+                                  cipher.oid_len);
     }
   }
 
@@ -102,6 +99,15 @@
   return 0;
 }
 
+const EVP_CIPHER *pkcs5_pbe2_nid_to_cipher(int nid) {
+  for (const auto &cipher : kCipherOIDs) {
+    if (cipher.nid == nid) {
+      return cipher.cipher_func();
+    }
+  }
+  return nullptr;
+}
+
 static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                                   const EVP_MD *pbkdf2_md, uint32_t iterations,
                                   const char *pass, size_t pass_len,
@@ -137,29 +143,27 @@
   }
 
   // See RFC 2898, appendix A.
-  CBB algorithm, oid, param, kdf, kdf_oid, kdf_param, salt_cbb, cipher_cbb,
-      iv_cbb;
+  CBB algorithm, param, kdf, kdf_param, cipher_cbb;
   if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, kPBES2, sizeof(kPBES2)) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, kPBES2,
+                            sizeof(kPBES2)) ||
       !CBB_add_asn1(&algorithm, &param, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1(&param, &kdf, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&kdf, &kdf_oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&kdf_oid, kPBKDF2, sizeof(kPBKDF2)) ||
+      !CBB_add_asn1_element(&kdf, CBS_ASN1_OBJECT, kPBKDF2, sizeof(kPBKDF2)) ||
       !CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&kdf_param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&salt_cbb, salt, salt_len) ||
+      !CBB_add_asn1_octet_string(&kdf_param, salt, salt_len) ||
       !CBB_add_asn1_uint64(&kdf_param, iterations) ||
       // Specify a key length for RC2.
       (cipher_nid == NID_rc2_cbc &&
        !CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) ||
       // Omit the PRF. We use the default hmacWithSHA1.
+      // TODO(crbug.com/396434682): Improve this defaults.
       !CBB_add_asn1(&param, &cipher_cbb, CBS_ASN1_SEQUENCE) ||
       !add_cipher_oid(&cipher_cbb, cipher_nid) ||
       // RFC 2898 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and
       // IV, but OpenSSL always uses an OCTET STRING IV, so we do the same.
-      !CBB_add_asn1(&cipher_cbb, &iv_cbb, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&iv_cbb, iv, EVP_CIPHER_iv_length(cipher)) ||
+      !CBB_add_asn1_octet_string(&cipher_cbb, iv,
+                                 EVP_CIPHER_iv_length(cipher)) ||
       !CBB_flush(out)) {
     return 0;
   }
diff --git a/src/crypto/pkcs8/pkcs12_test.cc b/src/crypto/pkcs8/pkcs12_test.cc
index e8d2c1b..eb1899f 100644
--- a/src/crypto/pkcs8/pkcs12_test.cc
+++ b/src/crypto/pkcs8/pkcs12_test.cc
@@ -135,10 +135,6 @@
 }
 
 TEST(PKCS12Test, TestEmptyPassword) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  return;  // The MAC check always passes in fuzzer mode.
-#endif
-
   // Generated with
   //   openssl pkcs12 -export -inkey ecdsa_p256_key.pem -in ecdsa_p256_cert.pem -password pass:  
   std::string data = GetTestData("crypto/pkcs8/test/empty_password.p12");
@@ -164,10 +160,6 @@
 }
 
 TEST(PKCS12Test, TestNullPassword) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  return;  // The MAC check always passes in fuzzer mode.
-#endif
-
   // Generated with
   //   openssl pkcs12 -export -inkey ecdsa_p256_key.pem -in ecdsa_p256_cert.pem -password pass:
   // But with OpenSSL patched to pass NULL into PKCS12_create and
@@ -424,6 +416,31 @@
                 {kTestCert2}, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
                 NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 100, 100);
 
+  // PBES2 ciphers.
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_rc2_cbc, NID_rc2_cbc, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_des_ede3_cbc, NID_des_ede3_cbc, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_aes_128_cbc, NID_aes_128_cbc, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_aes_192_cbc, NID_aes_192_cbc, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_aes_256_cbc, NID_aes_256_cbc, 100, 100);
+
+  // Mix and match.
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_pbe_WithSHA1And40BitRC2_CBC,
+                NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+                NID_aes_256_cbc, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_aes_256_cbc,
+                NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 100, 100);
+  TestRoundTrip(kPassword, nullptr /* no name */, kTestKey, kTestCert,
+                {kTestCert2}, NID_aes_128_cbc, NID_aes_256_cbc, 100, 100);
+
   // Test unencrypted and partially unencrypted PKCS#12 files.
   TestRoundTrip(kPassword, /*name=*/nullptr, kTestKey, kTestCert, {kTestCert2},
                 /*key_nid=*/-1,
diff --git a/src/crypto/pkcs8/pkcs8.cc b/src/crypto/pkcs8/pkcs8.cc
index 525b7ea..4b5609d 100644
--- a/src/crypto/pkcs8/pkcs8.cc
+++ b/src/crypto/pkcs8/pkcs8.cc
@@ -33,8 +33,8 @@
 
 static int pkcs12_encode_password(const char *in, size_t in_len, uint8_t **out,
                                   size_t *out_len) {
-  CBB cbb;
-  if (!CBB_init(&cbb, in_len * 2)) {
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), in_len * 2)) {
     return 0;
   }
 
@@ -44,22 +44,18 @@
   CBS_init(&cbs, (const uint8_t *)in, in_len);
   while (CBS_len(&cbs) != 0) {
     uint32_t c;
-    if (!CBS_get_utf8(&cbs, &c) || !CBB_add_ucs2_be(&cbb, c)) {
+    if (!CBS_get_utf8(&cbs, &c) || !CBB_add_ucs2_be(cbb.get(), c)) {
       OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INVALID_CHARACTERS);
-      goto err;
+      return 0;
     }
   }
 
   // Terminate the result with a UCS-2 NUL.
-  if (!CBB_add_ucs2_be(&cbb, 0) || !CBB_finish(&cbb, out, out_len)) {
-    goto err;
+  if (!CBB_add_ucs2_be(cbb.get(), 0) || !CBB_finish(cbb.get(), out, out_len)) {
+    return 0;
   }
 
   return 1;
-
-err:
-  CBB_cleanup(&cbb);
-  return 0;
 }
 
 int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
@@ -286,24 +282,32 @@
   return NULL;
 }
 
-int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg,
-                            uint32_t iterations, const char *pass,
-                            size_t pass_len, const uint8_t *salt,
-                            size_t salt_len) {
-  const struct pbe_suite *suite = get_pkcs12_pbe_suite(alg);
+int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg_nid,
+                            const EVP_CIPHER *alg_cipher, uint32_t iterations,
+                            const char *pass, size_t pass_len,
+                            const uint8_t *salt, size_t salt_len) {
+  // TODO(davidben): OpenSSL has since extended |pbe_nid| to control either
+  // the PBES1 scheme or the PBES2 PRF. E.g. passing |NID_hmacWithSHA256| will
+  // select PBES2 with HMAC-SHA256 as the PRF. Implement this if anything uses
+  // it. See 5693a30813a031d3921a016a870420e7eb93ec90 in OpenSSL.
+  if (alg_nid == -1) {
+    return PKCS5_pbe2_encrypt_init(out, ctx, alg_cipher, iterations, pass,
+                                   pass_len, salt, salt_len);
+  }
+
+  const struct pbe_suite *suite = get_pkcs12_pbe_suite(alg_nid);
   if (suite == NULL) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_ALGORITHM);
     return 0;
   }
 
   // See RFC 2898, appendix A.3.
-  CBB algorithm, oid, param, salt_cbb;
+  CBB algorithm, param;
   if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&oid, suite->oid, suite->oid_len) ||
+      !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, suite->oid,
+                            suite->oid_len) ||
       !CBB_add_asn1(&algorithm, &param, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&salt_cbb, salt, salt_len) ||
+      !CBB_add_asn1_octet_string(&param, salt, salt_len) ||
       !CBB_add_asn1_uint64(&param, iterations) || !CBB_flush(out)) {
     return 0;
   }
@@ -317,9 +321,7 @@
                       size_t in_len) {
   int ret = 0;
   uint8_t *buf = NULL;
-  ;
-  EVP_CIPHER_CTX ctx;
-  EVP_CIPHER_CTX_init(&ctx);
+  bssl::ScopedEVP_CIPHER_CTX ctx;
 
   CBS obj;
   const struct pbe_suite *suite = NULL;
@@ -339,7 +341,7 @@
     goto err;
   }
 
-  if (!suite->decrypt_init(suite, &ctx, pass, pass_len, algorithm)) {
+  if (!suite->decrypt_init(suite, ctx.get(), pass, pass_len, algorithm)) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE);
     goto err;
   }
@@ -355,8 +357,8 @@
   }
 
   int n1, n2;
-  if (!EVP_DecryptUpdate(&ctx, buf, &n1, in, (int)in_len) ||
-      !EVP_DecryptFinal_ex(&ctx, buf + n1, &n2)) {
+  if (!EVP_DecryptUpdate(ctx.get(), buf, &n1, in, (int)in_len) ||
+      !EVP_DecryptFinal_ex(ctx.get(), buf + n1, &n2)) {
     goto err;
   }
 
@@ -367,7 +369,6 @@
 
 err:
   OPENSSL_free(buf);
-  EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
 
@@ -405,8 +406,7 @@
   int ret = 0;
   uint8_t *plaintext = NULL, *salt_buf = NULL;
   size_t plaintext_len = 0;
-  EVP_CIPHER_CTX ctx;
-  EVP_CIPHER_CTX_init(&ctx);
+  bssl::ScopedEVP_CIPHER_CTX ctx;
 
   {
     // Generate a random salt if necessary.
@@ -437,29 +437,14 @@
     }
 
     CBB epki;
-    if (!CBB_add_asn1(out, &epki, CBS_ASN1_SEQUENCE)) {
+    if (!CBB_add_asn1(out, &epki, CBS_ASN1_SEQUENCE) ||
+        !pkcs12_pbe_encrypt_init(&epki, ctx.get(), pbe_nid, cipher,
+                                 (uint32_t)iterations, pass, pass_len, salt,
+                                 salt_len)) {
       goto err;
     }
 
-    // TODO(davidben): OpenSSL has since extended |pbe_nid| to control either
-    // the PBES1 scheme or the PBES2 PRF. E.g. passing |NID_hmacWithSHA256| will
-    // select PBES2 with HMAC-SHA256 as the PRF. Implement this if anything uses
-    // it. See 5693a30813a031d3921a016a870420e7eb93ec90 in OpenSSL.
-    int alg_ok;
-    if (pbe_nid == -1) {
-      alg_ok =
-          PKCS5_pbe2_encrypt_init(&epki, &ctx, cipher, (uint32_t)iterations,
-                                  pass, pass_len, salt, salt_len);
-    } else {
-      alg_ok =
-          pkcs12_pbe_encrypt_init(&epki, &ctx, pbe_nid, (uint32_t)iterations,
-                                  pass, pass_len, salt, salt_len);
-    }
-    if (!alg_ok) {
-      goto err;
-    }
-
-    size_t max_out = plaintext_len + EVP_CIPHER_CTX_block_size(&ctx);
+    size_t max_out = plaintext_len + EVP_CIPHER_CTX_block_size(ctx.get());
     if (max_out < plaintext_len) {
       OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
       goto err;
@@ -470,8 +455,8 @@
     int n1, n2;
     if (!CBB_add_asn1(&epki, &ciphertext, CBS_ASN1_OCTETSTRING) ||
         !CBB_reserve(&ciphertext, &ptr, max_out) ||
-        !EVP_CipherUpdate(&ctx, ptr, &n1, plaintext, plaintext_len) ||
-        !EVP_CipherFinal_ex(&ctx, ptr + n1, &n2) ||
+        !EVP_CipherUpdate(ctx.get(), ptr, &n1, plaintext, plaintext_len) ||
+        !EVP_CipherFinal_ex(ctx.get(), ptr + n1, &n2) ||
         !CBB_did_write(&ciphertext, n1 + n2) || !CBB_flush(out)) {
       goto err;
     }
@@ -482,6 +467,5 @@
 err:
   OPENSSL_free(plaintext);
   OPENSSL_free(salt_buf);
-  EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
diff --git a/src/crypto/pkcs8/pkcs8_x509.cc b/src/crypto/pkcs8/pkcs8_x509.cc
index 1e20e76..c5abc75 100644
--- a/src/crypto/pkcs8/pkcs8_x509.cc
+++ b/src/crypto/pkcs8/pkcs8_x509.cc
@@ -36,7 +36,7 @@
 
 
 int pkcs12_iterations_acceptable(uint64_t iterations) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
   static const uint64_t kIterationsLimit = 2048;
 #else
   // Windows imposes a limit of 600K. Mozilla say: “so them increasing
@@ -528,9 +528,9 @@
   }
 
   *out_mac_ok = CBS_mem_equal(expected_mac, hmac, hmac_len);
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  *out_mac_ok = 1;
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    *out_mac_ok = 1;
+  }
   ret = 1;
 
 err:
@@ -904,15 +904,15 @@
     return 1;  // Omit the OPTIONAL SET.
   }
   // See https://tools.ietf.org/html/rfc7292#section-4.2.
-  CBB attrs, attr, oid, values, value;
+  CBB attrs, attr, values, value;
   if (!CBB_add_asn1(bag, &attrs, CBS_ASN1_SET)) {
     return 0;
   }
   if (name_len != 0) {
     // See https://tools.ietf.org/html/rfc2985, section 5.5.1.
     if (!CBB_add_asn1(&attrs, &attr, CBS_ASN1_SEQUENCE) ||
-        !CBB_add_asn1(&attr, &oid, CBS_ASN1_OBJECT) ||
-        !CBB_add_bytes(&oid, kFriendlyName, sizeof(kFriendlyName)) ||
+        !CBB_add_asn1_element(&attr, CBS_ASN1_OBJECT, kFriendlyName,
+                              sizeof(kFriendlyName)) ||
         !CBB_add_asn1(&attr, &values, CBS_ASN1_SET) ||
         !CBB_add_asn1(&values, &value, CBS_ASN1_BMPSTRING)) {
       return 0;
@@ -931,11 +931,10 @@
   if (key_id_len != 0) {
     // See https://tools.ietf.org/html/rfc2985, section 5.5.2.
     if (!CBB_add_asn1(&attrs, &attr, CBS_ASN1_SEQUENCE) ||
-        !CBB_add_asn1(&attr, &oid, CBS_ASN1_OBJECT) ||
-        !CBB_add_bytes(&oid, kLocalKeyID, sizeof(kLocalKeyID)) ||
+        !CBB_add_asn1_element(&attr, CBS_ASN1_OBJECT, kLocalKeyID,
+                              sizeof(kLocalKeyID)) ||
         !CBB_add_asn1(&attr, &values, CBS_ASN1_SET) ||
-        !CBB_add_asn1(&values, &value, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&value, key_id, key_id_len)) {
+        !CBB_add_asn1_octet_string(&values, key_id, key_id_len)) {
       return 0;
     }
   }
@@ -944,17 +943,17 @@
 
 static int add_cert_bag(CBB *cbb, X509 *cert, const char *name,
                         const uint8_t *key_id, size_t key_id_len) {
-  CBB bag, bag_oid, bag_contents, cert_bag, cert_type, wrapped_cert, cert_value;
+  CBB bag, bag_contents, cert_bag, wrapped_cert, cert_value;
   if (  // See https://tools.ietf.org/html/rfc7292#section-4.2.
       !CBB_add_asn1(cbb, &bag, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&bag, &bag_oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&bag_oid, kCertBag, sizeof(kCertBag)) ||
+      !CBB_add_asn1_element(&bag, CBS_ASN1_OBJECT, kCertBag,
+                            sizeof(kCertBag)) ||
       !CBB_add_asn1(&bag, &bag_contents,
                     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
       // See https://tools.ietf.org/html/rfc7292#section-4.2.3.
       !CBB_add_asn1(&bag_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&cert_type, kX509Certificate, sizeof(kX509Certificate)) ||
+      !CBB_add_asn1_element(&cert_bag, CBS_ASN1_OBJECT, kX509Certificate,
+                            sizeof(kX509Certificate)) ||
       !CBB_add_asn1(&cert_bag, &wrapped_cert,
                     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
       !CBB_add_asn1(&wrapped_cert, &cert_value, CBS_ASN1_OCTETSTRING)) {
@@ -1005,23 +1004,26 @@
   return CBB_flush(cbb);
 }
 
-static int add_encrypted_data(CBB *out, int pbe_nid, const char *password,
-                              size_t password_len, uint32_t iterations,
-                              const uint8_t *in, size_t in_len) {
+// add_encrypted_data encrypts |in| with |pbe_nid| and |pbe_cipher|, writing the
+// result to |out|. It returns one on success and zero on error. |pbe_nid| and
+// |pbe_cipher| are interpreted as in |PKCS8_encrypt|.
+static int add_encrypted_data(CBB *out, int pbe_nid,
+                              const EVP_CIPHER *pbe_cipher,
+                              const char *password, size_t password_len,
+                              uint32_t iterations, const uint8_t *in,
+                              size_t in_len) {
   uint8_t salt[PKCS5_SALT_LEN];
   if (!RAND_bytes(salt, sizeof(salt))) {
     return 0;
   }
 
-  int ret = 0;
-  EVP_CIPHER_CTX ctx;
-  EVP_CIPHER_CTX_init(&ctx);
-  CBB content_info, type, wrapper, encrypted_data, encrypted_content_info,
-      inner_type, encrypted_content;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
+  CBB content_info, wrapper, encrypted_data, encrypted_content_info,
+      encrypted_content;
   if (  // Add the ContentInfo wrapping.
       !CBB_add_asn1(out, &content_info, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&content_info, &type, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&type, kPKCS7EncryptedData, sizeof(kPKCS7EncryptedData)) ||
+      !CBB_add_asn1_element(&content_info, CBS_ASN1_OBJECT, kPKCS7EncryptedData,
+                            sizeof(kPKCS7EncryptedData)) ||
       !CBB_add_asn1(&content_info, &wrapper,
                     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
       // See https://tools.ietf.org/html/rfc2315#section-13.
@@ -1030,47 +1032,42 @@
       // See https://tools.ietf.org/html/rfc2315#section-10.1.
       !CBB_add_asn1(&encrypted_data, &encrypted_content_info,
                     CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&encrypted_content_info, &inner_type, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&inner_type, kPKCS7Data, sizeof(kPKCS7Data)) ||
+      !CBB_add_asn1_element(&encrypted_content_info, CBS_ASN1_OBJECT,
+                            kPKCS7Data, sizeof(kPKCS7Data)) ||
       // Set up encryption and fill in contentEncryptionAlgorithm.
-      !pkcs12_pbe_encrypt_init(&encrypted_content_info, &ctx, pbe_nid,
-                               iterations, password, password_len, salt,
-                               sizeof(salt)) ||
+      !pkcs12_pbe_encrypt_init(&encrypted_content_info, ctx.get(), pbe_nid,
+                               pbe_cipher, iterations, password, password_len,
+                               salt, sizeof(salt)) ||
       // Note this tag is primitive. It is an implicitly-tagged OCTET_STRING, so
       // it inherits the inner tag's constructed bit.
       !CBB_add_asn1(&encrypted_content_info, &encrypted_content,
                     CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
-    goto err;
+    return 0;
   }
 
-  {
-    size_t max_out = in_len + EVP_CIPHER_CTX_block_size(&ctx);
-    if (max_out < in_len) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
-      goto err;
-    }
-
-    uint8_t *ptr;
-    int n1, n2;
-    if (!CBB_reserve(&encrypted_content, &ptr, max_out) ||
-        !EVP_CipherUpdate(&ctx, ptr, &n1, in, in_len) ||
-        !EVP_CipherFinal_ex(&ctx, ptr + n1, &n2) ||
-        !CBB_did_write(&encrypted_content, n1 + n2) || !CBB_flush(out)) {
-      goto err;
-    }
+  size_t max_out = in_len + EVP_CIPHER_CTX_block_size(ctx.get());
+  if (max_out < in_len) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
+    return 0;
   }
 
-  ret = 1;
+  uint8_t *ptr;
+  int n1, n2;
+  if (!CBB_reserve(&encrypted_content, &ptr, max_out) ||
+      !EVP_CipherUpdate(ctx.get(), ptr, &n1, in, in_len) ||
+      !EVP_CipherFinal_ex(ctx.get(), ptr + n1, &n2) ||
+      !CBB_did_write(&encrypted_content, n1 + n2) || !CBB_flush(out)) {
+    return 0;
+  }
 
-err:
-  EVP_CIPHER_CTX_cleanup(&ctx);
-  return ret;
+  return 1;
 }
 
 PKCS12 *PKCS12_create(const char *password, const char *name,
                       const EVP_PKEY *pkey, X509 *cert,
                       const STACK_OF(X509) *chain, int key_nid, int cert_nid,
                       int iterations, int mac_iterations, int key_type) {
+  // TODO(crbug.com/396434682): Improve these defaults.
   if (key_nid == 0) {
     key_nid = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
   }
@@ -1145,15 +1142,14 @@
 
   // See https://tools.ietf.org/html/rfc7292#section-4.
   PKCS12 *ret = NULL;
-  CBB cbb, pfx, auth_safe, auth_safe_oid, auth_safe_wrapper, auth_safe_data,
-      content_infos;
+  CBB cbb, pfx, auth_safe, auth_safe_wrapper, auth_safe_data, content_infos;
   uint8_t mac_key[EVP_MAX_MD_SIZE];
   if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &pfx, CBS_ASN1_SEQUENCE) ||
       !CBB_add_asn1_uint64(&pfx, 3) ||
       // auth_safe is a data ContentInfo.
       !CBB_add_asn1(&pfx, &auth_safe, CBS_ASN1_SEQUENCE) ||
-      !CBB_add_asn1(&auth_safe, &auth_safe_oid, CBS_ASN1_OBJECT) ||
-      !CBB_add_bytes(&auth_safe_oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
+      !CBB_add_asn1_element(&auth_safe, CBS_ASN1_OBJECT, kPKCS7Data,
+                            sizeof(kPKCS7Data)) ||
       !CBB_add_asn1(&auth_safe, &auth_safe_wrapper,
                     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
       !CBB_add_asn1(&auth_safe_wrapper, &auth_safe_data,
@@ -1173,10 +1169,10 @@
       // OpenSSL does not do this. We keep them separate for consistency. (Keys,
       // even when encrypted, are always placed in unencrypted ContentInfos.
       // PKCS#12 defines bag-level encryption for keys.)
-      CBB content_info, oid, wrapper, data;
+      CBB content_info, wrapper, data;
       if (!CBB_add_asn1(&content_infos, &content_info, CBS_ASN1_SEQUENCE) ||
-          !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
-          !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
+          !CBB_add_asn1_element(&content_info, CBS_ASN1_OBJECT, kPKCS7Data,
+                                sizeof(kPKCS7Data)) ||
           !CBB_add_asn1(&content_info, &wrapper,
                         CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
           !CBB_add_asn1(&wrapper, &data, CBS_ASN1_OCTETSTRING) ||
@@ -1186,13 +1182,21 @@
         goto err;
       }
     } else {
+      // This function differs from other OpenSSL functions in how PBES1 and
+      // PBES2 schemes are selected. If the NID matches a cipher, treat this as
+      // PBES2 instead. Convert to the other convention.
+      const EVP_CIPHER *cipher = pkcs5_pbe2_nid_to_cipher(cert_nid);
+      if (cipher != nullptr) {
+        cert_nid = -1;
+      }
       CBB plaintext_cbb;
-      int ok = CBB_init(&plaintext_cbb, 0) &&
-               add_cert_safe_contents(&plaintext_cbb, cert, chain, name, key_id,
-                                      key_id_len) &&
-               add_encrypted_data(
-                   &content_infos, cert_nid, password, password_len, iterations,
-                   CBB_data(&plaintext_cbb), CBB_len(&plaintext_cbb));
+      int ok =
+          CBB_init(&plaintext_cbb, 0) &&
+          add_cert_safe_contents(&plaintext_cbb, cert, chain, name, key_id,
+                                 key_id_len) &&
+          add_encrypted_data(&content_infos, cert_nid, cipher, password,
+                             password_len, iterations, CBB_data(&plaintext_cbb),
+                             CBB_len(&plaintext_cbb));
       CBB_cleanup(&plaintext_cbb);
       if (!ok) {
         goto err;
@@ -1205,35 +1209,41 @@
   // inside an encrypted ContentInfo, but OpenSSL does not do this and some
   // PKCS#12 consumers do not support KeyBags.)
   if (pkey != NULL) {
-    CBB content_info, oid, wrapper, data, safe_contents, bag, bag_oid,
-        bag_contents;
+    CBB content_info, wrapper, data, safe_contents, bag, bag_contents;
     if (  // Add another data ContentInfo.
         !CBB_add_asn1(&content_infos, &content_info, CBS_ASN1_SEQUENCE) ||
-        !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
-        !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
+        !CBB_add_asn1_element(&content_info, CBS_ASN1_OBJECT, kPKCS7Data,
+                              sizeof(kPKCS7Data)) ||
         !CBB_add_asn1(&content_info, &wrapper,
                       CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
         !CBB_add_asn1(&wrapper, &data, CBS_ASN1_OCTETSTRING) ||
         !CBB_add_asn1(&data, &safe_contents, CBS_ASN1_SEQUENCE) ||
         // Add a SafeBag containing a PKCS8ShroudedKeyBag.
-        !CBB_add_asn1(&safe_contents, &bag, CBS_ASN1_SEQUENCE) ||
-        !CBB_add_asn1(&bag, &bag_oid, CBS_ASN1_OBJECT)) {
+        !CBB_add_asn1(&safe_contents, &bag, CBS_ASN1_SEQUENCE)) {
       goto err;
     }
     if (key_nid < 0) {
-      if (!CBB_add_bytes(&bag_oid, kKeyBag, sizeof(kKeyBag)) ||
+      if (!CBB_add_asn1_element(&bag, CBS_ASN1_OBJECT, kKeyBag,
+                                sizeof(kKeyBag)) ||
           !CBB_add_asn1(&bag, &bag_contents,
                         CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
           !EVP_marshal_private_key(&bag_contents, pkey)) {
         goto err;
       }
     } else {
-      if (!CBB_add_bytes(&bag_oid, kPKCS8ShroudedKeyBag,
-                         sizeof(kPKCS8ShroudedKeyBag)) ||
+      // This function differs from other OpenSSL functions in how PBES1 and
+      // PBES2 schemes are selected. If the NID matches a cipher, treat this as
+      // PBES2 instead. Convert to the other convention.
+      const EVP_CIPHER *cipher = pkcs5_pbe2_nid_to_cipher(key_nid);
+      if (cipher != nullptr) {
+        key_nid = -1;
+      }
+      if (!CBB_add_asn1_element(&bag, CBS_ASN1_OBJECT, kPKCS8ShroudedKeyBag,
+                                sizeof(kPKCS8ShroudedKeyBag)) ||
           !CBB_add_asn1(&bag, &bag_contents,
                         CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
           !PKCS8_marshal_encrypted_private_key(
-              &bag_contents, key_nid, NULL, password, password_len,
+              &bag_contents, key_nid, cipher, password, password_len,
               NULL /* generate a random salt */,
               0 /* use default salt length */, iterations, pkey)) {
         goto err;
@@ -1266,14 +1276,22 @@
       goto err;
     }
 
-    CBB mac_data, digest_info, mac_cbb, mac_salt_cbb;
+    CBB mac_data, digest_info;
     if (!CBB_add_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE) ||
         !CBB_add_asn1(&mac_data, &digest_info, CBS_ASN1_SEQUENCE) ||
+        // OpenSSL and NSS always include a NULL parameter with the digest
+        // algorithm. Windows does not. RFC 7292 imports DigestInfo from PKCS
+        // #7. PKCS #7 does not actually use DigestInfo. It just describes
+        // RSASSA-PKCS1-v1_5 signing as encoding a DigestInfo and then
+        // "encrypting" it with the private key. In that context, NULL should be
+        // included. Confusingly, there is also a digestAlgorithm field in
+        // SignerInfo. There, RFC 5754 says to omit the NULL. But that field
+        // does not use DigestInfo per se.
+        //
+        // We match OpenSSL, NSS, and RSASSA-PKCS1-v1_5 in including the NULL.
         !EVP_marshal_digest_algorithm(&digest_info, mac_md) ||
-        !CBB_add_asn1(&digest_info, &mac_cbb, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&mac_cbb, mac, mac_len) ||
-        !CBB_add_asn1(&mac_data, &mac_salt_cbb, CBS_ASN1_OCTETSTRING) ||
-        !CBB_add_bytes(&mac_salt_cbb, mac_salt, sizeof(mac_salt)) ||
+        !CBB_add_asn1_octet_string(&digest_info, mac, mac_len) ||
+        !CBB_add_asn1_octet_string(&mac_data, mac_salt, sizeof(mac_salt)) ||
         // The iteration count has a DEFAULT of 1, but RFC 7292 says "The
         // default is for historical reasons and its use is deprecated." Thus we
         // explicitly encode the iteration count, though it is not valid DER.
diff --git a/src/crypto/poly1305/internal.h b/src/crypto/poly1305/internal.h
index 0ef2a9c..3447b4f 100644
--- a/src/crypto/poly1305/internal.h
+++ b/src/crypto/poly1305/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_POLY1305_INTERNAL_H
-#define OPENSSL_HEADER_POLY1305_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_POLY1305_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_POLY1305_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/poly1305.h>
@@ -38,4 +38,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_POLY1305_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_POLY1305_INTERNAL_H
diff --git a/src/crypto/pool/internal.h b/src/crypto/pool/internal.h
index bb119b1..2533fc9 100644
--- a/src/crypto/pool/internal.h
+++ b/src/crypto/pool/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_POOL_INTERNAL_H
-#define OPENSSL_HEADER_POOL_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_POOL_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_POOL_INTERNAL_H
 
 #include <openssl/lhash.h>
 #include <openssl/thread.h>
@@ -48,4 +48,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_POOL_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_POOL_INTERNAL_H
diff --git a/src/crypto/rand/deterministic.cc b/src/crypto/rand/deterministic.cc
index ab9bcf1..ca97d95 100644
--- a/src/crypto/rand/deterministic.cc
+++ b/src/crypto/rand/deterministic.cc
@@ -15,7 +15,7 @@
 #include <openssl/rand.h>
 
 #include "../bcm_support.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_DETERMINISTIC)
 
diff --git a/src/crypto/rand/fork_detect.cc b/src/crypto/rand/fork_detect.cc
index d7e482b..6870c20 100644
--- a/src/crypto/rand/fork_detect.cc
+++ b/src/crypto/rand/fork_detect.cc
@@ -17,6 +17,8 @@
 #endif
 
 #include "../bcm_support.h"
+#include "../internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_FORK_DETECTION_MADVISE)
 #include <assert.h>
@@ -34,8 +36,6 @@
 #include <unistd.h>
 #endif  // OPENSSL_FORK_DETECTION_PTHREAD_ATFORK
 
-#include "../internal.h"
-
 #if defined(OPENSSL_FORK_DETECTION_MADVISE)
 static int g_force_madv_wipeonfork;
 static int g_force_madv_wipeonfork_enabled;
diff --git a/src/crypto/rand/getentropy.cc b/src/crypto/rand/getentropy.cc
index 1bbb3f9..64cb3e9 100644
--- a/src/crypto/rand/getentropy.cc
+++ b/src/crypto/rand/getentropy.cc
@@ -19,7 +19,7 @@
 #include <openssl/rand.h>
 
 #include "../bcm_support.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_GETENTROPY)
 
diff --git a/src/crypto/rand/internal.h b/src/crypto/rand/internal.h
new file mode 100644
index 0000000..9ed080f
--- /dev/null
+++ b/src/crypto/rand/internal.h
@@ -0,0 +1,55 @@
+// Copyright 2024 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+#define OPENSSL_RAND_DETERMINISTIC
+#elif defined(OPENSSL_TRUSTY)
+#define OPENSSL_RAND_TRUSTY
+#elif defined(OPENSSL_WINDOWS)
+#define OPENSSL_RAND_WINDOWS
+#elif defined(OPENSSL_LINUX)
+#define OPENSSL_RAND_URANDOM
+#elif defined(OPENSSL_APPLE) && !defined(OPENSSL_MACOS)
+// Unlike macOS, iOS and similar hide away getentropy().
+#define OPENSSL_RAND_IOS
+#else
+// By default if you are integrating BoringSSL we expect you to
+// provide getentropy from the <unistd.h> header file.
+#define OPENSSL_RAND_GETENTROPY
+#endif
+
+#if defined(OPENSSL_LINUX)
+// On linux we use MADVISE instead of pthread_atfork(), due
+// to concerns about clone() being used for address space
+// duplication.
+#define OPENSSL_FORK_DETECTION
+#define OPENSSL_FORK_DETECTION_MADVISE
+#elif defined(OPENSSL_MACOS) || defined(OPENSSL_IOS) || \
+    defined(OPENSSL_OPENBSD) || defined(OPENSSL_FREEBSD)
+// These platforms may detect address space duplication with pthread_atfork.
+// iOS doesn't normally allow fork in apps, but it's there.
+#define OPENSSL_FORK_DETECTION
+#define OPENSSL_FORK_DETECTION_PTHREAD_ATFORK
+#elif defined(OPENSSL_WINDOWS) || defined(OPENSSL_TRUSTY) || \
+    defined(__ZEPHYR__) || defined(CROS_EC)
+// These platforms do not fork.
+#define OPENSSL_DOES_NOT_FORK
+#endif
+
+#endif  // OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
diff --git a/src/crypto/rand/ios.cc b/src/crypto/rand/ios.cc
index be13f1b..dd418df 100644
--- a/src/crypto/rand/ios.cc
+++ b/src/crypto/rand/ios.cc
@@ -15,7 +15,7 @@
 #include <openssl/rand.h>
 
 #include "../bcm_support.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_IOS)
 #include <stdlib.h>
diff --git a/src/crypto/rand/rand_test.cc b/src/crypto/rand/rand_test.cc
index b15b335..901ab49 100644
--- a/src/crypto/rand/rand_test.cc
+++ b/src/crypto/rand/rand_test.cc
@@ -55,7 +55,8 @@
 }
 
 #if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_IOS) && \
-    !defined(OPENSSL_FUCHSIA) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+    !defined(OPENSSL_FUCHSIA) &&                          \
+    !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 static bool ForkAndRand(bssl::Span<uint8_t> out, bool fork_unsafe_buffering) {
   int pipefds[2];
   if (pipe(pipefds) < 0) {
@@ -162,7 +163,7 @@
   }
 }
 #endif  // !OPENSSL_WINDOWS && !OPENSSL_IOS &&
-        // !OPENSSL_FUCHSIA && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE
+        // !OPENSSL_FUCHSIA && !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 
 #if defined(OPENSSL_THREADS)
 static void RunConcurrentRands(size_t num_threads) {
diff --git a/src/crypto/rand/sysrand_internal.h b/src/crypto/rand/sysrand_internal.h
deleted file mode 100644
index 90931a2..0000000
--- a/src/crypto/rand/sysrand_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2024 The BoringSSL Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef OPENSSL_HEADER_CRYPTO_SYSRAND_INTERNAL_H
-#define OPENSSL_HEADER_CRYPTO_SYSRAND_INTERNAL_H
-
-#include <openssl/base.h>
-
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-#define OPENSSL_RAND_DETERMINISTIC
-#elif defined(OPENSSL_TRUSTY)
-#define OPENSSL_RAND_TRUSTY
-#elif defined(OPENSSL_WINDOWS)
-#define OPENSSL_RAND_WINDOWS
-#elif defined(OPENSSL_LINUX)
-#define OPENSSL_RAND_URANDOM
-#elif defined(OPENSSL_APPLE) && !defined(OPENSSL_MACOS)
-// Unlike macOS, iOS and similar hide away getentropy().
-#define OPENSSL_RAND_IOS
-#else
-// By default if you are integrating BoringSSL we expect you to
-// provide getentropy from the <unistd.h> header file.
-#define OPENSSL_RAND_GETENTROPY
-#endif
-
-#endif  // OPENSSL_HEADER_CRYPTO__SYSRAND_INTERNAL_H
diff --git a/src/crypto/rand/trusty.cc b/src/crypto/rand/trusty.cc
index 9ddf024..a2b23ae 100644
--- a/src/crypto/rand/trusty.cc
+++ b/src/crypto/rand/trusty.cc
@@ -15,7 +15,7 @@
 #include <openssl/rand.h>
 
 #include "../bcm_support.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_TRUSTY)
 #include <stdint.h>
diff --git a/src/crypto/rand/urandom.cc b/src/crypto/rand/urandom.cc
index ce862b5..1d9062f 100644
--- a/src/crypto/rand/urandom.cc
+++ b/src/crypto/rand/urandom.cc
@@ -19,7 +19,7 @@
 #include <openssl/rand.h>
 
 #include "../bcm_support.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_URANDOM)
 
diff --git a/src/crypto/rand/windows.cc b/src/crypto/rand/windows.cc
index 884d789..59df467 100644
--- a/src/crypto/rand/windows.cc
+++ b/src/crypto/rand/windows.cc
@@ -16,15 +16,13 @@
 
 #include "../bcm_support.h"
 #include "../internal.h"
-#include "sysrand_internal.h"
+#include "internal.h"
 
 #if defined(OPENSSL_RAND_WINDOWS)
 
 #include <limits.h>
 #include <stdlib.h>
 
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
-
 #include <windows.h>
 
 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
@@ -33,8 +31,6 @@
 OPENSSL_MSVC_PRAGMA(comment(lib, "bcrypt.lib"))
 #endif  // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
 
-OPENSSL_MSVC_PRAGMA(warning(pop))
-
 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
     !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
index 4e88afd..21552bf 100644
--- a/src/crypto/rsa/internal.h
+++ b/src/crypto/rsa/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
-#define OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_RSA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_RSA_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -33,4 +33,4 @@
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_RSA_EXTRA_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_RSA_INTERNAL_H
diff --git a/src/crypto/rsa/rsa_crypt.cc b/src/crypto/rsa/rsa_crypt.cc
index acf207e..ce4ae7d 100644
--- a/src/crypto/rsa/rsa_crypt.cc
+++ b/src/crypto/rsa/rsa_crypt.cc
@@ -349,25 +349,21 @@
   }
 
   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;
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (ctx == nullptr) {
+    return 0;
   }
 
-  BN_CTX_start(ctx);
-  f = BN_CTX_get(ctx);
-  result = BN_CTX_get(ctx);
-  buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(rsa_size));
+  bssl::BN_CTXScope scope(ctx.get());
+  BIGNUM *f = BN_CTX_get(ctx.get());
+  BIGNUM *result = BN_CTX_get(ctx.get());
+  uint8_t *buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(rsa_size));
+  int i, ret = 0;
   if (!f || !result || !buf) {
     goto err;
   }
@@ -378,8 +374,8 @@
       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);
+      i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len, nullptr, 0,
+                                          nullptr, nullptr);
       break;
     case RSA_NO_PADDING:
       i = RSA_padding_add_none(buf, rsa_size, in, in_len);
@@ -393,7 +389,7 @@
     goto err;
   }
 
-  if (BN_bin2bn(buf, rsa_size, f) == NULL) {
+  if (BN_bin2bn(buf, rsa_size, f) == nullptr) {
     goto err;
   }
 
@@ -403,8 +399,9 @@
     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)) {
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx.get()) ||
+      !BN_mod_exp_mont(result, f, rsa->e, &rsa->mont_n->N, ctx.get(),
+                       rsa->mont_n)) {
     goto err;
   }
 
@@ -419,12 +416,7 @@
   ret = 1;
 
 err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
   OPENSSL_free(buf);
-
   return ret;
 }
 
diff --git a/src/crypto/slhdsa/slhdsa_test.cc b/src/crypto/slhdsa/slhdsa_test.cc
index aabebd8..c00a2f9 100644
--- a/src/crypto/slhdsa/slhdsa_test.cc
+++ b/src/crypto/slhdsa/slhdsa_test.cc
@@ -220,4 +220,15 @@
                 NISTPrehashSignatureVerificationFileTest);
 }
 
+TEST(SLHDSATest, Self) { boringssl_self_test_slhdsa(); }
+
+TEST(SLHDSATest, NullptrArgumentsToCreate) {
+  // For FIPS reasons, this should fail rather than crash.
+  ASSERT_EQ(BCM_slhdsa_sha2_128s_generate_key_fips(nullptr, nullptr),
+            bcm_status::failure);
+  ASSERT_EQ(BCM_slhdsa_sha2_128s_generate_key_from_seed_fips(nullptr, nullptr,
+                                                             nullptr),
+            bcm_status::failure);
+}
+
 }  // namespace
diff --git a/src/crypto/spake2plus/internal.h b/src/crypto/spake2plus/internal.h
index 49a8a28..c5c99cd 100644
--- a/src/crypto/spake2plus/internal.h
+++ b/src/crypto/spake2plus/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_SPAKE2PLUS_INTERNAL_H
-#define OPENSSL_HEADER_SPAKE2PLUS_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_SPAKE2PLUS_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_SPAKE2PLUS_INTERNAL_H
 
 #include <openssl/base.h>
 
@@ -201,4 +201,4 @@
 
 BSSL_NAMESPACE_END
 
-#endif  // OPENSSL_HEADER_SPAKE2PLUS_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_SPAKE2PLUS_INTERNAL_H
diff --git a/src/crypto/test/abi_test.cc b/src/crypto/test/abi_test.cc
index e37b675..2c300f4 100644
--- a/src/crypto/test/abi_test.cc
+++ b/src/crypto/test/abi_test.cc
@@ -40,10 +40,8 @@
 #include <unistd.h>
 #elif defined(OPENSSL_WINDOWS)
 #define SUPPORTS_UNWIND_TEST
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
 #include <dbghelp.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 #endif  // X86_64 && SUPPORTS_ABI_TEST
 
diff --git a/src/crypto/test/abi_test.h b/src/crypto/test/abi_test.h
index bb5ae94..ad65c57 100644
--- a/src/crypto/test/abi_test.h
+++ b/src/crypto/test/abi_test.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_ABI_TEST_H
-#define OPENSSL_HEADER_ABI_TEST_H
+#ifndef OPENSSL_HEADER_CRYPTO_TEST_ABI_TEST_H
+#define OPENSSL_HEADER_CRYPTO_TEST_ABI_TEST_H
 
 #include <gtest/gtest.h>
 
@@ -479,4 +479,4 @@
 #endif  // SUPPORTS_ABI_TEST
 
 
-#endif  // OPENSSL_HEADER_ABI_TEST_H
+#endif  // OPENSSL_HEADER_CRYPTO_TEST_ABI_TEST_H
diff --git a/src/crypto/test/file_test.h b/src/crypto/test/file_test.h
index b35056f..4cd22db 100644
--- a/src/crypto/test/file_test.h
+++ b/src/crypto/test/file_test.h
@@ -19,9 +19,6 @@
 
 #include <stdint.h>
 
-OPENSSL_MSVC_PRAGMA(warning(push))
-OPENSSL_MSVC_PRAGMA(warning(disable : 4702))
-
 #include <functional>
 #include <map>
 #include <memory>
@@ -29,8 +26,6 @@
 #include <string>
 #include <vector>
 
-OPENSSL_MSVC_PRAGMA(warning(pop))
-
 // File-based test framework.
 //
 // This module provides a file-based test framework. The file format is based on
diff --git a/src/crypto/test/file_util.cc b/src/crypto/test/file_util.cc
index 6a9c0ba..20d53f9 100644
--- a/src/crypto/test/file_util.cc
+++ b/src/crypto/test/file_util.cc
@@ -17,9 +17,7 @@
 #include <stdlib.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <fcntl.h>
 #include <sys/stat.h>
diff --git a/src/crypto/test/gtest_main.h b/src/crypto/test/gtest_main.h
index fee5fe3..8cb2900 100644
--- a/src/crypto/test/gtest_main.h
+++ b/src/crypto/test/gtest_main.h
@@ -24,9 +24,7 @@
 #include <openssl/err.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <signal.h>
 #endif
diff --git a/src/crypto/thread_win.cc b/src/crypto/thread_win.cc
index e50fc62..4e22c47 100644
--- a/src/crypto/thread_win.cc
+++ b/src/crypto/thread_win.cc
@@ -18,9 +18,7 @@
 
 #if defined(OPENSSL_WINDOWS_THREADS)
 
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 
 #include <assert.h>
 #include <stdlib.h>
diff --git a/src/crypto/trust_token/internal.h b/src/crypto/trust_token/internal.h
index 308a8e8..208e9c3 100644
--- a/src/crypto/trust_token/internal.h
+++ b/src/crypto/trust_token/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_TRUST_TOKEN_INTERNAL_H
-#define OPENSSL_HEADER_TRUST_TOKEN_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_TRUST_TOKEN_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_TRUST_TOKEN_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/ec.h>
@@ -409,4 +409,4 @@
 }  // extern C++
 #endif
 
-#endif  // OPENSSL_HEADER_TRUST_TOKEN_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_TRUST_TOKEN_INTERNAL_H
diff --git a/src/crypto/x509/a_sign.cc b/src/crypto/x509/a_sign.cc
index a790cbf..018a31b 100644
--- a/src/crypto/x509/a_sign.cc
+++ b/src/crypto/x509/a_sign.cc
@@ -31,13 +31,11 @@
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
     return 0;
   }
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
-    EVP_MD_CTX_cleanup(&ctx);
+  bssl::ScopedEVP_MD_CTX ctx;
+  if (!EVP_DigestSignInit(ctx.get(), nullptr, type, nullptr, pkey)) {
     return 0;
   }
-  return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+  return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx.get());
 }
 
 int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
diff --git a/src/crypto/x509/asn1_gen.cc b/src/crypto/x509/asn1_gen.cc
index 6b9769f..9b6bf17 100644
--- a/src/crypto/x509/asn1_gen.cc
+++ b/src/crypto/x509/asn1_gen.cc
@@ -58,27 +58,23 @@
 static int bitstr_cb(const char *elem, size_t len, void *bitstr);
 
 ASN1_TYPE *ASN1_generate_v3(const char *str, const X509V3_CTX *cnf) {
-  CBB cbb;
-  if (!CBB_init(&cbb, 0) ||  //
-      !generate_v3(&cbb, str, cnf, /*tag=*/0, ASN1_GEN_FORMAT_ASCII,
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||  //
+      !generate_v3(cbb.get(), str, cnf, /*tag=*/0, ASN1_GEN_FORMAT_ASCII,
                    /*depth=*/0)) {
-    CBB_cleanup(&cbb);
-    return NULL;
+    return nullptr;
   }
 
   // While not strictly necessary to avoid a DoS (we rely on any super-linear
   // checks being performed internally), cap the overall output to
   // |ASN1_GEN_MAX_OUTPUT| so the externally-visible behavior is consistent.
-  if (CBB_len(&cbb) > ASN1_GEN_MAX_OUTPUT) {
+  if (CBB_len(cbb.get()) > ASN1_GEN_MAX_OUTPUT) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-    CBB_cleanup(&cbb);
-    return NULL;
+    return nullptr;
   }
 
-  const uint8_t *der = CBB_data(&cbb);
-  ASN1_TYPE *ret = d2i_ASN1_TYPE(NULL, &der, CBB_len(&cbb));
-  CBB_cleanup(&cbb);
-  return ret;
+  const uint8_t *der = CBB_data(cbb.get());
+  return d2i_ASN1_TYPE(nullptr, &der, CBB_len(cbb.get()));
 }
 
 static int cbs_str_equal(const CBS *cbs, const char *str) {
diff --git a/src/crypto/x509/internal.h b/src/crypto/x509/internal.h
index 7e92c1f..1fab446 100644
--- a/src/crypto/x509/internal.h
+++ b/src/crypto/x509/internal.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_X509_INTERNAL_H
-#define OPENSSL_HEADER_X509_INTERNAL_H
+#ifndef OPENSSL_HEADER_CRYPTO_X509_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_X509_INTERNAL_H
 
 #include <openssl/base.h>
 #include <openssl/evp.h>
@@ -547,9 +547,21 @@
 // TODO(https://crbug.com/boringssl/695): Remove this.
 int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname);
 
+// x509_marshal_name marshals |in| as a DER-encoded, X.509 Name and writes the
+// result to |out|. It returns one on success and zero on error.
+//
+// TODO(https://crbug.com/boringssl/407): This function should be const and
+// thread-safe but is currently neither in some cases, notably if |in| was
+// mutated.
+int x509_marshal_name(CBB *out, X509_NAME *in);
+
+// x509_marshal_algorithm marshals |in| as a DER-encoded, AlgorithmIdentifier
+// and writes the result to |out|. It returns one on success and zero on error.
+int x509_marshal_algorithm(CBB *out, const X509_ALGOR *in);
+
 
 #if defined(__cplusplus)
 }  // extern C
 #endif
 
-#endif  // OPENSSL_HEADER_X509_INTERNAL_H
+#endif  // OPENSSL_HEADER_CRYPTO_X509_INTERNAL_H
diff --git a/src/crypto/x509/v3_conf.cc b/src/crypto/x509/v3_conf.cc
index 8b755d3..f48c128 100644
--- a/src/crypto/x509/v3_conf.cc
+++ b/src/crypto/x509/v3_conf.cc
@@ -226,49 +226,41 @@
 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
                                             int crit, int gen_type,
                                             const X509V3_CTX *ctx) {
-  unsigned char *ext_der = NULL;
-  size_t ext_len = 0;
-  ASN1_OBJECT *obj = NULL;
-  ASN1_OCTET_STRING *oct = NULL;
-  X509_EXTENSION *extension = NULL;
-  if (!(obj = OBJ_txt2obj(ext, 0))) {
+  bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj(ext, 0));
+  if (obj == nullptr) {
     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
     ERR_add_error_data(2, "name=", ext);
-    goto err;
+    return nullptr;
   }
 
+  bssl::UniquePtr<unsigned char> ext_der;
+  size_t ext_len = 0;
   if (gen_type == 1) {
-    ext_der = x509v3_hex_to_bytes(value, &ext_len);
+    ext_der.reset(x509v3_hex_to_bytes(value, &ext_len));
   } else if (gen_type == 2) {
-    ext_der = generic_asn1(value, ctx, &ext_len);
+    ext_der.reset(generic_asn1(value, ctx, &ext_len));
   }
 
-  if (ext_der == NULL) {
+  if (ext_der == nullptr) {
     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
     ERR_add_error_data(2, "value=", value);
-    goto err;
+    return nullptr;
   }
 
   if (ext_len > INT_MAX) {
     OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
-    goto err;
+    return nullptr;
   }
 
-  oct = ASN1_OCTET_STRING_new();
-  if (oct == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OCTET_STRING> oct(ASN1_OCTET_STRING_new());
+  if (oct == nullptr) {
+    return nullptr;
   }
 
-  ASN1_STRING_set0(oct, ext_der, (int)ext_len);
-  ext_der = NULL;
+  ASN1_STRING_set0(oct.get(), ext_der.get(), (int)ext_len);
+  ext_der.release();  // ASN1_STRING_set0 took ownership.
 
-  extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
-
-err:
-  ASN1_OBJECT_free(obj);
-  ASN1_OCTET_STRING_free(oct);
-  OPENSSL_free(ext_der);
-  return extension;
+  return X509_EXTENSION_create_by_OBJ(nullptr, obj.get(), crit, oct.get());
 }
 
 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
diff --git a/src/crypto/x509/v3_info.cc b/src/crypto/x509/v3_info.cc
index 5e149aa..4f6c69d 100644
--- a/src/crypto/x509/v3_info.cc
+++ b/src/crypto/x509/v3_info.cc
@@ -122,43 +122,40 @@
 static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method,
                                        const X509V3_CTX *ctx,
                                        const STACK_OF(CONF_VALUE) *nval) {
-  AUTHORITY_INFO_ACCESS *ainfo = NULL;
-  ACCESS_DESCRIPTION *acc;
-  if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
-    return NULL;
+  bssl::UniquePtr<AUTHORITY_INFO_ACCESS> ainfo(sk_ACCESS_DESCRIPTION_new_null());
+  if (ainfo == nullptr) {
+    return nullptr;
   }
   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
-    if (!(acc = ACCESS_DESCRIPTION_new()) ||
-        !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
-      goto err;
+    bssl::UniquePtr<ACCESS_DESCRIPTION> acc(ACCESS_DESCRIPTION_new());
+    if (acc == nullptr) {
+      return nullptr;
     }
     char *ptmp = strchr(cnf->name, ';');
     if (!ptmp) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
-      goto err;
+      return nullptr;
     }
     CONF_VALUE ctmp;
     ctmp.name = ptmp + 1;
     ctmp.value = cnf->value;
     if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) {
-      goto err;
+      return nullptr;
     }
-    char *objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name);
-    if (objtmp == NULL) {
-      goto err;
+    bssl::UniquePtr<char> objtmp(OPENSSL_strndup(cnf->name, ptmp - cnf->name));
+    if (objtmp == nullptr) {
+      return nullptr;
     }
-    acc->method = OBJ_txt2obj(objtmp, 0);
+    acc->method = OBJ_txt2obj(objtmp.get(), 0);
     if (!acc->method) {
       OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
-      ERR_add_error_data(2, "value=", objtmp);
-      OPENSSL_free(objtmp);
-      goto err;
+      ERR_add_error_data(2, "value=", objtmp.get());
+      return nullptr;
     }
-    OPENSSL_free(objtmp);
+    if (!bssl::PushToStack(ainfo.get(), std::move(acc))) {
+      return nullptr;
+    }
   }
-  return ainfo;
-err:
-  sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
-  return NULL;
+  return ainfo.release();
 }
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 2008957..aa96a28 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <functional>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -6463,6 +6464,31 @@
       {"policyMappings", "invalid_oid:2.2.2.2", nullptr, {}},
       {"policyMappings", "1.1.1.1:invalid_oid", nullptr, {}},
 
+      // authorityInfoAccess is a comma-separated list of
+      // accessMethod;accessLocation tuples, where the latter specifies a
+      // GeneralName.
+      {"authorityInfoAccess",
+       "caIssuers;URI:http://example.com/1, "
+       "caIssuers;URI:http://example.com/2, OCSP;URI:http://example.com/3, "
+       "OCSP;DNS:non-uri-does-not-make-sense-but-is-allowed.test",
+       nullptr,
+       {0x30, 0x81, 0xb3, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01,
+        0x01, 0x04, 0x81, 0xa6, 0x30, 0x81, 0xa3, 0x30, 0x20, 0x06, 0x08, 0x2b,
+        0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x14, 0x68, 0x74, 0x74,
+        0x70, 0x3a, 0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+        0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x30, 0x20, 0x06, 0x08, 0x2b, 0x06, 0x01,
+        0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x14, 0x68, 0x74, 0x74, 0x70, 0x3a,
+        0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+        0x6d, 0x2f, 0x32, 0x30, 0x20, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+        0x07, 0x30, 0x01, 0x86, 0x14, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+        0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+        0x33, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
+        0x01, 0x82, 0x2f, 0x6e, 0x6f, 0x6e, 0x2d, 0x75, 0x72, 0x69, 0x2d, 0x64,
+        0x6f, 0x65, 0x73, 0x2d, 0x6e, 0x6f, 0x74, 0x2d, 0x6d, 0x61, 0x6b, 0x65,
+        0x2d, 0x73, 0x65, 0x6e, 0x73, 0x65, 0x2d, 0x62, 0x75, 0x74, 0x2d, 0x69,
+        0x73, 0x2d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x74, 0x65,
+        0x73, 0x74}},
+
       // The "DER:" prefix just specifies an arbitrary byte string. Colons
       // separators are ignored.
       {kTestOID, "DER:0001020304", nullptr, {0x30, 0x15, 0x06, 0x0c, 0x2a, 0x86,
@@ -7126,20 +7152,16 @@
   static const char kOIDText[] = "1.2.840.113554.4.1.72585.0";
 
   auto encode_single_attribute_name =
-      [](CBS_ASN1_TAG tag,
-         const std::string &contents) -> std::vector<uint8_t> {
+      [](CBS_ASN1_TAG tag, std::string_view contents) -> std::vector<uint8_t> {
+    auto bytes = bssl::StringAsBytes(contents);
     bssl::ScopedCBB cbb;
-    CBB seq, rdn, attr, attr_type, attr_value;
+    CBB seq, rdn, attr;
     if (!CBB_init(cbb.get(), 128) ||
         !CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE) ||
         !CBB_add_asn1(&seq, &rdn, CBS_ASN1_SET) ||
         !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) ||
-        !CBB_add_asn1(&attr, &attr_type, CBS_ASN1_OBJECT) ||
-        !CBB_add_bytes(&attr_type, kOID, sizeof(kOID)) ||
-        !CBB_add_asn1(&attr, &attr_value, tag) ||
-        !CBB_add_bytes(&attr_value,
-                       reinterpret_cast<const uint8_t *>(contents.data()),
-                       contents.size()) ||
+        !CBB_add_asn1_element(&attr, CBS_ASN1_OBJECT, kOID, sizeof(kOID)) ||
+        !CBB_add_asn1_element(&attr, tag, bytes.data(), bytes.size()) ||
         !CBB_flush(cbb.get())) {
       ADD_FAILURE() << "Could not encode name";
       return {};
@@ -7165,35 +7187,52 @@
        V_ASN1_UNIVERSALSTRING, std::string("\0\0\0a", 4)},
       {CBS_ASN1_BMPSTRING, std::string("\0a", 2), V_ASN1_BMPSTRING,
        std::string("\0a", 2)},
+      {CBS_ASN1_OCTETSTRING, "abc", V_ASN1_OCTET_STRING, "abc"},
+      {CBS_ASN1_UTCTIME, "700101000000Z", V_ASN1_UTCTIME, "700101000000Z"},
+      {CBS_ASN1_GENERALIZEDTIME, "19700101000000Z", V_ASN1_GENERALIZEDTIME,
+       "19700101000000Z"},
 
       // ENUMERATED is supported but, currently, INTEGER is not.
+      {CBS_ASN1_INTEGER, "\x01", V_ASN1_INTEGER, "\x01"},
       {CBS_ASN1_ENUMERATED, "\x01", V_ASN1_ENUMERATED, "\x01"},
 
       // Test negative values. These are interesting because, when encoding, the
       // ASN.1 type must be determined from the string type, but the string type
       // has an extra |V_ASN1_NEG| bit.
+      {CBS_ASN1_INTEGER, "\xff", V_ASN1_NEG_INTEGER, "\x01"},
       {CBS_ASN1_ENUMERATED, "\xff", V_ASN1_NEG_ENUMERATED, "\x01"},
 
-      // SEQUENCE is supported but, currently, SET is not. Note the
-      // |ASN1_STRING| representation will include the tag and length.
+      // SEQUENCE and SET use their |ASN1_STRING| representation, which includes
+      // the tag and length.
       {CBS_ASN1_SEQUENCE, "", V_ASN1_SEQUENCE, std::string("\x30\x00", 2)},
+      {CBS_ASN1_SET, "", V_ASN1_SET, std::string("\x31\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 */, ""},
+      // NULL, BOOLEAN, and OBJECT IDENTIFIER use non-|ASN1_STRING|
+      // representations, so they are represented with |V_ASN1_OTHER|.
+      {CBS_ASN1_NULL, "", V_ASN1_OTHER, std::string("\x05\x00", 2)},
+      {CBS_ASN1_BOOLEAN, std::string("\x00", 1), V_ASN1_OTHER,
+       std::string("\x01\x01\x00", 3)},
+      {CBS_ASN1_BOOLEAN, "\xff", V_ASN1_OTHER, "\x01\x01\xff"},
+      {CBS_ASN1_OBJECT, "\x01\x02\x03\x04", V_ASN1_OTHER,
+       "\x06\x04\x01\x02\x03\x04"},
 
-      // 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.
+      // These types are not actually supported by the library, but we accept
+      // them as |V_ASN1_OTHER|.
+      {7 /* ObjectDescriptor */, "", V_ASN1_OTHER, std::string("\x07\x00", 2)},
+      {8 /* EXTERNAL */, "", V_ASN1_OTHER, std::string("\x08\x00", 2)},
+      {9 /* REAL */, "", V_ASN1_OTHER, std::string("\x09\x00", 2)},
+      {11 /* EMBEDDED PDV */, "", V_ASN1_OTHER, std::string("\x0b\x00", 2)},
+      {13 /* RELATIVE-OID */, "", V_ASN1_OTHER, std::string("\x0d\x00", 2)},
+      {14 /* TIME */, "", V_ASN1_OTHER, std::string("\x0e\x00", 2)},
+      {15 /* not a type; reserved value */, "", V_ASN1_OTHER,
+       std::string("\x0f\x00", 2)},
+      {29 /* CHARACTER STRING */, "", V_ASN1_OTHER, std::string("\x1d\x00", 2)},
+
+      // Non-universal tags are allowed as |V_ASN1_OTHER| too.
+      {CBS_ASN1_APPLICATION | CBS_ASN1_CONSTRUCTED | 42, "", V_ASN1_OTHER,
+       std::string("\x7f\x2a\x00", 3)},
+      {CBS_ASN1_APPLICATION | 42, "", V_ASN1_OTHER,
+       std::string("\x5f\x2a\x00", 3)},
   };
   for (const auto &t : kTests) {
     SCOPED_TRACE(t.der_tag);
@@ -7256,7 +7295,9 @@
       // Errors in supported universal types should be handled.
       {CBS_ASN1_NULL, "not null"},
       {CBS_ASN1_BOOLEAN, "not bool"},
+      {CBS_ASN1_BOOLEAN, "\1"},  // BOOL in DER must be 0x00 or 0xff.
       {CBS_ASN1_OBJECT, ""},
+      {CBS_ASN1_OBJECT, "\x80\x01"},  // Non-minimal OID encoding
       {CBS_ASN1_INTEGER, std::string("\0\0", 2)},
       {CBS_ASN1_ENUMERATED, std::string("\0\0", 2)},
       {CBS_ASN1_BITSTRING, ""},
@@ -7265,25 +7306,11 @@
       {CBS_ASN1_UNIVERSALSTRING, "not utf-32"},
       {CBS_ASN1_UTCTIME, "not utctime"},
       {CBS_ASN1_GENERALIZEDTIME, "not generalizedtime"},
+      {CBS_ASN1_NULL | CBS_ASN1_CONSTRUCTED, ""},
+      {CBS_ASN1_OBJECT | CBS_ASN1_CONSTRUCTED, "\x01\x02\x03\x04"},
+      {CBS_ASN1_BOOLEAN | CBS_ASN1_CONSTRUCTED, "\xff"},
       {CBS_ASN1_UTF8STRING | CBS_ASN1_CONSTRUCTED, ""},
       {CBS_ASN1_SEQUENCE & ~CBS_ASN1_CONSTRUCTED, ""},
-
-      // TODO(crbug.com/boringssl/412): The following inputs should parse, but
-      // are currently rejected because they cannot be represented in
-      // |ASN1_PRINTABLE|, either because they don't fit in |ASN1_STRING| or
-      // simply in the |B_ASN1_PRINTABLE| bitmask.
-      {CBS_ASN1_NULL, ""},
-      {CBS_ASN1_BOOLEAN, std::string("\x00", 1)},
-      {CBS_ASN1_BOOLEAN, "\xff"},
-      {CBS_ASN1_OBJECT, "\x01\x02\x03\x04"},
-      {CBS_ASN1_INTEGER, "\x01"},
-      {CBS_ASN1_INTEGER, "\xff"},
-      {CBS_ASN1_OCTETSTRING, ""},
-      {CBS_ASN1_UTCTIME, "700101000000Z"},
-      {CBS_ASN1_GENERALIZEDTIME, "19700101000000Z"},
-      {CBS_ASN1_SET, ""},
-      {CBS_ASN1_APPLICATION | CBS_ASN1_CONSTRUCTED | 42, ""},
-      {CBS_ASN1_APPLICATION | 42, ""},
   };
   for (const auto &t : kInvalidTests) {
     SCOPED_TRACE(t.der_tag);
diff --git a/src/crypto/x509/x509_vfy.cc b/src/crypto/x509/x509_vfy.cc
index 03f4612..92f154c 100644
--- a/src/crypto/x509/x509_vfy.cc
+++ b/src/crypto/x509/x509_vfy.cc
@@ -1020,6 +1020,8 @@
 
 // Check CRLDP and IDP
 static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score) {
+  // TODO(bbe): crbug.com/409778435 Make tests for the corner cases we hit
+  // here so that we stay correct for RFC 5280 6.3.3 steps b.1 and b.2
   if (crl->idp_flags & IDP_ONLYATTR) {
     return 0;
   }
@@ -1041,9 +1043,14 @@
     //
     // We also do not support indirect CRLs, and a CRL issuer can only match
     // indirect CRLs (RFC 5280, section 6.3.3, step b.1).
-    // support.
-    if (dp->reasons != NULL && dp->CRLissuer != NULL &&
-        (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint))) {
+    if (dp->reasons != NULL || dp->CRLissuer != NULL) {
+      continue;
+    }
+    // At this point we have already checked that the CRL issuer matches
+    // the certificate issuer (and set CRL_SCORE_ISSUER_NAME);
+
+    // RFC 5280 Section 6.3.3 step b.2
+    if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)){
       return 1;
     }
   }
diff --git a/src/crypto/x509/x_algor.cc b/src/crypto/x509/x_algor.cc
index 0a1162e..60eb006 100644
--- a/src/crypto/x509/x_algor.cc
+++ b/src/crypto/x509/x_algor.cc
@@ -20,6 +20,7 @@
 #include <openssl/obj.h>
 
 #include "../asn1/internal.h"
+#include "internal.h"
 
 
 ASN1_SEQUENCE(X509_ALGOR) = {
@@ -105,3 +106,11 @@
   }
   return ASN1_TYPE_cmp(a->parameter, b->parameter);
 }
+
+int x509_marshal_algorithm(CBB *out, const X509_ALGOR *in) {
+  uint8_t *ptr;
+  int len = i2d_X509_ALGOR(in, NULL);
+  return len > 0 &&  //
+         CBB_add_space(out, &ptr, static_cast<size_t>(len)) &&
+         i2d_X509_ALGOR(in, &ptr) == len;
+}
diff --git a/src/crypto/x509/x_name.cc b/src/crypto/x509/x_name.cc
index 767ebfd..035a03a 100644
--- a/src/crypto/x509/x_name.cc
+++ b/src/crypto/x509/x_name.cc
@@ -55,7 +55,7 @@
 
 ASN1_SEQUENCE(X509_NAME_ENTRY) = {
     ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
-    ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE),
+    ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_ANY_AS_STRING),
 } ASN1_SEQUENCE_END(X509_NAME_ENTRY)
 
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X509_NAME_ENTRY)
@@ -490,3 +490,12 @@
   }
   return 1;
 }
+
+int x509_marshal_name(CBB *out, X509_NAME *in) {
+  int len = i2d_X509_NAME(in, nullptr);
+  if (len <= 0) {
+    return 0;
+  }
+  uint8_t *ptr;
+  return CBB_add_space(out, &ptr, len) && i2d_X509_NAME(in, &ptr) == len;
+}
diff --git a/src/crypto/x509/x_x509.cc b/src/crypto/x509/x_x509.cc
index ebb20d5..485231f 100644
--- a/src/crypto/x509/x_x509.cc
+++ b/src/crypto/x509/x_x509.cc
@@ -17,6 +17,7 @@
 #include <stdio.h>
 
 #include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
@@ -109,7 +110,7 @@
       !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) ||
       !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE)) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
   // For just the signature field, we accept non-minimal BER lengths, though not
@@ -121,76 +122,70 @@
   size_t header_len;
   int indefinite;
   if (!CBS_get_any_ber_asn1_element(&cert, &sig, &tag, &header_len,
-                                    /*out_ber_found=*/NULL,
+                                    /*out_ber_found=*/nullptr,
                                     &indefinite) ||
       tag != CBS_ASN1_BITSTRING || indefinite ||  //
       !CBS_skip(&sig, header_len) ||              //
       CBS_len(&cert) != 0) {
     OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
-    return NULL;
+    return nullptr;
   }
 
-  X509 *ret = x509_new_null();
-  if (ret == NULL) {
-    return NULL;
+  bssl::UniquePtr<X509> ret(x509_new_null());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
-  {
-    // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
-    // from the tasn_*.c implementation, replace this with |CBS|-based
-    // functions.
-    const uint8_t *inp = CBS_data(&tbs);
-    if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs),
-                         ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1,
-                         /*aclass=*/0, /*opt=*/0, buf) <= 0 ||
-        inp != CBS_data(&tbs) + CBS_len(&tbs)) {
-      goto err;
-    }
-
-    inp = CBS_data(&sigalg);
-    ret->sig_alg = d2i_X509_ALGOR(NULL, &inp, CBS_len(&sigalg));
-    if (ret->sig_alg == NULL || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
-      goto err;
-    }
-
-    inp = CBS_data(&sig);
-    ret->signature = c2i_ASN1_BIT_STRING(NULL, &inp, CBS_len(&sig));
-    if (ret->signature == NULL || inp != CBS_data(&sig) + CBS_len(&sig)) {
-      goto err;
-    }
-
-    // The version must be one of v1(0), v2(1), or v3(2).
-    long version = X509_VERSION_1;
-    if (ret->cert_info->version != NULL) {
-      version = ASN1_INTEGER_get(ret->cert_info->version);
-      // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
-      // also be rejected here. This means an explicitly-encoded X.509v1
-      // version. v1 is DEFAULT, so DER requires it be omitted.
-      if (version < X509_VERSION_1 || version > X509_VERSION_3) {
-        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
-        goto err;
-      }
-    }
-
-    // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
-    if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL ||
-                                      ret->cert_info->subjectUID != NULL)) {
-      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
-      goto err;
-    }
-
-    // Per RFC 5280, section 4.1.2.9, extensions require v3.
-    if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) {
-      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
-      goto err;
-    }
-
-    return ret;
+  // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
+  // from the tasn_*.c implementation, replace this with |CBS|-based
+  // functions.
+  const uint8_t *inp = CBS_data(&tbs);
+  if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs),
+                       ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1,
+                       /*aclass=*/0, /*opt=*/0, buf) <= 0 ||
+      inp != CBS_data(&tbs) + CBS_len(&tbs)) {
+    return nullptr;
   }
 
-err:
-  X509_free(ret);
-  return NULL;
+  inp = CBS_data(&sigalg);
+  ret->sig_alg = d2i_X509_ALGOR(nullptr, &inp, CBS_len(&sigalg));
+  if (ret->sig_alg == nullptr || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
+    return nullptr;
+  }
+
+  inp = CBS_data(&sig);
+  ret->signature = c2i_ASN1_BIT_STRING(nullptr, &inp, CBS_len(&sig));
+  if (ret->signature == nullptr || inp != CBS_data(&sig) + CBS_len(&sig)) {
+    return nullptr;
+  }
+
+  // The version must be one of v1(0), v2(1), or v3(2).
+  long version = X509_VERSION_1;
+  if (ret->cert_info->version != nullptr) {
+    version = ASN1_INTEGER_get(ret->cert_info->version);
+    // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
+    // also be rejected here. This means an explicitly-encoded X.509v1
+    // version. v1 is DEFAULT, so DER requires it be omitted.
+    if (version < X509_VERSION_1 || version > X509_VERSION_3) {
+      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
+      return nullptr;
+    }
+  }
+
+  // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
+  if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != nullptr ||
+                                    ret->cert_info->subjectUID != nullptr)) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
+    return nullptr;
+  }
+
+  // Per RFC 5280, section 4.1.2.9, extensions require v3.
+  if (version != X509_VERSION_3 && ret->cert_info->extensions != nullptr) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
+    return nullptr;
+  }
+
+  return ret.release();
 }
 
 X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) {
@@ -223,42 +218,26 @@
     return -1;
   }
 
-  CBB cbb, cert;
-  int len;
-  if (!CBB_init(&cbb, 64) ||  //
-      !CBB_add_asn1(&cbb, &cert, CBS_ASN1_SEQUENCE)) {
-    goto err;
+  bssl::ScopedCBB cbb;
+  CBB cert;
+  if (!CBB_init(cbb.get(), 64) ||  //
+      !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE)) {
+    return -1;
   }
 
   // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
   // from the tasn_*.c implementation, replace this with |CBS|-based functions.
   uint8_t *out;
-  len = i2d_X509_CINF(x509->cert_info, NULL);
+  int len = i2d_X509_CINF(x509->cert_info, NULL);
   if (len < 0 ||  //
-      !CBB_add_space(&cert, &out, (size_t)len) ||
-      i2d_X509_CINF(x509->cert_info, &out) != len) {
-    goto err;
+      !CBB_add_space(&cert, &out, static_cast<size_t>(len)) ||
+      i2d_X509_CINF(x509->cert_info, &out) != len ||
+      !x509_marshal_algorithm(&cert, x509->sig_alg) ||
+      !asn1_marshal_bit_string(&cert, x509->signature, /*tag=*/0)) {
+    return -1;
   }
 
-  len = i2d_X509_ALGOR(x509->sig_alg, NULL);
-  if (len < 0 ||  //
-      !CBB_add_space(&cert, &out, (size_t)len) ||
-      i2d_X509_ALGOR(x509->sig_alg, &out) != len) {
-    goto err;
-  }
-
-  len = i2d_ASN1_BIT_STRING(x509->signature, NULL);
-  if (len < 0 ||  //
-      !CBB_add_space(&cert, &out, (size_t)len) ||
-      i2d_ASN1_BIT_STRING(x509->signature, &out) != len) {
-    goto err;
-  }
-
-  return CBB_finish_i2d(&cbb, outp);
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
+  return CBB_finish_i2d(cbb.get(), outp);
 }
 
 static int x509_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) {
diff --git a/src/crypto/x509/x_x509a.cc b/src/crypto/x509/x_x509a.cc
index f36fcaf..9318d43 100644
--- a/src/crypto/x509/x_x509a.cc
+++ b/src/crypto/x509/x_x509a.cc
@@ -109,49 +109,33 @@
 }
 
 int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj) {
-  X509_CERT_AUX *aux;
-  ASN1_OBJECT *objtmp = OBJ_dup(obj);
-  if (objtmp == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OBJECT> objtmp(OBJ_dup(obj));
+  if (objtmp == nullptr) {
+    return 0;
   }
-  aux = aux_get(x);
-  if (aux->trust == NULL) {
+  X509_CERT_AUX *aux = aux_get(x);
+  if (aux->trust == nullptr) {
     aux->trust = sk_ASN1_OBJECT_new_null();
-    if (aux->trust == NULL) {
-      goto err;
+    if (aux->trust == nullptr) {
+      return 0;
     }
   }
-  if (!sk_ASN1_OBJECT_push(aux->trust, objtmp)) {
-    goto err;
-  }
-  return 1;
-
-err:
-  ASN1_OBJECT_free(objtmp);
-  return 0;
+  return bssl::PushToStack(aux->trust, std::move(objtmp));
 }
 
 int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj) {
-  X509_CERT_AUX *aux;
-  ASN1_OBJECT *objtmp = OBJ_dup(obj);
-  if (objtmp == NULL) {
-    goto err;
+  bssl::UniquePtr<ASN1_OBJECT> objtmp(OBJ_dup(obj));
+  if (objtmp == nullptr) {
+    return 0;
   }
-  aux = aux_get(x);
-  if (aux->reject == NULL) {
+  X509_CERT_AUX *aux = aux_get(x);
+  if (aux->reject == nullptr) {
     aux->reject = sk_ASN1_OBJECT_new_null();
-    if (aux->reject == NULL) {
-      goto err;
+    if (aux->reject == nullptr) {
+      return 0;
     }
   }
-  if (!sk_ASN1_OBJECT_push(aux->reject, objtmp)) {
-    goto err;
-  }
-  return 1;
-
-err:
-  ASN1_OBJECT_free(objtmp);
-  return 0;
+  return bssl::PushToStack(aux->reject, std::move(objtmp));
 }
 
 void X509_trust_clear(X509 *x) {
diff --git a/src/decrepit/cast/cast.cc b/src/decrepit/cast/cast.cc
index 6e4c000..37e4684 100644
--- a/src/decrepit/cast/cast.cc
+++ b/src/decrepit/cast/cast.cc
@@ -17,9 +17,7 @@
 #include <openssl/obj.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <intrin.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include "../../crypto/fipsmodule/cipher/internal.h"
diff --git a/src/decrepit/dh/dh_decrepit.cc b/src/decrepit/dh/dh_decrepit.cc
index d8d1d2d..7f7b4b6 100644
--- a/src/decrepit/dh/dh_decrepit.cc
+++ b/src/decrepit/dh/dh_decrepit.cc
@@ -32,20 +32,18 @@
 DH *DH_generate_parameters(int prime_len, int generator,
                            void (*callback)(int, int, void *), void *cb_arg) {
   if (prime_len < 0 || generator < 0) {
-      return NULL;
+    return nullptr;
   }
 
-  DH *ret = DH_new();
-  if (ret == NULL) {
-      return NULL;
+  bssl::UniquePtr<DH> ret(DH_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   BN_GENCB gencb_storage;
-  BN_GENCB *cb = NULL;
-
+  BN_GENCB *cb = nullptr;
   struct wrapped_callback wrapped;
-
-  if (callback != NULL) {
+  if (callback != nullptr) {
     wrapped.callback = callback;
     wrapped.arg = cb_arg;
 
@@ -53,13 +51,9 @@
     BN_GENCB_set(cb, callback_wrapper, &wrapped);
   }
 
-  if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) {
-    goto err;
+  if (!DH_generate_parameters_ex(ret.get(), prime_len, generator, cb)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DH_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/src/decrepit/dsa/dsa_decrepit.cc b/src/decrepit/dsa/dsa_decrepit.cc
index c77c7ff..86586ca 100644
--- a/src/decrepit/dsa/dsa_decrepit.cc
+++ b/src/decrepit/dsa/dsa_decrepit.cc
@@ -33,20 +33,18 @@
                              int *counter_ret, unsigned long *h_ret,
                              void (*callback)(int, int, void *), void *cb_arg) {
   if (bits < 0 || seed_len < 0) {
-      return NULL;
+      return nullptr;
   }
 
-  DSA *ret = DSA_new();
-  if (ret == NULL) {
-      return NULL;
+  bssl::UniquePtr<DSA> ret(DSA_new());
+  if (ret == nullptr) {
+    return nullptr;
   }
 
   BN_GENCB gencb_storage;
-  BN_GENCB *cb = NULL;
-
+  BN_GENCB *cb = nullptr;
   struct wrapped_callback wrapped;
-
-  if (callback != NULL) {
+  if (callback != nullptr) {
     wrapped.callback = callback;
     wrapped.arg = cb_arg;
 
@@ -54,14 +52,10 @@
     BN_GENCB_set(cb, callback_wrapper, &wrapped);
   }
 
-  if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret,
-                                  h_ret, cb)) {
-    goto err;
+  if (!DSA_generate_parameters_ex(ret.get(), bits, seed_in, seed_len,
+                                  counter_ret, h_ret, cb)) {
+    return nullptr;
   }
 
-  return ret;
-
-err:
-  DSA_free(ret);
-  return NULL;
+  return ret.release();
 }
diff --git a/src/decrepit/rsa/rsa_decrepit.cc b/src/decrepit/rsa/rsa_decrepit.cc
index 22c9f01..a1b943f 100644
--- a/src/decrepit/rsa/rsa_decrepit.cc
+++ b/src/decrepit/rsa/rsa_decrepit.cc
@@ -21,26 +21,19 @@
 
 RSA *RSA_generate_key(int bits, uint64_t e_value, void *callback,
                       void *cb_arg) {
-  assert(callback == NULL);
-  assert(cb_arg == NULL);
+  assert(callback == nullptr);
+  assert(cb_arg == nullptr);
 
-  RSA *rsa = RSA_new();
-  BIGNUM *e = BN_new();
-
-  if (rsa == NULL ||
-      e == NULL ||
-      !BN_set_u64(e, e_value) ||
-      !RSA_generate_key_ex(rsa, bits, e, NULL)) {
-    goto err;
+  bssl::UniquePtr<RSA> rsa(RSA_new());
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  if (rsa == nullptr ||  //
+      e == nullptr ||    //
+      !BN_set_u64(e.get(), e_value) ||
+      !RSA_generate_key_ex(rsa.get(), bits, e.get(), nullptr)) {
+    return nullptr;
   }
 
-  BN_free(e);
-  return rsa;
-
-err:
-  BN_free(e);
-  RSA_free(rsa);
-  return NULL;
+  return rsa.release();
 }
 
 int RSA_padding_add_PKCS1_PSS(const RSA *rsa, uint8_t *EM, const uint8_t *mHash,
diff --git a/src/fuzz/CMakeLists.txt b/src/fuzz/CMakeLists.txt
index 1c784a1..bb4ee90 100644
--- a/src/fuzz/CMakeLists.txt
+++ b/src/fuzz/CMakeLists.txt
@@ -5,7 +5,7 @@
   cmake_path(GET fuzzer STEM name)
   add_executable(${name} ../${fuzzer})
   target_compile_options(${name} PRIVATE "-Wno-missing-prototypes")
-  target_link_libraries(${name} crypto ssl pki)
+  target_link_libraries(${name} ssl pki crypto)
   if(LIBFUZZER_FROM_DEPS)
     set_target_properties(${name} PROPERTIES LINK_FLAGS "-fsanitize=fuzzer-no-link")
     target_link_libraries(${name} Fuzzer)
diff --git a/src/fuzz/client.cc b/src/fuzz/client.cc
index 82fa0b8..86dcdc2 100644
--- a/src/fuzz/client.cc
+++ b/src/fuzz/client.cc
@@ -15,7 +15,8 @@
 #include "../ssl/test/fuzzer.h"
 
 
-static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kClient);
+static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kClient,
+                          TLSFuzzer::kFuzzerModeOn);
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
   return g_fuzzer.TestOneInput(buf, len);
diff --git a/src/fuzz/client_corpus/009fee313a3c113c542a5b4cfdfc26c55c225cbf b/src/fuzz/client_corpus/009fee313a3c113c542a5b4cfdfc26c55c225cbf
deleted file mode 100644
index c293357..0000000
--- a/src/fuzz/client_corpus/009fee313a3c113c542a5b4cfdfc26c55c225cbf
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/04c28ad57f2d16bed209a9761e1ec774010c0c63 b/src/fuzz/client_corpus/04c28ad57f2d16bed209a9761e1ec774010c0c63
new file mode 100644
index 0000000..c326fb8
--- /dev/null
+++ b/src/fuzz/client_corpus/04c28ad57f2d16bed209a9761e1ec774010c0c63
Binary files differ
diff --git a/src/fuzz/client_corpus/05a2f0df703eaf18e98c511148895b4b5e5b708e b/src/fuzz/client_corpus/05a2f0df703eaf18e98c511148895b4b5e5b708e
deleted file mode 100644
index 916e91a..0000000
--- a/src/fuzz/client_corpus/05a2f0df703eaf18e98c511148895b4b5e5b708e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/08b14e280eb84bd7d47def91b01337023a3c363c b/src/fuzz/client_corpus/08b14e280eb84bd7d47def91b01337023a3c363c
deleted file mode 100644
index 9d70fb8..0000000
--- a/src/fuzz/client_corpus/08b14e280eb84bd7d47def91b01337023a3c363c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/0907ed7a81cd827f9851ccc428a6d37691a442a1 b/src/fuzz/client_corpus/0907ed7a81cd827f9851ccc428a6d37691a442a1
new file mode 100644
index 0000000..3146f73
--- /dev/null
+++ b/src/fuzz/client_corpus/0907ed7a81cd827f9851ccc428a6d37691a442a1
Binary files differ
diff --git a/src/fuzz/client_corpus/0992337019c07c5a492a4c71da5a3cd9e9f33887 b/src/fuzz/client_corpus/0992337019c07c5a492a4c71da5a3cd9e9f33887
new file mode 100644
index 0000000..53d0f63
--- /dev/null
+++ b/src/fuzz/client_corpus/0992337019c07c5a492a4c71da5a3cd9e9f33887
Binary files differ
diff --git a/src/fuzz/client_corpus/16c66d315dc915d03daf45b14e66560591464b5d b/src/fuzz/client_corpus/16c66d315dc915d03daf45b14e66560591464b5d
deleted file mode 100644
index 9a36e78..0000000
--- a/src/fuzz/client_corpus/16c66d315dc915d03daf45b14e66560591464b5d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/1c4f68b0c7ff500dde6ed368b97913236e06b480 b/src/fuzz/client_corpus/1c4f68b0c7ff500dde6ed368b97913236e06b480
deleted file mode 100644
index 6172f31..0000000
--- a/src/fuzz/client_corpus/1c4f68b0c7ff500dde6ed368b97913236e06b480
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/21b58795c70fecfad292d278c3bb76bed9431d3e b/src/fuzz/client_corpus/21b58795c70fecfad292d278c3bb76bed9431d3e
deleted file mode 100644
index ce99b6c..0000000
--- a/src/fuzz/client_corpus/21b58795c70fecfad292d278c3bb76bed9431d3e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/2719ccc145a8813a7304811b6ebe1c58c067c241 b/src/fuzz/client_corpus/2719ccc145a8813a7304811b6ebe1c58c067c241
new file mode 100644
index 0000000..d49803f
--- /dev/null
+++ b/src/fuzz/client_corpus/2719ccc145a8813a7304811b6ebe1c58c067c241
Binary files differ
diff --git a/src/fuzz/client_corpus/271f300013a0c622c62053394768a322f128925f b/src/fuzz/client_corpus/271f300013a0c622c62053394768a322f128925f
deleted file mode 100644
index 3547612..0000000
--- a/src/fuzz/client_corpus/271f300013a0c622c62053394768a322f128925f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/2c4073fccda07d98ce3cfa12ce5067b92e7beaff b/src/fuzz/client_corpus/2c4073fccda07d98ce3cfa12ce5067b92e7beaff
new file mode 100644
index 0000000..f826918
--- /dev/null
+++ b/src/fuzz/client_corpus/2c4073fccda07d98ce3cfa12ce5067b92e7beaff
Binary files differ
diff --git a/src/fuzz/client_corpus/2e89bd3f1c6521c952ce5fc9803a6437a45db29a b/src/fuzz/client_corpus/2e89bd3f1c6521c952ce5fc9803a6437a45db29a
new file mode 100644
index 0000000..03c90c9
--- /dev/null
+++ b/src/fuzz/client_corpus/2e89bd3f1c6521c952ce5fc9803a6437a45db29a
Binary files differ
diff --git a/src/fuzz/client_corpus/3cc980bb071f463cac85ecf625d9d4e969f7bcfb b/src/fuzz/client_corpus/3cc980bb071f463cac85ecf625d9d4e969f7bcfb
new file mode 100644
index 0000000..732c715
--- /dev/null
+++ b/src/fuzz/client_corpus/3cc980bb071f463cac85ecf625d9d4e969f7bcfb
Binary files differ
diff --git a/src/fuzz/client_corpus/3d8da46b556049c4085ee3a2da4bccec185acdf2 b/src/fuzz/client_corpus/3d8da46b556049c4085ee3a2da4bccec185acdf2
new file mode 100644
index 0000000..46c15ca
--- /dev/null
+++ b/src/fuzz/client_corpus/3d8da46b556049c4085ee3a2da4bccec185acdf2
Binary files differ
diff --git a/src/fuzz/client_corpus/4323fb145fd5f4f1f9f99c5c1a6c27449022c706 b/src/fuzz/client_corpus/4323fb145fd5f4f1f9f99c5c1a6c27449022c706
deleted file mode 100644
index ac9d8bf..0000000
--- a/src/fuzz/client_corpus/4323fb145fd5f4f1f9f99c5c1a6c27449022c706
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/437945e8100673c4399a81cd662dc71775f81819 b/src/fuzz/client_corpus/437945e8100673c4399a81cd662dc71775f81819
new file mode 100644
index 0000000..7b8e1e9
--- /dev/null
+++ b/src/fuzz/client_corpus/437945e8100673c4399a81cd662dc71775f81819
Binary files differ
diff --git a/src/fuzz/client_corpus/45dbee5815a97b19e9ed9c8e11e517b551022745 b/src/fuzz/client_corpus/45dbee5815a97b19e9ed9c8e11e517b551022745
new file mode 100644
index 0000000..8336564
--- /dev/null
+++ b/src/fuzz/client_corpus/45dbee5815a97b19e9ed9c8e11e517b551022745
Binary files differ
diff --git a/src/fuzz/client_corpus/4d35fb4d0a819bdc1b8310e92661aae9088fc35c b/src/fuzz/client_corpus/4d35fb4d0a819bdc1b8310e92661aae9088fc35c
deleted file mode 100644
index 4a39038..0000000
--- a/src/fuzz/client_corpus/4d35fb4d0a819bdc1b8310e92661aae9088fc35c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/4fd403d6146f7f47c32aa9b75f7da8a3ed4abcfc b/src/fuzz/client_corpus/4fd403d6146f7f47c32aa9b75f7da8a3ed4abcfc
new file mode 100644
index 0000000..f097159
--- /dev/null
+++ b/src/fuzz/client_corpus/4fd403d6146f7f47c32aa9b75f7da8a3ed4abcfc
Binary files differ
diff --git a/src/fuzz/client_corpus/5368017ad7d58a595bb45a7b0cd22d958aea14d5 b/src/fuzz/client_corpus/5368017ad7d58a595bb45a7b0cd22d958aea14d5
new file mode 100644
index 0000000..3b058ab
--- /dev/null
+++ b/src/fuzz/client_corpus/5368017ad7d58a595bb45a7b0cd22d958aea14d5
Binary files differ
diff --git a/src/fuzz/client_corpus/53e899069841bf49f6750a134a3aa5f63b4903ad b/src/fuzz/client_corpus/53e899069841bf49f6750a134a3aa5f63b4903ad
deleted file mode 100644
index 755b841..0000000
--- a/src/fuzz/client_corpus/53e899069841bf49f6750a134a3aa5f63b4903ad
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/5a65f8bbbcd506ba2623a9e7c98a09ddbda67017 b/src/fuzz/client_corpus/5a65f8bbbcd506ba2623a9e7c98a09ddbda67017
new file mode 100644
index 0000000..12592f5
--- /dev/null
+++ b/src/fuzz/client_corpus/5a65f8bbbcd506ba2623a9e7c98a09ddbda67017
Binary files differ
diff --git a/src/fuzz/client_corpus/5c17c4704df42cc9b0bac7697ea2ec4e5b2d2984 b/src/fuzz/client_corpus/5c17c4704df42cc9b0bac7697ea2ec4e5b2d2984
deleted file mode 100644
index d33e21d..0000000
--- a/src/fuzz/client_corpus/5c17c4704df42cc9b0bac7697ea2ec4e5b2d2984
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/5c337957318db62fa0ee3a0396f842854fea0148 b/src/fuzz/client_corpus/5c337957318db62fa0ee3a0396f842854fea0148
new file mode 100644
index 0000000..d1f6b6f
--- /dev/null
+++ b/src/fuzz/client_corpus/5c337957318db62fa0ee3a0396f842854fea0148
Binary files differ
diff --git a/src/fuzz/client_corpus/5f574b9afa2f0722b4c3cd704304241592d2fec5 b/src/fuzz/client_corpus/5f574b9afa2f0722b4c3cd704304241592d2fec5
new file mode 100644
index 0000000..6b517ed
--- /dev/null
+++ b/src/fuzz/client_corpus/5f574b9afa2f0722b4c3cd704304241592d2fec5
Binary files differ
diff --git a/src/fuzz/client_corpus/6015fc30d96a89b41156000fcf38cf379c957517 b/src/fuzz/client_corpus/6015fc30d96a89b41156000fcf38cf379c957517
new file mode 100644
index 0000000..077112c
--- /dev/null
+++ b/src/fuzz/client_corpus/6015fc30d96a89b41156000fcf38cf379c957517
Binary files differ
diff --git a/src/fuzz/client_corpus/611053420e5261789e373f2313834a41e891ecba b/src/fuzz/client_corpus/611053420e5261789e373f2313834a41e891ecba
new file mode 100644
index 0000000..165eb3a
--- /dev/null
+++ b/src/fuzz/client_corpus/611053420e5261789e373f2313834a41e891ecba
Binary files differ
diff --git a/src/fuzz/client_corpus/631e3bfe44f7e32c78ead028502573df807dea55 b/src/fuzz/client_corpus/631e3bfe44f7e32c78ead028502573df807dea55
new file mode 100644
index 0000000..fdc3dc0
--- /dev/null
+++ b/src/fuzz/client_corpus/631e3bfe44f7e32c78ead028502573df807dea55
Binary files differ
diff --git a/src/fuzz/client_corpus/645ba3984c1c908c76a7a18a5ce22d1bac06a9d6 b/src/fuzz/client_corpus/645ba3984c1c908c76a7a18a5ce22d1bac06a9d6
new file mode 100644
index 0000000..897fe95
--- /dev/null
+++ b/src/fuzz/client_corpus/645ba3984c1c908c76a7a18a5ce22d1bac06a9d6
Binary files differ
diff --git a/src/fuzz/client_corpus/66a838dc7b430502f49aead72ce6b02316ec6f95 b/src/fuzz/client_corpus/66a838dc7b430502f49aead72ce6b02316ec6f95
deleted file mode 100644
index 3ac1bca..0000000
--- a/src/fuzz/client_corpus/66a838dc7b430502f49aead72ce6b02316ec6f95
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/6cb75744557e90e0a698789e774e8cb8884c79d8 b/src/fuzz/client_corpus/6cb75744557e90e0a698789e774e8cb8884c79d8
deleted file mode 100644
index 2a9640e..0000000
--- a/src/fuzz/client_corpus/6cb75744557e90e0a698789e774e8cb8884c79d8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/6d868c89c1e8737a7f87066322bb6e372858017e b/src/fuzz/client_corpus/6d868c89c1e8737a7f87066322bb6e372858017e
deleted file mode 100644
index f59dad2..0000000
--- a/src/fuzz/client_corpus/6d868c89c1e8737a7f87066322bb6e372858017e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/713644535bf06e6a885e3acf6f0911e02b76736e b/src/fuzz/client_corpus/713644535bf06e6a885e3acf6f0911e02b76736e
deleted file mode 100644
index aba9172..0000000
--- a/src/fuzz/client_corpus/713644535bf06e6a885e3acf6f0911e02b76736e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/744a34c9ad7b0b9207e1766ee087c3eb906ef27a b/src/fuzz/client_corpus/744a34c9ad7b0b9207e1766ee087c3eb906ef27a
new file mode 100644
index 0000000..83829fc
--- /dev/null
+++ b/src/fuzz/client_corpus/744a34c9ad7b0b9207e1766ee087c3eb906ef27a
Binary files differ
diff --git a/src/fuzz/client_corpus/748e3a934338a0e39b96d6e82430eb5ffaa1f3b0 b/src/fuzz/client_corpus/748e3a934338a0e39b96d6e82430eb5ffaa1f3b0
deleted file mode 100644
index e37d590..0000000
--- a/src/fuzz/client_corpus/748e3a934338a0e39b96d6e82430eb5ffaa1f3b0
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/7a4311b9751086b125edc64c4ec4c5baff811e62 b/src/fuzz/client_corpus/7a4311b9751086b125edc64c4ec4c5baff811e62
new file mode 100644
index 0000000..0d4b2de
--- /dev/null
+++ b/src/fuzz/client_corpus/7a4311b9751086b125edc64c4ec4c5baff811e62
Binary files differ
diff --git a/src/fuzz/client_corpus/7dcdcf07e319c36dd4dbad5a7860e853948f5019 b/src/fuzz/client_corpus/7dcdcf07e319c36dd4dbad5a7860e853948f5019
new file mode 100644
index 0000000..a6819ae
--- /dev/null
+++ b/src/fuzz/client_corpus/7dcdcf07e319c36dd4dbad5a7860e853948f5019
Binary files differ
diff --git a/src/fuzz/client_corpus/84ba7200e08f2995d5ae601a52006a1a9de6a7ef b/src/fuzz/client_corpus/84ba7200e08f2995d5ae601a52006a1a9de6a7ef
new file mode 100644
index 0000000..69a4ca0
--- /dev/null
+++ b/src/fuzz/client_corpus/84ba7200e08f2995d5ae601a52006a1a9de6a7ef
Binary files differ
diff --git a/src/fuzz/client_corpus/858cfdeaded389cf2c8720c4159107b4b9c7dd1d b/src/fuzz/client_corpus/858cfdeaded389cf2c8720c4159107b4b9c7dd1d
deleted file mode 100644
index a800224..0000000
--- a/src/fuzz/client_corpus/858cfdeaded389cf2c8720c4159107b4b9c7dd1d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/85cbb909a0f7309e0f4813aafaecef26fac20d10 b/src/fuzz/client_corpus/85cbb909a0f7309e0f4813aafaecef26fac20d10
new file mode 100644
index 0000000..7b64d21
--- /dev/null
+++ b/src/fuzz/client_corpus/85cbb909a0f7309e0f4813aafaecef26fac20d10
Binary files differ
diff --git a/src/fuzz/client_corpus/85e3e7e691b8378d49173edfd08244ca4807bf84 b/src/fuzz/client_corpus/85e3e7e691b8378d49173edfd08244ca4807bf84
deleted file mode 100644
index 5eeae87..0000000
--- a/src/fuzz/client_corpus/85e3e7e691b8378d49173edfd08244ca4807bf84
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/866d6333ab0de5db40fbe5b84efb0d4f26e08925 b/src/fuzz/client_corpus/866d6333ab0de5db40fbe5b84efb0d4f26e08925
deleted file mode 100644
index f4ff9af..0000000
--- a/src/fuzz/client_corpus/866d6333ab0de5db40fbe5b84efb0d4f26e08925
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/87b93509a12c43e3028c88370d8935dbc5719615 b/src/fuzz/client_corpus/87b93509a12c43e3028c88370d8935dbc5719615
new file mode 100644
index 0000000..584a777
--- /dev/null
+++ b/src/fuzz/client_corpus/87b93509a12c43e3028c88370d8935dbc5719615
Binary files differ
diff --git a/src/fuzz/client_corpus/89a62df92f2195df2fe77b45589633593286ee95 b/src/fuzz/client_corpus/89a62df92f2195df2fe77b45589633593286ee95
deleted file mode 100644
index da0a6e7..0000000
--- a/src/fuzz/client_corpus/89a62df92f2195df2fe77b45589633593286ee95
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/8b05fc845aab67d727037711de7808287412f064 b/src/fuzz/client_corpus/8b05fc845aab67d727037711de7808287412f064
new file mode 100644
index 0000000..e10b325
--- /dev/null
+++ b/src/fuzz/client_corpus/8b05fc845aab67d727037711de7808287412f064
Binary files differ
diff --git a/src/fuzz/client_corpus/8b62204034a82d2988d0c9dda3172538f4205d99 b/src/fuzz/client_corpus/8b62204034a82d2988d0c9dda3172538f4205d99
new file mode 100644
index 0000000..38a4c93
--- /dev/null
+++ b/src/fuzz/client_corpus/8b62204034a82d2988d0c9dda3172538f4205d99
Binary files differ
diff --git a/src/fuzz/client_corpus/8caaba40f209cede75f8b6d15dff0e14b11f4fdd b/src/fuzz/client_corpus/8caaba40f209cede75f8b6d15dff0e14b11f4fdd
deleted file mode 100644
index 15ad2dc..0000000
--- a/src/fuzz/client_corpus/8caaba40f209cede75f8b6d15dff0e14b11f4fdd
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/8ed2ff7918d27098892a855343194f2ccea3fac9 b/src/fuzz/client_corpus/8ed2ff7918d27098892a855343194f2ccea3fac9
deleted file mode 100644
index c13348a..0000000
--- a/src/fuzz/client_corpus/8ed2ff7918d27098892a855343194f2ccea3fac9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/92b9e0684e054723b2fae964f9e4a7fcdd8957fe b/src/fuzz/client_corpus/92b9e0684e054723b2fae964f9e4a7fcdd8957fe
deleted file mode 100644
index 21d204d..0000000
--- a/src/fuzz/client_corpus/92b9e0684e054723b2fae964f9e4a7fcdd8957fe
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/95920ea67c6bd01f38cc9c77bf11c253082d9330 b/src/fuzz/client_corpus/95920ea67c6bd01f38cc9c77bf11c253082d9330
new file mode 100644
index 0000000..a9f695a
--- /dev/null
+++ b/src/fuzz/client_corpus/95920ea67c6bd01f38cc9c77bf11c253082d9330
Binary files differ
diff --git a/src/fuzz/client_corpus/a09e50736a6dfd1fc930836f693150bd02adebfb b/src/fuzz/client_corpus/a09e50736a6dfd1fc930836f693150bd02adebfb
new file mode 100644
index 0000000..8c513eb
--- /dev/null
+++ b/src/fuzz/client_corpus/a09e50736a6dfd1fc930836f693150bd02adebfb
Binary files differ
diff --git a/src/fuzz/client_corpus/a1eb5db2d450c5d0959147cff41975bd08156655 b/src/fuzz/client_corpus/a1eb5db2d450c5d0959147cff41975bd08156655
deleted file mode 100644
index d0bf517..0000000
--- a/src/fuzz/client_corpus/a1eb5db2d450c5d0959147cff41975bd08156655
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/a261092ef8fbbb540490fc8f9773d88d65782748 b/src/fuzz/client_corpus/a261092ef8fbbb540490fc8f9773d88d65782748
new file mode 100644
index 0000000..1e59346
--- /dev/null
+++ b/src/fuzz/client_corpus/a261092ef8fbbb540490fc8f9773d88d65782748
Binary files differ
diff --git a/src/fuzz/client_corpus/a4f686b4aba889c331dd84e9c19ca729dc8caea8 b/src/fuzz/client_corpus/a4f686b4aba889c331dd84e9c19ca729dc8caea8
new file mode 100644
index 0000000..2e5a2be
--- /dev/null
+++ b/src/fuzz/client_corpus/a4f686b4aba889c331dd84e9c19ca729dc8caea8
Binary files differ
diff --git a/src/fuzz/client_corpus/abe52a0ca90b274b3f11f2e2035e0ac3294feafe b/src/fuzz/client_corpus/abe52a0ca90b274b3f11f2e2035e0ac3294feafe
new file mode 100644
index 0000000..85f7add
--- /dev/null
+++ b/src/fuzz/client_corpus/abe52a0ca90b274b3f11f2e2035e0ac3294feafe
Binary files differ
diff --git a/src/fuzz/client_corpus/ad1f576ae9df13a632ada14d5d908373239a808e b/src/fuzz/client_corpus/ad1f576ae9df13a632ada14d5d908373239a808e
new file mode 100644
index 0000000..af5fd93
--- /dev/null
+++ b/src/fuzz/client_corpus/ad1f576ae9df13a632ada14d5d908373239a808e
Binary files differ
diff --git a/src/fuzz/client_corpus/ad9a83794c7b095b3728ffa302a511640705b495 b/src/fuzz/client_corpus/ad9a83794c7b095b3728ffa302a511640705b495
deleted file mode 100644
index a1f90c5..0000000
--- a/src/fuzz/client_corpus/ad9a83794c7b095b3728ffa302a511640705b495
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/aefb0ebfa73939d1ad1090290b88728d36c215d7 b/src/fuzz/client_corpus/aefb0ebfa73939d1ad1090290b88728d36c215d7
new file mode 100644
index 0000000..34a2f00
--- /dev/null
+++ b/src/fuzz/client_corpus/aefb0ebfa73939d1ad1090290b88728d36c215d7
Binary files differ
diff --git a/src/fuzz/client_corpus/b00f6b1fc712ffc63610269cc5cc100e8f147a40 b/src/fuzz/client_corpus/b00f6b1fc712ffc63610269cc5cc100e8f147a40
deleted file mode 100644
index f2ead99..0000000
--- a/src/fuzz/client_corpus/b00f6b1fc712ffc63610269cc5cc100e8f147a40
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/b06ca89358a62d30e7f08f0ba726058606a891fd b/src/fuzz/client_corpus/b06ca89358a62d30e7f08f0ba726058606a891fd
new file mode 100644
index 0000000..5911427
--- /dev/null
+++ b/src/fuzz/client_corpus/b06ca89358a62d30e7f08f0ba726058606a891fd
Binary files differ
diff --git a/src/fuzz/client_corpus/b23a39fb04fdad2b78f714ce1c850af3f92bd438 b/src/fuzz/client_corpus/b23a39fb04fdad2b78f714ce1c850af3f92bd438
new file mode 100644
index 0000000..eea0c36
--- /dev/null
+++ b/src/fuzz/client_corpus/b23a39fb04fdad2b78f714ce1c850af3f92bd438
Binary files differ
diff --git a/src/fuzz/client_corpus/b25bccdf3174db4751ce450717d3fd8f2c00ce56 b/src/fuzz/client_corpus/b25bccdf3174db4751ce450717d3fd8f2c00ce56
new file mode 100644
index 0000000..863a655
--- /dev/null
+++ b/src/fuzz/client_corpus/b25bccdf3174db4751ce450717d3fd8f2c00ce56
Binary files differ
diff --git a/src/fuzz/client_corpus/b29e2be0d011aee1f45c308cff848c4d25c0f211 b/src/fuzz/client_corpus/b29e2be0d011aee1f45c308cff848c4d25c0f211
deleted file mode 100644
index e92d4a7..0000000
--- a/src/fuzz/client_corpus/b29e2be0d011aee1f45c308cff848c4d25c0f211
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/b5a0827c966b5e7771d5ee42d061ae30d583a60a b/src/fuzz/client_corpus/b5a0827c966b5e7771d5ee42d061ae30d583a60a
new file mode 100644
index 0000000..f675a12
--- /dev/null
+++ b/src/fuzz/client_corpus/b5a0827c966b5e7771d5ee42d061ae30d583a60a
Binary files differ
diff --git a/src/fuzz/client_corpus/b6e04e7f3faae67551f3b03de695d1f9efc1c094 b/src/fuzz/client_corpus/b6e04e7f3faae67551f3b03de695d1f9efc1c094
new file mode 100644
index 0000000..58ee9ea
--- /dev/null
+++ b/src/fuzz/client_corpus/b6e04e7f3faae67551f3b03de695d1f9efc1c094
Binary files differ
diff --git a/src/fuzz/client_corpus/b9f96d459a63cd1b85c113e5de8e4b9e02f22a48 b/src/fuzz/client_corpus/b9f96d459a63cd1b85c113e5de8e4b9e02f22a48
deleted file mode 100644
index a5bcd19..0000000
--- a/src/fuzz/client_corpus/b9f96d459a63cd1b85c113e5de8e4b9e02f22a48
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/ba063e83b4accfa28f356d3c0c3395c86002c680 b/src/fuzz/client_corpus/ba063e83b4accfa28f356d3c0c3395c86002c680
new file mode 100644
index 0000000..78d70c2
--- /dev/null
+++ b/src/fuzz/client_corpus/ba063e83b4accfa28f356d3c0c3395c86002c680
Binary files differ
diff --git a/src/fuzz/client_corpus/c173db0e63f3190b7f6dfb56d66d3790fad91fc4 b/src/fuzz/client_corpus/c173db0e63f3190b7f6dfb56d66d3790fad91fc4
deleted file mode 100644
index f73e875..0000000
--- a/src/fuzz/client_corpus/c173db0e63f3190b7f6dfb56d66d3790fad91fc4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/c4bd7329210c74eab1b00ca630503c94215957f2 b/src/fuzz/client_corpus/c4bd7329210c74eab1b00ca630503c94215957f2
deleted file mode 100644
index 39d14db..0000000
--- a/src/fuzz/client_corpus/c4bd7329210c74eab1b00ca630503c94215957f2
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/c53ede9e2bae8dc4191822b22c83cd97c74f75b9 b/src/fuzz/client_corpus/c53ede9e2bae8dc4191822b22c83cd97c74f75b9
new file mode 100644
index 0000000..e292ef1
--- /dev/null
+++ b/src/fuzz/client_corpus/c53ede9e2bae8dc4191822b22c83cd97c74f75b9
Binary files differ
diff --git a/src/fuzz/client_corpus/c788328c8de5099e6184a75f5191ef337f48e8a7 b/src/fuzz/client_corpus/c788328c8de5099e6184a75f5191ef337f48e8a7
deleted file mode 100644
index a4c276a..0000000
--- a/src/fuzz/client_corpus/c788328c8de5099e6184a75f5191ef337f48e8a7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/ccd924524e8d51b2eaba60977c13193afdb3f920 b/src/fuzz/client_corpus/ccd924524e8d51b2eaba60977c13193afdb3f920
new file mode 100644
index 0000000..2ba4255
--- /dev/null
+++ b/src/fuzz/client_corpus/ccd924524e8d51b2eaba60977c13193afdb3f920
Binary files differ
diff --git a/src/fuzz/client_corpus/d02cbd2fbcaae96d98fae62dc63655b76fa718d4 b/src/fuzz/client_corpus/d02cbd2fbcaae96d98fae62dc63655b76fa718d4
new file mode 100644
index 0000000..535d142
--- /dev/null
+++ b/src/fuzz/client_corpus/d02cbd2fbcaae96d98fae62dc63655b76fa718d4
Binary files differ
diff --git a/src/fuzz/client_corpus/d0fce1a992b77535716aac570b0f38f23c8e9b83 b/src/fuzz/client_corpus/d0fce1a992b77535716aac570b0f38f23c8e9b83
new file mode 100644
index 0000000..c4ca88f
--- /dev/null
+++ b/src/fuzz/client_corpus/d0fce1a992b77535716aac570b0f38f23c8e9b83
Binary files differ
diff --git a/src/fuzz/client_corpus/d1a8c6d76736e52a058557b2da02eea71b2da3c4 b/src/fuzz/client_corpus/d1a8c6d76736e52a058557b2da02eea71b2da3c4
deleted file mode 100644
index 49cbe76..0000000
--- a/src/fuzz/client_corpus/d1a8c6d76736e52a058557b2da02eea71b2da3c4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/d233b71cebdc920563b4b7067430cfb558ca855b b/src/fuzz/client_corpus/d233b71cebdc920563b4b7067430cfb558ca855b
deleted file mode 100644
index 2cd6ad6..0000000
--- a/src/fuzz/client_corpus/d233b71cebdc920563b4b7067430cfb558ca855b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/d5bd30086dbf53ae76c39eaf20cbb8d4ab59466e b/src/fuzz/client_corpus/d5bd30086dbf53ae76c39eaf20cbb8d4ab59466e
new file mode 100644
index 0000000..7d1d924
--- /dev/null
+++ b/src/fuzz/client_corpus/d5bd30086dbf53ae76c39eaf20cbb8d4ab59466e
Binary files differ
diff --git a/src/fuzz/client_corpus/da3daabe56539c4851e7dd21a54793fec1ed7aa2 b/src/fuzz/client_corpus/da3daabe56539c4851e7dd21a54793fec1ed7aa2
new file mode 100644
index 0000000..16cf321
--- /dev/null
+++ b/src/fuzz/client_corpus/da3daabe56539c4851e7dd21a54793fec1ed7aa2
Binary files differ
diff --git a/src/fuzz/client_corpus/db0a315e9d82a5d245048d6ffed7e05b42d85671 b/src/fuzz/client_corpus/db0a315e9d82a5d245048d6ffed7e05b42d85671
new file mode 100644
index 0000000..08ebc99
--- /dev/null
+++ b/src/fuzz/client_corpus/db0a315e9d82a5d245048d6ffed7e05b42d85671
Binary files differ
diff --git a/src/fuzz/client_corpus/e1027ed036ec96728acba3d72f0a0ea5d59b9cc8 b/src/fuzz/client_corpus/e1027ed036ec96728acba3d72f0a0ea5d59b9cc8
new file mode 100644
index 0000000..460a99d
--- /dev/null
+++ b/src/fuzz/client_corpus/e1027ed036ec96728acba3d72f0a0ea5d59b9cc8
Binary files differ
diff --git a/src/fuzz/client_corpus/e38ef2823e48f897ed118c510c643766fcf1768c b/src/fuzz/client_corpus/e38ef2823e48f897ed118c510c643766fcf1768c
deleted file mode 100644
index a258d2a..0000000
--- a/src/fuzz/client_corpus/e38ef2823e48f897ed118c510c643766fcf1768c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/e87218d1f2f884a66ca8bb2be3cb38f84b92edd6 b/src/fuzz/client_corpus/e87218d1f2f884a66ca8bb2be3cb38f84b92edd6
new file mode 100644
index 0000000..cbb4fb4
--- /dev/null
+++ b/src/fuzz/client_corpus/e87218d1f2f884a66ca8bb2be3cb38f84b92edd6
Binary files differ
diff --git a/src/fuzz/client_corpus/f0065bd261954ee93eae49517a624e3496b498ee b/src/fuzz/client_corpus/f0065bd261954ee93eae49517a624e3496b498ee
deleted file mode 100644
index 39bd8fd..0000000
--- a/src/fuzz/client_corpus/f0065bd261954ee93eae49517a624e3496b498ee
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/f35a4658f19df962e1ee63f7cedbf53aa70ac175 b/src/fuzz/client_corpus/f35a4658f19df962e1ee63f7cedbf53aa70ac175
deleted file mode 100644
index 5d20308..0000000
--- a/src/fuzz/client_corpus/f35a4658f19df962e1ee63f7cedbf53aa70ac175
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/f5af4da8f41eb4619e920f15badcaed52ab37a27 b/src/fuzz/client_corpus/f5af4da8f41eb4619e920f15badcaed52ab37a27
new file mode 100644
index 0000000..b4c60b0
--- /dev/null
+++ b/src/fuzz/client_corpus/f5af4da8f41eb4619e920f15badcaed52ab37a27
Binary files differ
diff --git a/src/fuzz/client_corpus/f63c9705fa48fff8dbd92be8a8215294da13a339 b/src/fuzz/client_corpus/f63c9705fa48fff8dbd92be8a8215294da13a339
deleted file mode 100644
index b719f44..0000000
--- a/src/fuzz/client_corpus/f63c9705fa48fff8dbd92be8a8215294da13a339
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus/fa29728083c19ba2b1fd8828499060828a6fbd9d b/src/fuzz/client_corpus/fa29728083c19ba2b1fd8828499060828a6fbd9d
new file mode 100644
index 0000000..a4ae5fe
--- /dev/null
+++ b/src/fuzz/client_corpus/fa29728083c19ba2b1fd8828499060828a6fbd9d
Binary files differ
diff --git a/src/fuzz/client_corpus/fc45a752e0663b7c446e31ff7dee01881334ed82 b/src/fuzz/client_corpus/fc45a752e0663b7c446e31ff7dee01881334ed82
new file mode 100644
index 0000000..ef3b22e
--- /dev/null
+++ b/src/fuzz/client_corpus/fc45a752e0663b7c446e31ff7dee01881334ed82
Binary files differ
diff --git a/src/fuzz/client_corpus/ffe71d0314b13356a01c259339dab080a47a2b81 b/src/fuzz/client_corpus/ffe71d0314b13356a01c259339dab080a47a2b81
deleted file mode 100644
index 9bb346c..0000000
--- a/src/fuzz/client_corpus/ffe71d0314b13356a01c259339dab080a47a2b81
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0ea2832073ae5d65cd3474ef7573dfc6a16254ec b/src/fuzz/client_corpus_no_fuzzer_mode/0ea2832073ae5d65cd3474ef7573dfc6a16254ec
deleted file mode 100644
index 899b618..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/0ea2832073ae5d65cd3474ef7573dfc6a16254ec
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/122a3e27fe2ecbe7e898dca7391bc1c96687e422 b/src/fuzz/client_corpus_no_fuzzer_mode/122a3e27fe2ecbe7e898dca7391bc1c96687e422
deleted file mode 100644
index 1d06e0f..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/122a3e27fe2ecbe7e898dca7391bc1c96687e422
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/17f6593543c8a78c1d6c241cd93770a5d0150ad7 b/src/fuzz/client_corpus_no_fuzzer_mode/17f6593543c8a78c1d6c241cd93770a5d0150ad7
deleted file mode 100644
index a428e7d..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/17f6593543c8a78c1d6c241cd93770a5d0150ad7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/27c5175e648ee441c45cdafc9ea65b0573fae7f1 b/src/fuzz/client_corpus_no_fuzzer_mode/27c5175e648ee441c45cdafc9ea65b0573fae7f1
deleted file mode 100644
index b23a1b0..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/27c5175e648ee441c45cdafc9ea65b0573fae7f1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/303b60bb9d1085c215b680de06130911f1456974 b/src/fuzz/client_corpus_no_fuzzer_mode/303b60bb9d1085c215b680de06130911f1456974
deleted file mode 100644
index 965bb98..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/303b60bb9d1085c215b680de06130911f1456974
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4b66cca03f93afc98bbe23921edbae7ec571349d b/src/fuzz/client_corpus_no_fuzzer_mode/4b66cca03f93afc98bbe23921edbae7ec571349d
deleted file mode 100644
index b3d263c..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/4b66cca03f93afc98bbe23921edbae7ec571349d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4f7845dba450bcb783b6960b6714053bc34137a3 b/src/fuzz/client_corpus_no_fuzzer_mode/4f7845dba450bcb783b6960b6714053bc34137a3
deleted file mode 100644
index 0728f77..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/4f7845dba450bcb783b6960b6714053bc34137a3
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/50df7fcb9d352351c357c3628cdccd408a4432a7 b/src/fuzz/client_corpus_no_fuzzer_mode/50df7fcb9d352351c357c3628cdccd408a4432a7
deleted file mode 100644
index 59b98dc..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/50df7fcb9d352351c357c3628cdccd408a4432a7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9e61c391be2478fa4a9e6ed79bf084d50aeaecde b/src/fuzz/client_corpus_no_fuzzer_mode/9e61c391be2478fa4a9e6ed79bf084d50aeaecde
deleted file mode 100644
index 6ee5c15..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/9e61c391be2478fa4a9e6ed79bf084d50aeaecde
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9e678acd3daf9fdcef9129b9e1e3177ead675540 b/src/fuzz/client_corpus_no_fuzzer_mode/9e678acd3daf9fdcef9129b9e1e3177ead675540
deleted file mode 100644
index c7e7b9f..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/9e678acd3daf9fdcef9129b9e1e3177ead675540
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a4aeb53df6a88dead0a1de205acd78a3b582ca1a b/src/fuzz/client_corpus_no_fuzzer_mode/a4aeb53df6a88dead0a1de205acd78a3b582ca1a
deleted file mode 100644
index 8df4378..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/a4aeb53df6a88dead0a1de205acd78a3b582ca1a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a64113ae9e2ca40e85f2da4693d8a50c3a663c13 b/src/fuzz/client_corpus_no_fuzzer_mode/a64113ae9e2ca40e85f2da4693d8a50c3a663c13
deleted file mode 100644
index 3900d8a..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/a64113ae9e2ca40e85f2da4693d8a50c3a663c13
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ae11a7a9c514ce51f109666719f6c07cb3e683e0 b/src/fuzz/client_corpus_no_fuzzer_mode/ae11a7a9c514ce51f109666719f6c07cb3e683e0
deleted file mode 100644
index 8f1f6de..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/ae11a7a9c514ce51f109666719f6c07cb3e683e0
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b1f61e1e7c66ad321f8f0cf3cc849531ce1a8ddd b/src/fuzz/client_corpus_no_fuzzer_mode/b1f61e1e7c66ad321f8f0cf3cc849531ce1a8ddd
deleted file mode 100644
index 9b16596..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/b1f61e1e7c66ad321f8f0cf3cc849531ce1a8ddd
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c1e33e5466c77656b4c9ca825a21a331dd02cc22 b/src/fuzz/client_corpus_no_fuzzer_mode/c1e33e5466c77656b4c9ca825a21a331dd02cc22
deleted file mode 100644
index 78c096a..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/c1e33e5466c77656b4c9ca825a21a331dd02cc22
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/cc60bd93b5b993282fe942a0b78cc5e14a93e527 b/src/fuzz/client_corpus_no_fuzzer_mode/cc60bd93b5b993282fe942a0b78cc5e14a93e527
deleted file mode 100644
index 44e6b39..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/cc60bd93b5b993282fe942a0b78cc5e14a93e527
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d233b71cebdc920563b4b7067430cfb558ca855b b/src/fuzz/client_corpus_no_fuzzer_mode/d233b71cebdc920563b4b7067430cfb558ca855b
deleted file mode 100644
index 2cd6ad6..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/d233b71cebdc920563b4b7067430cfb558ca855b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d636d9f8a5e92c6ffba412fc2dbc2c0c67ece39e b/src/fuzz/client_corpus_no_fuzzer_mode/d636d9f8a5e92c6ffba412fc2dbc2c0c67ece39e
deleted file mode 100644
index f836773..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/d636d9f8a5e92c6ffba412fc2dbc2c0c67ece39e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e53615202a537675257fa5bd9ea8aaaf1c2730dc b/src/fuzz/client_corpus_no_fuzzer_mode/e53615202a537675257fa5bd9ea8aaaf1c2730dc
deleted file mode 100644
index ea7f332..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/e53615202a537675257fa5bd9ea8aaaf1c2730dc
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ea910d676242f1bf4f0bd42d575ea204a84ec64d b/src/fuzz/client_corpus_no_fuzzer_mode/ea910d676242f1bf4f0bd42d575ea204a84ec64d
deleted file mode 100644
index 1d6a4d1..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/ea910d676242f1bf4f0bd42d575ea204a84ec64d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/f2991e821ea94b22f5c9d7b2fd76a2ded0171328 b/src/fuzz/client_corpus_no_fuzzer_mode/f2991e821ea94b22f5c9d7b2fd76a2ded0171328
deleted file mode 100644
index ba449ac..0000000
--- a/src/fuzz/client_corpus_no_fuzzer_mode/f2991e821ea94b22f5c9d7b2fd76a2ded0171328
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode.cc b/src/fuzz/client_no_fuzzer_mode.cc
new file mode 100644
index 0000000..e5f26ed
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "../ssl/test/fuzzer.h"
+
+
+static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kClient,
+                          TLSFuzzer::kFuzzerModeOff);
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
+  return g_fuzzer.TestOneInput(buf, len);
+}
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0406a0ce3873776e65a0fcb5f9f8e735cd110f8a b/src/fuzz/client_no_fuzzer_mode_corpus/0406a0ce3873776e65a0fcb5f9f8e735cd110f8a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/0406a0ce3873776e65a0fcb5f9f8e735cd110f8a
rename to src/fuzz/client_no_fuzzer_mode_corpus/0406a0ce3873776e65a0fcb5f9f8e735cd110f8a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/072afe5e9ba1fcec2b47f13e5628dff55f2131a9 b/src/fuzz/client_no_fuzzer_mode_corpus/072afe5e9ba1fcec2b47f13e5628dff55f2131a9
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/072afe5e9ba1fcec2b47f13e5628dff55f2131a9
rename to src/fuzz/client_no_fuzzer_mode_corpus/072afe5e9ba1fcec2b47f13e5628dff55f2131a9
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0885d2f5e56debe90d702b3885edbec580af8d24 b/src/fuzz/client_no_fuzzer_mode_corpus/0885d2f5e56debe90d702b3885edbec580af8d24
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/0885d2f5e56debe90d702b3885edbec580af8d24
rename to src/fuzz/client_no_fuzzer_mode_corpus/0885d2f5e56debe90d702b3885edbec580af8d24
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/096eddc240c9044debb4cb35995671a2dd555646 b/src/fuzz/client_no_fuzzer_mode_corpus/096eddc240c9044debb4cb35995671a2dd555646
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/096eddc240c9044debb4cb35995671a2dd555646
rename to src/fuzz/client_no_fuzzer_mode_corpus/096eddc240c9044debb4cb35995671a2dd555646
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/097b025d14e29f7d92152377e73b5ccb6bb900ad b/src/fuzz/client_no_fuzzer_mode_corpus/097b025d14e29f7d92152377e73b5ccb6bb900ad
new file mode 100644
index 0000000..c40cf42
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/097b025d14e29f7d92152377e73b5ccb6bb900ad
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0a1d783db7943f465520159b2c9b28e692cb1b2e b/src/fuzz/client_no_fuzzer_mode_corpus/0a1d783db7943f465520159b2c9b28e692cb1b2e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/0a1d783db7943f465520159b2c9b28e692cb1b2e
rename to src/fuzz/client_no_fuzzer_mode_corpus/0a1d783db7943f465520159b2c9b28e692cb1b2e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0b0f3818d48b140b7660d30630e2da7be213d13c b/src/fuzz/client_no_fuzzer_mode_corpus/0b0f3818d48b140b7660d30630e2da7be213d13c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/0b0f3818d48b140b7660d30630e2da7be213d13c
rename to src/fuzz/client_no_fuzzer_mode_corpus/0b0f3818d48b140b7660d30630e2da7be213d13c
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/0c387c40350d3f4259d32d875a1554d8252d8a50 b/src/fuzz/client_no_fuzzer_mode_corpus/0c387c40350d3f4259d32d875a1554d8252d8a50
new file mode 100644
index 0000000..fd144a0
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/0c387c40350d3f4259d32d875a1554d8252d8a50
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/0c8aabd31abb8e0ae4d7e1301220fb230d7dc99a b/src/fuzz/client_no_fuzzer_mode_corpus/0c8aabd31abb8e0ae4d7e1301220fb230d7dc99a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/0c8aabd31abb8e0ae4d7e1301220fb230d7dc99a
rename to src/fuzz/client_no_fuzzer_mode_corpus/0c8aabd31abb8e0ae4d7e1301220fb230d7dc99a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/11f842ca4f752d206c9f1d893f4af5b2a0ba39df b/src/fuzz/client_no_fuzzer_mode_corpus/11f842ca4f752d206c9f1d893f4af5b2a0ba39df
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/11f842ca4f752d206c9f1d893f4af5b2a0ba39df
rename to src/fuzz/client_no_fuzzer_mode_corpus/11f842ca4f752d206c9f1d893f4af5b2a0ba39df
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/13526c64ba521bed4c2da7620086ca463671592f b/src/fuzz/client_no_fuzzer_mode_corpus/13526c64ba521bed4c2da7620086ca463671592f
new file mode 100644
index 0000000..200e7bd
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/13526c64ba521bed4c2da7620086ca463671592f
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/1489f923c4dca729178b3e3233458550d8dddf29 b/src/fuzz/client_no_fuzzer_mode_corpus/1489f923c4dca729178b3e3233458550d8dddf29
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/1489f923c4dca729178b3e3233458550d8dddf29
rename to src/fuzz/client_no_fuzzer_mode_corpus/1489f923c4dca729178b3e3233458550d8dddf29
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/151f21f5cb1ffcb105ff9b51af388fef3780f217 b/src/fuzz/client_no_fuzzer_mode_corpus/151f21f5cb1ffcb105ff9b51af388fef3780f217
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/151f21f5cb1ffcb105ff9b51af388fef3780f217
rename to src/fuzz/client_no_fuzzer_mode_corpus/151f21f5cb1ffcb105ff9b51af388fef3780f217
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/15d88286efd2b01b2f19bed5be9d06e803b01200 b/src/fuzz/client_no_fuzzer_mode_corpus/15d88286efd2b01b2f19bed5be9d06e803b01200
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/15d88286efd2b01b2f19bed5be9d06e803b01200
rename to src/fuzz/client_no_fuzzer_mode_corpus/15d88286efd2b01b2f19bed5be9d06e803b01200
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/17bf733e2011f066cbc4dbd62ed9051b3bee44bc b/src/fuzz/client_no_fuzzer_mode_corpus/17bf733e2011f066cbc4dbd62ed9051b3bee44bc
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/17bf733e2011f066cbc4dbd62ed9051b3bee44bc
rename to src/fuzz/client_no_fuzzer_mode_corpus/17bf733e2011f066cbc4dbd62ed9051b3bee44bc
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/196024484e94a9d7aa4e1ed3fac5f9f4969c6956 b/src/fuzz/client_no_fuzzer_mode_corpus/196024484e94a9d7aa4e1ed3fac5f9f4969c6956
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/196024484e94a9d7aa4e1ed3fac5f9f4969c6956
rename to src/fuzz/client_no_fuzzer_mode_corpus/196024484e94a9d7aa4e1ed3fac5f9f4969c6956
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/198387c95d3a24ce414348516fc51ae5d6f46bff b/src/fuzz/client_no_fuzzer_mode_corpus/198387c95d3a24ce414348516fc51ae5d6f46bff
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/198387c95d3a24ce414348516fc51ae5d6f46bff
rename to src/fuzz/client_no_fuzzer_mode_corpus/198387c95d3a24ce414348516fc51ae5d6f46bff
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/1a99c05d8feb0b5db235cffea0d45dcaa78dd143 b/src/fuzz/client_no_fuzzer_mode_corpus/1a99c05d8feb0b5db235cffea0d45dcaa78dd143
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/1a99c05d8feb0b5db235cffea0d45dcaa78dd143
rename to src/fuzz/client_no_fuzzer_mode_corpus/1a99c05d8feb0b5db235cffea0d45dcaa78dd143
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/1bd3619ace632829246ecd717c5e2b6048649e5f b/src/fuzz/client_no_fuzzer_mode_corpus/1bd3619ace632829246ecd717c5e2b6048649e5f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/1bd3619ace632829246ecd717c5e2b6048649e5f
rename to src/fuzz/client_no_fuzzer_mode_corpus/1bd3619ace632829246ecd717c5e2b6048649e5f
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/1ef89e5a4c6308cb40d8167759ccd1987796a0b4 b/src/fuzz/client_no_fuzzer_mode_corpus/1ef89e5a4c6308cb40d8167759ccd1987796a0b4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/1ef89e5a4c6308cb40d8167759ccd1987796a0b4
rename to src/fuzz/client_no_fuzzer_mode_corpus/1ef89e5a4c6308cb40d8167759ccd1987796a0b4
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/1efd691b9e956ab5119a03a520a42f1855d095f8 b/src/fuzz/client_no_fuzzer_mode_corpus/1efd691b9e956ab5119a03a520a42f1855d095f8
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/1efd691b9e956ab5119a03a520a42f1855d095f8
rename to src/fuzz/client_no_fuzzer_mode_corpus/1efd691b9e956ab5119a03a520a42f1855d095f8
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/255472a1dff67bdd5cd03b12682189c32c36230f b/src/fuzz/client_no_fuzzer_mode_corpus/255472a1dff67bdd5cd03b12682189c32c36230f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/255472a1dff67bdd5cd03b12682189c32c36230f
rename to src/fuzz/client_no_fuzzer_mode_corpus/255472a1dff67bdd5cd03b12682189c32c36230f
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/27d953a930479f1e89cf2d33d9473e94e426598f b/src/fuzz/client_no_fuzzer_mode_corpus/27d953a930479f1e89cf2d33d9473e94e426598f
new file mode 100644
index 0000000..110a4a7
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/27d953a930479f1e89cf2d33d9473e94e426598f
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/28b2ccdfe98839ef49df6be3e7c87c67629cba3c b/src/fuzz/client_no_fuzzer_mode_corpus/28b2ccdfe98839ef49df6be3e7c87c67629cba3c
new file mode 100644
index 0000000..7551f49
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/28b2ccdfe98839ef49df6be3e7c87c67629cba3c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/28d25966f30bcb3fa3376830109d2dfcd1ec5e04 b/src/fuzz/client_no_fuzzer_mode_corpus/28d25966f30bcb3fa3376830109d2dfcd1ec5e04
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/28d25966f30bcb3fa3376830109d2dfcd1ec5e04
rename to src/fuzz/client_no_fuzzer_mode_corpus/28d25966f30bcb3fa3376830109d2dfcd1ec5e04
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/2ae0b8de2c353abb4352391fd013e5a6a9ac9e5e b/src/fuzz/client_no_fuzzer_mode_corpus/2ae0b8de2c353abb4352391fd013e5a6a9ac9e5e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/2ae0b8de2c353abb4352391fd013e5a6a9ac9e5e
rename to src/fuzz/client_no_fuzzer_mode_corpus/2ae0b8de2c353abb4352391fd013e5a6a9ac9e5e
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/2efb50ea788432cd71beffe0c38b36a338e57e8e b/src/fuzz/client_no_fuzzer_mode_corpus/2efb50ea788432cd71beffe0c38b36a338e57e8e
new file mode 100644
index 0000000..7a6f3c4
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/2efb50ea788432cd71beffe0c38b36a338e57e8e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/2f10f9e3ea83fa53d7bb9e514f468d1bfc3c01a9 b/src/fuzz/client_no_fuzzer_mode_corpus/2f10f9e3ea83fa53d7bb9e514f468d1bfc3c01a9
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/2f10f9e3ea83fa53d7bb9e514f468d1bfc3c01a9
rename to src/fuzz/client_no_fuzzer_mode_corpus/2f10f9e3ea83fa53d7bb9e514f468d1bfc3c01a9
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/2f7c35faedfcabf2e339a0855ba414a20a5b79f0 b/src/fuzz/client_no_fuzzer_mode_corpus/2f7c35faedfcabf2e339a0855ba414a20a5b79f0
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/2f7c35faedfcabf2e339a0855ba414a20a5b79f0
rename to src/fuzz/client_no_fuzzer_mode_corpus/2f7c35faedfcabf2e339a0855ba414a20a5b79f0
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3061373083005b2f9bc481a52ac2089de73d6a73 b/src/fuzz/client_no_fuzzer_mode_corpus/3061373083005b2f9bc481a52ac2089de73d6a73
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3061373083005b2f9bc481a52ac2089de73d6a73
rename to src/fuzz/client_no_fuzzer_mode_corpus/3061373083005b2f9bc481a52ac2089de73d6a73
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/308f27e07c79eb98b4964384ee4a411d637aca11 b/src/fuzz/client_no_fuzzer_mode_corpus/308f27e07c79eb98b4964384ee4a411d637aca11
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/308f27e07c79eb98b4964384ee4a411d637aca11
rename to src/fuzz/client_no_fuzzer_mode_corpus/308f27e07c79eb98b4964384ee4a411d637aca11
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/30bcbd3bf3da44431b4d8a9a50e8c936cdcbbe4e b/src/fuzz/client_no_fuzzer_mode_corpus/30bcbd3bf3da44431b4d8a9a50e8c936cdcbbe4e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/30bcbd3bf3da44431b4d8a9a50e8c936cdcbbe4e
rename to src/fuzz/client_no_fuzzer_mode_corpus/30bcbd3bf3da44431b4d8a9a50e8c936cdcbbe4e
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/3142b8fa87c64bda644eb691791d669b1781e2a0 b/src/fuzz/client_no_fuzzer_mode_corpus/3142b8fa87c64bda644eb691791d669b1781e2a0
new file mode 100644
index 0000000..cd0cd04
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/3142b8fa87c64bda644eb691791d669b1781e2a0
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/321847a2ce634faeaffa56ae79df8d5a568d4f41 b/src/fuzz/client_no_fuzzer_mode_corpus/321847a2ce634faeaffa56ae79df8d5a568d4f41
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/321847a2ce634faeaffa56ae79df8d5a568d4f41
rename to src/fuzz/client_no_fuzzer_mode_corpus/321847a2ce634faeaffa56ae79df8d5a568d4f41
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/32759b9b755a4793c190395f3a4f083c88de8100 b/src/fuzz/client_no_fuzzer_mode_corpus/32759b9b755a4793c190395f3a4f083c88de8100
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/32759b9b755a4793c190395f3a4f083c88de8100
rename to src/fuzz/client_no_fuzzer_mode_corpus/32759b9b755a4793c190395f3a4f083c88de8100
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/32928f8ffca1409175feb2eb227c37948a77a9ab b/src/fuzz/client_no_fuzzer_mode_corpus/32928f8ffca1409175feb2eb227c37948a77a9ab
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/32928f8ffca1409175feb2eb227c37948a77a9ab
rename to src/fuzz/client_no_fuzzer_mode_corpus/32928f8ffca1409175feb2eb227c37948a77a9ab
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/33534cd816af0da589f5acf0aff55d34f380af53 b/src/fuzz/client_no_fuzzer_mode_corpus/33534cd816af0da589f5acf0aff55d34f380af53
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/33534cd816af0da589f5acf0aff55d34f380af53
rename to src/fuzz/client_no_fuzzer_mode_corpus/33534cd816af0da589f5acf0aff55d34f380af53
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/35b6f5a0f0cf102b0ebe24deecb63e8a28f41bab b/src/fuzz/client_no_fuzzer_mode_corpus/35b6f5a0f0cf102b0ebe24deecb63e8a28f41bab
new file mode 100644
index 0000000..d88a343
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/35b6f5a0f0cf102b0ebe24deecb63e8a28f41bab
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/364fe53a69109d29ea9de3beb2377b173df412a1 b/src/fuzz/client_no_fuzzer_mode_corpus/364fe53a69109d29ea9de3beb2377b173df412a1
new file mode 100644
index 0000000..dbf5703
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/364fe53a69109d29ea9de3beb2377b173df412a1
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/372b95c854577b041dafad1e0f7005642e70d416 b/src/fuzz/client_no_fuzzer_mode_corpus/372b95c854577b041dafad1e0f7005642e70d416
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/372b95c854577b041dafad1e0f7005642e70d416
rename to src/fuzz/client_no_fuzzer_mode_corpus/372b95c854577b041dafad1e0f7005642e70d416
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3849f809f030d1094d19cce6a636befba1281009 b/src/fuzz/client_no_fuzzer_mode_corpus/3849f809f030d1094d19cce6a636befba1281009
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3849f809f030d1094d19cce6a636befba1281009
rename to src/fuzz/client_no_fuzzer_mode_corpus/3849f809f030d1094d19cce6a636befba1281009
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/39448989ad2e60a738afa81c2cbd14e0fa44a72c b/src/fuzz/client_no_fuzzer_mode_corpus/39448989ad2e60a738afa81c2cbd14e0fa44a72c
new file mode 100644
index 0000000..54a4e47
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/39448989ad2e60a738afa81c2cbd14e0fa44a72c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3948bed942bd57a28bd3b0b78bc8760f625b8c0c b/src/fuzz/client_no_fuzzer_mode_corpus/3948bed942bd57a28bd3b0b78bc8760f625b8c0c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3948bed942bd57a28bd3b0b78bc8760f625b8c0c
rename to src/fuzz/client_no_fuzzer_mode_corpus/3948bed942bd57a28bd3b0b78bc8760f625b8c0c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/39d44f5e3d2c70593e82506504825e556f1003ad b/src/fuzz/client_no_fuzzer_mode_corpus/39d44f5e3d2c70593e82506504825e556f1003ad
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/39d44f5e3d2c70593e82506504825e556f1003ad
rename to src/fuzz/client_no_fuzzer_mode_corpus/39d44f5e3d2c70593e82506504825e556f1003ad
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/3a63ce2d84ccc70bc35b6c7b2849b606785dd032 b/src/fuzz/client_no_fuzzer_mode_corpus/3a63ce2d84ccc70bc35b6c7b2849b606785dd032
new file mode 100644
index 0000000..cc07ddc
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/3a63ce2d84ccc70bc35b6c7b2849b606785dd032
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/3b402925b3ed581d86ba39c3949810f26f6f28ad b/src/fuzz/client_no_fuzzer_mode_corpus/3b402925b3ed581d86ba39c3949810f26f6f28ad
new file mode 100644
index 0000000..c2dcec7
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/3b402925b3ed581d86ba39c3949810f26f6f28ad
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3d543946691b7da695c51f06788f1fbdbba0078e b/src/fuzz/client_no_fuzzer_mode_corpus/3d543946691b7da695c51f06788f1fbdbba0078e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3d543946691b7da695c51f06788f1fbdbba0078e
rename to src/fuzz/client_no_fuzzer_mode_corpus/3d543946691b7da695c51f06788f1fbdbba0078e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3e153e6b6d0146a43ec3fd09464f942704daf1a4 b/src/fuzz/client_no_fuzzer_mode_corpus/3e153e6b6d0146a43ec3fd09464f942704daf1a4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3e153e6b6d0146a43ec3fd09464f942704daf1a4
rename to src/fuzz/client_no_fuzzer_mode_corpus/3e153e6b6d0146a43ec3fd09464f942704daf1a4
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/3fb9220ae4d3f9b932efb342db26b96938767750 b/src/fuzz/client_no_fuzzer_mode_corpus/3fb9220ae4d3f9b932efb342db26b96938767750
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/3fb9220ae4d3f9b932efb342db26b96938767750
rename to src/fuzz/client_no_fuzzer_mode_corpus/3fb9220ae4d3f9b932efb342db26b96938767750
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/40b6d468cd4142d775eb3b79f6b1900405502b90 b/src/fuzz/client_no_fuzzer_mode_corpus/40b6d468cd4142d775eb3b79f6b1900405502b90
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/40b6d468cd4142d775eb3b79f6b1900405502b90
rename to src/fuzz/client_no_fuzzer_mode_corpus/40b6d468cd4142d775eb3b79f6b1900405502b90
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/41a069cf62fef316e92aa67f42a0265ec974d1b3 b/src/fuzz/client_no_fuzzer_mode_corpus/41a069cf62fef316e92aa67f42a0265ec974d1b3
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/41a069cf62fef316e92aa67f42a0265ec974d1b3
rename to src/fuzz/client_no_fuzzer_mode_corpus/41a069cf62fef316e92aa67f42a0265ec974d1b3
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/4231fbee5082d2873c44ce777f37a5acf705b415 b/src/fuzz/client_no_fuzzer_mode_corpus/4231fbee5082d2873c44ce777f37a5acf705b415
new file mode 100644
index 0000000..0d7d42d
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/4231fbee5082d2873c44ce777f37a5acf705b415
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/42f8174145a9cd2d15016b4cf0d6db97cb884b04 b/src/fuzz/client_no_fuzzer_mode_corpus/42f8174145a9cd2d15016b4cf0d6db97cb884b04
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/42f8174145a9cd2d15016b4cf0d6db97cb884b04
rename to src/fuzz/client_no_fuzzer_mode_corpus/42f8174145a9cd2d15016b4cf0d6db97cb884b04
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/43008da4f82a6b0997a881bd55a4f1448b14f6a2 b/src/fuzz/client_no_fuzzer_mode_corpus/43008da4f82a6b0997a881bd55a4f1448b14f6a2
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/43008da4f82a6b0997a881bd55a4f1448b14f6a2
rename to src/fuzz/client_no_fuzzer_mode_corpus/43008da4f82a6b0997a881bd55a4f1448b14f6a2
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/43d550b1eef83a237a3d96a85eca01afca7f4064 b/src/fuzz/client_no_fuzzer_mode_corpus/43d550b1eef83a237a3d96a85eca01afca7f4064
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/43d550b1eef83a237a3d96a85eca01afca7f4064
rename to src/fuzz/client_no_fuzzer_mode_corpus/43d550b1eef83a237a3d96a85eca01afca7f4064
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4552802489552783e316f1edf339a112643381f9 b/src/fuzz/client_no_fuzzer_mode_corpus/4552802489552783e316f1edf339a112643381f9
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4552802489552783e316f1edf339a112643381f9
rename to src/fuzz/client_no_fuzzer_mode_corpus/4552802489552783e316f1edf339a112643381f9
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/461bb6e7d93af42775a640b70b6043d3c43f990d b/src/fuzz/client_no_fuzzer_mode_corpus/461bb6e7d93af42775a640b70b6043d3c43f990d
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/461bb6e7d93af42775a640b70b6043d3c43f990d
rename to src/fuzz/client_no_fuzzer_mode_corpus/461bb6e7d93af42775a640b70b6043d3c43f990d
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/46a9fc44bab25ddf24e92c4f137080bbd8684f10 b/src/fuzz/client_no_fuzzer_mode_corpus/46a9fc44bab25ddf24e92c4f137080bbd8684f10
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/46a9fc44bab25ddf24e92c4f137080bbd8684f10
rename to src/fuzz/client_no_fuzzer_mode_corpus/46a9fc44bab25ddf24e92c4f137080bbd8684f10
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/46be951703158b1af3986c9f0eade0bdb618f5c3 b/src/fuzz/client_no_fuzzer_mode_corpus/46be951703158b1af3986c9f0eade0bdb618f5c3
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/46be951703158b1af3986c9f0eade0bdb618f5c3
rename to src/fuzz/client_no_fuzzer_mode_corpus/46be951703158b1af3986c9f0eade0bdb618f5c3
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4856721e2cf47eebec756e23c877558b4cb10f3f b/src/fuzz/client_no_fuzzer_mode_corpus/4856721e2cf47eebec756e23c877558b4cb10f3f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4856721e2cf47eebec756e23c877558b4cb10f3f
rename to src/fuzz/client_no_fuzzer_mode_corpus/4856721e2cf47eebec756e23c877558b4cb10f3f
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4a43d832406bb9eb0706b717e5af4c977d88f67e b/src/fuzz/client_no_fuzzer_mode_corpus/4a43d832406bb9eb0706b717e5af4c977d88f67e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4a43d832406bb9eb0706b717e5af4c977d88f67e
rename to src/fuzz/client_no_fuzzer_mode_corpus/4a43d832406bb9eb0706b717e5af4c977d88f67e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4a8349850aab837eadebfe0d1a49a84adac18fab b/src/fuzz/client_no_fuzzer_mode_corpus/4a8349850aab837eadebfe0d1a49a84adac18fab
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4a8349850aab837eadebfe0d1a49a84adac18fab
rename to src/fuzz/client_no_fuzzer_mode_corpus/4a8349850aab837eadebfe0d1a49a84adac18fab
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4ad796d335814bab0d3bbe5b50c1898eb9eb96d4 b/src/fuzz/client_no_fuzzer_mode_corpus/4ad796d335814bab0d3bbe5b50c1898eb9eb96d4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4ad796d335814bab0d3bbe5b50c1898eb9eb96d4
rename to src/fuzz/client_no_fuzzer_mode_corpus/4ad796d335814bab0d3bbe5b50c1898eb9eb96d4
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4b67f6e81d4c05c21b1cbc336c8bfa632dd7fc18 b/src/fuzz/client_no_fuzzer_mode_corpus/4b67f6e81d4c05c21b1cbc336c8bfa632dd7fc18
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4b67f6e81d4c05c21b1cbc336c8bfa632dd7fc18
rename to src/fuzz/client_no_fuzzer_mode_corpus/4b67f6e81d4c05c21b1cbc336c8bfa632dd7fc18
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4c108c7588df5d3a0a70725d2ee59b180b30f455 b/src/fuzz/client_no_fuzzer_mode_corpus/4c108c7588df5d3a0a70725d2ee59b180b30f455
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4c108c7588df5d3a0a70725d2ee59b180b30f455
rename to src/fuzz/client_no_fuzzer_mode_corpus/4c108c7588df5d3a0a70725d2ee59b180b30f455
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/4cfff273128abfdf42e0ead3c0c98d53bab74a68 b/src/fuzz/client_no_fuzzer_mode_corpus/4cfff273128abfdf42e0ead3c0c98d53bab74a68
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/4cfff273128abfdf42e0ead3c0c98d53bab74a68
rename to src/fuzz/client_no_fuzzer_mode_corpus/4cfff273128abfdf42e0ead3c0c98d53bab74a68
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/52eab1080ae6856eb5dc5e13996ebb225d97b918 b/src/fuzz/client_no_fuzzer_mode_corpus/52eab1080ae6856eb5dc5e13996ebb225d97b918
new file mode 100644
index 0000000..22b4618
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/52eab1080ae6856eb5dc5e13996ebb225d97b918
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5326b1ab999cbca2d5e4525e368b4a31f0357088 b/src/fuzz/client_no_fuzzer_mode_corpus/5326b1ab999cbca2d5e4525e368b4a31f0357088
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5326b1ab999cbca2d5e4525e368b4a31f0357088
rename to src/fuzz/client_no_fuzzer_mode_corpus/5326b1ab999cbca2d5e4525e368b4a31f0357088
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/53ca7b40934b63df766c5dc95abd75fac34eab0c b/src/fuzz/client_no_fuzzer_mode_corpus/53ca7b40934b63df766c5dc95abd75fac34eab0c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/53ca7b40934b63df766c5dc95abd75fac34eab0c
rename to src/fuzz/client_no_fuzzer_mode_corpus/53ca7b40934b63df766c5dc95abd75fac34eab0c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/54de963a4c073668a7728fd22f83881451b46b65 b/src/fuzz/client_no_fuzzer_mode_corpus/54de963a4c073668a7728fd22f83881451b46b65
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/54de963a4c073668a7728fd22f83881451b46b65
rename to src/fuzz/client_no_fuzzer_mode_corpus/54de963a4c073668a7728fd22f83881451b46b65
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/554d380008acbad20916f43fdf249e94b822ddfe b/src/fuzz/client_no_fuzzer_mode_corpus/554d380008acbad20916f43fdf249e94b822ddfe
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/554d380008acbad20916f43fdf249e94b822ddfe
rename to src/fuzz/client_no_fuzzer_mode_corpus/554d380008acbad20916f43fdf249e94b822ddfe
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/564cfd52b7873bea5d715c87b4ec56053ebd14e4 b/src/fuzz/client_no_fuzzer_mode_corpus/564cfd52b7873bea5d715c87b4ec56053ebd14e4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/564cfd52b7873bea5d715c87b4ec56053ebd14e4
rename to src/fuzz/client_no_fuzzer_mode_corpus/564cfd52b7873bea5d715c87b4ec56053ebd14e4
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/57cdb41b10c91c1461a690397683acce0bc23595 b/src/fuzz/client_no_fuzzer_mode_corpus/57cdb41b10c91c1461a690397683acce0bc23595
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/57cdb41b10c91c1461a690397683acce0bc23595
rename to src/fuzz/client_no_fuzzer_mode_corpus/57cdb41b10c91c1461a690397683acce0bc23595
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/57e66cd964d46e9a1eb8bb03c35b5a9b6c79487b b/src/fuzz/client_no_fuzzer_mode_corpus/57e66cd964d46e9a1eb8bb03c35b5a9b6c79487b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/57e66cd964d46e9a1eb8bb03c35b5a9b6c79487b
rename to src/fuzz/client_no_fuzzer_mode_corpus/57e66cd964d46e9a1eb8bb03c35b5a9b6c79487b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5837fe69b76cfe5fba1d11efccddcab6f2396b5a b/src/fuzz/client_no_fuzzer_mode_corpus/5837fe69b76cfe5fba1d11efccddcab6f2396b5a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5837fe69b76cfe5fba1d11efccddcab6f2396b5a
rename to src/fuzz/client_no_fuzzer_mode_corpus/5837fe69b76cfe5fba1d11efccddcab6f2396b5a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/58b40f20324f77a88604e1866e6dbe13182e8b72 b/src/fuzz/client_no_fuzzer_mode_corpus/58b40f20324f77a88604e1866e6dbe13182e8b72
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/58b40f20324f77a88604e1866e6dbe13182e8b72
rename to src/fuzz/client_no_fuzzer_mode_corpus/58b40f20324f77a88604e1866e6dbe13182e8b72
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5a470bceaa3bae05ed0f360a6b410c779ba0003b b/src/fuzz/client_no_fuzzer_mode_corpus/5a470bceaa3bae05ed0f360a6b410c779ba0003b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5a470bceaa3bae05ed0f360a6b410c779ba0003b
rename to src/fuzz/client_no_fuzzer_mode_corpus/5a470bceaa3bae05ed0f360a6b410c779ba0003b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5bcda6ff42d95781bdf79b7df73362743181bb37 b/src/fuzz/client_no_fuzzer_mode_corpus/5bcda6ff42d95781bdf79b7df73362743181bb37
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5bcda6ff42d95781bdf79b7df73362743181bb37
rename to src/fuzz/client_no_fuzzer_mode_corpus/5bcda6ff42d95781bdf79b7df73362743181bb37
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5d68e739190e5f8eceed6fa26c5c24d454974b76 b/src/fuzz/client_no_fuzzer_mode_corpus/5d68e739190e5f8eceed6fa26c5c24d454974b76
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5d68e739190e5f8eceed6fa26c5c24d454974b76
rename to src/fuzz/client_no_fuzzer_mode_corpus/5d68e739190e5f8eceed6fa26c5c24d454974b76
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5d8c35e774db92e469cb224592a4afdae9ec8846 b/src/fuzz/client_no_fuzzer_mode_corpus/5d8c35e774db92e469cb224592a4afdae9ec8846
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5d8c35e774db92e469cb224592a4afdae9ec8846
rename to src/fuzz/client_no_fuzzer_mode_corpus/5d8c35e774db92e469cb224592a4afdae9ec8846
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/5ec26ce93fcfef50c4d818b5852dccc3d964cd88 b/src/fuzz/client_no_fuzzer_mode_corpus/5ec26ce93fcfef50c4d818b5852dccc3d964cd88
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/5ec26ce93fcfef50c4d818b5852dccc3d964cd88
rename to src/fuzz/client_no_fuzzer_mode_corpus/5ec26ce93fcfef50c4d818b5852dccc3d964cd88
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6293fac74bf94aefe343aaaa979f05d63d217664 b/src/fuzz/client_no_fuzzer_mode_corpus/6293fac74bf94aefe343aaaa979f05d63d217664
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6293fac74bf94aefe343aaaa979f05d63d217664
rename to src/fuzz/client_no_fuzzer_mode_corpus/6293fac74bf94aefe343aaaa979f05d63d217664
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/641f9bf3f164cc63c71b806fc0eaf673ec796b09 b/src/fuzz/client_no_fuzzer_mode_corpus/641f9bf3f164cc63c71b806fc0eaf673ec796b09
new file mode 100644
index 0000000..ec20253
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/641f9bf3f164cc63c71b806fc0eaf673ec796b09
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6485e23f6bc3d84a6fb8cff8ffcdc1854b0e4ba4 b/src/fuzz/client_no_fuzzer_mode_corpus/6485e23f6bc3d84a6fb8cff8ffcdc1854b0e4ba4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6485e23f6bc3d84a6fb8cff8ffcdc1854b0e4ba4
rename to src/fuzz/client_no_fuzzer_mode_corpus/6485e23f6bc3d84a6fb8cff8ffcdc1854b0e4ba4
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/669266bdf7f920870d296bb56b84c5e887e1f51b b/src/fuzz/client_no_fuzzer_mode_corpus/669266bdf7f920870d296bb56b84c5e887e1f51b
new file mode 100644
index 0000000..25bc695
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/669266bdf7f920870d296bb56b84c5e887e1f51b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/66e7a5d0682175c1c0125b2b46d5312e07bcde98 b/src/fuzz/client_no_fuzzer_mode_corpus/66e7a5d0682175c1c0125b2b46d5312e07bcde98
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/66e7a5d0682175c1c0125b2b46d5312e07bcde98
rename to src/fuzz/client_no_fuzzer_mode_corpus/66e7a5d0682175c1c0125b2b46d5312e07bcde98
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6755737227f4a22c52504d5d8f40ae9b4e64cffb b/src/fuzz/client_no_fuzzer_mode_corpus/6755737227f4a22c52504d5d8f40ae9b4e64cffb
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6755737227f4a22c52504d5d8f40ae9b4e64cffb
rename to src/fuzz/client_no_fuzzer_mode_corpus/6755737227f4a22c52504d5d8f40ae9b4e64cffb
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6788b372c40f83a7dd2d29dd2d0f8f94d7f077bd b/src/fuzz/client_no_fuzzer_mode_corpus/6788b372c40f83a7dd2d29dd2d0f8f94d7f077bd
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6788b372c40f83a7dd2d29dd2d0f8f94d7f077bd
rename to src/fuzz/client_no_fuzzer_mode_corpus/6788b372c40f83a7dd2d29dd2d0f8f94d7f077bd
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6991365467c8619c71581bffc9c30f65975e700c b/src/fuzz/client_no_fuzzer_mode_corpus/6991365467c8619c71581bffc9c30f65975e700c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6991365467c8619c71581bffc9c30f65975e700c
rename to src/fuzz/client_no_fuzzer_mode_corpus/6991365467c8619c71581bffc9c30f65975e700c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6bb2c140712c00af87ee8f7208ce5843af6e7072 b/src/fuzz/client_no_fuzzer_mode_corpus/6bb2c140712c00af87ee8f7208ce5843af6e7072
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6bb2c140712c00af87ee8f7208ce5843af6e7072
rename to src/fuzz/client_no_fuzzer_mode_corpus/6bb2c140712c00af87ee8f7208ce5843af6e7072
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6c4da1109f815449cd487b96fe59ddc3060a535f b/src/fuzz/client_no_fuzzer_mode_corpus/6c4da1109f815449cd487b96fe59ddc3060a535f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6c4da1109f815449cd487b96fe59ddc3060a535f
rename to src/fuzz/client_no_fuzzer_mode_corpus/6c4da1109f815449cd487b96fe59ddc3060a535f
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6d869da19df18992541b89b783009cc5e69868bd b/src/fuzz/client_no_fuzzer_mode_corpus/6d869da19df18992541b89b783009cc5e69868bd
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6d869da19df18992541b89b783009cc5e69868bd
rename to src/fuzz/client_no_fuzzer_mode_corpus/6d869da19df18992541b89b783009cc5e69868bd
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/6e2ccd0ae5e2d1934e717cbd1ecb6befa9ed6140 b/src/fuzz/client_no_fuzzer_mode_corpus/6e2ccd0ae5e2d1934e717cbd1ecb6befa9ed6140
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/6e2ccd0ae5e2d1934e717cbd1ecb6befa9ed6140
rename to src/fuzz/client_no_fuzzer_mode_corpus/6e2ccd0ae5e2d1934e717cbd1ecb6befa9ed6140
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/6f2ef80912b8292e54be7d627ae04b056ec32cb0 b/src/fuzz/client_no_fuzzer_mode_corpus/6f2ef80912b8292e54be7d627ae04b056ec32cb0
new file mode 100644
index 0000000..e8e0a74
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/6f2ef80912b8292e54be7d627ae04b056ec32cb0
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/715ea107bb66d37a57161139384852e434f5e9af b/src/fuzz/client_no_fuzzer_mode_corpus/715ea107bb66d37a57161139384852e434f5e9af
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/715ea107bb66d37a57161139384852e434f5e9af
rename to src/fuzz/client_no_fuzzer_mode_corpus/715ea107bb66d37a57161139384852e434f5e9af
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/71a53759871766a1777635ac953a0397aec89b49 b/src/fuzz/client_no_fuzzer_mode_corpus/71a53759871766a1777635ac953a0397aec89b49
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/71a53759871766a1777635ac953a0397aec89b49
rename to src/fuzz/client_no_fuzzer_mode_corpus/71a53759871766a1777635ac953a0397aec89b49
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/72db38ec7e0b96489820750d33cfeca38868cc50 b/src/fuzz/client_no_fuzzer_mode_corpus/72db38ec7e0b96489820750d33cfeca38868cc50
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/72db38ec7e0b96489820750d33cfeca38868cc50
rename to src/fuzz/client_no_fuzzer_mode_corpus/72db38ec7e0b96489820750d33cfeca38868cc50
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7461f62ca214c576c43dc6024f126056f54c044f b/src/fuzz/client_no_fuzzer_mode_corpus/7461f62ca214c576c43dc6024f126056f54c044f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7461f62ca214c576c43dc6024f126056f54c044f
rename to src/fuzz/client_no_fuzzer_mode_corpus/7461f62ca214c576c43dc6024f126056f54c044f
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/74de0c746d7d094bd79797a013743e8531d6b642 b/src/fuzz/client_no_fuzzer_mode_corpus/74de0c746d7d094bd79797a013743e8531d6b642
new file mode 100644
index 0000000..f221bff
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/74de0c746d7d094bd79797a013743e8531d6b642
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/752ba4ace927edd3ef0fc70516b2fc55c383c1ca b/src/fuzz/client_no_fuzzer_mode_corpus/752ba4ace927edd3ef0fc70516b2fc55c383c1ca
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/752ba4ace927edd3ef0fc70516b2fc55c383c1ca
rename to src/fuzz/client_no_fuzzer_mode_corpus/752ba4ace927edd3ef0fc70516b2fc55c383c1ca
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/759606f3e01eb7a55aa16d40af0b9d4dc03ca02a b/src/fuzz/client_no_fuzzer_mode_corpus/759606f3e01eb7a55aa16d40af0b9d4dc03ca02a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/759606f3e01eb7a55aa16d40af0b9d4dc03ca02a
rename to src/fuzz/client_no_fuzzer_mode_corpus/759606f3e01eb7a55aa16d40af0b9d4dc03ca02a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7690aaee06c6d307efabc1ec7b40ae8035323bd6 b/src/fuzz/client_no_fuzzer_mode_corpus/7690aaee06c6d307efabc1ec7b40ae8035323bd6
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7690aaee06c6d307efabc1ec7b40ae8035323bd6
rename to src/fuzz/client_no_fuzzer_mode_corpus/7690aaee06c6d307efabc1ec7b40ae8035323bd6
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/76a6426c9e3c75daa67a10c125a9bc3b79ee4908 b/src/fuzz/client_no_fuzzer_mode_corpus/76a6426c9e3c75daa67a10c125a9bc3b79ee4908
new file mode 100644
index 0000000..5f56335
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/76a6426c9e3c75daa67a10c125a9bc3b79ee4908
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/780a84fcc9d2572b250467d8084def560be9073c b/src/fuzz/client_no_fuzzer_mode_corpus/780a84fcc9d2572b250467d8084def560be9073c
new file mode 100644
index 0000000..da7dd18
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/780a84fcc9d2572b250467d8084def560be9073c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/78be03dce34d5a034897e179c051ddcfe0e7f9e5 b/src/fuzz/client_no_fuzzer_mode_corpus/78be03dce34d5a034897e179c051ddcfe0e7f9e5
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/78be03dce34d5a034897e179c051ddcfe0e7f9e5
rename to src/fuzz/client_no_fuzzer_mode_corpus/78be03dce34d5a034897e179c051ddcfe0e7f9e5
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/798eb6f6cd396eaefcc583e5105c7b4298ac3f3c b/src/fuzz/client_no_fuzzer_mode_corpus/798eb6f6cd396eaefcc583e5105c7b4298ac3f3c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/798eb6f6cd396eaefcc583e5105c7b4298ac3f3c
rename to src/fuzz/client_no_fuzzer_mode_corpus/798eb6f6cd396eaefcc583e5105c7b4298ac3f3c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/79e14f63c4d09bea200ca22765808d1566dbbfb6 b/src/fuzz/client_no_fuzzer_mode_corpus/79e14f63c4d09bea200ca22765808d1566dbbfb6
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/79e14f63c4d09bea200ca22765808d1566dbbfb6
rename to src/fuzz/client_no_fuzzer_mode_corpus/79e14f63c4d09bea200ca22765808d1566dbbfb6
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7a960e8b8537fa769d9d105ae28792149bc7b546 b/src/fuzz/client_no_fuzzer_mode_corpus/7a960e8b8537fa769d9d105ae28792149bc7b546
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7a960e8b8537fa769d9d105ae28792149bc7b546
rename to src/fuzz/client_no_fuzzer_mode_corpus/7a960e8b8537fa769d9d105ae28792149bc7b546
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7bbc30cc86d24f0d0462ba712c786bd56821d699 b/src/fuzz/client_no_fuzzer_mode_corpus/7bbc30cc86d24f0d0462ba712c786bd56821d699
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7bbc30cc86d24f0d0462ba712c786bd56821d699
rename to src/fuzz/client_no_fuzzer_mode_corpus/7bbc30cc86d24f0d0462ba712c786bd56821d699
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/7bf2629128b91edc6fd53bafa9b56b6108ea0562 b/src/fuzz/client_no_fuzzer_mode_corpus/7bf2629128b91edc6fd53bafa9b56b6108ea0562
new file mode 100644
index 0000000..70e1546
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/7bf2629128b91edc6fd53bafa9b56b6108ea0562
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/7d7f767e98437ae3f09759a9ebc5b9f9c9864110 b/src/fuzz/client_no_fuzzer_mode_corpus/7d7f767e98437ae3f09759a9ebc5b9f9c9864110
new file mode 100644
index 0000000..0f36a6c
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/7d7f767e98437ae3f09759a9ebc5b9f9c9864110
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7ef87ee636938c2bb4235227cc5347d8adae7196 b/src/fuzz/client_no_fuzzer_mode_corpus/7ef87ee636938c2bb4235227cc5347d8adae7196
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7ef87ee636938c2bb4235227cc5347d8adae7196
rename to src/fuzz/client_no_fuzzer_mode_corpus/7ef87ee636938c2bb4235227cc5347d8adae7196
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/7f94fe1d8d2e9fcbe8a689ea405d283e0dbdec53 b/src/fuzz/client_no_fuzzer_mode_corpus/7f94fe1d8d2e9fcbe8a689ea405d283e0dbdec53
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/7f94fe1d8d2e9fcbe8a689ea405d283e0dbdec53
rename to src/fuzz/client_no_fuzzer_mode_corpus/7f94fe1d8d2e9fcbe8a689ea405d283e0dbdec53
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8172072778eeb36c76c630dfe2df10ad2e538b55 b/src/fuzz/client_no_fuzzer_mode_corpus/8172072778eeb36c76c630dfe2df10ad2e538b55
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8172072778eeb36c76c630dfe2df10ad2e538b55
rename to src/fuzz/client_no_fuzzer_mode_corpus/8172072778eeb36c76c630dfe2df10ad2e538b55
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/81de5ce745cff95ee4005cd3d00e5d149cce4013 b/src/fuzz/client_no_fuzzer_mode_corpus/81de5ce745cff95ee4005cd3d00e5d149cce4013
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/81de5ce745cff95ee4005cd3d00e5d149cce4013
rename to src/fuzz/client_no_fuzzer_mode_corpus/81de5ce745cff95ee4005cd3d00e5d149cce4013
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/820f772e67ae14c9c876144baed0c94a30d4cfad b/src/fuzz/client_no_fuzzer_mode_corpus/820f772e67ae14c9c876144baed0c94a30d4cfad
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/820f772e67ae14c9c876144baed0c94a30d4cfad
rename to src/fuzz/client_no_fuzzer_mode_corpus/820f772e67ae14c9c876144baed0c94a30d4cfad
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8369bfd82d90cd8fa5bd6baefee91bc5d20d15d2 b/src/fuzz/client_no_fuzzer_mode_corpus/8369bfd82d90cd8fa5bd6baefee91bc5d20d15d2
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8369bfd82d90cd8fa5bd6baefee91bc5d20d15d2
rename to src/fuzz/client_no_fuzzer_mode_corpus/8369bfd82d90cd8fa5bd6baefee91bc5d20d15d2
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/838e4e375d628e8fa42d455b603c888a83d70d05 b/src/fuzz/client_no_fuzzer_mode_corpus/838e4e375d628e8fa42d455b603c888a83d70d05
new file mode 100644
index 0000000..8b23655
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/838e4e375d628e8fa42d455b603c888a83d70d05
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/850c011baf104aa882f5b27d4048f299c7ff902d b/src/fuzz/client_no_fuzzer_mode_corpus/850c011baf104aa882f5b27d4048f299c7ff902d
new file mode 100644
index 0000000..c7444db
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/850c011baf104aa882f5b27d4048f299c7ff902d
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/8662df29e6376489a950812aa5a5ff9c44a2a65d b/src/fuzz/client_no_fuzzer_mode_corpus/8662df29e6376489a950812aa5a5ff9c44a2a65d
new file mode 100644
index 0000000..c894cb7
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/8662df29e6376489a950812aa5a5ff9c44a2a65d
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/87762fe096e0042e7d6b376c705010bbbdada192 b/src/fuzz/client_no_fuzzer_mode_corpus/87762fe096e0042e7d6b376c705010bbbdada192
new file mode 100644
index 0000000..ac2da76
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/87762fe096e0042e7d6b376c705010bbbdada192
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8a1c75bde791aa363cba0a6a146a098aef100e07 b/src/fuzz/client_no_fuzzer_mode_corpus/8a1c75bde791aa363cba0a6a146a098aef100e07
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8a1c75bde791aa363cba0a6a146a098aef100e07
rename to src/fuzz/client_no_fuzzer_mode_corpus/8a1c75bde791aa363cba0a6a146a098aef100e07
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8a59f02a23c0345533220925e57c316ef7de552b b/src/fuzz/client_no_fuzzer_mode_corpus/8a59f02a23c0345533220925e57c316ef7de552b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8a59f02a23c0345533220925e57c316ef7de552b
rename to src/fuzz/client_no_fuzzer_mode_corpus/8a59f02a23c0345533220925e57c316ef7de552b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8c1d1ac4961975e7ff6592a8293046e8b00d87b1 b/src/fuzz/client_no_fuzzer_mode_corpus/8c1d1ac4961975e7ff6592a8293046e8b00d87b1
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8c1d1ac4961975e7ff6592a8293046e8b00d87b1
rename to src/fuzz/client_no_fuzzer_mode_corpus/8c1d1ac4961975e7ff6592a8293046e8b00d87b1
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8cc3c96276b65dfa9cdd6012fdc0bc6a085ea146 b/src/fuzz/client_no_fuzzer_mode_corpus/8cc3c96276b65dfa9cdd6012fdc0bc6a085ea146
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8cc3c96276b65dfa9cdd6012fdc0bc6a085ea146
rename to src/fuzz/client_no_fuzzer_mode_corpus/8cc3c96276b65dfa9cdd6012fdc0bc6a085ea146
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8d95927e1a1d8deaf76c328979171a041ed0cd6a b/src/fuzz/client_no_fuzzer_mode_corpus/8d95927e1a1d8deaf76c328979171a041ed0cd6a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8d95927e1a1d8deaf76c328979171a041ed0cd6a
rename to src/fuzz/client_no_fuzzer_mode_corpus/8d95927e1a1d8deaf76c328979171a041ed0cd6a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/8d9d6cfc1b60fff0eac72f537aa04900e3b6049b b/src/fuzz/client_no_fuzzer_mode_corpus/8d9d6cfc1b60fff0eac72f537aa04900e3b6049b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/8d9d6cfc1b60fff0eac72f537aa04900e3b6049b
rename to src/fuzz/client_no_fuzzer_mode_corpus/8d9d6cfc1b60fff0eac72f537aa04900e3b6049b
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/90ce0951f9404f14c7bcff894f86b5adfbe2ea55 b/src/fuzz/client_no_fuzzer_mode_corpus/90ce0951f9404f14c7bcff894f86b5adfbe2ea55
new file mode 100644
index 0000000..52459b6
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/90ce0951f9404f14c7bcff894f86b5adfbe2ea55
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/91085e28b15a76c0eb952e29a32958c64210fa22 b/src/fuzz/client_no_fuzzer_mode_corpus/91085e28b15a76c0eb952e29a32958c64210fa22
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/91085e28b15a76c0eb952e29a32958c64210fa22
rename to src/fuzz/client_no_fuzzer_mode_corpus/91085e28b15a76c0eb952e29a32958c64210fa22
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/911b77a559df01da7635687f76d5332317c7e08b b/src/fuzz/client_no_fuzzer_mode_corpus/911b77a559df01da7635687f76d5332317c7e08b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/911b77a559df01da7635687f76d5332317c7e08b
rename to src/fuzz/client_no_fuzzer_mode_corpus/911b77a559df01da7635687f76d5332317c7e08b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/92bae4073f6ff276cdee0096302c3e9f8d6c10fd b/src/fuzz/client_no_fuzzer_mode_corpus/92bae4073f6ff276cdee0096302c3e9f8d6c10fd
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/92bae4073f6ff276cdee0096302c3e9f8d6c10fd
rename to src/fuzz/client_no_fuzzer_mode_corpus/92bae4073f6ff276cdee0096302c3e9f8d6c10fd
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/92e6ca7ef1f7fef8fbd3d1d590d9e5ae6b766f42 b/src/fuzz/client_no_fuzzer_mode_corpus/92e6ca7ef1f7fef8fbd3d1d590d9e5ae6b766f42
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/92e6ca7ef1f7fef8fbd3d1d590d9e5ae6b766f42
rename to src/fuzz/client_no_fuzzer_mode_corpus/92e6ca7ef1f7fef8fbd3d1d590d9e5ae6b766f42
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/932ac830ad5d51d928c2369a54f50a4f5b924f66 b/src/fuzz/client_no_fuzzer_mode_corpus/932ac830ad5d51d928c2369a54f50a4f5b924f66
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/932ac830ad5d51d928c2369a54f50a4f5b924f66
rename to src/fuzz/client_no_fuzzer_mode_corpus/932ac830ad5d51d928c2369a54f50a4f5b924f66
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/934e88078ef793c18c2395e0bc96d8caa35e8841 b/src/fuzz/client_no_fuzzer_mode_corpus/934e88078ef793c18c2395e0bc96d8caa35e8841
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/934e88078ef793c18c2395e0bc96d8caa35e8841
rename to src/fuzz/client_no_fuzzer_mode_corpus/934e88078ef793c18c2395e0bc96d8caa35e8841
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/93d0f7fb2676b2ceffee437b9009cdb9970d484c b/src/fuzz/client_no_fuzzer_mode_corpus/93d0f7fb2676b2ceffee437b9009cdb9970d484c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/93d0f7fb2676b2ceffee437b9009cdb9970d484c
rename to src/fuzz/client_no_fuzzer_mode_corpus/93d0f7fb2676b2ceffee437b9009cdb9970d484c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/964a71f0e7be3d918e17930feb8cb493cd320c49 b/src/fuzz/client_no_fuzzer_mode_corpus/964a71f0e7be3d918e17930feb8cb493cd320c49
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/964a71f0e7be3d918e17930feb8cb493cd320c49
rename to src/fuzz/client_no_fuzzer_mode_corpus/964a71f0e7be3d918e17930feb8cb493cd320c49
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9763c6b7d81835078e3b20fdb41b5288cab9930d b/src/fuzz/client_no_fuzzer_mode_corpus/9763c6b7d81835078e3b20fdb41b5288cab9930d
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9763c6b7d81835078e3b20fdb41b5288cab9930d
rename to src/fuzz/client_no_fuzzer_mode_corpus/9763c6b7d81835078e3b20fdb41b5288cab9930d
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/990fc339eeb1c77883a5f078f566a7b33ef2bc71 b/src/fuzz/client_no_fuzzer_mode_corpus/990fc339eeb1c77883a5f078f566a7b33ef2bc71
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/990fc339eeb1c77883a5f078f566a7b33ef2bc71
rename to src/fuzz/client_no_fuzzer_mode_corpus/990fc339eeb1c77883a5f078f566a7b33ef2bc71
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/99c689cce634fc93c6da78966eead9e035ad4cfa b/src/fuzz/client_no_fuzzer_mode_corpus/99c689cce634fc93c6da78966eead9e035ad4cfa
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/99c689cce634fc93c6da78966eead9e035ad4cfa
rename to src/fuzz/client_no_fuzzer_mode_corpus/99c689cce634fc93c6da78966eead9e035ad4cfa
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9a3e583c686b703985312b4e7b5363976c059ee4 b/src/fuzz/client_no_fuzzer_mode_corpus/9a3e583c686b703985312b4e7b5363976c059ee4
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9a3e583c686b703985312b4e7b5363976c059ee4
rename to src/fuzz/client_no_fuzzer_mode_corpus/9a3e583c686b703985312b4e7b5363976c059ee4
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9c26ea944d6af8ca8a40fbe140b1546c35bed999 b/src/fuzz/client_no_fuzzer_mode_corpus/9c26ea944d6af8ca8a40fbe140b1546c35bed999
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9c26ea944d6af8ca8a40fbe140b1546c35bed999
rename to src/fuzz/client_no_fuzzer_mode_corpus/9c26ea944d6af8ca8a40fbe140b1546c35bed999
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9c658f6134d4ee8d92cbb14c17ef3f95866f9244 b/src/fuzz/client_no_fuzzer_mode_corpus/9c658f6134d4ee8d92cbb14c17ef3f95866f9244
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9c658f6134d4ee8d92cbb14c17ef3f95866f9244
rename to src/fuzz/client_no_fuzzer_mode_corpus/9c658f6134d4ee8d92cbb14c17ef3f95866f9244
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9e7480708f1639b3d7d28c24b8d0069872cd9792 b/src/fuzz/client_no_fuzzer_mode_corpus/9e7480708f1639b3d7d28c24b8d0069872cd9792
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9e7480708f1639b3d7d28c24b8d0069872cd9792
rename to src/fuzz/client_no_fuzzer_mode_corpus/9e7480708f1639b3d7d28c24b8d0069872cd9792
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/9f512feaf6dedde799fb54ca956d3919d80cae5a b/src/fuzz/client_no_fuzzer_mode_corpus/9f512feaf6dedde799fb54ca956d3919d80cae5a
new file mode 100644
index 0000000..e24bb8f
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/9f512feaf6dedde799fb54ca956d3919d80cae5a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9fb42b24e724fcc7b045403afbfdd101cb7cbf22 b/src/fuzz/client_no_fuzzer_mode_corpus/9fb42b24e724fcc7b045403afbfdd101cb7cbf22
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9fb42b24e724fcc7b045403afbfdd101cb7cbf22
rename to src/fuzz/client_no_fuzzer_mode_corpus/9fb42b24e724fcc7b045403afbfdd101cb7cbf22
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/9fb493abce1d36d1279c94f79909b0c02ccf9dfe b/src/fuzz/client_no_fuzzer_mode_corpus/9fb493abce1d36d1279c94f79909b0c02ccf9dfe
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/9fb493abce1d36d1279c94f79909b0c02ccf9dfe
rename to src/fuzz/client_no_fuzzer_mode_corpus/9fb493abce1d36d1279c94f79909b0c02ccf9dfe
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a0ae9f3a0a7f4e296a2dc204f0ce4bb20b7681ec b/src/fuzz/client_no_fuzzer_mode_corpus/a0ae9f3a0a7f4e296a2dc204f0ce4bb20b7681ec
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a0ae9f3a0a7f4e296a2dc204f0ce4bb20b7681ec
rename to src/fuzz/client_no_fuzzer_mode_corpus/a0ae9f3a0a7f4e296a2dc204f0ce4bb20b7681ec
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a15d97ec9dfa09552cb5a2c6f76b7841a2f5e22c b/src/fuzz/client_no_fuzzer_mode_corpus/a15d97ec9dfa09552cb5a2c6f76b7841a2f5e22c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a15d97ec9dfa09552cb5a2c6f76b7841a2f5e22c
rename to src/fuzz/client_no_fuzzer_mode_corpus/a15d97ec9dfa09552cb5a2c6f76b7841a2f5e22c
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/a164f5d41fc8a52882e4da1eab21d684d75575ed b/src/fuzz/client_no_fuzzer_mode_corpus/a164f5d41fc8a52882e4da1eab21d684d75575ed
new file mode 100644
index 0000000..2e11644
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/a164f5d41fc8a52882e4da1eab21d684d75575ed
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a31485be9beb36c2e8de3c8dff871f5a7ebe6286 b/src/fuzz/client_no_fuzzer_mode_corpus/a31485be9beb36c2e8de3c8dff871f5a7ebe6286
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a31485be9beb36c2e8de3c8dff871f5a7ebe6286
rename to src/fuzz/client_no_fuzzer_mode_corpus/a31485be9beb36c2e8de3c8dff871f5a7ebe6286
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a36c75741c2a634a8e15e4a79f7d530f0857461d b/src/fuzz/client_no_fuzzer_mode_corpus/a36c75741c2a634a8e15e4a79f7d530f0857461d
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a36c75741c2a634a8e15e4a79f7d530f0857461d
rename to src/fuzz/client_no_fuzzer_mode_corpus/a36c75741c2a634a8e15e4a79f7d530f0857461d
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a48061bd3de257ac7f848d715308b6b83cbaef0e b/src/fuzz/client_no_fuzzer_mode_corpus/a48061bd3de257ac7f848d715308b6b83cbaef0e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a48061bd3de257ac7f848d715308b6b83cbaef0e
rename to src/fuzz/client_no_fuzzer_mode_corpus/a48061bd3de257ac7f848d715308b6b83cbaef0e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a57ddf52041372f881af848f2b624a17e939d38d b/src/fuzz/client_no_fuzzer_mode_corpus/a57ddf52041372f881af848f2b624a17e939d38d
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a57ddf52041372f881af848f2b624a17e939d38d
rename to src/fuzz/client_no_fuzzer_mode_corpus/a57ddf52041372f881af848f2b624a17e939d38d
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a5dfc336934d434aad04cc9914d27426d00c2a34 b/src/fuzz/client_no_fuzzer_mode_corpus/a5dfc336934d434aad04cc9914d27426d00c2a34
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a5dfc336934d434aad04cc9914d27426d00c2a34
rename to src/fuzz/client_no_fuzzer_mode_corpus/a5dfc336934d434aad04cc9914d27426d00c2a34
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a6c05de8e45ea2b821158d004808c6beebaf0301 b/src/fuzz/client_no_fuzzer_mode_corpus/a6c05de8e45ea2b821158d004808c6beebaf0301
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a6c05de8e45ea2b821158d004808c6beebaf0301
rename to src/fuzz/client_no_fuzzer_mode_corpus/a6c05de8e45ea2b821158d004808c6beebaf0301
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a73e17bb891d223f500c95916dd2ba549661f9ae b/src/fuzz/client_no_fuzzer_mode_corpus/a73e17bb891d223f500c95916dd2ba549661f9ae
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a73e17bb891d223f500c95916dd2ba549661f9ae
rename to src/fuzz/client_no_fuzzer_mode_corpus/a73e17bb891d223f500c95916dd2ba549661f9ae
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a8870d429c8e771cc689d8c5f5d3c2bb26d9470e b/src/fuzz/client_no_fuzzer_mode_corpus/a8870d429c8e771cc689d8c5f5d3c2bb26d9470e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a8870d429c8e771cc689d8c5f5d3c2bb26d9470e
rename to src/fuzz/client_no_fuzzer_mode_corpus/a8870d429c8e771cc689d8c5f5d3c2bb26d9470e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a8d671e53e7e66c2a627a21f04de9617fc7d1ce5 b/src/fuzz/client_no_fuzzer_mode_corpus/a8d671e53e7e66c2a627a21f04de9617fc7d1ce5
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a8d671e53e7e66c2a627a21f04de9617fc7d1ce5
rename to src/fuzz/client_no_fuzzer_mode_corpus/a8d671e53e7e66c2a627a21f04de9617fc7d1ce5
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a90d298af651bb2dff49a9eab4a1b3a8434ddd58 b/src/fuzz/client_no_fuzzer_mode_corpus/a90d298af651bb2dff49a9eab4a1b3a8434ddd58
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a90d298af651bb2dff49a9eab4a1b3a8434ddd58
rename to src/fuzz/client_no_fuzzer_mode_corpus/a90d298af651bb2dff49a9eab4a1b3a8434ddd58
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/a9dee07816a237b7c8b3366bf4e939fbfa855a11 b/src/fuzz/client_no_fuzzer_mode_corpus/a9dee07816a237b7c8b3366bf4e939fbfa855a11
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/a9dee07816a237b7c8b3366bf4e939fbfa855a11
rename to src/fuzz/client_no_fuzzer_mode_corpus/a9dee07816a237b7c8b3366bf4e939fbfa855a11
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/aa42f1d9302651c1d42487c5f0ed597f9cac7f00 b/src/fuzz/client_no_fuzzer_mode_corpus/aa42f1d9302651c1d42487c5f0ed597f9cac7f00
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/aa42f1d9302651c1d42487c5f0ed597f9cac7f00
rename to src/fuzz/client_no_fuzzer_mode_corpus/aa42f1d9302651c1d42487c5f0ed597f9cac7f00
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/ab16b90e9c6ffadad9ca78492e011e9467b93ade b/src/fuzz/client_no_fuzzer_mode_corpus/ab16b90e9c6ffadad9ca78492e011e9467b93ade
new file mode 100644
index 0000000..188c58d
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/ab16b90e9c6ffadad9ca78492e011e9467b93ade
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/abc84e32c9322d849428edcc88f300c6b5092201 b/src/fuzz/client_no_fuzzer_mode_corpus/abc84e32c9322d849428edcc88f300c6b5092201
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/abc84e32c9322d849428edcc88f300c6b5092201
rename to src/fuzz/client_no_fuzzer_mode_corpus/abc84e32c9322d849428edcc88f300c6b5092201
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ae1efc0b2a8d3c8ef85c46a688647d458441df6b b/src/fuzz/client_no_fuzzer_mode_corpus/ae1efc0b2a8d3c8ef85c46a688647d458441df6b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ae1efc0b2a8d3c8ef85c46a688647d458441df6b
rename to src/fuzz/client_no_fuzzer_mode_corpus/ae1efc0b2a8d3c8ef85c46a688647d458441df6b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/af44ac4c3b0371c29f408f6b42edf8b8403785d9 b/src/fuzz/client_no_fuzzer_mode_corpus/af44ac4c3b0371c29f408f6b42edf8b8403785d9
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/af44ac4c3b0371c29f408f6b42edf8b8403785d9
rename to src/fuzz/client_no_fuzzer_mode_corpus/af44ac4c3b0371c29f408f6b42edf8b8403785d9
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/af745b0ef88bf0ef382e3410e758043ad993ee84 b/src/fuzz/client_no_fuzzer_mode_corpus/af745b0ef88bf0ef382e3410e758043ad993ee84
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/af745b0ef88bf0ef382e3410e758043ad993ee84
rename to src/fuzz/client_no_fuzzer_mode_corpus/af745b0ef88bf0ef382e3410e758043ad993ee84
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b01af8aca6a58bcda50555e3afab1c40bcf7f582 b/src/fuzz/client_no_fuzzer_mode_corpus/b01af8aca6a58bcda50555e3afab1c40bcf7f582
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b01af8aca6a58bcda50555e3afab1c40bcf7f582
rename to src/fuzz/client_no_fuzzer_mode_corpus/b01af8aca6a58bcda50555e3afab1c40bcf7f582
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/b030e2429fc53927881d58145d088d06452f6a26 b/src/fuzz/client_no_fuzzer_mode_corpus/b030e2429fc53927881d58145d088d06452f6a26
new file mode 100644
index 0000000..1a577d0
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/b030e2429fc53927881d58145d088d06452f6a26
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b1376725e3bf74c6519c219c6472c6d81515182a b/src/fuzz/client_no_fuzzer_mode_corpus/b1376725e3bf74c6519c219c6472c6d81515182a
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b1376725e3bf74c6519c219c6472c6d81515182a
rename to src/fuzz/client_no_fuzzer_mode_corpus/b1376725e3bf74c6519c219c6472c6d81515182a
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b217013fcc4b7f16e856b8c91df61f7e071c5cd2 b/src/fuzz/client_no_fuzzer_mode_corpus/b217013fcc4b7f16e856b8c91df61f7e071c5cd2
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b217013fcc4b7f16e856b8c91df61f7e071c5cd2
rename to src/fuzz/client_no_fuzzer_mode_corpus/b217013fcc4b7f16e856b8c91df61f7e071c5cd2
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b4fb2886caa7253df5484e13fc1f5b5e064ac310 b/src/fuzz/client_no_fuzzer_mode_corpus/b4fb2886caa7253df5484e13fc1f5b5e064ac310
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b4fb2886caa7253df5484e13fc1f5b5e064ac310
rename to src/fuzz/client_no_fuzzer_mode_corpus/b4fb2886caa7253df5484e13fc1f5b5e064ac310
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b7d6540600ab6d67e85b698a97ba5d39e9ad7a66 b/src/fuzz/client_no_fuzzer_mode_corpus/b7d6540600ab6d67e85b698a97ba5d39e9ad7a66
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b7d6540600ab6d67e85b698a97ba5d39e9ad7a66
rename to src/fuzz/client_no_fuzzer_mode_corpus/b7d6540600ab6d67e85b698a97ba5d39e9ad7a66
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b7f51c55bd011598a8e3e1d0671fc9d4a17a4d09 b/src/fuzz/client_no_fuzzer_mode_corpus/b7f51c55bd011598a8e3e1d0671fc9d4a17a4d09
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b7f51c55bd011598a8e3e1d0671fc9d4a17a4d09
rename to src/fuzz/client_no_fuzzer_mode_corpus/b7f51c55bd011598a8e3e1d0671fc9d4a17a4d09
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/b7f92e1901074aad1041b2e33b02ab2cf2757f2c b/src/fuzz/client_no_fuzzer_mode_corpus/b7f92e1901074aad1041b2e33b02ab2cf2757f2c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/b7f92e1901074aad1041b2e33b02ab2cf2757f2c
rename to src/fuzz/client_no_fuzzer_mode_corpus/b7f92e1901074aad1041b2e33b02ab2cf2757f2c
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/b93a61088b431cc110b6a2f1c0908b56133d473e b/src/fuzz/client_no_fuzzer_mode_corpus/b93a61088b431cc110b6a2f1c0908b56133d473e
new file mode 100644
index 0000000..c885602
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/b93a61088b431cc110b6a2f1c0908b56133d473e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/bb78e3d26db4f97235fda0a0329847a655bac48e b/src/fuzz/client_no_fuzzer_mode_corpus/bb78e3d26db4f97235fda0a0329847a655bac48e
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/bb78e3d26db4f97235fda0a0329847a655bac48e
rename to src/fuzz/client_no_fuzzer_mode_corpus/bb78e3d26db4f97235fda0a0329847a655bac48e
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/bbad23c67780619ce04acfab4995c6ba06039863 b/src/fuzz/client_no_fuzzer_mode_corpus/bbad23c67780619ce04acfab4995c6ba06039863
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/bbad23c67780619ce04acfab4995c6ba06039863
rename to src/fuzz/client_no_fuzzer_mode_corpus/bbad23c67780619ce04acfab4995c6ba06039863
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/bbb0dc96445fec9c12306e6e6202696ae48add91 b/src/fuzz/client_no_fuzzer_mode_corpus/bbb0dc96445fec9c12306e6e6202696ae48add91
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/bbb0dc96445fec9c12306e6e6202696ae48add91
rename to src/fuzz/client_no_fuzzer_mode_corpus/bbb0dc96445fec9c12306e6e6202696ae48add91
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/bc19949a4f9d9309a48ec184fb6c59002f42e86c b/src/fuzz/client_no_fuzzer_mode_corpus/bc19949a4f9d9309a48ec184fb6c59002f42e86c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/bc19949a4f9d9309a48ec184fb6c59002f42e86c
rename to src/fuzz/client_no_fuzzer_mode_corpus/bc19949a4f9d9309a48ec184fb6c59002f42e86c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/bf8a9329652af9d8c79a4049a63000282fcc1fba b/src/fuzz/client_no_fuzzer_mode_corpus/bf8a9329652af9d8c79a4049a63000282fcc1fba
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/bf8a9329652af9d8c79a4049a63000282fcc1fba
rename to src/fuzz/client_no_fuzzer_mode_corpus/bf8a9329652af9d8c79a4049a63000282fcc1fba
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/c175d2816aceebfe5d24c64a610238b8a640033c b/src/fuzz/client_no_fuzzer_mode_corpus/c175d2816aceebfe5d24c64a610238b8a640033c
new file mode 100644
index 0000000..2be7b41
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/c175d2816aceebfe5d24c64a610238b8a640033c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c42fe981d6fe631b3780b6d3054fdfc38630bc44 b/src/fuzz/client_no_fuzzer_mode_corpus/c42fe981d6fe631b3780b6d3054fdfc38630bc44
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/c42fe981d6fe631b3780b6d3054fdfc38630bc44
rename to src/fuzz/client_no_fuzzer_mode_corpus/c42fe981d6fe631b3780b6d3054fdfc38630bc44
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c61d8cf81fa324aa38ecf1ef94738ed7bafc217c b/src/fuzz/client_no_fuzzer_mode_corpus/c61d8cf81fa324aa38ecf1ef94738ed7bafc217c
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/c61d8cf81fa324aa38ecf1ef94738ed7bafc217c
rename to src/fuzz/client_no_fuzzer_mode_corpus/c61d8cf81fa324aa38ecf1ef94738ed7bafc217c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c7b5dca54cc0ebdf9a47878a0629eba3242a69ee b/src/fuzz/client_no_fuzzer_mode_corpus/c7b5dca54cc0ebdf9a47878a0629eba3242a69ee
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/c7b5dca54cc0ebdf9a47878a0629eba3242a69ee
rename to src/fuzz/client_no_fuzzer_mode_corpus/c7b5dca54cc0ebdf9a47878a0629eba3242a69ee
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c7c685c2d3992a29cb0ac5f3491481a81e9c37ed b/src/fuzz/client_no_fuzzer_mode_corpus/c7c685c2d3992a29cb0ac5f3491481a81e9c37ed
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/c7c685c2d3992a29cb0ac5f3491481a81e9c37ed
rename to src/fuzz/client_no_fuzzer_mode_corpus/c7c685c2d3992a29cb0ac5f3491481a81e9c37ed
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/c88decc00c709493fd2b46582cc39fb2d90b9c2f b/src/fuzz/client_no_fuzzer_mode_corpus/c88decc00c709493fd2b46582cc39fb2d90b9c2f
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/c88decc00c709493fd2b46582cc39fb2d90b9c2f
rename to src/fuzz/client_no_fuzzer_mode_corpus/c88decc00c709493fd2b46582cc39fb2d90b9c2f
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ca2ed4c4f6f6fd8ac15b8e778686d9bfe181c5fb b/src/fuzz/client_no_fuzzer_mode_corpus/ca2ed4c4f6f6fd8ac15b8e778686d9bfe181c5fb
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ca2ed4c4f6f6fd8ac15b8e778686d9bfe181c5fb
rename to src/fuzz/client_no_fuzzer_mode_corpus/ca2ed4c4f6f6fd8ac15b8e778686d9bfe181c5fb
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/cb4fbcb22b4625792d9d9eee7b4284c69ab6a257 b/src/fuzz/client_no_fuzzer_mode_corpus/cb4fbcb22b4625792d9d9eee7b4284c69ab6a257
new file mode 100644
index 0000000..c39a764
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/cb4fbcb22b4625792d9d9eee7b4284c69ab6a257
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/cc3f076cf16324863c399adb8b3f5064036641ce b/src/fuzz/client_no_fuzzer_mode_corpus/cc3f076cf16324863c399adb8b3f5064036641ce
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/cc3f076cf16324863c399adb8b3f5064036641ce
rename to src/fuzz/client_no_fuzzer_mode_corpus/cc3f076cf16324863c399adb8b3f5064036641ce
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/cd280adb132d1fc580a5411d9b3544d24909e0bf b/src/fuzz/client_no_fuzzer_mode_corpus/cd280adb132d1fc580a5411d9b3544d24909e0bf
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/cd280adb132d1fc580a5411d9b3544d24909e0bf
rename to src/fuzz/client_no_fuzzer_mode_corpus/cd280adb132d1fc580a5411d9b3544d24909e0bf
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d1584204aa43ad0785402278756663e39a8e7804 b/src/fuzz/client_no_fuzzer_mode_corpus/d1584204aa43ad0785402278756663e39a8e7804
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/d1584204aa43ad0785402278756663e39a8e7804
rename to src/fuzz/client_no_fuzzer_mode_corpus/d1584204aa43ad0785402278756663e39a8e7804
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d2328f74204a8ab6cfe30cd2700bd87cf824ff70 b/src/fuzz/client_no_fuzzer_mode_corpus/d2328f74204a8ab6cfe30cd2700bd87cf824ff70
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/d2328f74204a8ab6cfe30cd2700bd87cf824ff70
rename to src/fuzz/client_no_fuzzer_mode_corpus/d2328f74204a8ab6cfe30cd2700bd87cf824ff70
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d7e3f40604984ffa180fd18d02b25d2d6db0fed3 b/src/fuzz/client_no_fuzzer_mode_corpus/d7e3f40604984ffa180fd18d02b25d2d6db0fed3
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/d7e3f40604984ffa180fd18d02b25d2d6db0fed3
rename to src/fuzz/client_no_fuzzer_mode_corpus/d7e3f40604984ffa180fd18d02b25d2d6db0fed3
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/d90ce69847da6a1e6afa0ef67dea51c3232921c0 b/src/fuzz/client_no_fuzzer_mode_corpus/d90ce69847da6a1e6afa0ef67dea51c3232921c0
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/d90ce69847da6a1e6afa0ef67dea51c3232921c0
rename to src/fuzz/client_no_fuzzer_mode_corpus/d90ce69847da6a1e6afa0ef67dea51c3232921c0
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/db0dc10acf7ec0d014ec49f891d95aac21c50a94 b/src/fuzz/client_no_fuzzer_mode_corpus/db0dc10acf7ec0d014ec49f891d95aac21c50a94
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/db0dc10acf7ec0d014ec49f891d95aac21c50a94
rename to src/fuzz/client_no_fuzzer_mode_corpus/db0dc10acf7ec0d014ec49f891d95aac21c50a94
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/db6253a552c9b15d05c75abd422b002def6179f7 b/src/fuzz/client_no_fuzzer_mode_corpus/db6253a552c9b15d05c75abd422b002def6179f7
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/db6253a552c9b15d05c75abd422b002def6179f7
rename to src/fuzz/client_no_fuzzer_mode_corpus/db6253a552c9b15d05c75abd422b002def6179f7
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/dc29d977fce71e060b9ae6a7feb965ed9bd2abc8 b/src/fuzz/client_no_fuzzer_mode_corpus/dc29d977fce71e060b9ae6a7feb965ed9bd2abc8
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/dc29d977fce71e060b9ae6a7feb965ed9bd2abc8
rename to src/fuzz/client_no_fuzzer_mode_corpus/dc29d977fce71e060b9ae6a7feb965ed9bd2abc8
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ddff64620b2c59316fa331ffe65da25a4667f0b3 b/src/fuzz/client_no_fuzzer_mode_corpus/ddff64620b2c59316fa331ffe65da25a4667f0b3
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ddff64620b2c59316fa331ffe65da25a4667f0b3
rename to src/fuzz/client_no_fuzzer_mode_corpus/ddff64620b2c59316fa331ffe65da25a4667f0b3
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/df69f4b2fbc627d7f1719c0eb8f9b44b8c1f1fc9 b/src/fuzz/client_no_fuzzer_mode_corpus/df69f4b2fbc627d7f1719c0eb8f9b44b8c1f1fc9
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/df69f4b2fbc627d7f1719c0eb8f9b44b8c1f1fc9
rename to src/fuzz/client_no_fuzzer_mode_corpus/df69f4b2fbc627d7f1719c0eb8f9b44b8c1f1fc9
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/dfb41c32dca4464951f14eb246f0386afd2f8b87 b/src/fuzz/client_no_fuzzer_mode_corpus/dfb41c32dca4464951f14eb246f0386afd2f8b87
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/dfb41c32dca4464951f14eb246f0386afd2f8b87
rename to src/fuzz/client_no_fuzzer_mode_corpus/dfb41c32dca4464951f14eb246f0386afd2f8b87
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e02445df45e951ea7c2819584678658b987234a7 b/src/fuzz/client_no_fuzzer_mode_corpus/e02445df45e951ea7c2819584678658b987234a7
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/e02445df45e951ea7c2819584678658b987234a7
rename to src/fuzz/client_no_fuzzer_mode_corpus/e02445df45e951ea7c2819584678658b987234a7
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e180ab112d2cfe38105931af1ec32b63e7293997 b/src/fuzz/client_no_fuzzer_mode_corpus/e180ab112d2cfe38105931af1ec32b63e7293997
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/e180ab112d2cfe38105931af1ec32b63e7293997
rename to src/fuzz/client_no_fuzzer_mode_corpus/e180ab112d2cfe38105931af1ec32b63e7293997
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/e1c4b3f06aa06b9686aeab585832383003365963 b/src/fuzz/client_no_fuzzer_mode_corpus/e1c4b3f06aa06b9686aeab585832383003365963
new file mode 100644
index 0000000..5a7f378
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/e1c4b3f06aa06b9686aeab585832383003365963
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e2c512cb0534f93ebf02a528019f50cc677792db b/src/fuzz/client_no_fuzzer_mode_corpus/e2c512cb0534f93ebf02a528019f50cc677792db
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/e2c512cb0534f93ebf02a528019f50cc677792db
rename to src/fuzz/client_no_fuzzer_mode_corpus/e2c512cb0534f93ebf02a528019f50cc677792db
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e631a562a9a07024bd3905583c6feb1a557a2356 b/src/fuzz/client_no_fuzzer_mode_corpus/e631a562a9a07024bd3905583c6feb1a557a2356
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/e631a562a9a07024bd3905583c6feb1a557a2356
rename to src/fuzz/client_no_fuzzer_mode_corpus/e631a562a9a07024bd3905583c6feb1a557a2356
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/e6760514765cf56f5544cdd72a48e845a1648665 b/src/fuzz/client_no_fuzzer_mode_corpus/e6760514765cf56f5544cdd72a48e845a1648665
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/e6760514765cf56f5544cdd72a48e845a1648665
rename to src/fuzz/client_no_fuzzer_mode_corpus/e6760514765cf56f5544cdd72a48e845a1648665
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/e72e007032c5cdcf65b3c91bed4e90403d3f7f59 b/src/fuzz/client_no_fuzzer_mode_corpus/e72e007032c5cdcf65b3c91bed4e90403d3f7f59
new file mode 100644
index 0000000..7d85ce0
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/e72e007032c5cdcf65b3c91bed4e90403d3f7f59
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/e93e86d33769c266fc3c8ef19eb06a7e3c6aedab b/src/fuzz/client_no_fuzzer_mode_corpus/e93e86d33769c266fc3c8ef19eb06a7e3c6aedab
new file mode 100644
index 0000000..05ea71c
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/e93e86d33769c266fc3c8ef19eb06a7e3c6aedab
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/eae093893ad367e52f83275a9e85e2042b4f3839 b/src/fuzz/client_no_fuzzer_mode_corpus/eae093893ad367e52f83275a9e85e2042b4f3839
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/eae093893ad367e52f83275a9e85e2042b4f3839
rename to src/fuzz/client_no_fuzzer_mode_corpus/eae093893ad367e52f83275a9e85e2042b4f3839
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ebffac674a30c42965f2b0db2782bbf4f5b2beac b/src/fuzz/client_no_fuzzer_mode_corpus/ebffac674a30c42965f2b0db2782bbf4f5b2beac
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ebffac674a30c42965f2b0db2782bbf4f5b2beac
rename to src/fuzz/client_no_fuzzer_mode_corpus/ebffac674a30c42965f2b0db2782bbf4f5b2beac
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ec26ae2d7ce633f0ad20c29219a43b275d112e56 b/src/fuzz/client_no_fuzzer_mode_corpus/ec26ae2d7ce633f0ad20c29219a43b275d112e56
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ec26ae2d7ce633f0ad20c29219a43b275d112e56
rename to src/fuzz/client_no_fuzzer_mode_corpus/ec26ae2d7ce633f0ad20c29219a43b275d112e56
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ed49f8e682adc4e286abc8f03a20b348cc340504 b/src/fuzz/client_no_fuzzer_mode_corpus/ed49f8e682adc4e286abc8f03a20b348cc340504
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ed49f8e682adc4e286abc8f03a20b348cc340504
rename to src/fuzz/client_no_fuzzer_mode_corpus/ed49f8e682adc4e286abc8f03a20b348cc340504
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/eeb06e0fab0469910b4116f4c41265afe2723f5d b/src/fuzz/client_no_fuzzer_mode_corpus/eeb06e0fab0469910b4116f4c41265afe2723f5d
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/eeb06e0fab0469910b4116f4c41265afe2723f5d
rename to src/fuzz/client_no_fuzzer_mode_corpus/eeb06e0fab0469910b4116f4c41265afe2723f5d
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/eee378854e90402bc4a80bc0c5d35a9a11c39a68 b/src/fuzz/client_no_fuzzer_mode_corpus/eee378854e90402bc4a80bc0c5d35a9a11c39a68
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/eee378854e90402bc4a80bc0c5d35a9a11c39a68
rename to src/fuzz/client_no_fuzzer_mode_corpus/eee378854e90402bc4a80bc0c5d35a9a11c39a68
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/f6c2fc500115c6db954ddb0a4cff9e105f5124e7 b/src/fuzz/client_no_fuzzer_mode_corpus/f6c2fc500115c6db954ddb0a4cff9e105f5124e7
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/f6c2fc500115c6db954ddb0a4cff9e105f5124e7
rename to src/fuzz/client_no_fuzzer_mode_corpus/f6c2fc500115c6db954ddb0a4cff9e105f5124e7
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/f6d5ec326e8f1027a68accda8da48489b705564b b/src/fuzz/client_no_fuzzer_mode_corpus/f6d5ec326e8f1027a68accda8da48489b705564b
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/f6d5ec326e8f1027a68accda8da48489b705564b
rename to src/fuzz/client_no_fuzzer_mode_corpus/f6d5ec326e8f1027a68accda8da48489b705564b
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/f9e44b77292e35b43bc0d0e485447e1ecdab88e5 b/src/fuzz/client_no_fuzzer_mode_corpus/f9e44b77292e35b43bc0d0e485447e1ecdab88e5
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/f9e44b77292e35b43bc0d0e485447e1ecdab88e5
rename to src/fuzz/client_no_fuzzer_mode_corpus/f9e44b77292e35b43bc0d0e485447e1ecdab88e5
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/f9fad23530597588efd0af3187526e3bb0151e31 b/src/fuzz/client_no_fuzzer_mode_corpus/f9fad23530597588efd0af3187526e3bb0151e31
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/f9fad23530597588efd0af3187526e3bb0151e31
rename to src/fuzz/client_no_fuzzer_mode_corpus/f9fad23530597588efd0af3187526e3bb0151e31
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/fa2cefdf344569957b3ea326c8f759738face0eb b/src/fuzz/client_no_fuzzer_mode_corpus/fa2cefdf344569957b3ea326c8f759738face0eb
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/fa2cefdf344569957b3ea326c8f759738face0eb
rename to src/fuzz/client_no_fuzzer_mode_corpus/fa2cefdf344569957b3ea326c8f759738face0eb
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/fb1007d8cc0a626dcf13b4910cbe3cef5ec564a3 b/src/fuzz/client_no_fuzzer_mode_corpus/fb1007d8cc0a626dcf13b4910cbe3cef5ec564a3
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/fb1007d8cc0a626dcf13b4910cbe3cef5ec564a3
rename to src/fuzz/client_no_fuzzer_mode_corpus/fb1007d8cc0a626dcf13b4910cbe3cef5ec564a3
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/fb1a5d0a53477c504d6bf01e36c2680d941c12c1 b/src/fuzz/client_no_fuzzer_mode_corpus/fb1a5d0a53477c504d6bf01e36c2680d941c12c1
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/fb1a5d0a53477c504d6bf01e36c2680d941c12c1
rename to src/fuzz/client_no_fuzzer_mode_corpus/fb1a5d0a53477c504d6bf01e36c2680d941c12c1
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/fba3e36ff9038e8cc1139d722fda5b9fa7f5d901 b/src/fuzz/client_no_fuzzer_mode_corpus/fba3e36ff9038e8cc1139d722fda5b9fa7f5d901
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/fba3e36ff9038e8cc1139d722fda5b9fa7f5d901
rename to src/fuzz/client_no_fuzzer_mode_corpus/fba3e36ff9038e8cc1139d722fda5b9fa7f5d901
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/fbb0d2ec0fa012edbb368960f141773bd7193f2c b/src/fuzz/client_no_fuzzer_mode_corpus/fbb0d2ec0fa012edbb368960f141773bd7193f2c
new file mode 100644
index 0000000..1516996
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/fbb0d2ec0fa012edbb368960f141773bd7193f2c
Binary files differ
diff --git a/src/fuzz/client_corpus_no_fuzzer_mode/ff261b7426d59abe341f87143f622f47ba3b9289 b/src/fuzz/client_no_fuzzer_mode_corpus/ff261b7426d59abe341f87143f622f47ba3b9289
similarity index 100%
rename from src/fuzz/client_corpus_no_fuzzer_mode/ff261b7426d59abe341f87143f622f47ba3b9289
rename to src/fuzz/client_no_fuzzer_mode_corpus/ff261b7426d59abe341f87143f622f47ba3b9289
Binary files differ
diff --git a/src/fuzz/client_no_fuzzer_mode_corpus/ff867841f39f078b4c08e7a6915cf07341e95a8c b/src/fuzz/client_no_fuzzer_mode_corpus/ff867841f39f078b4c08e7a6915cf07341e95a8c
new file mode 100644
index 0000000..6d13c7e
--- /dev/null
+++ b/src/fuzz/client_no_fuzzer_mode_corpus/ff867841f39f078b4c08e7a6915cf07341e95a8c
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/195d372ef6ed267cf60dfd56978d82c8ba1d6b68 b/src/fuzz/decode_client_hello_inner_corpus/195d372ef6ed267cf60dfd56978d82c8ba1d6b68
new file mode 100644
index 0000000..18b86ee
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/195d372ef6ed267cf60dfd56978d82c8ba1d6b68
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/27af6473351f2ab64838dcfe3e4cb4fa3d08f198 b/src/fuzz/decode_client_hello_inner_corpus/27af6473351f2ab64838dcfe3e4cb4fa3d08f198
new file mode 100644
index 0000000..1cc792b
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/27af6473351f2ab64838dcfe3e4cb4fa3d08f198
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/3b0782d27c1bbe783588e48e50e83bf35d8159f8 b/src/fuzz/decode_client_hello_inner_corpus/3b0782d27c1bbe783588e48e50e83bf35d8159f8
new file mode 100644
index 0000000..1ad992a
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/3b0782d27c1bbe783588e48e50e83bf35d8159f8
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/5d04d5c50fa239df2d82e908587381fa51eac5b3 b/src/fuzz/decode_client_hello_inner_corpus/5d04d5c50fa239df2d82e908587381fa51eac5b3
new file mode 100644
index 0000000..a493362
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/5d04d5c50fa239df2d82e908587381fa51eac5b3
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/6b59bce768423c920a740b12cd18f3bad925fd78 b/src/fuzz/decode_client_hello_inner_corpus/6b59bce768423c920a740b12cd18f3bad925fd78
deleted file mode 100644
index 8f538fe..0000000
--- a/src/fuzz/decode_client_hello_inner_corpus/6b59bce768423c920a740b12cd18f3bad925fd78
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/8f26d09f836be335b9c2e478615395c0954f9b74 b/src/fuzz/decode_client_hello_inner_corpus/8f26d09f836be335b9c2e478615395c0954f9b74
new file mode 100644
index 0000000..bb633e4
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/8f26d09f836be335b9c2e478615395c0954f9b74
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/93d475fdb214a1ac30d26e1504f26791bbd74bb7 b/src/fuzz/decode_client_hello_inner_corpus/93d475fdb214a1ac30d26e1504f26791bbd74bb7
new file mode 100644
index 0000000..a22102e
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/93d475fdb214a1ac30d26e1504f26791bbd74bb7
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/981cc58bf5297f1bb8a07c11fa8c7c31b93f5402 b/src/fuzz/decode_client_hello_inner_corpus/981cc58bf5297f1bb8a07c11fa8c7c31b93f5402
new file mode 100644
index 0000000..aec1003
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/981cc58bf5297f1bb8a07c11fa8c7c31b93f5402
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/a9d80dd82f2d0415d224ebd3c184397746cecbb4 b/src/fuzz/decode_client_hello_inner_corpus/a9d80dd82f2d0415d224ebd3c184397746cecbb4
new file mode 100644
index 0000000..14def9d
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/a9d80dd82f2d0415d224ebd3c184397746cecbb4
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/c2bb18319c8702195a0acc9a0f2151b35f6357a7 b/src/fuzz/decode_client_hello_inner_corpus/c2bb18319c8702195a0acc9a0f2151b35f6357a7
deleted file mode 100644
index ccadfa8..0000000
--- a/src/fuzz/decode_client_hello_inner_corpus/c2bb18319c8702195a0acc9a0f2151b35f6357a7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/ca4621477e43b3765cad52d56fe14a9f8ca91dee b/src/fuzz/decode_client_hello_inner_corpus/ca4621477e43b3765cad52d56fe14a9f8ca91dee
deleted file mode 100644
index a7d3245..0000000
--- a/src/fuzz/decode_client_hello_inner_corpus/ca4621477e43b3765cad52d56fe14a9f8ca91dee
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/d608cfbc975dc08e7d035a9f17496d60a89579b3 b/src/fuzz/decode_client_hello_inner_corpus/d608cfbc975dc08e7d035a9f17496d60a89579b3
new file mode 100644
index 0000000..d8f9884
--- /dev/null
+++ b/src/fuzz/decode_client_hello_inner_corpus/d608cfbc975dc08e7d035a9f17496d60a89579b3
Binary files differ
diff --git a/src/fuzz/decode_client_hello_inner_corpus/e20653e9cefe9005887cc7d11f96f4cc99c3a4e8 b/src/fuzz/decode_client_hello_inner_corpus/e20653e9cefe9005887cc7d11f96f4cc99c3a4e8
deleted file mode 100644
index fad1872..0000000
--- a/src/fuzz/decode_client_hello_inner_corpus/e20653e9cefe9005887cc7d11f96f4cc99c3a4e8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/der_roundtrip.cc b/src/fuzz/der_roundtrip.cc
index ffce3b9..5df58ff 100644
--- a/src/fuzz/der_roundtrip.cc
+++ b/src/fuzz/der_roundtrip.cc
@@ -29,11 +29,9 @@
     // correctly.
     size_t consumed = len - CBS_len(&cbs);
     bssl::ScopedCBB cbb;
-    CBB body_cbb;
     if (!CBB_init(cbb.get(), consumed) ||
-        !CBB_add_asn1(cbb.get(), &body_cbb, tag) ||
-        !CBB_add_bytes(&body_cbb, CBS_data(&body), CBS_len(&body)) ||
-        !CBB_flush(cbb.get()) ||
+        !CBB_add_asn1_element(cbb.get(), tag, CBS_data(&body),
+                              CBS_len(&body)) ||
         CBB_len(cbb.get()) != consumed ||
         memcmp(CBB_data(cbb.get()), buf, consumed) != 0) {
       abort();
diff --git a/src/fuzz/dtls_client.cc b/src/fuzz/dtls_client.cc
index c73e47e..f5ce885 100644
--- a/src/fuzz/dtls_client.cc
+++ b/src/fuzz/dtls_client.cc
@@ -15,7 +15,8 @@
 #include "../ssl/test/fuzzer.h"
 
 
-static TLSFuzzer g_fuzzer(TLSFuzzer::kDTLS, TLSFuzzer::kClient);
+static TLSFuzzer g_fuzzer(TLSFuzzer::kDTLS, TLSFuzzer::kClient,
+                          TLSFuzzer::kFuzzerModeOn);
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
   return g_fuzzer.TestOneInput(buf, len);
diff --git a/src/fuzz/dtls_client_corpus/041362f31da6c05403821b4350eaeabf321ee892 b/src/fuzz/dtls_client_corpus/041362f31da6c05403821b4350eaeabf321ee892
new file mode 100644
index 0000000..54f2304
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/041362f31da6c05403821b4350eaeabf321ee892
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/047004be89c0a1f302611570def65a023d6abba3 b/src/fuzz/dtls_client_corpus/047004be89c0a1f302611570def65a023d6abba3
new file mode 100644
index 0000000..f0fb66f
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/047004be89c0a1f302611570def65a023d6abba3
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/05474066990baed9e18653244a6db30617c09816 b/src/fuzz/dtls_client_corpus/05474066990baed9e18653244a6db30617c09816
new file mode 100644
index 0000000..bad43a1
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/05474066990baed9e18653244a6db30617c09816
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/158b982b0520e17d0489ca8ae891cd53022e1456 b/src/fuzz/dtls_client_corpus/158b982b0520e17d0489ca8ae891cd53022e1456
deleted file mode 100644
index 67d1878..0000000
--- a/src/fuzz/dtls_client_corpus/158b982b0520e17d0489ca8ae891cd53022e1456
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/182c0022271354bab9ca17039fcaf484d3e7d691 b/src/fuzz/dtls_client_corpus/182c0022271354bab9ca17039fcaf484d3e7d691
new file mode 100644
index 0000000..4b5a70e
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/182c0022271354bab9ca17039fcaf484d3e7d691
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/1932fedc680a4f2c8bb53221249c1ca8251fa7dc b/src/fuzz/dtls_client_corpus/1932fedc680a4f2c8bb53221249c1ca8251fa7dc
new file mode 100644
index 0000000..f7c7650
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/1932fedc680a4f2c8bb53221249c1ca8251fa7dc
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/1b5c9c7cfe90fcafee3ebf0495b343ca308af677 b/src/fuzz/dtls_client_corpus/1b5c9c7cfe90fcafee3ebf0495b343ca308af677
new file mode 100644
index 0000000..30f33d4
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/1b5c9c7cfe90fcafee3ebf0495b343ca308af677
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/1bdfc7f32c3e72eebb26b25fad44440f865bf3c7 b/src/fuzz/dtls_client_corpus/1bdfc7f32c3e72eebb26b25fad44440f865bf3c7
new file mode 100644
index 0000000..a20cfcd
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/1bdfc7f32c3e72eebb26b25fad44440f865bf3c7
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/1d7280e26a2ba73cc4b32d3674a445f99efc2fa3 b/src/fuzz/dtls_client_corpus/1d7280e26a2ba73cc4b32d3674a445f99efc2fa3
deleted file mode 100644
index 3225df4..0000000
--- a/src/fuzz/dtls_client_corpus/1d7280e26a2ba73cc4b32d3674a445f99efc2fa3
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/25e0104cb51c2c90f2ce1c447202dc68867529e6 b/src/fuzz/dtls_client_corpus/25e0104cb51c2c90f2ce1c447202dc68867529e6
new file mode 100644
index 0000000..473f814
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/25e0104cb51c2c90f2ce1c447202dc68867529e6
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/29b11dac1649bf2e855fb152449915f2188c1f5b b/src/fuzz/dtls_client_corpus/29b11dac1649bf2e855fb152449915f2188c1f5b
deleted file mode 100644
index f06050e..0000000
--- a/src/fuzz/dtls_client_corpus/29b11dac1649bf2e855fb152449915f2188c1f5b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/2be05b76e7f3741f4fbabe82adc3a3785087501e b/src/fuzz/dtls_client_corpus/2be05b76e7f3741f4fbabe82adc3a3785087501e
deleted file mode 100644
index b3d657d..0000000
--- a/src/fuzz/dtls_client_corpus/2be05b76e7f3741f4fbabe82adc3a3785087501e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/2d3fdca1b5fff996ee56640369be5e75ba1db5d4 b/src/fuzz/dtls_client_corpus/2d3fdca1b5fff996ee56640369be5e75ba1db5d4
new file mode 100644
index 0000000..05cdf6b
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/2d3fdca1b5fff996ee56640369be5e75ba1db5d4
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/3136f05af0df34d84f99ed061b97de080d933278 b/src/fuzz/dtls_client_corpus/3136f05af0df34d84f99ed061b97de080d933278
deleted file mode 100644
index 2ed647c..0000000
--- a/src/fuzz/dtls_client_corpus/3136f05af0df34d84f99ed061b97de080d933278
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/363f4acb20737ec6f2daaca58f58c3134e7758d0 b/src/fuzz/dtls_client_corpus/363f4acb20737ec6f2daaca58f58c3134e7758d0
deleted file mode 100644
index a31ce3e..0000000
--- a/src/fuzz/dtls_client_corpus/363f4acb20737ec6f2daaca58f58c3134e7758d0
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/37434ded0b5b1cd5ddae96af353331e2a9ee2fc1 b/src/fuzz/dtls_client_corpus/37434ded0b5b1cd5ddae96af353331e2a9ee2fc1
new file mode 100644
index 0000000..8e97c8a
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/37434ded0b5b1cd5ddae96af353331e2a9ee2fc1
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/3fa0f1925fa1fb8a72c2813d20bb6aad716949d2 b/src/fuzz/dtls_client_corpus/3fa0f1925fa1fb8a72c2813d20bb6aad716949d2
new file mode 100644
index 0000000..6231803
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/3fa0f1925fa1fb8a72c2813d20bb6aad716949d2
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/3fdf6f325607e0d54b8702224deff33b57f8f267 b/src/fuzz/dtls_client_corpus/3fdf6f325607e0d54b8702224deff33b57f8f267
new file mode 100644
index 0000000..59efaf6
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/3fdf6f325607e0d54b8702224deff33b57f8f267
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/413e9bfecceddf63e304006240e89bddf3f6fd1d b/src/fuzz/dtls_client_corpus/413e9bfecceddf63e304006240e89bddf3f6fd1d
new file mode 100644
index 0000000..3267887
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/413e9bfecceddf63e304006240e89bddf3f6fd1d
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/441df3d2904892dae21aae7be22f782c6d52f789 b/src/fuzz/dtls_client_corpus/441df3d2904892dae21aae7be22f782c6d52f789
new file mode 100644
index 0000000..a4a5eb1
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/441df3d2904892dae21aae7be22f782c6d52f789
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/4868aaf8ea86ed3de57eb2a54eddb8a6d77ea60b b/src/fuzz/dtls_client_corpus/4868aaf8ea86ed3de57eb2a54eddb8a6d77ea60b
new file mode 100644
index 0000000..2e5cd70
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/4868aaf8ea86ed3de57eb2a54eddb8a6d77ea60b
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/4a23e7aa3e70a542e900c4b97c050362cf9a752f b/src/fuzz/dtls_client_corpus/4a23e7aa3e70a542e900c4b97c050362cf9a752f
deleted file mode 100644
index c7700ef..0000000
--- a/src/fuzz/dtls_client_corpus/4a23e7aa3e70a542e900c4b97c050362cf9a752f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/4b2a75c634e97d8d1509af720465982a629c4b4a b/src/fuzz/dtls_client_corpus/4b2a75c634e97d8d1509af720465982a629c4b4a
deleted file mode 100644
index a2ad28d..0000000
--- a/src/fuzz/dtls_client_corpus/4b2a75c634e97d8d1509af720465982a629c4b4a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/4fceb3c47f7fe10bec69e3301949058bfeb0021d b/src/fuzz/dtls_client_corpus/4fceb3c47f7fe10bec69e3301949058bfeb0021d
new file mode 100644
index 0000000..a78c19d
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/4fceb3c47f7fe10bec69e3301949058bfeb0021d
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/522dc10bcac57ae649b8101d076c33e0559c6060 b/src/fuzz/dtls_client_corpus/522dc10bcac57ae649b8101d076c33e0559c6060
new file mode 100644
index 0000000..292d7ea
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/522dc10bcac57ae649b8101d076c33e0559c6060
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/57697062552842ec22b73c681e5ec791f8f9c607 b/src/fuzz/dtls_client_corpus/57697062552842ec22b73c681e5ec791f8f9c607
deleted file mode 100644
index e976984..0000000
--- a/src/fuzz/dtls_client_corpus/57697062552842ec22b73c681e5ec791f8f9c607
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/597db602bc71b88812a5324e3c08d02dfba0c41d b/src/fuzz/dtls_client_corpus/597db602bc71b88812a5324e3c08d02dfba0c41d
deleted file mode 100644
index 949267f..0000000
--- a/src/fuzz/dtls_client_corpus/597db602bc71b88812a5324e3c08d02dfba0c41d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/5dae0700e336c6b3c4d9dfc2af7f2716a484862e b/src/fuzz/dtls_client_corpus/5dae0700e336c6b3c4d9dfc2af7f2716a484862e
new file mode 100644
index 0000000..72c4a6f
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/5dae0700e336c6b3c4d9dfc2af7f2716a484862e
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/5ddbc31979a4d501710dc4749ba4e73ec8f12be2 b/src/fuzz/dtls_client_corpus/5ddbc31979a4d501710dc4749ba4e73ec8f12be2
new file mode 100644
index 0000000..21a7ef7
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/5ddbc31979a4d501710dc4749ba4e73ec8f12be2
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/5e40aa8bce2d0acf10e033b317e9bf0b65bb3764 b/src/fuzz/dtls_client_corpus/5e40aa8bce2d0acf10e033b317e9bf0b65bb3764
new file mode 100644
index 0000000..c646ba0
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/5e40aa8bce2d0acf10e033b317e9bf0b65bb3764
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/6072d76d059c0e2e962e8953a33c2ddba807b04c b/src/fuzz/dtls_client_corpus/6072d76d059c0e2e962e8953a33c2ddba807b04c
deleted file mode 100644
index 0965933..0000000
--- a/src/fuzz/dtls_client_corpus/6072d76d059c0e2e962e8953a33c2ddba807b04c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/626ca01e4a61fea7f7fc456779391b6335e6c422 b/src/fuzz/dtls_client_corpus/626ca01e4a61fea7f7fc456779391b6335e6c422
new file mode 100644
index 0000000..0ee2cb0
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/626ca01e4a61fea7f7fc456779391b6335e6c422
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/628e600b81ae7c48cfd3fbddc1012ad8936060c9 b/src/fuzz/dtls_client_corpus/628e600b81ae7c48cfd3fbddc1012ad8936060c9
new file mode 100644
index 0000000..dc97640
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/628e600b81ae7c48cfd3fbddc1012ad8936060c9
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/639758c54be9c435d966c585adb5a3a18e60f5e9 b/src/fuzz/dtls_client_corpus/639758c54be9c435d966c585adb5a3a18e60f5e9
new file mode 100644
index 0000000..c60c7b3
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/639758c54be9c435d966c585adb5a3a18e60f5e9
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/661bad319f2fe1328742b4032d3e0667b452d848 b/src/fuzz/dtls_client_corpus/661bad319f2fe1328742b4032d3e0667b452d848
new file mode 100644
index 0000000..782c53b
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/661bad319f2fe1328742b4032d3e0667b452d848
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/68a5b70038bd04395fe98157364da1d86f3d831e b/src/fuzz/dtls_client_corpus/68a5b70038bd04395fe98157364da1d86f3d831e
deleted file mode 100644
index 52a6d9b..0000000
--- a/src/fuzz/dtls_client_corpus/68a5b70038bd04395fe98157364da1d86f3d831e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/696878f56f7a6fe20c95bbf5248dbb7079600b0f b/src/fuzz/dtls_client_corpus/696878f56f7a6fe20c95bbf5248dbb7079600b0f
new file mode 100644
index 0000000..4550688
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/696878f56f7a6fe20c95bbf5248dbb7079600b0f
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/6a97bfc9a6785a72411fcc7d4c3a11986550cccd b/src/fuzz/dtls_client_corpus/6a97bfc9a6785a72411fcc7d4c3a11986550cccd
new file mode 100644
index 0000000..b50218a
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/6a97bfc9a6785a72411fcc7d4c3a11986550cccd
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/6bfb96ccf744774b8f59a9396053e937e8619cc3 b/src/fuzz/dtls_client_corpus/6bfb96ccf744774b8f59a9396053e937e8619cc3
deleted file mode 100644
index ea2e748..0000000
--- a/src/fuzz/dtls_client_corpus/6bfb96ccf744774b8f59a9396053e937e8619cc3
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/6c8a552b290fc66b323028b947a3b7f0e62b91d4 b/src/fuzz/dtls_client_corpus/6c8a552b290fc66b323028b947a3b7f0e62b91d4
deleted file mode 100644
index 5d325c1..0000000
--- a/src/fuzz/dtls_client_corpus/6c8a552b290fc66b323028b947a3b7f0e62b91d4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/71ddc6053a48e0e90b140c4c78048d841f3fa226 b/src/fuzz/dtls_client_corpus/71ddc6053a48e0e90b140c4c78048d841f3fa226
deleted file mode 100644
index 25814bd..0000000
--- a/src/fuzz/dtls_client_corpus/71ddc6053a48e0e90b140c4c78048d841f3fa226
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/726d716220ad95706d5f4eb587a27af3496854cc b/src/fuzz/dtls_client_corpus/726d716220ad95706d5f4eb587a27af3496854cc
new file mode 100644
index 0000000..8576360
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/726d716220ad95706d5f4eb587a27af3496854cc
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/733bd91414992c60794e88df7014ec4317816a34 b/src/fuzz/dtls_client_corpus/733bd91414992c60794e88df7014ec4317816a34
new file mode 100644
index 0000000..ff540ee
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/733bd91414992c60794e88df7014ec4317816a34
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/743aa2322c72a9876ec2857ab7173f335ff31341 b/src/fuzz/dtls_client_corpus/743aa2322c72a9876ec2857ab7173f335ff31341
new file mode 100644
index 0000000..eb45e66
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/743aa2322c72a9876ec2857ab7173f335ff31341
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/74bb6df8293bb681e9b1b0fb3213e1c743c2380f b/src/fuzz/dtls_client_corpus/74bb6df8293bb681e9b1b0fb3213e1c743c2380f
new file mode 100644
index 0000000..c5b4b2b
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/74bb6df8293bb681e9b1b0fb3213e1c743c2380f
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/78a63a29db708ac9939b88f8585f4ec8a92a2f41 b/src/fuzz/dtls_client_corpus/78a63a29db708ac9939b88f8585f4ec8a92a2f41
new file mode 100644
index 0000000..fb6075e
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/78a63a29db708ac9939b88f8585f4ec8a92a2f41
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/81b5b780dbab6b406c756b534dd82c53e8daab4e b/src/fuzz/dtls_client_corpus/81b5b780dbab6b406c756b534dd82c53e8daab4e
deleted file mode 100644
index 1bca2c8..0000000
--- a/src/fuzz/dtls_client_corpus/81b5b780dbab6b406c756b534dd82c53e8daab4e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/8713f75eb9831ba67d3d1953cf45a77988ade56b b/src/fuzz/dtls_client_corpus/8713f75eb9831ba67d3d1953cf45a77988ade56b
new file mode 100644
index 0000000..5483be7
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/8713f75eb9831ba67d3d1953cf45a77988ade56b
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/891f38d705f746fc70e63f37873a7fc07a90eabe b/src/fuzz/dtls_client_corpus/891f38d705f746fc70e63f37873a7fc07a90eabe
deleted file mode 100644
index e18a17c..0000000
--- a/src/fuzz/dtls_client_corpus/891f38d705f746fc70e63f37873a7fc07a90eabe
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/8c0ba4119b643b37d6ce7de2e5aeb1a30e594a1a b/src/fuzz/dtls_client_corpus/8c0ba4119b643b37d6ce7de2e5aeb1a30e594a1a
new file mode 100644
index 0000000..f7a0eb5
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/8c0ba4119b643b37d6ce7de2e5aeb1a30e594a1a
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/8cb4439d89fce95a855c5b1f15ab504178822cf1 b/src/fuzz/dtls_client_corpus/8cb4439d89fce95a855c5b1f15ab504178822cf1
deleted file mode 100644
index 62cae2c..0000000
--- a/src/fuzz/dtls_client_corpus/8cb4439d89fce95a855c5b1f15ab504178822cf1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/8dcd92d13e566481268302277e8b39c32d452998 b/src/fuzz/dtls_client_corpus/8dcd92d13e566481268302277e8b39c32d452998
deleted file mode 100644
index 16a9e0c..0000000
--- a/src/fuzz/dtls_client_corpus/8dcd92d13e566481268302277e8b39c32d452998
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/91bba88b342d01b90c2e00f4cc518d727d57798a b/src/fuzz/dtls_client_corpus/91bba88b342d01b90c2e00f4cc518d727d57798a
new file mode 100644
index 0000000..62b3218
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/91bba88b342d01b90c2e00f4cc518d727d57798a
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/927b3dfc765ecf948c603f1ae290ff571263d958 b/src/fuzz/dtls_client_corpus/927b3dfc765ecf948c603f1ae290ff571263d958
new file mode 100644
index 0000000..5d8c099
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/927b3dfc765ecf948c603f1ae290ff571263d958
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/954e182849c0f4ae5252b3dfd2236a251774acb4 b/src/fuzz/dtls_client_corpus/954e182849c0f4ae5252b3dfd2236a251774acb4
new file mode 100644
index 0000000..47d4935
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/954e182849c0f4ae5252b3dfd2236a251774acb4
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/9c2cd9bf3505671f0ce173fe835b7b7c5679c433 b/src/fuzz/dtls_client_corpus/9c2cd9bf3505671f0ce173fe835b7b7c5679c433
new file mode 100644
index 0000000..a1b2a02
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/9c2cd9bf3505671f0ce173fe835b7b7c5679c433
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/9cc208beec6e1f47cc09daa03eeddd3fc117481f b/src/fuzz/dtls_client_corpus/9cc208beec6e1f47cc09daa03eeddd3fc117481f
deleted file mode 100644
index bf0997c..0000000
--- a/src/fuzz/dtls_client_corpus/9cc208beec6e1f47cc09daa03eeddd3fc117481f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/9e71be37d2f1a0fbfa83a66885504e17fc145190 b/src/fuzz/dtls_client_corpus/9e71be37d2f1a0fbfa83a66885504e17fc145190
deleted file mode 100644
index c00f478..0000000
--- a/src/fuzz/dtls_client_corpus/9e71be37d2f1a0fbfa83a66885504e17fc145190
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/a00e02d6a66867a528efb3cee7b104399eb62f0f b/src/fuzz/dtls_client_corpus/a00e02d6a66867a528efb3cee7b104399eb62f0f
deleted file mode 100644
index bd3496c..0000000
--- a/src/fuzz/dtls_client_corpus/a00e02d6a66867a528efb3cee7b104399eb62f0f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/a42d64535920ecb5873c86fe13c2b71b6523408d b/src/fuzz/dtls_client_corpus/a42d64535920ecb5873c86fe13c2b71b6523408d
new file mode 100644
index 0000000..fd48eff
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/a42d64535920ecb5873c86fe13c2b71b6523408d
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/a6a762790cf6d347a07baa602fba7548bbe49694 b/src/fuzz/dtls_client_corpus/a6a762790cf6d347a07baa602fba7548bbe49694
new file mode 100644
index 0000000..f107182
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/a6a762790cf6d347a07baa602fba7548bbe49694
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/a6b230d953b2d6ddd1cfe881a62c69f5995b366d b/src/fuzz/dtls_client_corpus/a6b230d953b2d6ddd1cfe881a62c69f5995b366d
new file mode 100644
index 0000000..8e19c20
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/a6b230d953b2d6ddd1cfe881a62c69f5995b366d
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/ad70020137ab9f826ff903243ae3bb388bff1b97 b/src/fuzz/dtls_client_corpus/ad70020137ab9f826ff903243ae3bb388bff1b97
new file mode 100644
index 0000000..f648ced
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/ad70020137ab9f826ff903243ae3bb388bff1b97
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/b00a5fcb7d799ee039d50d6ed0e7761ddd829bab b/src/fuzz/dtls_client_corpus/b00a5fcb7d799ee039d50d6ed0e7761ddd829bab
new file mode 100644
index 0000000..0fcb555
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/b00a5fcb7d799ee039d50d6ed0e7761ddd829bab
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/b1c4d1babe5a49123dfac762bbed954ca76e87ab b/src/fuzz/dtls_client_corpus/b1c4d1babe5a49123dfac762bbed954ca76e87ab
new file mode 100644
index 0000000..d66fa57
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/b1c4d1babe5a49123dfac762bbed954ca76e87ab
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/b29e2054e14dc0fe51974cd199c7053eb7dd384f b/src/fuzz/dtls_client_corpus/b29e2054e14dc0fe51974cd199c7053eb7dd384f
new file mode 100644
index 0000000..d586220
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/b29e2054e14dc0fe51974cd199c7053eb7dd384f
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/b3962ca9c82812733027a79be8db8f4c3de076bf b/src/fuzz/dtls_client_corpus/b3962ca9c82812733027a79be8db8f4c3de076bf
new file mode 100644
index 0000000..c4ea102
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/b3962ca9c82812733027a79be8db8f4c3de076bf
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/b3c3b9e27e6dcc78747b8e79e9d44188e0149bfd b/src/fuzz/dtls_client_corpus/b3c3b9e27e6dcc78747b8e79e9d44188e0149bfd
new file mode 100644
index 0000000..ead1ada
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/b3c3b9e27e6dcc78747b8e79e9d44188e0149bfd
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/ba3f40f6bf53fd26e3450ba091a755fae59468c6 b/src/fuzz/dtls_client_corpus/ba3f40f6bf53fd26e3450ba091a755fae59468c6
new file mode 100644
index 0000000..8ba5cff
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/ba3f40f6bf53fd26e3450ba091a755fae59468c6
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/bd9a28c9a13ff988b1d1c04427992fcfb6562edd b/src/fuzz/dtls_client_corpus/bd9a28c9a13ff988b1d1c04427992fcfb6562edd
new file mode 100644
index 0000000..2e9086c
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/bd9a28c9a13ff988b1d1c04427992fcfb6562edd
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/c97e4b695be2cfd280d6ae25742b44c932e3f0eb b/src/fuzz/dtls_client_corpus/c97e4b695be2cfd280d6ae25742b44c932e3f0eb
new file mode 100644
index 0000000..f21433b
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/c97e4b695be2cfd280d6ae25742b44c932e3f0eb
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/c9b75e57af9f50f74ec62c218be40982d81a081a b/src/fuzz/dtls_client_corpus/c9b75e57af9f50f74ec62c218be40982d81a081a
deleted file mode 100644
index 97e1d38..0000000
--- a/src/fuzz/dtls_client_corpus/c9b75e57af9f50f74ec62c218be40982d81a081a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/cc68fc86bd19ab73b81f76a2c4ea5765ebdc7c52 b/src/fuzz/dtls_client_corpus/cc68fc86bd19ab73b81f76a2c4ea5765ebdc7c52
new file mode 100644
index 0000000..5c241d7
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/cc68fc86bd19ab73b81f76a2c4ea5765ebdc7c52
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/cf35c1b963e072b6403fff72283626fb32cc4ba6 b/src/fuzz/dtls_client_corpus/cf35c1b963e072b6403fff72283626fb32cc4ba6
deleted file mode 100644
index 48d8623..0000000
--- a/src/fuzz/dtls_client_corpus/cf35c1b963e072b6403fff72283626fb32cc4ba6
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/d2357faac1dff3b0d3e558c73d9bf11e492f591a b/src/fuzz/dtls_client_corpus/d2357faac1dff3b0d3e558c73d9bf11e492f591a
deleted file mode 100644
index 77bca70..0000000
--- a/src/fuzz/dtls_client_corpus/d2357faac1dff3b0d3e558c73d9bf11e492f591a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/d4d02b75cc8de4a7aa89e3042a046a91472e3c98 b/src/fuzz/dtls_client_corpus/d4d02b75cc8de4a7aa89e3042a046a91472e3c98
deleted file mode 100644
index 111f206..0000000
--- a/src/fuzz/dtls_client_corpus/d4d02b75cc8de4a7aa89e3042a046a91472e3c98
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/d683d1367d037118cf5c62bc14889743432b957c b/src/fuzz/dtls_client_corpus/d683d1367d037118cf5c62bc14889743432b957c
new file mode 100644
index 0000000..eb3d22e
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/d683d1367d037118cf5c62bc14889743432b957c
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/d6b3b7d7f8c96f72ef4ac861d463d49e03db5008 b/src/fuzz/dtls_client_corpus/d6b3b7d7f8c96f72ef4ac861d463d49e03db5008
new file mode 100644
index 0000000..ee5419c
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/d6b3b7d7f8c96f72ef4ac861d463d49e03db5008
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/dbbc66a7bfd35108d439fac636a755f66045dde7 b/src/fuzz/dtls_client_corpus/dbbc66a7bfd35108d439fac636a755f66045dde7
new file mode 100644
index 0000000..ae48113
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/dbbc66a7bfd35108d439fac636a755f66045dde7
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/dc3f70aeabbef9d00901443f39e544d0b86a914b b/src/fuzz/dtls_client_corpus/dc3f70aeabbef9d00901443f39e544d0b86a914b
new file mode 100644
index 0000000..3c97892
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/dc3f70aeabbef9d00901443f39e544d0b86a914b
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/f4ebae33ef1956e524d6e6a9c89ba661d6e5a061 b/src/fuzz/dtls_client_corpus/f4ebae33ef1956e524d6e6a9c89ba661d6e5a061
new file mode 100644
index 0000000..7daacd5
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/f4ebae33ef1956e524d6e6a9c89ba661d6e5a061
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/f4f6da6d7f4ba0db5e062240c338a42401f12a68 b/src/fuzz/dtls_client_corpus/f4f6da6d7f4ba0db5e062240c338a42401f12a68
new file mode 100644
index 0000000..39b5010
--- /dev/null
+++ b/src/fuzz/dtls_client_corpus/f4f6da6d7f4ba0db5e062240c338a42401f12a68
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/f5b5fb343a4e2d9bc972bf8e30ffb5a6a56c1b1e b/src/fuzz/dtls_client_corpus/f5b5fb343a4e2d9bc972bf8e30ffb5a6a56c1b1e
deleted file mode 100644
index ba61fca..0000000
--- a/src/fuzz/dtls_client_corpus/f5b5fb343a4e2d9bc972bf8e30ffb5a6a56c1b1e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_client_corpus/fcf5d6b900fddcad52149522f69c93556831b311 b/src/fuzz/dtls_client_corpus/fcf5d6b900fddcad52149522f69c93556831b311
deleted file mode 100644
index ec77983..0000000
--- a/src/fuzz/dtls_client_corpus/fcf5d6b900fddcad52149522f69c93556831b311
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server.cc b/src/fuzz/dtls_server.cc
index fc9718e..410ef3a 100644
--- a/src/fuzz/dtls_server.cc
+++ b/src/fuzz/dtls_server.cc
@@ -15,7 +15,8 @@
 #include "../ssl/test/fuzzer.h"
 
 
-static TLSFuzzer g_fuzzer(TLSFuzzer::kDTLS, TLSFuzzer::kServer);
+static TLSFuzzer g_fuzzer(TLSFuzzer::kDTLS, TLSFuzzer::kServer,
+                          TLSFuzzer::kFuzzerModeOn);
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
   return g_fuzzer.TestOneInput(buf, len);
diff --git a/src/fuzz/dtls_server_corpus/008916cded453a950ba4eb58899b0e62a56d0f65 b/src/fuzz/dtls_server_corpus/008916cded453a950ba4eb58899b0e62a56d0f65
new file mode 100644
index 0000000..8a4f06a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/008916cded453a950ba4eb58899b0e62a56d0f65
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/051d9e6248e1592734fe606ba7ec372d8f8253fb b/src/fuzz/dtls_server_corpus/051d9e6248e1592734fe606ba7ec372d8f8253fb
deleted file mode 100644
index e2ba055..0000000
--- a/src/fuzz/dtls_server_corpus/051d9e6248e1592734fe606ba7ec372d8f8253fb
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/09fc14b96cad9e32c38c2f709fb06da97327c111 b/src/fuzz/dtls_server_corpus/09fc14b96cad9e32c38c2f709fb06da97327c111
new file mode 100644
index 0000000..e0c4c4d
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/09fc14b96cad9e32c38c2f709fb06da97327c111
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/0ae90b427382f5b78da273b666138d5f844e9ab8 b/src/fuzz/dtls_server_corpus/0ae90b427382f5b78da273b666138d5f844e9ab8
new file mode 100644
index 0000000..3f9dc05
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/0ae90b427382f5b78da273b666138d5f844e9ab8
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/0c4f6903c2627a7d0a83e793b22ad7284356e3a3 b/src/fuzz/dtls_server_corpus/0c4f6903c2627a7d0a83e793b22ad7284356e3a3
deleted file mode 100644
index 3b724a3..0000000
--- a/src/fuzz/dtls_server_corpus/0c4f6903c2627a7d0a83e793b22ad7284356e3a3
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/1271659c755766883a8287e85077aa6a003ee00d b/src/fuzz/dtls_server_corpus/1271659c755766883a8287e85077aa6a003ee00d
new file mode 100644
index 0000000..e60004a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/1271659c755766883a8287e85077aa6a003ee00d
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/14e234c1ea0ff56c3204bb0cc2cfa2bbb3c45bfe b/src/fuzz/dtls_server_corpus/14e234c1ea0ff56c3204bb0cc2cfa2bbb3c45bfe
new file mode 100644
index 0000000..ba2cdcb
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/14e234c1ea0ff56c3204bb0cc2cfa2bbb3c45bfe
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/1a23e8c210e8b79f702c1501a0d4f6e97b72b6d9 b/src/fuzz/dtls_server_corpus/1a23e8c210e8b79f702c1501a0d4f6e97b72b6d9
deleted file mode 100644
index 29c93cf..0000000
--- a/src/fuzz/dtls_server_corpus/1a23e8c210e8b79f702c1501a0d4f6e97b72b6d9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/1b18e5f61ff3d871059599f371f88c185742b19f b/src/fuzz/dtls_server_corpus/1b18e5f61ff3d871059599f371f88c185742b19f
deleted file mode 100644
index 39e2d3b..0000000
--- a/src/fuzz/dtls_server_corpus/1b18e5f61ff3d871059599f371f88c185742b19f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/1e0c6b28a070046904db2f5ffee717694a1c2eb5 b/src/fuzz/dtls_server_corpus/1e0c6b28a070046904db2f5ffee717694a1c2eb5
new file mode 100644
index 0000000..fd5932d
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/1e0c6b28a070046904db2f5ffee717694a1c2eb5
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/24973bbed6527f9fffa3792322500447cedc8717 b/src/fuzz/dtls_server_corpus/24973bbed6527f9fffa3792322500447cedc8717
deleted file mode 100644
index 5596dfc..0000000
--- a/src/fuzz/dtls_server_corpus/24973bbed6527f9fffa3792322500447cedc8717
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/296d678b2d972651f64ff9b8900377cd7c88af9a b/src/fuzz/dtls_server_corpus/296d678b2d972651f64ff9b8900377cd7c88af9a
new file mode 100644
index 0000000..cd6591a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/296d678b2d972651f64ff9b8900377cd7c88af9a
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/2b65c81933ac0a88fb35956334f86c9d5cce38f3 b/src/fuzz/dtls_server_corpus/2b65c81933ac0a88fb35956334f86c9d5cce38f3
new file mode 100644
index 0000000..6d514f4
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/2b65c81933ac0a88fb35956334f86c9d5cce38f3
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/2eb49392be464058d80e4badfa20d84d06d69800 b/src/fuzz/dtls_server_corpus/2eb49392be464058d80e4badfa20d84d06d69800
new file mode 100644
index 0000000..b544d21
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/2eb49392be464058d80e4badfa20d84d06d69800
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/2eb834e0a83f13f0f9d20ff64be7b58a87f09f25 b/src/fuzz/dtls_server_corpus/2eb834e0a83f13f0f9d20ff64be7b58a87f09f25
deleted file mode 100644
index 53568f0..0000000
--- a/src/fuzz/dtls_server_corpus/2eb834e0a83f13f0f9d20ff64be7b58a87f09f25
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/31ed79ccfda79cdeba6017a9740e60af3e360aa1 b/src/fuzz/dtls_server_corpus/31ed79ccfda79cdeba6017a9740e60af3e360aa1
deleted file mode 100644
index 3b0c82d..0000000
--- a/src/fuzz/dtls_server_corpus/31ed79ccfda79cdeba6017a9740e60af3e360aa1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/325bf586b38eb2d39309abd1de06e2d72e8aa2c4 b/src/fuzz/dtls_server_corpus/325bf586b38eb2d39309abd1de06e2d72e8aa2c4
deleted file mode 100644
index 7cc1bea..0000000
--- a/src/fuzz/dtls_server_corpus/325bf586b38eb2d39309abd1de06e2d72e8aa2c4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/328daea98a65aa522edf51b482ab5a7d757d6116 b/src/fuzz/dtls_server_corpus/328daea98a65aa522edf51b482ab5a7d757d6116
deleted file mode 100644
index 91e7697..0000000
--- a/src/fuzz/dtls_server_corpus/328daea98a65aa522edf51b482ab5a7d757d6116
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/3c4b77d13c51c48c61e6e298dc8cab84165b6fcc b/src/fuzz/dtls_server_corpus/3c4b77d13c51c48c61e6e298dc8cab84165b6fcc
deleted file mode 100644
index 2a20a1b..0000000
--- a/src/fuzz/dtls_server_corpus/3c4b77d13c51c48c61e6e298dc8cab84165b6fcc
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/3cb976417bf6735470d85b1b4d34e92238d7d9d2 b/src/fuzz/dtls_server_corpus/3cb976417bf6735470d85b1b4d34e92238d7d9d2
deleted file mode 100644
index 3662644..0000000
--- a/src/fuzz/dtls_server_corpus/3cb976417bf6735470d85b1b4d34e92238d7d9d2
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/3fa1997f91f472c0bb037d0072ca1a0a28f63fe4 b/src/fuzz/dtls_server_corpus/3fa1997f91f472c0bb037d0072ca1a0a28f63fe4
new file mode 100644
index 0000000..b26e4d4
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/3fa1997f91f472c0bb037d0072ca1a0a28f63fe4
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/40d7c5c4e89ef81179a3e50632f5b179ccdd0fb9 b/src/fuzz/dtls_server_corpus/40d7c5c4e89ef81179a3e50632f5b179ccdd0fb9
new file mode 100644
index 0000000..88123f9
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/40d7c5c4e89ef81179a3e50632f5b179ccdd0fb9
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/426b6791308c372fc4866694ac5b27b7a5901696 b/src/fuzz/dtls_server_corpus/426b6791308c372fc4866694ac5b27b7a5901696
new file mode 100644
index 0000000..0fc0a9e
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/426b6791308c372fc4866694ac5b27b7a5901696
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/42c9d88358d353ffe0759248daba7810641f3ea9 b/src/fuzz/dtls_server_corpus/42c9d88358d353ffe0759248daba7810641f3ea9
new file mode 100644
index 0000000..66bb2f0
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/42c9d88358d353ffe0759248daba7810641f3ea9
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/434334bf305970ddf81d750c0cf4df1a9f1da15e b/src/fuzz/dtls_server_corpus/434334bf305970ddf81d750c0cf4df1a9f1da15e
new file mode 100644
index 0000000..2693e70
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/434334bf305970ddf81d750c0cf4df1a9f1da15e
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/46201a375d8fe71db07a32073dcda27b38eddd57 b/src/fuzz/dtls_server_corpus/46201a375d8fe71db07a32073dcda27b38eddd57
new file mode 100644
index 0000000..76076ef
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/46201a375d8fe71db07a32073dcda27b38eddd57
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/49937915a71ddf43a13c88a5d13f4000dc0a6112 b/src/fuzz/dtls_server_corpus/49937915a71ddf43a13c88a5d13f4000dc0a6112
deleted file mode 100644
index 03142b7..0000000
--- a/src/fuzz/dtls_server_corpus/49937915a71ddf43a13c88a5d13f4000dc0a6112
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/4f50e0f40fbff8cb0eb5e0fa2cb772565eec84d5 b/src/fuzz/dtls_server_corpus/4f50e0f40fbff8cb0eb5e0fa2cb772565eec84d5
deleted file mode 100644
index 4a1dd79..0000000
--- a/src/fuzz/dtls_server_corpus/4f50e0f40fbff8cb0eb5e0fa2cb772565eec84d5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/515e847811f0f11a4593435e8f8c283c941e9030 b/src/fuzz/dtls_server_corpus/515e847811f0f11a4593435e8f8c283c941e9030
new file mode 100644
index 0000000..d521480
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/515e847811f0f11a4593435e8f8c283c941e9030
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/517c8306ac9d724c6d39b03322619161816b15ed b/src/fuzz/dtls_server_corpus/517c8306ac9d724c6d39b03322619161816b15ed
new file mode 100644
index 0000000..f0b9fe1
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/517c8306ac9d724c6d39b03322619161816b15ed
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/54eb56610f3a663105006f03d0e83b9d2f5ee8eb b/src/fuzz/dtls_server_corpus/54eb56610f3a663105006f03d0e83b9d2f5ee8eb
deleted file mode 100644
index 9a5906c..0000000
--- a/src/fuzz/dtls_server_corpus/54eb56610f3a663105006f03d0e83b9d2f5ee8eb
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/57521321cc5d80586609338975fff6bb065b568e b/src/fuzz/dtls_server_corpus/57521321cc5d80586609338975fff6bb065b568e
deleted file mode 100644
index 4c6fc6d..0000000
--- a/src/fuzz/dtls_server_corpus/57521321cc5d80586609338975fff6bb065b568e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/62517c394ce01e3730dee9f60ae393d6cd262747 b/src/fuzz/dtls_server_corpus/62517c394ce01e3730dee9f60ae393d6cd262747
new file mode 100644
index 0000000..f82265a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/62517c394ce01e3730dee9f60ae393d6cd262747
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/62817eb73d3fcd3ca81008a123517e7c455b5116 b/src/fuzz/dtls_server_corpus/62817eb73d3fcd3ca81008a123517e7c455b5116
new file mode 100644
index 0000000..3ce6400
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/62817eb73d3fcd3ca81008a123517e7c455b5116
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/632ec0d29c72f874aa92f915d674cd9b0e3bf50c b/src/fuzz/dtls_server_corpus/632ec0d29c72f874aa92f915d674cd9b0e3bf50c
new file mode 100644
index 0000000..5f61065
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/632ec0d29c72f874aa92f915d674cd9b0e3bf50c
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/652db1114d3581629061c4db6265ef77eba7b2c9 b/src/fuzz/dtls_server_corpus/652db1114d3581629061c4db6265ef77eba7b2c9
new file mode 100644
index 0000000..e10bf30
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/652db1114d3581629061c4db6265ef77eba7b2c9
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/67543416d15e7f335700c0d00480365c31e0d072 b/src/fuzz/dtls_server_corpus/67543416d15e7f335700c0d00480365c31e0d072
new file mode 100644
index 0000000..4378ab8
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/67543416d15e7f335700c0d00480365c31e0d072
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/684c44a1c50cb8cea94089907a359953ef9ee8b7 b/src/fuzz/dtls_server_corpus/684c44a1c50cb8cea94089907a359953ef9ee8b7
new file mode 100644
index 0000000..5558353
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/684c44a1c50cb8cea94089907a359953ef9ee8b7
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/6d26870ebdceef0f4a0b374613a91c21efe3900c b/src/fuzz/dtls_server_corpus/6d26870ebdceef0f4a0b374613a91c21efe3900c
new file mode 100644
index 0000000..54e58c4
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/6d26870ebdceef0f4a0b374613a91c21efe3900c
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/6d9ab3f08bfb7af1fb7ebe11c5e4f5185aa301c7 b/src/fuzz/dtls_server_corpus/6d9ab3f08bfb7af1fb7ebe11c5e4f5185aa301c7
new file mode 100644
index 0000000..47fad3a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/6d9ab3f08bfb7af1fb7ebe11c5e4f5185aa301c7
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/6e303ef2848592afbc8972a07f98b0b9559f5f94 b/src/fuzz/dtls_server_corpus/6e303ef2848592afbc8972a07f98b0b9559f5f94
new file mode 100644
index 0000000..64bbc7e
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/6e303ef2848592afbc8972a07f98b0b9559f5f94
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/72932a25bbd3100f478589c32dfb3bb71cb6b578 b/src/fuzz/dtls_server_corpus/72932a25bbd3100f478589c32dfb3bb71cb6b578
deleted file mode 100644
index ff577c1..0000000
--- a/src/fuzz/dtls_server_corpus/72932a25bbd3100f478589c32dfb3bb71cb6b578
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/798b4f764f0126c8d792b2e5108ac009c61a59a7 b/src/fuzz/dtls_server_corpus/798b4f764f0126c8d792b2e5108ac009c61a59a7
new file mode 100644
index 0000000..0ee293d
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/798b4f764f0126c8d792b2e5108ac009c61a59a7
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/7d007d3eed467fd54f92713426c9ede8a174c967 b/src/fuzz/dtls_server_corpus/7d007d3eed467fd54f92713426c9ede8a174c967
deleted file mode 100644
index 1235171..0000000
--- a/src/fuzz/dtls_server_corpus/7d007d3eed467fd54f92713426c9ede8a174c967
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/7f5504997c90e8cbac8d365a5ccd1567f2127baf b/src/fuzz/dtls_server_corpus/7f5504997c90e8cbac8d365a5ccd1567f2127baf
new file mode 100644
index 0000000..582dfb8
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/7f5504997c90e8cbac8d365a5ccd1567f2127baf
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/8291a8b5e99562067229514187884e663e1e3b88 b/src/fuzz/dtls_server_corpus/8291a8b5e99562067229514187884e663e1e3b88
new file mode 100644
index 0000000..7273c7d
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/8291a8b5e99562067229514187884e663e1e3b88
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/85bdd0276d33adb0a0dd33fcd65249fd5d3b9b95 b/src/fuzz/dtls_server_corpus/85bdd0276d33adb0a0dd33fcd65249fd5d3b9b95
new file mode 100644
index 0000000..6a87c85
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/85bdd0276d33adb0a0dd33fcd65249fd5d3b9b95
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/85e30c0aab2d9143fff241281291f45d4510207d b/src/fuzz/dtls_server_corpus/85e30c0aab2d9143fff241281291f45d4510207d
deleted file mode 100644
index d4aed84..0000000
--- a/src/fuzz/dtls_server_corpus/85e30c0aab2d9143fff241281291f45d4510207d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/8b4a84b78ec7b407accce5896c0e4d5a187ce0ed b/src/fuzz/dtls_server_corpus/8b4a84b78ec7b407accce5896c0e4d5a187ce0ed
new file mode 100644
index 0000000..82a14c0
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/8b4a84b78ec7b407accce5896c0e4d5a187ce0ed
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/8b705efebd6aab7ce4c294978df0947be39f5c10 b/src/fuzz/dtls_server_corpus/8b705efebd6aab7ce4c294978df0947be39f5c10
deleted file mode 100644
index 8876722..0000000
--- a/src/fuzz/dtls_server_corpus/8b705efebd6aab7ce4c294978df0947be39f5c10
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/8ea94fa89d7100c68dca6323289357f5c57fdf5f b/src/fuzz/dtls_server_corpus/8ea94fa89d7100c68dca6323289357f5c57fdf5f
new file mode 100644
index 0000000..c88bc6e
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/8ea94fa89d7100c68dca6323289357f5c57fdf5f
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/8f1392e9baf4a7f354da3ba2705ba420241d9fd9 b/src/fuzz/dtls_server_corpus/8f1392e9baf4a7f354da3ba2705ba420241d9fd9
new file mode 100644
index 0000000..fa89ae6
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/8f1392e9baf4a7f354da3ba2705ba420241d9fd9
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/90776700965014bd67bcd1cee51bd33ab32ac0e7 b/src/fuzz/dtls_server_corpus/90776700965014bd67bcd1cee51bd33ab32ac0e7
new file mode 100644
index 0000000..cf34ee6
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/90776700965014bd67bcd1cee51bd33ab32ac0e7
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/91641c5cbc157a2682393ba6a67a002d7432bf05 b/src/fuzz/dtls_server_corpus/91641c5cbc157a2682393ba6a67a002d7432bf05
deleted file mode 100644
index 6bf0210..0000000
--- a/src/fuzz/dtls_server_corpus/91641c5cbc157a2682393ba6a67a002d7432bf05
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/936319cc795785d56cf38b1a25e4784428b39320 b/src/fuzz/dtls_server_corpus/936319cc795785d56cf38b1a25e4784428b39320
deleted file mode 100644
index 137421f..0000000
--- a/src/fuzz/dtls_server_corpus/936319cc795785d56cf38b1a25e4784428b39320
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/94c8b423e9a6fa62746ab72aa80bb8dcdd84a5dc b/src/fuzz/dtls_server_corpus/94c8b423e9a6fa62746ab72aa80bb8dcdd84a5dc
deleted file mode 100644
index 181229b..0000000
--- a/src/fuzz/dtls_server_corpus/94c8b423e9a6fa62746ab72aa80bb8dcdd84a5dc
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/96c813a1f097ff92498058d80ba0e338a8f172c9 b/src/fuzz/dtls_server_corpus/96c813a1f097ff92498058d80ba0e338a8f172c9
deleted file mode 100644
index 707f21d..0000000
--- a/src/fuzz/dtls_server_corpus/96c813a1f097ff92498058d80ba0e338a8f172c9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/9a64574c75f98921fef9466fd31474afde298c5b b/src/fuzz/dtls_server_corpus/9a64574c75f98921fef9466fd31474afde298c5b
new file mode 100644
index 0000000..9a0cb1c
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/9a64574c75f98921fef9466fd31474afde298c5b
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/9e2515c32d7538bac3668e47f8a75940b19f8847 b/src/fuzz/dtls_server_corpus/9e2515c32d7538bac3668e47f8a75940b19f8847
new file mode 100644
index 0000000..eb3ba38
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/9e2515c32d7538bac3668e47f8a75940b19f8847
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/a0e84144cca6b2692f60b456769401654541e8b9 b/src/fuzz/dtls_server_corpus/a0e84144cca6b2692f60b456769401654541e8b9
deleted file mode 100644
index 327dfa4..0000000
--- a/src/fuzz/dtls_server_corpus/a0e84144cca6b2692f60b456769401654541e8b9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/a1fc98bda30c3698cb440c5d5c27609bd03c47b3 b/src/fuzz/dtls_server_corpus/a1fc98bda30c3698cb440c5d5c27609bd03c47b3
new file mode 100644
index 0000000..536c3ea
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/a1fc98bda30c3698cb440c5d5c27609bd03c47b3
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/a44c468a599211d043aaae73a9dd55a4fde864af b/src/fuzz/dtls_server_corpus/a44c468a599211d043aaae73a9dd55a4fde864af
new file mode 100644
index 0000000..7c39575
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/a44c468a599211d043aaae73a9dd55a4fde864af
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/aede02c55d31db32186d6d4ba9f2d9e840d0c0f8 b/src/fuzz/dtls_server_corpus/aede02c55d31db32186d6d4ba9f2d9e840d0c0f8
new file mode 100644
index 0000000..88d73e0
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/aede02c55d31db32186d6d4ba9f2d9e840d0c0f8
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/b2048942476dabac368de4ebcc72c09c929d34c6 b/src/fuzz/dtls_server_corpus/b2048942476dabac368de4ebcc72c09c929d34c6
new file mode 100644
index 0000000..a630ad3
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/b2048942476dabac368de4ebcc72c09c929d34c6
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/b6d19df92f0ffb86a10fdbf8093e215dadb43ccc b/src/fuzz/dtls_server_corpus/b6d19df92f0ffb86a10fdbf8093e215dadb43ccc
new file mode 100644
index 0000000..00ba9aa
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/b6d19df92f0ffb86a10fdbf8093e215dadb43ccc
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/b7e518d9041f284f5a69c3fa943ee71ebb48dfd1 b/src/fuzz/dtls_server_corpus/b7e518d9041f284f5a69c3fa943ee71ebb48dfd1
new file mode 100644
index 0000000..ec159d8
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/b7e518d9041f284f5a69c3fa943ee71ebb48dfd1
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/be84b42eb37c2ec846a83e086f1c272a47c71eeb b/src/fuzz/dtls_server_corpus/be84b42eb37c2ec846a83e086f1c272a47c71eeb
new file mode 100644
index 0000000..8fc5417
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/be84b42eb37c2ec846a83e086f1c272a47c71eeb
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/ce86bb5be4dada1d7077b151a419d8716d4f8af4 b/src/fuzz/dtls_server_corpus/ce86bb5be4dada1d7077b151a419d8716d4f8af4
new file mode 100644
index 0000000..027d84a
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/ce86bb5be4dada1d7077b151a419d8716d4f8af4
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/cf25227c38996d1330f55e17fdcefad821750b33 b/src/fuzz/dtls_server_corpus/cf25227c38996d1330f55e17fdcefad821750b33
new file mode 100644
index 0000000..9788ba7
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/cf25227c38996d1330f55e17fdcefad821750b33
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/cfc49e6b495f0e023c9b16d3ce14184ed79f5c19 b/src/fuzz/dtls_server_corpus/cfc49e6b495f0e023c9b16d3ce14184ed79f5c19
new file mode 100644
index 0000000..8f6fdab
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/cfc49e6b495f0e023c9b16d3ce14184ed79f5c19
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/d5c52e9e1a33d990733e5b6e04f5ff8ae37a7e86 b/src/fuzz/dtls_server_corpus/d5c52e9e1a33d990733e5b6e04f5ff8ae37a7e86
new file mode 100644
index 0000000..50106f8
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/d5c52e9e1a33d990733e5b6e04f5ff8ae37a7e86
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/d6a253345c55e76e191c0a0f790f872e8b04d2a7 b/src/fuzz/dtls_server_corpus/d6a253345c55e76e191c0a0f790f872e8b04d2a7
deleted file mode 100644
index 1ec04bc..0000000
--- a/src/fuzz/dtls_server_corpus/d6a253345c55e76e191c0a0f790f872e8b04d2a7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/d7105bcebf00ca854441d2ec300eeaca92ff3568 b/src/fuzz/dtls_server_corpus/d7105bcebf00ca854441d2ec300eeaca92ff3568
deleted file mode 100644
index 955d0a7..0000000
--- a/src/fuzz/dtls_server_corpus/d7105bcebf00ca854441d2ec300eeaca92ff3568
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/e15640971571892811059f8d6046bdcb12fe948f b/src/fuzz/dtls_server_corpus/e15640971571892811059f8d6046bdcb12fe948f
deleted file mode 100644
index 264c9d2..0000000
--- a/src/fuzz/dtls_server_corpus/e15640971571892811059f8d6046bdcb12fe948f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/e3defbc805bf5cb16d044424adbc05c76788ec1e b/src/fuzz/dtls_server_corpus/e3defbc805bf5cb16d044424adbc05c76788ec1e
new file mode 100644
index 0000000..0431383
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/e3defbc805bf5cb16d044424adbc05c76788ec1e
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/e3e3751d904e9df88e060b9830743941431c0f6b b/src/fuzz/dtls_server_corpus/e3e3751d904e9df88e060b9830743941431c0f6b
deleted file mode 100644
index 89134a4..0000000
--- a/src/fuzz/dtls_server_corpus/e3e3751d904e9df88e060b9830743941431c0f6b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/e7f20beb38c842e821b53df5c1e3d9de42b46824 b/src/fuzz/dtls_server_corpus/e7f20beb38c842e821b53df5c1e3d9de42b46824
new file mode 100644
index 0000000..c81be68
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/e7f20beb38c842e821b53df5c1e3d9de42b46824
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/f0cffff85783c7cecf6cfadaace3cff80c5d3025 b/src/fuzz/dtls_server_corpus/f0cffff85783c7cecf6cfadaace3cff80c5d3025
deleted file mode 100644
index 8a8cffd..0000000
--- a/src/fuzz/dtls_server_corpus/f0cffff85783c7cecf6cfadaace3cff80c5d3025
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/f36112d755c2a835d699da80f00e91782c545645 b/src/fuzz/dtls_server_corpus/f36112d755c2a835d699da80f00e91782c545645
new file mode 100644
index 0000000..30c6935
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/f36112d755c2a835d699da80f00e91782c545645
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/f4efaee12aa3ea9b57b0f44f1cb963871d617ab1 b/src/fuzz/dtls_server_corpus/f4efaee12aa3ea9b57b0f44f1cb963871d617ab1
deleted file mode 100644
index b1afc71..0000000
--- a/src/fuzz/dtls_server_corpus/f4efaee12aa3ea9b57b0f44f1cb963871d617ab1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/f5d004345957d50b25a6e8308236a8e1d4dd965b b/src/fuzz/dtls_server_corpus/f5d004345957d50b25a6e8308236a8e1d4dd965b
new file mode 100644
index 0000000..c90d270
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/f5d004345957d50b25a6e8308236a8e1d4dd965b
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/f78786eccd28b6e14ee5265e3bf071dd4917046e b/src/fuzz/dtls_server_corpus/f78786eccd28b6e14ee5265e3bf071dd4917046e
new file mode 100644
index 0000000..8f2da00
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/f78786eccd28b6e14ee5265e3bf071dd4917046e
Binary files differ
diff --git a/src/fuzz/dtls_server_corpus/feeb97b07440ae300a89bf3076bcd503ad8506c0 b/src/fuzz/dtls_server_corpus/feeb97b07440ae300a89bf3076bcd503ad8506c0
new file mode 100644
index 0000000..6833eb9
--- /dev/null
+++ b/src/fuzz/dtls_server_corpus/feeb97b07440ae300a89bf3076bcd503ad8506c0
Binary files differ
diff --git a/src/fuzz/pkcs8.cc b/src/fuzz/pkcs8.cc
index 9f8dc03..4aeaaa5 100644
--- a/src/fuzz/pkcs8.cc
+++ b/src/fuzz/pkcs8.cc
@@ -12,12 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <openssl/crypto.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+  CRYPTO_set_fuzzer_mode(1);
+#endif
+
   CBS cbs;
   CBS_init(&cbs, buf, len);
   EVP_PKEY *pkey = EVP_parse_private_key(&cbs);
diff --git a/src/fuzz/refresh_ssl_corpora.sh b/src/fuzz/refresh_ssl_corpora.sh
index 2688030..81d5251 100755
--- a/src/fuzz/refresh_ssl_corpora.sh
+++ b/src/fuzz/refresh_ssl_corpora.sh
@@ -15,38 +15,21 @@
 
 set -ex
 
-if [[ $# -ne 2 ]]; then
-  echo "Usage: $0 fuzzer_mode_build_dir no_fuzzer_mode_build_dir"
+if [[ $# -ne 1 ]]; then
+  echo "Usage: $0 build_dir"
   exit 1
 fi
 
-fuzzer_mode_build_dir=$1
-no_fuzzer_mode_build_dir=$2
+build_dir=$1
 
 
-# Sanity-check the build directories.
+# Sanity-check the build directory.
 
-if ! grep -q '^FUZZ:' "$fuzzer_mode_build_dir/CMakeCache.txt"; then
-  echo "$fuzzer_mode_build_dir was not built with -DFUZZ=1"
+if ! grep -q '^FUZZ:' "$build_dir/CMakeCache.txt"; then
+  echo "$build_dir was not built with -DFUZZ=1"
   exit 1
 fi
 
-if grep -q '^NO_FUZZER_MODE:' "$fuzzer_mode_build_dir/CMakeCache.txt"; then
-  echo "$fuzzer_mode_build_dir was built with -DNO_FUZZER_MODE=1"
-  exit 1
-fi
-
-if ! grep -q '^FUZZ:' "$no_fuzzer_mode_build_dir/CMakeCache.txt"; then
-  echo "$no_fuzzer_mode_build_dir was not built with -DFUZZ=1"
-  exit 1
-fi
-
-if ! grep -q '^NO_FUZZER_MODE:' "$no_fuzzer_mode_build_dir/CMakeCache.txt"; then
-  echo "$no_fuzzer_mode_build_dir was not built with -DNO_FUZZER_MODE=1"
-  exit 1
-fi
-
-
 # Sanity-check the current working directory.
 
 assert_directory() {
@@ -57,71 +40,60 @@
 }
 
 assert_directory client_corpus
-assert_directory client_corpus_no_fuzzer_mode
+assert_directory client_no_fuzzer_mode_corpus
 assert_directory server_corpus
-assert_directory server_corpus_no_fuzzer_mode
+assert_directory server_no_fuzzer_mode_corpus
 assert_directory dtls_client_corpus
 assert_directory dtls_server_corpus
 
 
 # Gather new transcripts. Ignore errors in running the tests.
 
-fuzzer_mode_shim=$(readlink -f "$fuzzer_mode_build_dir/ssl/test/bssl_shim")
-no_fuzzer_mode_shim=$(readlink -f \
-    "$no_fuzzer_mode_build_dir/ssl/test/bssl_shim")
-
-fuzzer_mode_handshaker=$(readlink -f \
-    "$fuzzer_mode_build_dir/ssl/test/handshaker")
-no_fuzzer_mode_handshaker=$(readlink -f \
-    "$no_fuzzer_mode_build_dir/ssl/test/handshaker")
+shim="$(readlink -f "$build_dir")/ssl/test/bssl_shim"
+handshaker="$(readlink -f "$build_dir")/ssl/test/handshaker"
 
 fuzzer_mode_transcripts=$(mktemp -d '/tmp/boringssl-transcript-fuzzer-mode.XXXXXX')
 no_fuzzer_mode_transcripts=$(mktemp -d '/tmp/boringssl-transcript-no-fuzzer-mode.XXXXXX')
 
 echo Recording fuzzer-mode transcripts
 (cd ../ssl/test/runner/ && go test \
-    -shim-path "$fuzzer_mode_shim" \
-    -handshaker-path "$fuzzer_mode_handshaker" \
+    -shim-path "$shim" \
+    -handshaker-path "$handshaker" \
     -transcript-dir "$fuzzer_mode_transcripts" \
     -fuzzer \
     -deterministic) || true
 
 echo Recording non-fuzzer-mode transcripts
 (cd ../ssl/test/runner/ && go test \
-    -shim-path "$no_fuzzer_mode_shim" \
-    -handshaker-path "$no_fuzzer_mode_handshaker" \
+    -shim-path "$shim" \
+    -handshaker-path "$handshaker" \
     -transcript-dir "$no_fuzzer_mode_transcripts" \
     -deterministic)
 
 
-# Minimize the existing corpora.
+# Update corpora.
 
-minimize_corpus() {
-  local fuzzer="$1"
-  local corpus="$2"
+update_corpus() {
+  local fuzzer_name="$1"
+  local transcript_dir="$2"
+
+  local fuzzer="$build_dir/fuzz/$fuzzer_name"
+  local corpus="${fuzzer_name}_corpus"
 
   echo "Minimizing ${corpus}"
   mv "$corpus" "${corpus}_old"
   mkdir "$corpus"
   "$fuzzer" -max_len=50000 -merge=1 "$corpus" "${corpus}_old"
   rm -Rf "${corpus}_old"
+
+  echo "Merging transcripts from ${transcript_dir} into ${corpus}"
+  "$fuzzer" -max_len=50000 -merge=1 "$corpus" "$transcript_dir"
 }
 
-minimize_corpus "$fuzzer_mode_build_dir/fuzz/client" client_corpus
-minimize_corpus "$fuzzer_mode_build_dir/fuzz/server" server_corpus
-minimize_corpus "$no_fuzzer_mode_build_dir/fuzz/client" client_corpus_no_fuzzer_mode
-minimize_corpus "$no_fuzzer_mode_build_dir/fuzz/server" server_corpus_no_fuzzer_mode
-minimize_corpus "$fuzzer_mode_build_dir/fuzz/dtls_client" dtls_client_corpus
-minimize_corpus "$fuzzer_mode_build_dir/fuzz/dtls_server" dtls_server_corpus
-minimize_corpus "$fuzzer_mode_build_dir/fuzz/decode_client_hello_inner" decode_client_hello_inner_corpus
-
-
-# Incorporate the new transcripts.
-
-"$fuzzer_mode_build_dir/fuzz/client" -max_len=50000 -merge=1 client_corpus "${fuzzer_mode_transcripts}/tls/client"
-"$fuzzer_mode_build_dir/fuzz/server" -max_len=50000 -merge=1 server_corpus "${fuzzer_mode_transcripts}/tls/server"
-"$no_fuzzer_mode_build_dir/fuzz/client" -max_len=50000 -merge=1 client_corpus_no_fuzzer_mode "${no_fuzzer_mode_transcripts}/tls/client"
-"$no_fuzzer_mode_build_dir/fuzz/server" -max_len=50000 -merge=1 server_corpus_no_fuzzer_mode "${no_fuzzer_mode_transcripts}/tls/server"
-"$fuzzer_mode_build_dir/fuzz/dtls_client" -max_len=50000 -merge=1 dtls_client_corpus "${fuzzer_mode_transcripts}/dtls/client"
-"$fuzzer_mode_build_dir/fuzz/dtls_server" -max_len=50000 -merge=1 dtls_server_corpus "${fuzzer_mode_transcripts}/dtls/server"
-"$fuzzer_mode_build_dir/fuzz/decode_client_hello_inner" -max_len=50000 -merge=1 decode_client_hello_inner_corpus "${fuzzer_mode_transcripts}/decode_client_hello_inner"
+update_corpus client "${fuzzer_mode_transcripts}/tls/client"
+update_corpus server "${fuzzer_mode_transcripts}/tls/server"
+update_corpus client_no_fuzzer_mode "${no_fuzzer_mode_transcripts}/tls/client"
+update_corpus server_no_fuzzer_mode "${no_fuzzer_mode_transcripts}/tls/server"
+update_corpus dtls_client "${fuzzer_mode_transcripts}/dtls/client"
+update_corpus dtls_server "${fuzzer_mode_transcripts}/dtls/server"
+update_corpus decode_client_hello_inner "${fuzzer_mode_transcripts}/decode_client_hello_inner"
diff --git a/src/fuzz/server.cc b/src/fuzz/server.cc
index c167dd3..d7a8842 100644
--- a/src/fuzz/server.cc
+++ b/src/fuzz/server.cc
@@ -15,7 +15,8 @@
 #include "../ssl/test/fuzzer.h"
 
 
-static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kServer);
+static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kServer,
+                          TLSFuzzer::kFuzzerModeOn);
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
   return g_fuzzer.TestOneInput(buf, len);
diff --git a/src/fuzz/server_corpus/00297505661b08ffccf461853d5210e89c4fdadc b/src/fuzz/server_corpus/00297505661b08ffccf461853d5210e89c4fdadc
new file mode 100644
index 0000000..fb37dba
--- /dev/null
+++ b/src/fuzz/server_corpus/00297505661b08ffccf461853d5210e89c4fdadc
Binary files differ
diff --git a/src/fuzz/server_corpus/014ec357b2c469af87fc67873c9e951bbdad3cf8 b/src/fuzz/server_corpus/014ec357b2c469af87fc67873c9e951bbdad3cf8
deleted file mode 100644
index 6da25af..0000000
--- a/src/fuzz/server_corpus/014ec357b2c469af87fc67873c9e951bbdad3cf8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/025aed12958abc20757a7074a767f924274d5ca8 b/src/fuzz/server_corpus/025aed12958abc20757a7074a767f924274d5ca8
deleted file mode 100644
index 1d4377d..0000000
--- a/src/fuzz/server_corpus/025aed12958abc20757a7074a767f924274d5ca8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/0436f13e178d7c96273d1f7e520529abc853db7f b/src/fuzz/server_corpus/0436f13e178d7c96273d1f7e520529abc853db7f
deleted file mode 100644
index 444e333..0000000
--- a/src/fuzz/server_corpus/0436f13e178d7c96273d1f7e520529abc853db7f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/04f5750d6d1c2f88d1dc68a667445069e2ea33b3 b/src/fuzz/server_corpus/04f5750d6d1c2f88d1dc68a667445069e2ea33b3
new file mode 100644
index 0000000..514dde9
--- /dev/null
+++ b/src/fuzz/server_corpus/04f5750d6d1c2f88d1dc68a667445069e2ea33b3
Binary files differ
diff --git a/src/fuzz/server_corpus/05ce6c45d8f16253845eaa0f513c0b1267927161 b/src/fuzz/server_corpus/05ce6c45d8f16253845eaa0f513c0b1267927161
deleted file mode 100644
index 120771a..0000000
--- a/src/fuzz/server_corpus/05ce6c45d8f16253845eaa0f513c0b1267927161
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/0f8a1d27b3ea511f1a05ebc331a4cbcc8ece8cb2 b/src/fuzz/server_corpus/0f8a1d27b3ea511f1a05ebc331a4cbcc8ece8cb2
deleted file mode 100644
index a186f2f..0000000
--- a/src/fuzz/server_corpus/0f8a1d27b3ea511f1a05ebc331a4cbcc8ece8cb2
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/11640368a03c0ab4f33619bd9b6c6e7533935e1a b/src/fuzz/server_corpus/11640368a03c0ab4f33619bd9b6c6e7533935e1a
new file mode 100644
index 0000000..14eddeb
--- /dev/null
+++ b/src/fuzz/server_corpus/11640368a03c0ab4f33619bd9b6c6e7533935e1a
Binary files differ
diff --git a/src/fuzz/server_corpus/120cb9b864dcd4e16393a192e672933ecdcf5093 b/src/fuzz/server_corpus/120cb9b864dcd4e16393a192e672933ecdcf5093
deleted file mode 100644
index f49747c..0000000
--- a/src/fuzz/server_corpus/120cb9b864dcd4e16393a192e672933ecdcf5093
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/1249d7fe45a9f391f0d8aadd7fbeb4446a0f72f8 b/src/fuzz/server_corpus/1249d7fe45a9f391f0d8aadd7fbeb4446a0f72f8
deleted file mode 100644
index 885772e..0000000
--- a/src/fuzz/server_corpus/1249d7fe45a9f391f0d8aadd7fbeb4446a0f72f8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/13dcd2b4e39e9a7d2d50498d0681c0041f2ba647 b/src/fuzz/server_corpus/13dcd2b4e39e9a7d2d50498d0681c0041f2ba647
deleted file mode 100644
index 130afdd..0000000
--- a/src/fuzz/server_corpus/13dcd2b4e39e9a7d2d50498d0681c0041f2ba647
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/1555e6ab4962e50ba793dec7cf28f58630a79d56 b/src/fuzz/server_corpus/1555e6ab4962e50ba793dec7cf28f58630a79d56
deleted file mode 100644
index ca65b22..0000000
--- a/src/fuzz/server_corpus/1555e6ab4962e50ba793dec7cf28f58630a79d56
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/1c531ea117559cb08cd537418dbbdff7444d8dfa b/src/fuzz/server_corpus/1c531ea117559cb08cd537418dbbdff7444d8dfa
new file mode 100644
index 0000000..f5bc5ee
--- /dev/null
+++ b/src/fuzz/server_corpus/1c531ea117559cb08cd537418dbbdff7444d8dfa
Binary files differ
diff --git a/src/fuzz/server_corpus/1d26010a0564c39d5a2cb53dc15c824d463a1722 b/src/fuzz/server_corpus/1d26010a0564c39d5a2cb53dc15c824d463a1722
deleted file mode 100644
index 7d62d39..0000000
--- a/src/fuzz/server_corpus/1d26010a0564c39d5a2cb53dc15c824d463a1722
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/1da4b909dd658b346b2e4c1553f0781d269de04f b/src/fuzz/server_corpus/1da4b909dd658b346b2e4c1553f0781d269de04f
deleted file mode 100644
index 1219a0a..0000000
--- a/src/fuzz/server_corpus/1da4b909dd658b346b2e4c1553f0781d269de04f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/1ed70b69f19cc328d13550da30247e27376e3e42 b/src/fuzz/server_corpus/1ed70b69f19cc328d13550da30247e27376e3e42
new file mode 100644
index 0000000..1e38811
--- /dev/null
+++ b/src/fuzz/server_corpus/1ed70b69f19cc328d13550da30247e27376e3e42
Binary files differ
diff --git a/src/fuzz/server_corpus/256c797f5fd2672727a5446d3b338289ea3255ff b/src/fuzz/server_corpus/256c797f5fd2672727a5446d3b338289ea3255ff
new file mode 100644
index 0000000..3fcc1e4
--- /dev/null
+++ b/src/fuzz/server_corpus/256c797f5fd2672727a5446d3b338289ea3255ff
Binary files differ
diff --git a/src/fuzz/server_corpus/275de3921437094dc3d06f4693b6109dfd2b8349 b/src/fuzz/server_corpus/275de3921437094dc3d06f4693b6109dfd2b8349
deleted file mode 100644
index 1f5deb9..0000000
--- a/src/fuzz/server_corpus/275de3921437094dc3d06f4693b6109dfd2b8349
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/27ccb66ad1a8b4d1ed8f998248afed6118272a75 b/src/fuzz/server_corpus/27ccb66ad1a8b4d1ed8f998248afed6118272a75
new file mode 100644
index 0000000..aefce8d
--- /dev/null
+++ b/src/fuzz/server_corpus/27ccb66ad1a8b4d1ed8f998248afed6118272a75
Binary files differ
diff --git a/src/fuzz/server_corpus/2ae9f0733b55e6da8c3323488e847a90cd4a3fe9 b/src/fuzz/server_corpus/2ae9f0733b55e6da8c3323488e847a90cd4a3fe9
deleted file mode 100644
index 039f2ed..0000000
--- a/src/fuzz/server_corpus/2ae9f0733b55e6da8c3323488e847a90cd4a3fe9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/2bd8befd0ff11db3cf644f8680bb1bfc67716b73 b/src/fuzz/server_corpus/2bd8befd0ff11db3cf644f8680bb1bfc67716b73
new file mode 100644
index 0000000..20bca5f
--- /dev/null
+++ b/src/fuzz/server_corpus/2bd8befd0ff11db3cf644f8680bb1bfc67716b73
Binary files differ
diff --git a/src/fuzz/server_corpus/2decb8e0bda759216a98beb017aea06581ca2081 b/src/fuzz/server_corpus/2decb8e0bda759216a98beb017aea06581ca2081
new file mode 100644
index 0000000..cedab5a
--- /dev/null
+++ b/src/fuzz/server_corpus/2decb8e0bda759216a98beb017aea06581ca2081
Binary files differ
diff --git a/src/fuzz/server_corpus/30c5597adc8546d84ce258457365dbfcd1d3b33e b/src/fuzz/server_corpus/30c5597adc8546d84ce258457365dbfcd1d3b33e
deleted file mode 100644
index 992ee35..0000000
--- a/src/fuzz/server_corpus/30c5597adc8546d84ce258457365dbfcd1d3b33e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/31faf51e693067afea269a4699b04a29852ee1af b/src/fuzz/server_corpus/31faf51e693067afea269a4699b04a29852ee1af
new file mode 100644
index 0000000..65f8dda
--- /dev/null
+++ b/src/fuzz/server_corpus/31faf51e693067afea269a4699b04a29852ee1af
Binary files differ
diff --git a/src/fuzz/server_corpus/328d5d60c646d83e1f6df13ff0fd60f4b249b7c6 b/src/fuzz/server_corpus/328d5d60c646d83e1f6df13ff0fd60f4b249b7c6
new file mode 100644
index 0000000..39761c9
--- /dev/null
+++ b/src/fuzz/server_corpus/328d5d60c646d83e1f6df13ff0fd60f4b249b7c6
Binary files differ
diff --git a/src/fuzz/server_corpus/3298398dd6130869015408bba20122fece4e2ab5 b/src/fuzz/server_corpus/3298398dd6130869015408bba20122fece4e2ab5
new file mode 100644
index 0000000..6e15036
--- /dev/null
+++ b/src/fuzz/server_corpus/3298398dd6130869015408bba20122fece4e2ab5
Binary files differ
diff --git a/src/fuzz/server_corpus/33f597d30d38793ccb2b87802e1dfd64d051ffbb b/src/fuzz/server_corpus/33f597d30d38793ccb2b87802e1dfd64d051ffbb
deleted file mode 100644
index 6a224db..0000000
--- a/src/fuzz/server_corpus/33f597d30d38793ccb2b87802e1dfd64d051ffbb
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/35463fa0278db6c1ad7a91d35d19bb9c84b2efd9 b/src/fuzz/server_corpus/35463fa0278db6c1ad7a91d35d19bb9c84b2efd9
deleted file mode 100644
index abcaf2d..0000000
--- a/src/fuzz/server_corpus/35463fa0278db6c1ad7a91d35d19bb9c84b2efd9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/35dcc02c10b87bbded51c738e7e8f9f31ec4353d b/src/fuzz/server_corpus/35dcc02c10b87bbded51c738e7e8f9f31ec4353d
new file mode 100644
index 0000000..fd91a66
--- /dev/null
+++ b/src/fuzz/server_corpus/35dcc02c10b87bbded51c738e7e8f9f31ec4353d
Binary files differ
diff --git a/src/fuzz/server_corpus/381d7638c8d78731018eb45ccef62656102a1edd b/src/fuzz/server_corpus/381d7638c8d78731018eb45ccef62656102a1edd
new file mode 100644
index 0000000..f3af4a2
--- /dev/null
+++ b/src/fuzz/server_corpus/381d7638c8d78731018eb45ccef62656102a1edd
Binary files differ
diff --git a/src/fuzz/server_corpus/3dc81f53361ab02ee05134aa43d6288424980bdd b/src/fuzz/server_corpus/3dc81f53361ab02ee05134aa43d6288424980bdd
new file mode 100644
index 0000000..151ec61
--- /dev/null
+++ b/src/fuzz/server_corpus/3dc81f53361ab02ee05134aa43d6288424980bdd
Binary files differ
diff --git a/src/fuzz/server_corpus/416bad0364df5d4a1d10526d45181e294b79027e b/src/fuzz/server_corpus/416bad0364df5d4a1d10526d45181e294b79027e
new file mode 100644
index 0000000..bf788ba
--- /dev/null
+++ b/src/fuzz/server_corpus/416bad0364df5d4a1d10526d45181e294b79027e
Binary files differ
diff --git a/src/fuzz/server_corpus/42d4400dfdd879fdf475a0d8db19512c120bf018 b/src/fuzz/server_corpus/42d4400dfdd879fdf475a0d8db19512c120bf018
new file mode 100644
index 0000000..bc50467
--- /dev/null
+++ b/src/fuzz/server_corpus/42d4400dfdd879fdf475a0d8db19512c120bf018
Binary files differ
diff --git a/src/fuzz/server_corpus/468d8dce2bd41adf834040605a56466d5e709e8a b/src/fuzz/server_corpus/468d8dce2bd41adf834040605a56466d5e709e8a
new file mode 100644
index 0000000..7df8a2b
--- /dev/null
+++ b/src/fuzz/server_corpus/468d8dce2bd41adf834040605a56466d5e709e8a
Binary files differ
diff --git a/src/fuzz/server_corpus/4a608931b94ef2d65e6ad9c5c97fcc268c6330d0 b/src/fuzz/server_corpus/4a608931b94ef2d65e6ad9c5c97fcc268c6330d0
new file mode 100644
index 0000000..b6dad73
--- /dev/null
+++ b/src/fuzz/server_corpus/4a608931b94ef2d65e6ad9c5c97fcc268c6330d0
Binary files differ
diff --git a/src/fuzz/server_corpus/4e3b996b7383b7baa62ec07b0c8e9c2772d7b948 b/src/fuzz/server_corpus/4e3b996b7383b7baa62ec07b0c8e9c2772d7b948
deleted file mode 100644
index 9783ba4..0000000
--- a/src/fuzz/server_corpus/4e3b996b7383b7baa62ec07b0c8e9c2772d7b948
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/4f2598a6e30c860dd845fbae49edf2ea5259dbd8 b/src/fuzz/server_corpus/4f2598a6e30c860dd845fbae49edf2ea5259dbd8
deleted file mode 100644
index ab04806..0000000
--- a/src/fuzz/server_corpus/4f2598a6e30c860dd845fbae49edf2ea5259dbd8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/503ff204bcc3ad87d8582c9520a7cccddc053d58 b/src/fuzz/server_corpus/503ff204bcc3ad87d8582c9520a7cccddc053d58
new file mode 100644
index 0000000..9523b7e
--- /dev/null
+++ b/src/fuzz/server_corpus/503ff204bcc3ad87d8582c9520a7cccddc053d58
Binary files differ
diff --git a/src/fuzz/server_corpus/524a3538cfac30bcbb11367f95bd8280c9a53d36 b/src/fuzz/server_corpus/524a3538cfac30bcbb11367f95bd8280c9a53d36
deleted file mode 100644
index c398eb4..0000000
--- a/src/fuzz/server_corpus/524a3538cfac30bcbb11367f95bd8280c9a53d36
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/5498159c0e193cb9f11d67ac91a6823a78bb1738 b/src/fuzz/server_corpus/5498159c0e193cb9f11d67ac91a6823a78bb1738
deleted file mode 100644
index e9ae637..0000000
--- a/src/fuzz/server_corpus/5498159c0e193cb9f11d67ac91a6823a78bb1738
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/550c6de19d52cf0178d12b3eece0a701186f798f b/src/fuzz/server_corpus/550c6de19d52cf0178d12b3eece0a701186f798f
new file mode 100644
index 0000000..dd6b96c
--- /dev/null
+++ b/src/fuzz/server_corpus/550c6de19d52cf0178d12b3eece0a701186f798f
Binary files differ
diff --git a/src/fuzz/server_corpus/5571632273db47491815793c16570f5e8454bcac b/src/fuzz/server_corpus/5571632273db47491815793c16570f5e8454bcac
deleted file mode 100644
index 68a338e..0000000
--- a/src/fuzz/server_corpus/5571632273db47491815793c16570f5e8454bcac
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/564040068a5e1f2ca9f9c3f79dd3b6ccbb3525b6 b/src/fuzz/server_corpus/564040068a5e1f2ca9f9c3f79dd3b6ccbb3525b6
deleted file mode 100644
index b05c10c..0000000
--- a/src/fuzz/server_corpus/564040068a5e1f2ca9f9c3f79dd3b6ccbb3525b6
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/5820645412502aa980e7d300e2fbd8ea5e6fe156 b/src/fuzz/server_corpus/5820645412502aa980e7d300e2fbd8ea5e6fe156
new file mode 100644
index 0000000..fd11b49
--- /dev/null
+++ b/src/fuzz/server_corpus/5820645412502aa980e7d300e2fbd8ea5e6fe156
Binary files differ
diff --git a/src/fuzz/server_corpus/59e20226c6da2b30debdeb914678414383ce287a b/src/fuzz/server_corpus/59e20226c6da2b30debdeb914678414383ce287a
deleted file mode 100644
index 123c7fd..0000000
--- a/src/fuzz/server_corpus/59e20226c6da2b30debdeb914678414383ce287a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/5ab138ec34db3a88a6657ff3c92e9e2ac961788d b/src/fuzz/server_corpus/5ab138ec34db3a88a6657ff3c92e9e2ac961788d
new file mode 100644
index 0000000..4d58ef2
--- /dev/null
+++ b/src/fuzz/server_corpus/5ab138ec34db3a88a6657ff3c92e9e2ac961788d
Binary files differ
diff --git a/src/fuzz/server_corpus/5ba1f9d656416c114ed1df61343a0d8ab083c0b7 b/src/fuzz/server_corpus/5ba1f9d656416c114ed1df61343a0d8ab083c0b7
deleted file mode 100644
index e08e1f2..0000000
--- a/src/fuzz/server_corpus/5ba1f9d656416c114ed1df61343a0d8ab083c0b7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/5bdf24223a3247c80c560e0117551fdac036dd90 b/src/fuzz/server_corpus/5bdf24223a3247c80c560e0117551fdac036dd90
new file mode 100644
index 0000000..80e2280
--- /dev/null
+++ b/src/fuzz/server_corpus/5bdf24223a3247c80c560e0117551fdac036dd90
Binary files differ
diff --git a/src/fuzz/server_corpus/5bebfe9ba65801179484ee57ffea7e93d6245d15 b/src/fuzz/server_corpus/5bebfe9ba65801179484ee57ffea7e93d6245d15
new file mode 100644
index 0000000..be430b2
--- /dev/null
+++ b/src/fuzz/server_corpus/5bebfe9ba65801179484ee57ffea7e93d6245d15
Binary files differ
diff --git a/src/fuzz/server_corpus/5cab4135b16d0aaa5f4a5b5b3bc7257754eb6fe1 b/src/fuzz/server_corpus/5cab4135b16d0aaa5f4a5b5b3bc7257754eb6fe1
new file mode 100644
index 0000000..e83dfe7
--- /dev/null
+++ b/src/fuzz/server_corpus/5cab4135b16d0aaa5f4a5b5b3bc7257754eb6fe1
Binary files differ
diff --git a/src/fuzz/server_corpus/5edf784543003743dc69d76dbc94ea3f2f9d8063 b/src/fuzz/server_corpus/5edf784543003743dc69d76dbc94ea3f2f9d8063
new file mode 100644
index 0000000..e39c8a0
--- /dev/null
+++ b/src/fuzz/server_corpus/5edf784543003743dc69d76dbc94ea3f2f9d8063
Binary files differ
diff --git a/src/fuzz/server_corpus/5f4c395558016c1c8d7ade8dc39bf38a7cdda7d1 b/src/fuzz/server_corpus/5f4c395558016c1c8d7ade8dc39bf38a7cdda7d1
deleted file mode 100644
index 59d05a9..0000000
--- a/src/fuzz/server_corpus/5f4c395558016c1c8d7ade8dc39bf38a7cdda7d1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/5fa52b26c8eef100680278c4cf019d1edcdba1d7 b/src/fuzz/server_corpus/5fa52b26c8eef100680278c4cf019d1edcdba1d7
deleted file mode 100644
index 9a0a6fc..0000000
--- a/src/fuzz/server_corpus/5fa52b26c8eef100680278c4cf019d1edcdba1d7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b b/src/fuzz/server_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b
new file mode 100644
index 0000000..9fa4a3a
--- /dev/null
+++ b/src/fuzz/server_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b
Binary files differ
diff --git a/src/fuzz/server_corpus/69cdf589463ee275905e6610673df15aebe2a93a b/src/fuzz/server_corpus/69cdf589463ee275905e6610673df15aebe2a93a
deleted file mode 100644
index 88977f3..0000000
--- a/src/fuzz/server_corpus/69cdf589463ee275905e6610673df15aebe2a93a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/6a8d0acbcbf53ed119d50eb88bbf5c71c1f70bdf b/src/fuzz/server_corpus/6a8d0acbcbf53ed119d50eb88bbf5c71c1f70bdf
deleted file mode 100644
index 6d9bc7e..0000000
--- a/src/fuzz/server_corpus/6a8d0acbcbf53ed119d50eb88bbf5c71c1f70bdf
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/6c1d519d8abdc17bf8eb0c650d4912e8d4717516 b/src/fuzz/server_corpus/6c1d519d8abdc17bf8eb0c650d4912e8d4717516
new file mode 100644
index 0000000..947bfb0
--- /dev/null
+++ b/src/fuzz/server_corpus/6c1d519d8abdc17bf8eb0c650d4912e8d4717516
Binary files differ
diff --git a/src/fuzz/server_corpus/6ea216f5c04893a84c9a3c3f8a2736e4d9dcc47d b/src/fuzz/server_corpus/6ea216f5c04893a84c9a3c3f8a2736e4d9dcc47d
deleted file mode 100644
index 7b22efa..0000000
--- a/src/fuzz/server_corpus/6ea216f5c04893a84c9a3c3f8a2736e4d9dcc47d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/6f1a320acc1519666e923edbd54ffba0770878da b/src/fuzz/server_corpus/6f1a320acc1519666e923edbd54ffba0770878da
new file mode 100644
index 0000000..7515569
--- /dev/null
+++ b/src/fuzz/server_corpus/6f1a320acc1519666e923edbd54ffba0770878da
Binary files differ
diff --git a/src/fuzz/server_corpus/745299cb67ee3b5afd64802787b6224d8bfa5921 b/src/fuzz/server_corpus/745299cb67ee3b5afd64802787b6224d8bfa5921
new file mode 100644
index 0000000..5ad184e
--- /dev/null
+++ b/src/fuzz/server_corpus/745299cb67ee3b5afd64802787b6224d8bfa5921
Binary files differ
diff --git a/src/fuzz/server_corpus/75a4d4273220ff40a717e8c698c173f2238010a6 b/src/fuzz/server_corpus/75a4d4273220ff40a717e8c698c173f2238010a6
deleted file mode 100644
index e1a551f..0000000
--- a/src/fuzz/server_corpus/75a4d4273220ff40a717e8c698c173f2238010a6
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/75ad0a44c84ef1f754bdf896bc2f6b9473a0fb31 b/src/fuzz/server_corpus/75ad0a44c84ef1f754bdf896bc2f6b9473a0fb31
deleted file mode 100644
index e6d84e3..0000000
--- a/src/fuzz/server_corpus/75ad0a44c84ef1f754bdf896bc2f6b9473a0fb31
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b b/src/fuzz/server_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b
new file mode 100644
index 0000000..21688ed
--- /dev/null
+++ b/src/fuzz/server_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b
Binary files differ
diff --git a/src/fuzz/server_corpus/7739f5537ee34a4a7962dc0acfdddf431b34f11c b/src/fuzz/server_corpus/7739f5537ee34a4a7962dc0acfdddf431b34f11c
deleted file mode 100644
index b9b2e17..0000000
--- a/src/fuzz/server_corpus/7739f5537ee34a4a7962dc0acfdddf431b34f11c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/775c260b97fdc32cd7f9eeb0748460779ec03c6c b/src/fuzz/server_corpus/775c260b97fdc32cd7f9eeb0748460779ec03c6c
deleted file mode 100644
index dca1327..0000000
--- a/src/fuzz/server_corpus/775c260b97fdc32cd7f9eeb0748460779ec03c6c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/79da62d0e1044d89d911ff630d975ebfdcfdd8df b/src/fuzz/server_corpus/79da62d0e1044d89d911ff630d975ebfdcfdd8df
new file mode 100644
index 0000000..86ca972
--- /dev/null
+++ b/src/fuzz/server_corpus/79da62d0e1044d89d911ff630d975ebfdcfdd8df
Binary files differ
diff --git a/src/fuzz/server_corpus/7a2227a3b569158f7047d10aabe56145675036e4 b/src/fuzz/server_corpus/7a2227a3b569158f7047d10aabe56145675036e4
deleted file mode 100644
index 74fbd55..0000000
--- a/src/fuzz/server_corpus/7a2227a3b569158f7047d10aabe56145675036e4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7b23e66225ed9efaf237332143a122ad916b5b1b b/src/fuzz/server_corpus/7b23e66225ed9efaf237332143a122ad916b5b1b
deleted file mode 100644
index 13a87212..0000000
--- a/src/fuzz/server_corpus/7b23e66225ed9efaf237332143a122ad916b5b1b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7b350f1c552d937fc537b18f7c7643a2cef162a8 b/src/fuzz/server_corpus/7b350f1c552d937fc537b18f7c7643a2cef162a8
new file mode 100644
index 0000000..bf18e0a
--- /dev/null
+++ b/src/fuzz/server_corpus/7b350f1c552d937fc537b18f7c7643a2cef162a8
Binary files differ
diff --git a/src/fuzz/server_corpus/7ba7fdd8bdda15cdc2dcbe2492e60cd5a8856ebc b/src/fuzz/server_corpus/7ba7fdd8bdda15cdc2dcbe2492e60cd5a8856ebc
deleted file mode 100644
index c25f653..0000000
--- a/src/fuzz/server_corpus/7ba7fdd8bdda15cdc2dcbe2492e60cd5a8856ebc
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7c88218dd676309a2250b91520717651a2f4daaf b/src/fuzz/server_corpus/7c88218dd676309a2250b91520717651a2f4daaf
deleted file mode 100644
index b82b873..0000000
--- a/src/fuzz/server_corpus/7c88218dd676309a2250b91520717651a2f4daaf
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7cb312ce57dea0c9f799f1f414c87d5ef73502db b/src/fuzz/server_corpus/7cb312ce57dea0c9f799f1f414c87d5ef73502db
deleted file mode 100644
index 154d480..0000000
--- a/src/fuzz/server_corpus/7cb312ce57dea0c9f799f1f414c87d5ef73502db
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7d0a8149f3da5c3f5df45b1dd3a425b0d7e13dac b/src/fuzz/server_corpus/7d0a8149f3da5c3f5df45b1dd3a425b0d7e13dac
deleted file mode 100644
index 77567ad..0000000
--- a/src/fuzz/server_corpus/7d0a8149f3da5c3f5df45b1dd3a425b0d7e13dac
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/7e49f7eed0f563792d57ef3192e0f3d8f940362b b/src/fuzz/server_corpus/7e49f7eed0f563792d57ef3192e0f3d8f940362b
new file mode 100644
index 0000000..3276ea4
--- /dev/null
+++ b/src/fuzz/server_corpus/7e49f7eed0f563792d57ef3192e0f3d8f940362b
Binary files differ
diff --git a/src/fuzz/server_corpus/802c8691245f7112ed1f16568397463138f1a071 b/src/fuzz/server_corpus/802c8691245f7112ed1f16568397463138f1a071
new file mode 100644
index 0000000..da561e8
--- /dev/null
+++ b/src/fuzz/server_corpus/802c8691245f7112ed1f16568397463138f1a071
Binary files differ
diff --git a/src/fuzz/server_corpus/81ecee1e06d345b7988442e3504955bd80809671 b/src/fuzz/server_corpus/81ecee1e06d345b7988442e3504955bd80809671
deleted file mode 100644
index 846821d..0000000
--- a/src/fuzz/server_corpus/81ecee1e06d345b7988442e3504955bd80809671
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/824aad3da574c6e693c53d3105b299e16d3f2388 b/src/fuzz/server_corpus/824aad3da574c6e693c53d3105b299e16d3f2388
new file mode 100644
index 0000000..b1bc207
--- /dev/null
+++ b/src/fuzz/server_corpus/824aad3da574c6e693c53d3105b299e16d3f2388
Binary files differ
diff --git a/src/fuzz/server_corpus/8311155ac46bae1fc887b1f05c260972e689d88d b/src/fuzz/server_corpus/8311155ac46bae1fc887b1f05c260972e689d88d
new file mode 100644
index 0000000..f30f9f3
--- /dev/null
+++ b/src/fuzz/server_corpus/8311155ac46bae1fc887b1f05c260972e689d88d
Binary files differ
diff --git a/src/fuzz/server_corpus/83272d11959a79af08221aa9c4a20de4b8a9b774 b/src/fuzz/server_corpus/83272d11959a79af08221aa9c4a20de4b8a9b774
deleted file mode 100644
index a238d3b..0000000
--- a/src/fuzz/server_corpus/83272d11959a79af08221aa9c4a20de4b8a9b774
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/8352d97ee9c64daa58d1e15625ecaad669129d65 b/src/fuzz/server_corpus/8352d97ee9c64daa58d1e15625ecaad669129d65
deleted file mode 100644
index f513ee5..0000000
--- a/src/fuzz/server_corpus/8352d97ee9c64daa58d1e15625ecaad669129d65
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/854f3f31adc537ba98549be0edaf65bb19092da3 b/src/fuzz/server_corpus/854f3f31adc537ba98549be0edaf65bb19092da3
deleted file mode 100644
index 1ed3f0c..0000000
--- a/src/fuzz/server_corpus/854f3f31adc537ba98549be0edaf65bb19092da3
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/85f1e01d6239dc78abde28e857a3be39ee32a9ec b/src/fuzz/server_corpus/85f1e01d6239dc78abde28e857a3be39ee32a9ec
deleted file mode 100644
index c2eac74..0000000
--- a/src/fuzz/server_corpus/85f1e01d6239dc78abde28e857a3be39ee32a9ec
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/8880050cf344d92305b839411ee91a98e1a7b8f2 b/src/fuzz/server_corpus/8880050cf344d92305b839411ee91a98e1a7b8f2
deleted file mode 100644
index cfee464..0000000
--- a/src/fuzz/server_corpus/8880050cf344d92305b839411ee91a98e1a7b8f2
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/895f1b87f6d991d9d690dbdf6f54761fcd975582 b/src/fuzz/server_corpus/895f1b87f6d991d9d690dbdf6f54761fcd975582
new file mode 100644
index 0000000..eb20df7
--- /dev/null
+++ b/src/fuzz/server_corpus/895f1b87f6d991d9d690dbdf6f54761fcd975582
Binary files differ
diff --git a/src/fuzz/server_corpus/8baeb58c7c4a2d0297f9e350f0554f0b61919891 b/src/fuzz/server_corpus/8baeb58c7c4a2d0297f9e350f0554f0b61919891
new file mode 100644
index 0000000..1cefea8
--- /dev/null
+++ b/src/fuzz/server_corpus/8baeb58c7c4a2d0297f9e350f0554f0b61919891
Binary files differ
diff --git a/src/fuzz/server_corpus/8e254c80621ea0342086a4935f807c9097718b5a b/src/fuzz/server_corpus/8e254c80621ea0342086a4935f807c9097718b5a
deleted file mode 100644
index 4c16830..0000000
--- a/src/fuzz/server_corpus/8e254c80621ea0342086a4935f807c9097718b5a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/9463bad3abd25f33e55847f46ee4aa37f29a9013 b/src/fuzz/server_corpus/9463bad3abd25f33e55847f46ee4aa37f29a9013
new file mode 100644
index 0000000..43a839e
--- /dev/null
+++ b/src/fuzz/server_corpus/9463bad3abd25f33e55847f46ee4aa37f29a9013
Binary files differ
diff --git a/src/fuzz/server_corpus/95a329aa666948e3c7e26a0f9802a8b730698f9b b/src/fuzz/server_corpus/95a329aa666948e3c7e26a0f9802a8b730698f9b
new file mode 100644
index 0000000..dbcf78a
--- /dev/null
+++ b/src/fuzz/server_corpus/95a329aa666948e3c7e26a0f9802a8b730698f9b
Binary files differ
diff --git a/src/fuzz/server_corpus/96bc7958cd9b948713b7eef66c25b7b24d6fce77 b/src/fuzz/server_corpus/96bc7958cd9b948713b7eef66c25b7b24d6fce77
deleted file mode 100644
index 9f5dde0..0000000
--- a/src/fuzz/server_corpus/96bc7958cd9b948713b7eef66c25b7b24d6fce77
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/9756b988afe8bf1c64c983c8cf67ae2de7f7a700 b/src/fuzz/server_corpus/9756b988afe8bf1c64c983c8cf67ae2de7f7a700
new file mode 100644
index 0000000..f9b1827
--- /dev/null
+++ b/src/fuzz/server_corpus/9756b988afe8bf1c64c983c8cf67ae2de7f7a700
Binary files differ
diff --git a/src/fuzz/server_corpus/9b2454996cb666d576b66726d795e12eb3282f60 b/src/fuzz/server_corpus/9b2454996cb666d576b66726d795e12eb3282f60
new file mode 100644
index 0000000..e674ba9
--- /dev/null
+++ b/src/fuzz/server_corpus/9b2454996cb666d576b66726d795e12eb3282f60
Binary files differ
diff --git a/src/fuzz/server_corpus/9bcf275bae2c3965820c447a331f95f1a159175f b/src/fuzz/server_corpus/9bcf275bae2c3965820c447a331f95f1a159175f
new file mode 100644
index 0000000..1facdce
--- /dev/null
+++ b/src/fuzz/server_corpus/9bcf275bae2c3965820c447a331f95f1a159175f
Binary files differ
diff --git a/src/fuzz/server_corpus/9c1f4fe4d428e4e2929696c8ebdbc2c597309c96 b/src/fuzz/server_corpus/9c1f4fe4d428e4e2929696c8ebdbc2c597309c96
deleted file mode 100644
index 96ff73d..0000000
--- a/src/fuzz/server_corpus/9c1f4fe4d428e4e2929696c8ebdbc2c597309c96
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/9eb764534f27c0ec431288ec168cb0d1bc1dc79c b/src/fuzz/server_corpus/9eb764534f27c0ec431288ec168cb0d1bc1dc79c
deleted file mode 100644
index fbcc95a..0000000
--- a/src/fuzz/server_corpus/9eb764534f27c0ec431288ec168cb0d1bc1dc79c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/a069da70e9c99dcf045164ba5a3d7c46d2767c58 b/src/fuzz/server_corpus/a069da70e9c99dcf045164ba5a3d7c46d2767c58
deleted file mode 100644
index 7c30bca..0000000
--- a/src/fuzz/server_corpus/a069da70e9c99dcf045164ba5a3d7c46d2767c58
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/a3b32f588723a5e570b649a21e0582a58ad961f0 b/src/fuzz/server_corpus/a3b32f588723a5e570b649a21e0582a58ad961f0
new file mode 100644
index 0000000..0905b59
--- /dev/null
+++ b/src/fuzz/server_corpus/a3b32f588723a5e570b649a21e0582a58ad961f0
Binary files differ
diff --git a/src/fuzz/server_corpus/a80fcf70c297cb0d39f4c900fff3f411e932f3d4 b/src/fuzz/server_corpus/a80fcf70c297cb0d39f4c900fff3f411e932f3d4
deleted file mode 100644
index 4577da7..0000000
--- a/src/fuzz/server_corpus/a80fcf70c297cb0d39f4c900fff3f411e932f3d4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/a8214199e6bc6e40662ed6450e66d903dbe54844 b/src/fuzz/server_corpus/a8214199e6bc6e40662ed6450e66d903dbe54844
new file mode 100644
index 0000000..57d54df
--- /dev/null
+++ b/src/fuzz/server_corpus/a8214199e6bc6e40662ed6450e66d903dbe54844
Binary files differ
diff --git a/src/fuzz/server_corpus/a92393954fb7770060b70a37143b03c7ac8f17e0 b/src/fuzz/server_corpus/a92393954fb7770060b70a37143b03c7ac8f17e0
new file mode 100644
index 0000000..0c8b24d
--- /dev/null
+++ b/src/fuzz/server_corpus/a92393954fb7770060b70a37143b03c7ac8f17e0
Binary files differ
diff --git a/src/fuzz/server_corpus/aae019279a0c7900da44485a1b0a5dc6142ea21d b/src/fuzz/server_corpus/aae019279a0c7900da44485a1b0a5dc6142ea21d
new file mode 100644
index 0000000..e4a21ca
--- /dev/null
+++ b/src/fuzz/server_corpus/aae019279a0c7900da44485a1b0a5dc6142ea21d
Binary files differ
diff --git a/src/fuzz/server_corpus/aafff906acf6636012e8c1abc35405c90f842497 b/src/fuzz/server_corpus/aafff906acf6636012e8c1abc35405c90f842497
new file mode 100644
index 0000000..4000189
--- /dev/null
+++ b/src/fuzz/server_corpus/aafff906acf6636012e8c1abc35405c90f842497
Binary files differ
diff --git a/src/fuzz/server_corpus/ab6fdeee6ccfd0c9ce0784a11182813abc816b2a b/src/fuzz/server_corpus/ab6fdeee6ccfd0c9ce0784a11182813abc816b2a
new file mode 100644
index 0000000..518dfb5
--- /dev/null
+++ b/src/fuzz/server_corpus/ab6fdeee6ccfd0c9ce0784a11182813abc816b2a
Binary files differ
diff --git a/src/fuzz/server_corpus/af706c19a32116c657c2458ac4370722d72d67af b/src/fuzz/server_corpus/af706c19a32116c657c2458ac4370722d72d67af
new file mode 100644
index 0000000..b2f06ed
--- /dev/null
+++ b/src/fuzz/server_corpus/af706c19a32116c657c2458ac4370722d72d67af
Binary files differ
diff --git a/src/fuzz/server_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12 b/src/fuzz/server_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12
new file mode 100644
index 0000000..209948a
--- /dev/null
+++ b/src/fuzz/server_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12
Binary files differ
diff --git a/src/fuzz/server_corpus/b25cebfdbc7bf85a58f490d8108a5c68be905bd1 b/src/fuzz/server_corpus/b25cebfdbc7bf85a58f490d8108a5c68be905bd1
deleted file mode 100644
index 04b9c5b..0000000
--- a/src/fuzz/server_corpus/b25cebfdbc7bf85a58f490d8108a5c68be905bd1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/b70bdea5a03ed33b09f274056d6cf2208b5fbbfd b/src/fuzz/server_corpus/b70bdea5a03ed33b09f274056d6cf2208b5fbbfd
deleted file mode 100644
index 7b86e94..0000000
--- a/src/fuzz/server_corpus/b70bdea5a03ed33b09f274056d6cf2208b5fbbfd
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/b977d9992664fbd686c0233b72050c6f67e6ea19 b/src/fuzz/server_corpus/b977d9992664fbd686c0233b72050c6f67e6ea19
deleted file mode 100644
index e57f904..0000000
--- a/src/fuzz/server_corpus/b977d9992664fbd686c0233b72050c6f67e6ea19
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/bdc936fe5e844e65fc34223ba22650edae0e58fe b/src/fuzz/server_corpus/bdc936fe5e844e65fc34223ba22650edae0e58fe
deleted file mode 100644
index b25124f..0000000
--- a/src/fuzz/server_corpus/bdc936fe5e844e65fc34223ba22650edae0e58fe
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/be867e61ea41c571c4485204f394f97188be5047 b/src/fuzz/server_corpus/be867e61ea41c571c4485204f394f97188be5047
deleted file mode 100644
index 12beebc..0000000
--- a/src/fuzz/server_corpus/be867e61ea41c571c4485204f394f97188be5047
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/c095ef83741e7dc39bd78b51cfad9a983b7130b9 b/src/fuzz/server_corpus/c095ef83741e7dc39bd78b51cfad9a983b7130b9
new file mode 100644
index 0000000..95ec963
--- /dev/null
+++ b/src/fuzz/server_corpus/c095ef83741e7dc39bd78b51cfad9a983b7130b9
Binary files differ
diff --git a/src/fuzz/server_corpus/c49b86641c88d6fef43e5d8934186ec00cc4ab9c b/src/fuzz/server_corpus/c49b86641c88d6fef43e5d8934186ec00cc4ab9c
new file mode 100644
index 0000000..74860b7
--- /dev/null
+++ b/src/fuzz/server_corpus/c49b86641c88d6fef43e5d8934186ec00cc4ab9c
Binary files differ
diff --git a/src/fuzz/server_corpus/c6b4907fc1c449f2d5d1f99b215ad11253fa5055 b/src/fuzz/server_corpus/c6b4907fc1c449f2d5d1f99b215ad11253fa5055
new file mode 100644
index 0000000..09afd7d
--- /dev/null
+++ b/src/fuzz/server_corpus/c6b4907fc1c449f2d5d1f99b215ad11253fa5055
Binary files differ
diff --git a/src/fuzz/server_corpus/c86ea6491a2fc788eb6f463c590b83517ba3ded4 b/src/fuzz/server_corpus/c86ea6491a2fc788eb6f463c590b83517ba3ded4
new file mode 100644
index 0000000..a90da59
--- /dev/null
+++ b/src/fuzz/server_corpus/c86ea6491a2fc788eb6f463c590b83517ba3ded4
Binary files differ
diff --git a/src/fuzz/server_corpus/ca8f557e1b0af61e87a19c0291b1b3bee424f451 b/src/fuzz/server_corpus/ca8f557e1b0af61e87a19c0291b1b3bee424f451
deleted file mode 100644
index ca42f35..0000000
--- a/src/fuzz/server_corpus/ca8f557e1b0af61e87a19c0291b1b3bee424f451
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/cba7661f1bb778d5fd731b4d07dbaeef535efb8a b/src/fuzz/server_corpus/cba7661f1bb778d5fd731b4d07dbaeef535efb8a
new file mode 100644
index 0000000..c291dc4
--- /dev/null
+++ b/src/fuzz/server_corpus/cba7661f1bb778d5fd731b4d07dbaeef535efb8a
Binary files differ
diff --git a/src/fuzz/server_corpus/cde43b90cb067eae1fef4bffdbe000945b94854f b/src/fuzz/server_corpus/cde43b90cb067eae1fef4bffdbe000945b94854f
deleted file mode 100644
index 941a1b5..0000000
--- a/src/fuzz/server_corpus/cde43b90cb067eae1fef4bffdbe000945b94854f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ce0becbb650090efd38fc81c6f3580a0f3729917 b/src/fuzz/server_corpus/ce0becbb650090efd38fc81c6f3580a0f3729917
new file mode 100644
index 0000000..3c9301a
--- /dev/null
+++ b/src/fuzz/server_corpus/ce0becbb650090efd38fc81c6f3580a0f3729917
Binary files differ
diff --git a/src/fuzz/server_corpus/ce4dfbed92584a5c9116323cd03156c1c31a59ce b/src/fuzz/server_corpus/ce4dfbed92584a5c9116323cd03156c1c31a59ce
deleted file mode 100644
index 3beb50e..0000000
--- a/src/fuzz/server_corpus/ce4dfbed92584a5c9116323cd03156c1c31a59ce
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d0224525e8fad9c133a64f7f603baaf497976c49 b/src/fuzz/server_corpus/d0224525e8fad9c133a64f7f603baaf497976c49
deleted file mode 100644
index fd450d3..0000000
--- a/src/fuzz/server_corpus/d0224525e8fad9c133a64f7f603baaf497976c49
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d6a5da220e7194d818b1ae06b7687f54c61b1caf b/src/fuzz/server_corpus/d6a5da220e7194d818b1ae06b7687f54c61b1caf
deleted file mode 100644
index 667300e..0000000
--- a/src/fuzz/server_corpus/d6a5da220e7194d818b1ae06b7687f54c61b1caf
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d74958d7ded9655e12085dc88f5e2c642918982d b/src/fuzz/server_corpus/d74958d7ded9655e12085dc88f5e2c642918982d
deleted file mode 100644
index 1bc1ac9..0000000
--- a/src/fuzz/server_corpus/d74958d7ded9655e12085dc88f5e2c642918982d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d785752aafee099086b12f6a4313f5114f52e987 b/src/fuzz/server_corpus/d785752aafee099086b12f6a4313f5114f52e987
deleted file mode 100644
index 8b1502d..0000000
--- a/src/fuzz/server_corpus/d785752aafee099086b12f6a4313f5114f52e987
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d9134c524c8b52304442e63fdaad499f61227f75 b/src/fuzz/server_corpus/d9134c524c8b52304442e63fdaad499f61227f75
deleted file mode 100644
index 508e0ec..0000000
--- a/src/fuzz/server_corpus/d9134c524c8b52304442e63fdaad499f61227f75
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/d9bf4fd919800d6de015ca85b5f9c0e8f15c79ca b/src/fuzz/server_corpus/d9bf4fd919800d6de015ca85b5f9c0e8f15c79ca
deleted file mode 100644
index 226fe03..0000000
--- a/src/fuzz/server_corpus/d9bf4fd919800d6de015ca85b5f9c0e8f15c79ca
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/da78bf3dd1a1b85075870fa99805d2d855fac2fa b/src/fuzz/server_corpus/da78bf3dd1a1b85075870fa99805d2d855fac2fa
new file mode 100644
index 0000000..82b7433
--- /dev/null
+++ b/src/fuzz/server_corpus/da78bf3dd1a1b85075870fa99805d2d855fac2fa
Binary files differ
diff --git a/src/fuzz/server_corpus/dbf421a7b48a775c408486ec027d5b5cff649803 b/src/fuzz/server_corpus/dbf421a7b48a775c408486ec027d5b5cff649803
deleted file mode 100644
index f879b8f..0000000
--- a/src/fuzz/server_corpus/dbf421a7b48a775c408486ec027d5b5cff649803
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/dcb092222eb041a250db952c72f3802630740d2a b/src/fuzz/server_corpus/dcb092222eb041a250db952c72f3802630740d2a
deleted file mode 100644
index c2d1c85..0000000
--- a/src/fuzz/server_corpus/dcb092222eb041a250db952c72f3802630740d2a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/dd1e5f0f9346baef3d9149bd9ebe55ddc8aa3a7f b/src/fuzz/server_corpus/dd1e5f0f9346baef3d9149bd9ebe55ddc8aa3a7f
new file mode 100644
index 0000000..6d60aaf
--- /dev/null
+++ b/src/fuzz/server_corpus/dd1e5f0f9346baef3d9149bd9ebe55ddc8aa3a7f
Binary files differ
diff --git a/src/fuzz/server_corpus/e07dc003c37f086542adc752f8a07b32add64a18 b/src/fuzz/server_corpus/e07dc003c37f086542adc752f8a07b32add64a18
deleted file mode 100644
index 446eb35..0000000
--- a/src/fuzz/server_corpus/e07dc003c37f086542adc752f8a07b32add64a18
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/e2b024abe5d8cc9953f0fc232bb0f9221dfd3702 b/src/fuzz/server_corpus/e2b024abe5d8cc9953f0fc232bb0f9221dfd3702
deleted file mode 100644
index 1a5a8b7..0000000
--- a/src/fuzz/server_corpus/e2b024abe5d8cc9953f0fc232bb0f9221dfd3702
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/e4c534d22c6571469ff83761d883623d3546e466 b/src/fuzz/server_corpus/e4c534d22c6571469ff83761d883623d3546e466
new file mode 100644
index 0000000..5da99e0
--- /dev/null
+++ b/src/fuzz/server_corpus/e4c534d22c6571469ff83761d883623d3546e466
Binary files differ
diff --git a/src/fuzz/server_corpus/e530250fcb8697a8f8fc77ab4555e859d90a6eb7 b/src/fuzz/server_corpus/e530250fcb8697a8f8fc77ab4555e859d90a6eb7
deleted file mode 100644
index 776691a..0000000
--- a/src/fuzz/server_corpus/e530250fcb8697a8f8fc77ab4555e859d90a6eb7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ec01750e7e23f69741af69a969ff3b333ccb783b b/src/fuzz/server_corpus/ec01750e7e23f69741af69a969ff3b333ccb783b
deleted file mode 100644
index ec0a410..0000000
--- a/src/fuzz/server_corpus/ec01750e7e23f69741af69a969ff3b333ccb783b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ed5a94a0e1eeb9152b92066d064c3917845191b7 b/src/fuzz/server_corpus/ed5a94a0e1eeb9152b92066d064c3917845191b7
deleted file mode 100644
index 4dcf159..0000000
--- a/src/fuzz/server_corpus/ed5a94a0e1eeb9152b92066d064c3917845191b7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ee0a8a759193ac7ced60744d3e7d06decdfaa53f b/src/fuzz/server_corpus/ee0a8a759193ac7ced60744d3e7d06decdfaa53f
deleted file mode 100644
index 5712a97..0000000
--- a/src/fuzz/server_corpus/ee0a8a759193ac7ced60744d3e7d06decdfaa53f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ee31b271ce14cbd5372de311c6fcc5ae9262e05b b/src/fuzz/server_corpus/ee31b271ce14cbd5372de311c6fcc5ae9262e05b
new file mode 100644
index 0000000..8a35953
--- /dev/null
+++ b/src/fuzz/server_corpus/ee31b271ce14cbd5372de311c6fcc5ae9262e05b
Binary files differ
diff --git a/src/fuzz/server_corpus/eed3e358965b6d88b5101daca716bb076d66a2aa b/src/fuzz/server_corpus/eed3e358965b6d88b5101daca716bb076d66a2aa
deleted file mode 100644
index c4b1e91..0000000
--- a/src/fuzz/server_corpus/eed3e358965b6d88b5101daca716bb076d66a2aa
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/eee9e0ae5db8160112409a3483159733b6f2ae8f b/src/fuzz/server_corpus/eee9e0ae5db8160112409a3483159733b6f2ae8f
deleted file mode 100644
index d4ee8ea..0000000
--- a/src/fuzz/server_corpus/eee9e0ae5db8160112409a3483159733b6f2ae8f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/ef5b4b1cb3449d6e698238a0882c56c261a5bde5 b/src/fuzz/server_corpus/ef5b4b1cb3449d6e698238a0882c56c261a5bde5
deleted file mode 100644
index 085332c..0000000
--- a/src/fuzz/server_corpus/ef5b4b1cb3449d6e698238a0882c56c261a5bde5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/f1d0ea910f242833845a97bbcda344e3bd518538 b/src/fuzz/server_corpus/f1d0ea910f242833845a97bbcda344e3bd518538
deleted file mode 100644
index 80a6e82..0000000
--- a/src/fuzz/server_corpus/f1d0ea910f242833845a97bbcda344e3bd518538
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/f3b0fb38fefff0d049362dbe2aa8cf3c8b5aa51d b/src/fuzz/server_corpus/f3b0fb38fefff0d049362dbe2aa8cf3c8b5aa51d
new file mode 100644
index 0000000..56951d2
--- /dev/null
+++ b/src/fuzz/server_corpus/f3b0fb38fefff0d049362dbe2aa8cf3c8b5aa51d
Binary files differ
diff --git a/src/fuzz/server_corpus/f5e8405a64c467bb16890553c654aba3f6946fdb b/src/fuzz/server_corpus/f5e8405a64c467bb16890553c654aba3f6946fdb
deleted file mode 100644
index a895b2e..0000000
--- a/src/fuzz/server_corpus/f5e8405a64c467bb16890553c654aba3f6946fdb
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/fa2e950dee2e2dfb6dfe81e6f47242e9e1f16dc5 b/src/fuzz/server_corpus/fa2e950dee2e2dfb6dfe81e6f47242e9e1f16dc5
new file mode 100644
index 0000000..153c307
--- /dev/null
+++ b/src/fuzz/server_corpus/fa2e950dee2e2dfb6dfe81e6f47242e9e1f16dc5
Binary files differ
diff --git a/src/fuzz/server_corpus/fb28a57faa3ce2cccee6808d14fa807854432467 b/src/fuzz/server_corpus/fb28a57faa3ce2cccee6808d14fa807854432467
deleted file mode 100644
index 491eb4f..0000000
--- a/src/fuzz/server_corpus/fb28a57faa3ce2cccee6808d14fa807854432467
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/fbfbaf58b8f21fe18a1ea1ee20f646f3b004e8b8 b/src/fuzz/server_corpus/fbfbaf58b8f21fe18a1ea1ee20f646f3b004e8b8
deleted file mode 100644
index b372ac5..0000000
--- a/src/fuzz/server_corpus/fbfbaf58b8f21fe18a1ea1ee20f646f3b004e8b8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/fc01f1ace942785f1a03b32c349cca249327e085 b/src/fuzz/server_corpus/fc01f1ace942785f1a03b32c349cca249327e085
deleted file mode 100644
index af1d99a..0000000
--- a/src/fuzz/server_corpus/fc01f1ace942785f1a03b32c349cca249327e085
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus/fcb6fc93b91bc83b5a41ce5a60b15785231bc342 b/src/fuzz/server_corpus/fcb6fc93b91bc83b5a41ce5a60b15785231bc342
new file mode 100644
index 0000000..84513cb
--- /dev/null
+++ b/src/fuzz/server_corpus/fcb6fc93b91bc83b5a41ce5a60b15785231bc342
Binary files differ
diff --git a/src/fuzz/server_corpus/ffc928938510a6704bff891e999acf92572f461b b/src/fuzz/server_corpus/ffc928938510a6704bff891e999acf92572f461b
new file mode 100644
index 0000000..ee2f182
--- /dev/null
+++ b/src/fuzz/server_corpus/ffc928938510a6704bff891e999acf92572f461b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0aaa7bc749620d01823c9e9e5dcb19bca73127fa b/src/fuzz/server_corpus_no_fuzzer_mode/0aaa7bc749620d01823c9e9e5dcb19bca73127fa
deleted file mode 100644
index c056142..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/0aaa7bc749620d01823c9e9e5dcb19bca73127fa
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/10be60167b4ac838e237f1bba9a7d25e512f48a2 b/src/fuzz/server_corpus_no_fuzzer_mode/10be60167b4ac838e237f1bba9a7d25e512f48a2
deleted file mode 100644
index 518ec7b..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/10be60167b4ac838e237f1bba9a7d25e512f48a2
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/11dd22a25a28ab59ad43316a17c4fa8e19ab8bca b/src/fuzz/server_corpus_no_fuzzer_mode/11dd22a25a28ab59ad43316a17c4fa8e19ab8bca
deleted file mode 100644
index a63df2f..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/11dd22a25a28ab59ad43316a17c4fa8e19ab8bca
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/14c57a6336b1fe8a30ccd2149842bc3ed2c11d96 b/src/fuzz/server_corpus_no_fuzzer_mode/14c57a6336b1fe8a30ccd2149842bc3ed2c11d96
deleted file mode 100644
index e5c259a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/14c57a6336b1fe8a30ccd2149842bc3ed2c11d96
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/14ec5669a702b68b29d0af0b4fe33e61a7577202 b/src/fuzz/server_corpus_no_fuzzer_mode/14ec5669a702b68b29d0af0b4fe33e61a7577202
deleted file mode 100644
index 1e2aa42..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/14ec5669a702b68b29d0af0b4fe33e61a7577202
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/179ebb3f16d124fb9338ca7ee488b01a2bcc0376 b/src/fuzz/server_corpus_no_fuzzer_mode/179ebb3f16d124fb9338ca7ee488b01a2bcc0376
deleted file mode 100644
index 7129a14..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/179ebb3f16d124fb9338ca7ee488b01a2bcc0376
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1a07d9c506d55df88ee448f743b7c2451dc3104a b/src/fuzz/server_corpus_no_fuzzer_mode/1a07d9c506d55df88ee448f743b7c2451dc3104a
deleted file mode 100644
index c6f2cf6..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/1a07d9c506d55df88ee448f743b7c2451dc3104a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/26fb7c4907fd86a9a0c9d4561b9db5477ddbde57 b/src/fuzz/server_corpus_no_fuzzer_mode/26fb7c4907fd86a9a0c9d4561b9db5477ddbde57
deleted file mode 100644
index 4af989a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/26fb7c4907fd86a9a0c9d4561b9db5477ddbde57
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/26fd3354a220b1f23c3777a78323bbc4405edb37 b/src/fuzz/server_corpus_no_fuzzer_mode/26fd3354a220b1f23c3777a78323bbc4405edb37
deleted file mode 100644
index 0a8bfe2..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/26fd3354a220b1f23c3777a78323bbc4405edb37
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2741cea11b4ef8ba9d65e97e405fbc22c1590cd7 b/src/fuzz/server_corpus_no_fuzzer_mode/2741cea11b4ef8ba9d65e97e405fbc22c1590cd7
deleted file mode 100644
index 6c20e94..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/2741cea11b4ef8ba9d65e97e405fbc22c1590cd7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/27e4902a8010cbf7d7f2bf1238d6bcb954bff074 b/src/fuzz/server_corpus_no_fuzzer_mode/27e4902a8010cbf7d7f2bf1238d6bcb954bff074
deleted file mode 100644
index 7ee8bb5..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/27e4902a8010cbf7d7f2bf1238d6bcb954bff074
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/28dd36c0a377316c23fbcd4f867de576345c368a b/src/fuzz/server_corpus_no_fuzzer_mode/28dd36c0a377316c23fbcd4f867de576345c368a
deleted file mode 100644
index 0fe94ed..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/28dd36c0a377316c23fbcd4f867de576345c368a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2c34e1e6a14c7e64d50986b3b2bad3e56c7d8c39 b/src/fuzz/server_corpus_no_fuzzer_mode/2c34e1e6a14c7e64d50986b3b2bad3e56c7d8c39
deleted file mode 100644
index 4705059..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/2c34e1e6a14c7e64d50986b3b2bad3e56c7d8c39
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2c7f972a4aabfc19d7c4ca5d5cd7ed7f2ff32009 b/src/fuzz/server_corpus_no_fuzzer_mode/2c7f972a4aabfc19d7c4ca5d5cd7ed7f2ff32009
deleted file mode 100644
index fba5509..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/2c7f972a4aabfc19d7c4ca5d5cd7ed7f2ff32009
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2c93fe561d7e12257551cbc928d6ebb7a40a7e81 b/src/fuzz/server_corpus_no_fuzzer_mode/2c93fe561d7e12257551cbc928d6ebb7a40a7e81
deleted file mode 100644
index c1be7d5..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/2c93fe561d7e12257551cbc928d6ebb7a40a7e81
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/30b0405e3042db2089842bc5935fb0f74aa61ad6 b/src/fuzz/server_corpus_no_fuzzer_mode/30b0405e3042db2089842bc5935fb0f74aa61ad6
deleted file mode 100644
index 4fbf097..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/30b0405e3042db2089842bc5935fb0f74aa61ad6
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/31eaa3d8fe6e5772404f3b5d4310f389346021da b/src/fuzz/server_corpus_no_fuzzer_mode/31eaa3d8fe6e5772404f3b5d4310f389346021da
deleted file mode 100644
index 9938855..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/31eaa3d8fe6e5772404f3b5d4310f389346021da
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/34cb7a9f829dce65bb6dfd1b63c786e9927559b4 b/src/fuzz/server_corpus_no_fuzzer_mode/34cb7a9f829dce65bb6dfd1b63c786e9927559b4
deleted file mode 100644
index 7a13352..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/34cb7a9f829dce65bb6dfd1b63c786e9927559b4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3ad67d3b9b1a566c92915bc6b1ad6f6c0df20bf5 b/src/fuzz/server_corpus_no_fuzzer_mode/3ad67d3b9b1a566c92915bc6b1ad6f6c0df20bf5
deleted file mode 100644
index 215deae..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/3ad67d3b9b1a566c92915bc6b1ad6f6c0df20bf5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/46dac3ed93ba5d03e6d08f905eeefa7e91157ced b/src/fuzz/server_corpus_no_fuzzer_mode/46dac3ed93ba5d03e6d08f905eeefa7e91157ced
deleted file mode 100644
index 7c06cf0..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/46dac3ed93ba5d03e6d08f905eeefa7e91157ced
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/52401e80c09ac328e4ff7aac4c93f484239ee25c b/src/fuzz/server_corpus_no_fuzzer_mode/52401e80c09ac328e4ff7aac4c93f484239ee25c
deleted file mode 100644
index e6eeece..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/52401e80c09ac328e4ff7aac4c93f484239ee25c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/525c87b164fade1e132df1e26d03eeba63039fa9 b/src/fuzz/server_corpus_no_fuzzer_mode/525c87b164fade1e132df1e26d03eeba63039fa9
deleted file mode 100644
index 17258a7..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/525c87b164fade1e132df1e26d03eeba63039fa9
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5715af1004650fae6ec49920cc32b5eb1780f7bc b/src/fuzz/server_corpus_no_fuzzer_mode/5715af1004650fae6ec49920cc32b5eb1780f7bc
deleted file mode 100644
index 01f3cd3..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/5715af1004650fae6ec49920cc32b5eb1780f7bc
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/57c174742566eb238be4955456487502eb4e47d0 b/src/fuzz/server_corpus_no_fuzzer_mode/57c174742566eb238be4955456487502eb4e47d0
deleted file mode 100644
index 6b2a870..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/57c174742566eb238be4955456487502eb4e47d0
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/57dacc1fbd6bc65f5c236a44ebf0445402d5f595 b/src/fuzz/server_corpus_no_fuzzer_mode/57dacc1fbd6bc65f5c236a44ebf0445402d5f595
deleted file mode 100644
index f09faac..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/57dacc1fbd6bc65f5c236a44ebf0445402d5f595
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/597dee9fac708a8ab25dc087b7b3e1033e91ef9f b/src/fuzz/server_corpus_no_fuzzer_mode/597dee9fac708a8ab25dc087b7b3e1033e91ef9f
deleted file mode 100644
index 2c86d21..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/597dee9fac708a8ab25dc087b7b3e1033e91ef9f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5a626a3ee9d907c8e96816195ffcd58035bf8297 b/src/fuzz/server_corpus_no_fuzzer_mode/5a626a3ee9d907c8e96816195ffcd58035bf8297
deleted file mode 100644
index 457573e..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/5a626a3ee9d907c8e96816195ffcd58035bf8297
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5da1c19c98b66dda146e49555d89193bb357aea5 b/src/fuzz/server_corpus_no_fuzzer_mode/5da1c19c98b66dda146e49555d89193bb357aea5
deleted file mode 100644
index 371d0bd..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/5da1c19c98b66dda146e49555d89193bb357aea5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5fd0a6765eee8e3ac16741d43e942489c427550d b/src/fuzz/server_corpus_no_fuzzer_mode/5fd0a6765eee8e3ac16741d43e942489c427550d
deleted file mode 100644
index 873e522..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/5fd0a6765eee8e3ac16741d43e942489c427550d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/62709f5d6c53b7bcb11cd5c9a98bf99daf0533ff b/src/fuzz/server_corpus_no_fuzzer_mode/62709f5d6c53b7bcb11cd5c9a98bf99daf0533ff
deleted file mode 100644
index f897a4b..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/62709f5d6c53b7bcb11cd5c9a98bf99daf0533ff
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/62d145dff485aebbd0e9ab91a193f33390f9bd32 b/src/fuzz/server_corpus_no_fuzzer_mode/62d145dff485aebbd0e9ab91a193f33390f9bd32
deleted file mode 100644
index cdb9c51..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/62d145dff485aebbd0e9ab91a193f33390f9bd32
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/71a68062c2a288672411c719dfe064ef6b527aa1 b/src/fuzz/server_corpus_no_fuzzer_mode/71a68062c2a288672411c719dfe064ef6b527aa1
deleted file mode 100644
index 46022fa..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/71a68062c2a288672411c719dfe064ef6b527aa1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7255fcf5cfb255ba3d91071fce2ece8c1db6290f b/src/fuzz/server_corpus_no_fuzzer_mode/7255fcf5cfb255ba3d91071fce2ece8c1db6290f
deleted file mode 100644
index d18a889..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/7255fcf5cfb255ba3d91071fce2ece8c1db6290f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/836d26bcfdebc4573ab9772cdd267fdea80a7d72 b/src/fuzz/server_corpus_no_fuzzer_mode/836d26bcfdebc4573ab9772cdd267fdea80a7d72
deleted file mode 100644
index 1ae68f3..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/836d26bcfdebc4573ab9772cdd267fdea80a7d72
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/84db07d470de108408623e822ab8a3ac0582f61b b/src/fuzz/server_corpus_no_fuzzer_mode/84db07d470de108408623e822ab8a3ac0582f61b
deleted file mode 100644
index 4a4cb98..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/84db07d470de108408623e822ab8a3ac0582f61b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/84f0de0936cfe1da662effc01a3610c2b34b0bed b/src/fuzz/server_corpus_no_fuzzer_mode/84f0de0936cfe1da662effc01a3610c2b34b0bed
deleted file mode 100644
index 1c7cba3..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/84f0de0936cfe1da662effc01a3610c2b34b0bed
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8b69734df8a377757b0ddab21256ca7bcf8184e7 b/src/fuzz/server_corpus_no_fuzzer_mode/8b69734df8a377757b0ddab21256ca7bcf8184e7
deleted file mode 100644
index e6a3de7..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/8b69734df8a377757b0ddab21256ca7bcf8184e7
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8b70c7e172fcaf65fad4f41bef000bad151bf5a4 b/src/fuzz/server_corpus_no_fuzzer_mode/8b70c7e172fcaf65fad4f41bef000bad151bf5a4
deleted file mode 100644
index 355adb1..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/8b70c7e172fcaf65fad4f41bef000bad151bf5a4
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8e061386f97303e9355245910b475a257109cf23 b/src/fuzz/server_corpus_no_fuzzer_mode/8e061386f97303e9355245910b475a257109cf23
deleted file mode 100644
index 38cb6f1..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/8e061386f97303e9355245910b475a257109cf23
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/969ab1928ae3fc6d8566f8057875872006063413 b/src/fuzz/server_corpus_no_fuzzer_mode/969ab1928ae3fc6d8566f8057875872006063413
deleted file mode 100644
index f78c66d..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/969ab1928ae3fc6d8566f8057875872006063413
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/96c6b411547f3c01cbdac3cc5eb2b0f4fc4c2e7d b/src/fuzz/server_corpus_no_fuzzer_mode/96c6b411547f3c01cbdac3cc5eb2b0f4fc4c2e7d
deleted file mode 100644
index 23fb4d2..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/96c6b411547f3c01cbdac3cc5eb2b0f4fc4c2e7d
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9819d42507b9c48a48e8d0a2e7f77c20c521e4fe b/src/fuzz/server_corpus_no_fuzzer_mode/9819d42507b9c48a48e8d0a2e7f77c20c521e4fe
deleted file mode 100644
index 8848bae..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/9819d42507b9c48a48e8d0a2e7f77c20c521e4fe
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9dd511b02af3bd011a184f7dc9f87ec28aab4b24 b/src/fuzz/server_corpus_no_fuzzer_mode/9dd511b02af3bd011a184f7dc9f87ec28aab4b24
deleted file mode 100644
index 5461d4e..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/9dd511b02af3bd011a184f7dc9f87ec28aab4b24
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9e5e9160291853b6580dadcee0a153e3b9fc581c b/src/fuzz/server_corpus_no_fuzzer_mode/9e5e9160291853b6580dadcee0a153e3b9fc581c
deleted file mode 100644
index 21b3d7f..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/9e5e9160291853b6580dadcee0a153e3b9fc581c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a b/src/fuzz/server_corpus_no_fuzzer_mode/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a
deleted file mode 100644
index 16e8193..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a2a68ce5763ce52f314c351b4b6e0f7491a1b1ef b/src/fuzz/server_corpus_no_fuzzer_mode/a2a68ce5763ce52f314c351b4b6e0f7491a1b1ef
deleted file mode 100644
index 1e7bd8a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/a2a68ce5763ce52f314c351b4b6e0f7491a1b1ef
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a817264a33a681a1ccff2e1343a5fe5bd32a15f6 b/src/fuzz/server_corpus_no_fuzzer_mode/a817264a33a681a1ccff2e1343a5fe5bd32a15f6
deleted file mode 100644
index bf75049..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/a817264a33a681a1ccff2e1343a5fe5bd32a15f6
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/aab46b7c52807d38609b0b96b5cdae2bf928d4e8 b/src/fuzz/server_corpus_no_fuzzer_mode/aab46b7c52807d38609b0b96b5cdae2bf928d4e8
deleted file mode 100644
index a19fd51..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/aab46b7c52807d38609b0b96b5cdae2bf928d4e8
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ac60a4ca03e8927aafd6c040c2384eda237f7f8a b/src/fuzz/server_corpus_no_fuzzer_mode/ac60a4ca03e8927aafd6c040c2384eda237f7f8a
deleted file mode 100644
index fea817a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/ac60a4ca03e8927aafd6c040c2384eda237f7f8a
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/adf26ae8fa42f2533d910e07f59ec60c056172f1 b/src/fuzz/server_corpus_no_fuzzer_mode/adf26ae8fa42f2533d910e07f59ec60c056172f1
deleted file mode 100644
index 794ad17..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/adf26ae8fa42f2533d910e07f59ec60c056172f1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b043d2a513990ff8b3d35ca5b52d37f012509277 b/src/fuzz/server_corpus_no_fuzzer_mode/b043d2a513990ff8b3d35ca5b52d37f012509277
deleted file mode 100644
index e1b15b0..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b043d2a513990ff8b3d35ca5b52d37f012509277
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b2d8e9a49812f3a8d3eee8b96b9d5c7c36c79501 b/src/fuzz/server_corpus_no_fuzzer_mode/b2d8e9a49812f3a8d3eee8b96b9d5c7c36c79501
deleted file mode 100644
index b77da8d6..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b2d8e9a49812f3a8d3eee8b96b9d5c7c36c79501
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b5fe89b6961bd7b4863d131a6a42d0820b04ec38 b/src/fuzz/server_corpus_no_fuzzer_mode/b5fe89b6961bd7b4863d131a6a42d0820b04ec38
deleted file mode 100644
index 6eb5767..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b5fe89b6961bd7b4863d131a6a42d0820b04ec38
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b6485e7a666843db742b42045804336195bdc59e b/src/fuzz/server_corpus_no_fuzzer_mode/b6485e7a666843db742b42045804336195bdc59e
deleted file mode 100644
index 2af4819..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b6485e7a666843db742b42045804336195bdc59e
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b65c75355b17e615db239f15c34a9da20feb0a65 b/src/fuzz/server_corpus_no_fuzzer_mode/b65c75355b17e615db239f15c34a9da20feb0a65
deleted file mode 100644
index ca231c8..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b65c75355b17e615db239f15c34a9da20feb0a65
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b6f879bf9ff09f31f138368036b9e2d357327f4f b/src/fuzz/server_corpus_no_fuzzer_mode/b6f879bf9ff09f31f138368036b9e2d357327f4f
deleted file mode 100644
index ae4d6db..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/b6f879bf9ff09f31f138368036b9e2d357327f4f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/beb7ac161af3ea5d739e54f40d2f6bb08e71fa29 b/src/fuzz/server_corpus_no_fuzzer_mode/beb7ac161af3ea5d739e54f40d2f6bb08e71fa29
deleted file mode 100644
index f4bf56a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/beb7ac161af3ea5d739e54f40d2f6bb08e71fa29
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c38478b0b6bd4d7bcfd9783afe020a8750e6e36f b/src/fuzz/server_corpus_no_fuzzer_mode/c38478b0b6bd4d7bcfd9783afe020a8750e6e36f
deleted file mode 100644
index b7cd983..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/c38478b0b6bd4d7bcfd9783afe020a8750e6e36f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c40f822fff3902d4f6361cb1636e2054d7e09611 b/src/fuzz/server_corpus_no_fuzzer_mode/c40f822fff3902d4f6361cb1636e2054d7e09611
deleted file mode 100644
index 4692f70..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/c40f822fff3902d4f6361cb1636e2054d7e09611
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c57c035dea7729c87193c0390bc33391cf26bd5c b/src/fuzz/server_corpus_no_fuzzer_mode/c57c035dea7729c87193c0390bc33391cf26bd5c
deleted file mode 100644
index 9a65f88..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/c57c035dea7729c87193c0390bc33391cf26bd5c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c9cdc0380defaf3a5d27af8dec90e61fb3b2d582 b/src/fuzz/server_corpus_no_fuzzer_mode/c9cdc0380defaf3a5d27af8dec90e61fb3b2d582
deleted file mode 100644
index 7875f7a..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/c9cdc0380defaf3a5d27af8dec90e61fb3b2d582
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cb06afac80a6b9dfd82b3d169f409fe8ef364765 b/src/fuzz/server_corpus_no_fuzzer_mode/cb06afac80a6b9dfd82b3d169f409fe8ef364765
deleted file mode 100644
index 0d46a8c..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/cb06afac80a6b9dfd82b3d169f409fe8ef364765
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cb6fd663240ac5776442e08b3709a14c0cba41c5 b/src/fuzz/server_corpus_no_fuzzer_mode/cb6fd663240ac5776442e08b3709a14c0cba41c5
deleted file mode 100644
index ddc6f0e..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/cb6fd663240ac5776442e08b3709a14c0cba41c5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d1b3efd7d1abab95e7b935b85963c91d20a8f75f b/src/fuzz/server_corpus_no_fuzzer_mode/d1b3efd7d1abab95e7b935b85963c91d20a8f75f
deleted file mode 100644
index fb7f3f8..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/d1b3efd7d1abab95e7b935b85963c91d20a8f75f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d78073e1735f4b632986c6bd9d17e2c87f2011b5 b/src/fuzz/server_corpus_no_fuzzer_mode/d78073e1735f4b632986c6bd9d17e2c87f2011b5
deleted file mode 100644
index 3f425d1..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/d78073e1735f4b632986c6bd9d17e2c87f2011b5
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/de5791761d6bbc9c595373a484947b1bf5f3120f b/src/fuzz/server_corpus_no_fuzzer_mode/de5791761d6bbc9c595373a484947b1bf5f3120f
deleted file mode 100644
index 20995eb..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/de5791761d6bbc9c595373a484947b1bf5f3120f
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e5cb3ea7ebe0ae1c6bc2f7cc165ba326b0598bd1 b/src/fuzz/server_corpus_no_fuzzer_mode/e5cb3ea7ebe0ae1c6bc2f7cc165ba326b0598bd1
deleted file mode 100644
index 3206df9..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/e5cb3ea7ebe0ae1c6bc2f7cc165ba326b0598bd1
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e6a24bd5fe36bfbd21dbd34388090f97997b4c42 b/src/fuzz/server_corpus_no_fuzzer_mode/e6a24bd5fe36bfbd21dbd34388090f97997b4c42
deleted file mode 100644
index 7468760..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/e6a24bd5fe36bfbd21dbd34388090f97997b4c42
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e8992d0eeeb13c4001b460db1217819bfd678ef0 b/src/fuzz/server_corpus_no_fuzzer_mode/e8992d0eeeb13c4001b460db1217819bfd678ef0
deleted file mode 100644
index 8bbcfa8..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/e8992d0eeeb13c4001b460db1217819bfd678ef0
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ecd9d4fe7da648ad26d5383c75e60a2dba8c39cf b/src/fuzz/server_corpus_no_fuzzer_mode/ecd9d4fe7da648ad26d5383c75e60a2dba8c39cf
deleted file mode 100644
index b056993..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/ecd9d4fe7da648ad26d5383c75e60a2dba8c39cf
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ed80228ea25f1e452417ade7b465ab2165fb1378 b/src/fuzz/server_corpus_no_fuzzer_mode/ed80228ea25f1e452417ade7b465ab2165fb1378
deleted file mode 100644
index 213ec27..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/ed80228ea25f1e452417ade7b465ab2165fb1378
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/efa1a25f1fdc8df35956bb7c68861d0480d4cc6c b/src/fuzz/server_corpus_no_fuzzer_mode/efa1a25f1fdc8df35956bb7c68861d0480d4cc6c
deleted file mode 100644
index a31027d..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/efa1a25f1fdc8df35956bb7c68861d0480d4cc6c
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f9efc3b72aa68f4dbd59212dd5d7c7906507ef11 b/src/fuzz/server_corpus_no_fuzzer_mode/f9efc3b72aa68f4dbd59212dd5d7c7906507ef11
deleted file mode 100644
index 43d4bc9..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/f9efc3b72aa68f4dbd59212dd5d7c7906507ef11
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f9f6b53bebe6b57557c971f098f2cc33c2c7955b b/src/fuzz/server_corpus_no_fuzzer_mode/f9f6b53bebe6b57557c971f098f2cc33c2c7955b
deleted file mode 100644
index 16a59a4..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/f9f6b53bebe6b57557c971f098f2cc33c2c7955b
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fe164ba4b42f210df1e740f3440cd99520a08042 b/src/fuzz/server_corpus_no_fuzzer_mode/fe164ba4b42f210df1e740f3440cd99520a08042
deleted file mode 100644
index ece6650..0000000
--- a/src/fuzz/server_corpus_no_fuzzer_mode/fe164ba4b42f210df1e740f3440cd99520a08042
+++ /dev/null
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode.cc b/src/fuzz/server_no_fuzzer_mode.cc
new file mode 100644
index 0000000..9944e4d
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "../ssl/test/fuzzer.h"
+
+
+static TLSFuzzer g_fuzzer(TLSFuzzer::kTLS, TLSFuzzer::kServer,
+                          TLSFuzzer::kFuzzerModeOff);
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
+  return g_fuzzer.TestOneInput(buf, len);
+}
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/004fa174d6a55815aaa28a643663e4f7defe17b7 b/src/fuzz/server_no_fuzzer_mode_corpus/004fa174d6a55815aaa28a643663e4f7defe17b7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/004fa174d6a55815aaa28a643663e4f7defe17b7
rename to src/fuzz/server_no_fuzzer_mode_corpus/004fa174d6a55815aaa28a643663e4f7defe17b7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/00a5d300edb498ed6ad6c6e1d89542aab9a02b22 b/src/fuzz/server_no_fuzzer_mode_corpus/00a5d300edb498ed6ad6c6e1d89542aab9a02b22
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/00a5d300edb498ed6ad6c6e1d89542aab9a02b22
rename to src/fuzz/server_no_fuzzer_mode_corpus/00a5d300edb498ed6ad6c6e1d89542aab9a02b22
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/00d25fd7ea0f58eb6f4a82c851ed8a931e65dd64 b/src/fuzz/server_no_fuzzer_mode_corpus/00d25fd7ea0f58eb6f4a82c851ed8a931e65dd64
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/00d25fd7ea0f58eb6f4a82c851ed8a931e65dd64
rename to src/fuzz/server_no_fuzzer_mode_corpus/00d25fd7ea0f58eb6f4a82c851ed8a931e65dd64
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0102298d15e9282866a5f2260302eff322a13c13 b/src/fuzz/server_no_fuzzer_mode_corpus/0102298d15e9282866a5f2260302eff322a13c13
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0102298d15e9282866a5f2260302eff322a13c13
rename to src/fuzz/server_no_fuzzer_mode_corpus/0102298d15e9282866a5f2260302eff322a13c13
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/01e0cbccb0834c995ec281f2cef6bc2a74d58ad4 b/src/fuzz/server_no_fuzzer_mode_corpus/01e0cbccb0834c995ec281f2cef6bc2a74d58ad4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/01e0cbccb0834c995ec281f2cef6bc2a74d58ad4
rename to src/fuzz/server_no_fuzzer_mode_corpus/01e0cbccb0834c995ec281f2cef6bc2a74d58ad4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0204408e62b9b167d6ccf405f42a7d7b3ac8df45 b/src/fuzz/server_no_fuzzer_mode_corpus/0204408e62b9b167d6ccf405f42a7d7b3ac8df45
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0204408e62b9b167d6ccf405f42a7d7b3ac8df45
rename to src/fuzz/server_no_fuzzer_mode_corpus/0204408e62b9b167d6ccf405f42a7d7b3ac8df45
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/023f6ec7de2d391c3a5df308362bf03c343b5c4a b/src/fuzz/server_no_fuzzer_mode_corpus/023f6ec7de2d391c3a5df308362bf03c343b5c4a
new file mode 100644
index 0000000..ac19fe2
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/023f6ec7de2d391c3a5df308362bf03c343b5c4a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/03225608b841a3768e061337c015e55514ed439a b/src/fuzz/server_no_fuzzer_mode_corpus/03225608b841a3768e061337c015e55514ed439a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/03225608b841a3768e061337c015e55514ed439a
rename to src/fuzz/server_no_fuzzer_mode_corpus/03225608b841a3768e061337c015e55514ed439a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/035f22634e63cc269a411f33ccd2fa73b8509ece b/src/fuzz/server_no_fuzzer_mode_corpus/035f22634e63cc269a411f33ccd2fa73b8509ece
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/035f22634e63cc269a411f33ccd2fa73b8509ece
rename to src/fuzz/server_no_fuzzer_mode_corpus/035f22634e63cc269a411f33ccd2fa73b8509ece
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/03d8a3c5c91cee6f44ecf79c6b7729a9680a0489 b/src/fuzz/server_no_fuzzer_mode_corpus/03d8a3c5c91cee6f44ecf79c6b7729a9680a0489
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/03d8a3c5c91cee6f44ecf79c6b7729a9680a0489
rename to src/fuzz/server_no_fuzzer_mode_corpus/03d8a3c5c91cee6f44ecf79c6b7729a9680a0489
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/040be56e0312f0675b002650988abb8733779d4c b/src/fuzz/server_no_fuzzer_mode_corpus/040be56e0312f0675b002650988abb8733779d4c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/040be56e0312f0675b002650988abb8733779d4c
rename to src/fuzz/server_no_fuzzer_mode_corpus/040be56e0312f0675b002650988abb8733779d4c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/041fd0d839026e1b1c71e9e6e45ae3442495edf8 b/src/fuzz/server_no_fuzzer_mode_corpus/041fd0d839026e1b1c71e9e6e45ae3442495edf8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/041fd0d839026e1b1c71e9e6e45ae3442495edf8
rename to src/fuzz/server_no_fuzzer_mode_corpus/041fd0d839026e1b1c71e9e6e45ae3442495edf8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/04c5c81fba6070627d1635396370059b02afc975 b/src/fuzz/server_no_fuzzer_mode_corpus/04c5c81fba6070627d1635396370059b02afc975
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/04c5c81fba6070627d1635396370059b02afc975
rename to src/fuzz/server_no_fuzzer_mode_corpus/04c5c81fba6070627d1635396370059b02afc975
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/06201bff91e6af9e6acabe82dfcd2ff7f3e39186 b/src/fuzz/server_no_fuzzer_mode_corpus/06201bff91e6af9e6acabe82dfcd2ff7f3e39186
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/06201bff91e6af9e6acabe82dfcd2ff7f3e39186
rename to src/fuzz/server_no_fuzzer_mode_corpus/06201bff91e6af9e6acabe82dfcd2ff7f3e39186
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/063057c4179560dbf246978e5721d226fe2bacf8 b/src/fuzz/server_no_fuzzer_mode_corpus/063057c4179560dbf246978e5721d226fe2bacf8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/063057c4179560dbf246978e5721d226fe2bacf8
rename to src/fuzz/server_no_fuzzer_mode_corpus/063057c4179560dbf246978e5721d226fe2bacf8
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/06a0473104336191d845d5147a96c18e7188851f b/src/fuzz/server_no_fuzzer_mode_corpus/06a0473104336191d845d5147a96c18e7188851f
new file mode 100644
index 0000000..8765cee
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/06a0473104336191d845d5147a96c18e7188851f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/074c9a9417a8abed82ecc1b4d3cbdd3b32a45b9b b/src/fuzz/server_no_fuzzer_mode_corpus/074c9a9417a8abed82ecc1b4d3cbdd3b32a45b9b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/074c9a9417a8abed82ecc1b4d3cbdd3b32a45b9b
rename to src/fuzz/server_no_fuzzer_mode_corpus/074c9a9417a8abed82ecc1b4d3cbdd3b32a45b9b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/079bbcaa8d43e42750d6ced26e9d67a594d38386 b/src/fuzz/server_no_fuzzer_mode_corpus/079bbcaa8d43e42750d6ced26e9d67a594d38386
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/079bbcaa8d43e42750d6ced26e9d67a594d38386
rename to src/fuzz/server_no_fuzzer_mode_corpus/079bbcaa8d43e42750d6ced26e9d67a594d38386
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/07a9b5a6f0e6ab3b32ddafa7d6afa062a170b590 b/src/fuzz/server_no_fuzzer_mode_corpus/07a9b5a6f0e6ab3b32ddafa7d6afa062a170b590
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/07a9b5a6f0e6ab3b32ddafa7d6afa062a170b590
rename to src/fuzz/server_no_fuzzer_mode_corpus/07a9b5a6f0e6ab3b32ddafa7d6afa062a170b590
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/07d5b3bcdcd13284acbbdc30e6052d9317c84ff5 b/src/fuzz/server_no_fuzzer_mode_corpus/07d5b3bcdcd13284acbbdc30e6052d9317c84ff5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/07d5b3bcdcd13284acbbdc30e6052d9317c84ff5
rename to src/fuzz/server_no_fuzzer_mode_corpus/07d5b3bcdcd13284acbbdc30e6052d9317c84ff5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0845b7db11759cb6e1b42e4454c76526e39f6055 b/src/fuzz/server_no_fuzzer_mode_corpus/0845b7db11759cb6e1b42e4454c76526e39f6055
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0845b7db11759cb6e1b42e4454c76526e39f6055
rename to src/fuzz/server_no_fuzzer_mode_corpus/0845b7db11759cb6e1b42e4454c76526e39f6055
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/090318ebc9cf1da627cb9bbd06364a63b0c3c860 b/src/fuzz/server_no_fuzzer_mode_corpus/090318ebc9cf1da627cb9bbd06364a63b0c3c860
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/090318ebc9cf1da627cb9bbd06364a63b0c3c860
rename to src/fuzz/server_no_fuzzer_mode_corpus/090318ebc9cf1da627cb9bbd06364a63b0c3c860
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0a1fa52ace56fa15987bea607bcfc5b1036ba8e6 b/src/fuzz/server_no_fuzzer_mode_corpus/0a1fa52ace56fa15987bea607bcfc5b1036ba8e6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0a1fa52ace56fa15987bea607bcfc5b1036ba8e6
rename to src/fuzz/server_no_fuzzer_mode_corpus/0a1fa52ace56fa15987bea607bcfc5b1036ba8e6
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/0a29785fc7793363905fd9dc5b68db5a8563159a b/src/fuzz/server_no_fuzzer_mode_corpus/0a29785fc7793363905fd9dc5b68db5a8563159a
new file mode 100644
index 0000000..e20ea48
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/0a29785fc7793363905fd9dc5b68db5a8563159a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0ad14ebc9369516f1887c9610a0a5bee991603ea b/src/fuzz/server_no_fuzzer_mode_corpus/0ad14ebc9369516f1887c9610a0a5bee991603ea
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0ad14ebc9369516f1887c9610a0a5bee991603ea
rename to src/fuzz/server_no_fuzzer_mode_corpus/0ad14ebc9369516f1887c9610a0a5bee991603ea
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0b7d4daa747ce6d4e04090076ed2592f33cca1f9 b/src/fuzz/server_no_fuzzer_mode_corpus/0b7d4daa747ce6d4e04090076ed2592f33cca1f9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0b7d4daa747ce6d4e04090076ed2592f33cca1f9
rename to src/fuzz/server_no_fuzzer_mode_corpus/0b7d4daa747ce6d4e04090076ed2592f33cca1f9
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/0bef2cd9e280962d885ef79be5f9d6b2677ced20 b/src/fuzz/server_no_fuzzer_mode_corpus/0bef2cd9e280962d885ef79be5f9d6b2677ced20
new file mode 100644
index 0000000..961ada4
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/0bef2cd9e280962d885ef79be5f9d6b2677ced20
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0d3467650586d68ce881887c569b9beb26d57c48 b/src/fuzz/server_no_fuzzer_mode_corpus/0d3467650586d68ce881887c569b9beb26d57c48
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0d3467650586d68ce881887c569b9beb26d57c48
rename to src/fuzz/server_no_fuzzer_mode_corpus/0d3467650586d68ce881887c569b9beb26d57c48
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0dc21f7863914bf167cd2d79d42c1c7e425deb5d b/src/fuzz/server_no_fuzzer_mode_corpus/0dc21f7863914bf167cd2d79d42c1c7e425deb5d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0dc21f7863914bf167cd2d79d42c1c7e425deb5d
rename to src/fuzz/server_no_fuzzer_mode_corpus/0dc21f7863914bf167cd2d79d42c1c7e425deb5d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0dda9ab2464b2c919969510c6f9c6c67cce3a08a b/src/fuzz/server_no_fuzzer_mode_corpus/0dda9ab2464b2c919969510c6f9c6c67cce3a08a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0dda9ab2464b2c919969510c6f9c6c67cce3a08a
rename to src/fuzz/server_no_fuzzer_mode_corpus/0dda9ab2464b2c919969510c6f9c6c67cce3a08a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0df0ecc9f0e1976dccc8101c324c3e0078ad6e0a b/src/fuzz/server_no_fuzzer_mode_corpus/0df0ecc9f0e1976dccc8101c324c3e0078ad6e0a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0df0ecc9f0e1976dccc8101c324c3e0078ad6e0a
rename to src/fuzz/server_no_fuzzer_mode_corpus/0df0ecc9f0e1976dccc8101c324c3e0078ad6e0a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0e70573c236286a5ddc0353b749f94ff11860c73 b/src/fuzz/server_no_fuzzer_mode_corpus/0e70573c236286a5ddc0353b749f94ff11860c73
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0e70573c236286a5ddc0353b749f94ff11860c73
rename to src/fuzz/server_no_fuzzer_mode_corpus/0e70573c236286a5ddc0353b749f94ff11860c73
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0eea88830d13a4081c0048c5bcee0519446792b3 b/src/fuzz/server_no_fuzzer_mode_corpus/0eea88830d13a4081c0048c5bcee0519446792b3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0eea88830d13a4081c0048c5bcee0519446792b3
rename to src/fuzz/server_no_fuzzer_mode_corpus/0eea88830d13a4081c0048c5bcee0519446792b3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/0fc0d891f2b05996e455fad7f8b1931dd93f3d17 b/src/fuzz/server_no_fuzzer_mode_corpus/0fc0d891f2b05996e455fad7f8b1931dd93f3d17
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/0fc0d891f2b05996e455fad7f8b1931dd93f3d17
rename to src/fuzz/server_no_fuzzer_mode_corpus/0fc0d891f2b05996e455fad7f8b1931dd93f3d17
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/10bda1aaab9f5500a831b5311d55e4a6fb5b22af b/src/fuzz/server_no_fuzzer_mode_corpus/10bda1aaab9f5500a831b5311d55e4a6fb5b22af
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/10bda1aaab9f5500a831b5311d55e4a6fb5b22af
rename to src/fuzz/server_no_fuzzer_mode_corpus/10bda1aaab9f5500a831b5311d55e4a6fb5b22af
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/10c246224654166896d7802847d2781109aa6730 b/src/fuzz/server_no_fuzzer_mode_corpus/10c246224654166896d7802847d2781109aa6730
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/10c246224654166896d7802847d2781109aa6730
rename to src/fuzz/server_no_fuzzer_mode_corpus/10c246224654166896d7802847d2781109aa6730
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/119c3806868a614658090de3963276aec44b64c0 b/src/fuzz/server_no_fuzzer_mode_corpus/119c3806868a614658090de3963276aec44b64c0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/119c3806868a614658090de3963276aec44b64c0
rename to src/fuzz/server_no_fuzzer_mode_corpus/119c3806868a614658090de3963276aec44b64c0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/11c91d3aa29f06d800aacbf6a388d3c02a666ff4 b/src/fuzz/server_no_fuzzer_mode_corpus/11c91d3aa29f06d800aacbf6a388d3c02a666ff4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/11c91d3aa29f06d800aacbf6a388d3c02a666ff4
rename to src/fuzz/server_no_fuzzer_mode_corpus/11c91d3aa29f06d800aacbf6a388d3c02a666ff4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/12201bf41e3ab5f51e3645469cabf1e82758b488 b/src/fuzz/server_no_fuzzer_mode_corpus/12201bf41e3ab5f51e3645469cabf1e82758b488
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/12201bf41e3ab5f51e3645469cabf1e82758b488
rename to src/fuzz/server_no_fuzzer_mode_corpus/12201bf41e3ab5f51e3645469cabf1e82758b488
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/12286b7d2caa026577cad2ac90b001663ce79730 b/src/fuzz/server_no_fuzzer_mode_corpus/12286b7d2caa026577cad2ac90b001663ce79730
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/12286b7d2caa026577cad2ac90b001663ce79730
rename to src/fuzz/server_no_fuzzer_mode_corpus/12286b7d2caa026577cad2ac90b001663ce79730
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1269bc0ff52e5b0c7478ddeae0654280c837041c b/src/fuzz/server_no_fuzzer_mode_corpus/1269bc0ff52e5b0c7478ddeae0654280c837041c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1269bc0ff52e5b0c7478ddeae0654280c837041c
rename to src/fuzz/server_no_fuzzer_mode_corpus/1269bc0ff52e5b0c7478ddeae0654280c837041c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/12c4a4c3a7c0e9702fb69a15b1a21bfddc33d57b b/src/fuzz/server_no_fuzzer_mode_corpus/12c4a4c3a7c0e9702fb69a15b1a21bfddc33d57b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/12c4a4c3a7c0e9702fb69a15b1a21bfddc33d57b
rename to src/fuzz/server_no_fuzzer_mode_corpus/12c4a4c3a7c0e9702fb69a15b1a21bfddc33d57b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/12d6352ace21a4bddc93e04b4befc9fa456667c2 b/src/fuzz/server_no_fuzzer_mode_corpus/12d6352ace21a4bddc93e04b4befc9fa456667c2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/12d6352ace21a4bddc93e04b4befc9fa456667c2
rename to src/fuzz/server_no_fuzzer_mode_corpus/12d6352ace21a4bddc93e04b4befc9fa456667c2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/13046cba999eb24ca290d3a51ece837488502d67 b/src/fuzz/server_no_fuzzer_mode_corpus/13046cba999eb24ca290d3a51ece837488502d67
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/13046cba999eb24ca290d3a51ece837488502d67
rename to src/fuzz/server_no_fuzzer_mode_corpus/13046cba999eb24ca290d3a51ece837488502d67
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1314921c35bcf2033155d3091e5bf87fdd7e2423 b/src/fuzz/server_no_fuzzer_mode_corpus/1314921c35bcf2033155d3091e5bf87fdd7e2423
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1314921c35bcf2033155d3091e5bf87fdd7e2423
rename to src/fuzz/server_no_fuzzer_mode_corpus/1314921c35bcf2033155d3091e5bf87fdd7e2423
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/13704026841a0d07225402f780f3a6465aaebea8 b/src/fuzz/server_no_fuzzer_mode_corpus/13704026841a0d07225402f780f3a6465aaebea8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/13704026841a0d07225402f780f3a6465aaebea8
rename to src/fuzz/server_no_fuzzer_mode_corpus/13704026841a0d07225402f780f3a6465aaebea8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/138679e5a423adcb8c6be1ef9d34166465c25f72 b/src/fuzz/server_no_fuzzer_mode_corpus/138679e5a423adcb8c6be1ef9d34166465c25f72
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/138679e5a423adcb8c6be1ef9d34166465c25f72
rename to src/fuzz/server_no_fuzzer_mode_corpus/138679e5a423adcb8c6be1ef9d34166465c25f72
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/13b2490d5da9d5a43a2162008004ac290e629bec b/src/fuzz/server_no_fuzzer_mode_corpus/13b2490d5da9d5a43a2162008004ac290e629bec
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/13b2490d5da9d5a43a2162008004ac290e629bec
rename to src/fuzz/server_no_fuzzer_mode_corpus/13b2490d5da9d5a43a2162008004ac290e629bec
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/14209811578c32a959299259a2090f012e4881d9 b/src/fuzz/server_no_fuzzer_mode_corpus/14209811578c32a959299259a2090f012e4881d9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/14209811578c32a959299259a2090f012e4881d9
rename to src/fuzz/server_no_fuzzer_mode_corpus/14209811578c32a959299259a2090f012e4881d9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1489f923c4dca729178b3e3233458550d8dddf29 b/src/fuzz/server_no_fuzzer_mode_corpus/1489f923c4dca729178b3e3233458550d8dddf29
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1489f923c4dca729178b3e3233458550d8dddf29
rename to src/fuzz/server_no_fuzzer_mode_corpus/1489f923c4dca729178b3e3233458550d8dddf29
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/15225c241c1c56fc666cd8e52ae9c666f6bc0e60 b/src/fuzz/server_no_fuzzer_mode_corpus/15225c241c1c56fc666cd8e52ae9c666f6bc0e60
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/15225c241c1c56fc666cd8e52ae9c666f6bc0e60
rename to src/fuzz/server_no_fuzzer_mode_corpus/15225c241c1c56fc666cd8e52ae9c666f6bc0e60
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1573211bae710105a5ec8007eb30165361674477 b/src/fuzz/server_no_fuzzer_mode_corpus/1573211bae710105a5ec8007eb30165361674477
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1573211bae710105a5ec8007eb30165361674477
rename to src/fuzz/server_no_fuzzer_mode_corpus/1573211bae710105a5ec8007eb30165361674477
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/15dc111ac3f4ef92733d50415fcae488bc3d0c7c b/src/fuzz/server_no_fuzzer_mode_corpus/15dc111ac3f4ef92733d50415fcae488bc3d0c7c
new file mode 100644
index 0000000..012e674
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/15dc111ac3f4ef92733d50415fcae488bc3d0c7c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/164c004717340af31817d65e90c5bb57e717abbc b/src/fuzz/server_no_fuzzer_mode_corpus/164c004717340af31817d65e90c5bb57e717abbc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/164c004717340af31817d65e90c5bb57e717abbc
rename to src/fuzz/server_no_fuzzer_mode_corpus/164c004717340af31817d65e90c5bb57e717abbc
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1693b2794e49f4bf5ae68f4993fb3dbe13082e76 b/src/fuzz/server_no_fuzzer_mode_corpus/1693b2794e49f4bf5ae68f4993fb3dbe13082e76
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1693b2794e49f4bf5ae68f4993fb3dbe13082e76
rename to src/fuzz/server_no_fuzzer_mode_corpus/1693b2794e49f4bf5ae68f4993fb3dbe13082e76
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1696b64a30ff9f652f70b6853114b6a4d9495d92 b/src/fuzz/server_no_fuzzer_mode_corpus/1696b64a30ff9f652f70b6853114b6a4d9495d92
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1696b64a30ff9f652f70b6853114b6a4d9495d92
rename to src/fuzz/server_no_fuzzer_mode_corpus/1696b64a30ff9f652f70b6853114b6a4d9495d92
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/17a11f55cc31839a468c5ce54c5fdd6df65daa4c b/src/fuzz/server_no_fuzzer_mode_corpus/17a11f55cc31839a468c5ce54c5fdd6df65daa4c
new file mode 100644
index 0000000..ca81b3e
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/17a11f55cc31839a468c5ce54c5fdd6df65daa4c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/18372eeeba5efd2ad8d36bf84ae8feec4d5fbba4 b/src/fuzz/server_no_fuzzer_mode_corpus/18372eeeba5efd2ad8d36bf84ae8feec4d5fbba4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/18372eeeba5efd2ad8d36bf84ae8feec4d5fbba4
rename to src/fuzz/server_no_fuzzer_mode_corpus/18372eeeba5efd2ad8d36bf84ae8feec4d5fbba4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/195ecb2a6b9f63fdc8fa84dc8b1c3abb67ef3fa6 b/src/fuzz/server_no_fuzzer_mode_corpus/195ecb2a6b9f63fdc8fa84dc8b1c3abb67ef3fa6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/195ecb2a6b9f63fdc8fa84dc8b1c3abb67ef3fa6
rename to src/fuzz/server_no_fuzzer_mode_corpus/195ecb2a6b9f63fdc8fa84dc8b1c3abb67ef3fa6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1a6b0a34883df3fe0fc342275ad60e3edd67fc3d b/src/fuzz/server_no_fuzzer_mode_corpus/1a6b0a34883df3fe0fc342275ad60e3edd67fc3d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1a6b0a34883df3fe0fc342275ad60e3edd67fc3d
rename to src/fuzz/server_no_fuzzer_mode_corpus/1a6b0a34883df3fe0fc342275ad60e3edd67fc3d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1b924c2a6ed3315c60e7f70bc3c3a272ea3411c3 b/src/fuzz/server_no_fuzzer_mode_corpus/1b924c2a6ed3315c60e7f70bc3c3a272ea3411c3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1b924c2a6ed3315c60e7f70bc3c3a272ea3411c3
rename to src/fuzz/server_no_fuzzer_mode_corpus/1b924c2a6ed3315c60e7f70bc3c3a272ea3411c3
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/1bd4feee0785eef8ff1e8c70882af1cf46b8945f b/src/fuzz/server_no_fuzzer_mode_corpus/1bd4feee0785eef8ff1e8c70882af1cf46b8945f
new file mode 100644
index 0000000..cf8de08
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/1bd4feee0785eef8ff1e8c70882af1cf46b8945f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1be74a4b3069487d2ab4e3fc38582d13fbfc6982 b/src/fuzz/server_no_fuzzer_mode_corpus/1be74a4b3069487d2ab4e3fc38582d13fbfc6982
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1be74a4b3069487d2ab4e3fc38582d13fbfc6982
rename to src/fuzz/server_no_fuzzer_mode_corpus/1be74a4b3069487d2ab4e3fc38582d13fbfc6982
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1c634714f8a6359cc53f1bc1c7a1348f39b2f9ea b/src/fuzz/server_no_fuzzer_mode_corpus/1c634714f8a6359cc53f1bc1c7a1348f39b2f9ea
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1c634714f8a6359cc53f1bc1c7a1348f39b2f9ea
rename to src/fuzz/server_no_fuzzer_mode_corpus/1c634714f8a6359cc53f1bc1c7a1348f39b2f9ea
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1d42ff3a79a609bb91813f06b2a8b4d91afe54a7 b/src/fuzz/server_no_fuzzer_mode_corpus/1d42ff3a79a609bb91813f06b2a8b4d91afe54a7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1d42ff3a79a609bb91813f06b2a8b4d91afe54a7
rename to src/fuzz/server_no_fuzzer_mode_corpus/1d42ff3a79a609bb91813f06b2a8b4d91afe54a7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1d66bf16a89f32b85fefe906753d2f23b0fda8f9 b/src/fuzz/server_no_fuzzer_mode_corpus/1d66bf16a89f32b85fefe906753d2f23b0fda8f9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1d66bf16a89f32b85fefe906753d2f23b0fda8f9
rename to src/fuzz/server_no_fuzzer_mode_corpus/1d66bf16a89f32b85fefe906753d2f23b0fda8f9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1d92c060ea2a91d536c9ed016314f20fa2411788 b/src/fuzz/server_no_fuzzer_mode_corpus/1d92c060ea2a91d536c9ed016314f20fa2411788
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1d92c060ea2a91d536c9ed016314f20fa2411788
rename to src/fuzz/server_no_fuzzer_mode_corpus/1d92c060ea2a91d536c9ed016314f20fa2411788
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1e74eaa6f82c33ede12903604d1c018ae2ec7b67 b/src/fuzz/server_no_fuzzer_mode_corpus/1e74eaa6f82c33ede12903604d1c018ae2ec7b67
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1e74eaa6f82c33ede12903604d1c018ae2ec7b67
rename to src/fuzz/server_no_fuzzer_mode_corpus/1e74eaa6f82c33ede12903604d1c018ae2ec7b67
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/1f04d58e13c50cbdbb989781c4154d021b2437af b/src/fuzz/server_no_fuzzer_mode_corpus/1f04d58e13c50cbdbb989781c4154d021b2437af
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/1f04d58e13c50cbdbb989781c4154d021b2437af
rename to src/fuzz/server_no_fuzzer_mode_corpus/1f04d58e13c50cbdbb989781c4154d021b2437af
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2003175cdfd0c765027642e4cbacf6fdc4002154 b/src/fuzz/server_no_fuzzer_mode_corpus/2003175cdfd0c765027642e4cbacf6fdc4002154
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2003175cdfd0c765027642e4cbacf6fdc4002154
rename to src/fuzz/server_no_fuzzer_mode_corpus/2003175cdfd0c765027642e4cbacf6fdc4002154
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/20c101d0d759880be159128d7a652751648d3338 b/src/fuzz/server_no_fuzzer_mode_corpus/20c101d0d759880be159128d7a652751648d3338
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/20c101d0d759880be159128d7a652751648d3338
rename to src/fuzz/server_no_fuzzer_mode_corpus/20c101d0d759880be159128d7a652751648d3338
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2134e034dafd716f2f416313abcb9f3f7ea858e9 b/src/fuzz/server_no_fuzzer_mode_corpus/2134e034dafd716f2f416313abcb9f3f7ea858e9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2134e034dafd716f2f416313abcb9f3f7ea858e9
rename to src/fuzz/server_no_fuzzer_mode_corpus/2134e034dafd716f2f416313abcb9f3f7ea858e9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/21e95c8e2790d9bffec74e4a0d8f94d989e2589d b/src/fuzz/server_no_fuzzer_mode_corpus/21e95c8e2790d9bffec74e4a0d8f94d989e2589d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/21e95c8e2790d9bffec74e4a0d8f94d989e2589d
rename to src/fuzz/server_no_fuzzer_mode_corpus/21e95c8e2790d9bffec74e4a0d8f94d989e2589d
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/2250f8e04cc212126b2df3bac6ed84293e83715a b/src/fuzz/server_no_fuzzer_mode_corpus/2250f8e04cc212126b2df3bac6ed84293e83715a
new file mode 100644
index 0000000..72b488b
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/2250f8e04cc212126b2df3bac6ed84293e83715a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2282590f86aa9e6346694931c88ab0427efc255a b/src/fuzz/server_no_fuzzer_mode_corpus/2282590f86aa9e6346694931c88ab0427efc255a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2282590f86aa9e6346694931c88ab0427efc255a
rename to src/fuzz/server_no_fuzzer_mode_corpus/2282590f86aa9e6346694931c88ab0427efc255a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/22ed42b85618274ca56f412dbc95cf158076864a b/src/fuzz/server_no_fuzzer_mode_corpus/22ed42b85618274ca56f412dbc95cf158076864a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/22ed42b85618274ca56f412dbc95cf158076864a
rename to src/fuzz/server_no_fuzzer_mode_corpus/22ed42b85618274ca56f412dbc95cf158076864a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/22f989f35ca560a1f7da05c0cc454f98a44d6c1c b/src/fuzz/server_no_fuzzer_mode_corpus/22f989f35ca560a1f7da05c0cc454f98a44d6c1c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/22f989f35ca560a1f7da05c0cc454f98a44d6c1c
rename to src/fuzz/server_no_fuzzer_mode_corpus/22f989f35ca560a1f7da05c0cc454f98a44d6c1c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2334fb59f8b4b7852c4546f36e5e3b241e5a8f04 b/src/fuzz/server_no_fuzzer_mode_corpus/2334fb59f8b4b7852c4546f36e5e3b241e5a8f04
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2334fb59f8b4b7852c4546f36e5e3b241e5a8f04
rename to src/fuzz/server_no_fuzzer_mode_corpus/2334fb59f8b4b7852c4546f36e5e3b241e5a8f04
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/23b47ae3f11c3f4a3573d1531128c5d0efedcdd9 b/src/fuzz/server_no_fuzzer_mode_corpus/23b47ae3f11c3f4a3573d1531128c5d0efedcdd9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/23b47ae3f11c3f4a3573d1531128c5d0efedcdd9
rename to src/fuzz/server_no_fuzzer_mode_corpus/23b47ae3f11c3f4a3573d1531128c5d0efedcdd9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/241422d7ee7a1c86910ac543c840ae040d3dcf77 b/src/fuzz/server_no_fuzzer_mode_corpus/241422d7ee7a1c86910ac543c840ae040d3dcf77
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/241422d7ee7a1c86910ac543c840ae040d3dcf77
rename to src/fuzz/server_no_fuzzer_mode_corpus/241422d7ee7a1c86910ac543c840ae040d3dcf77
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/245c140f4a5800adfa7a6e94ecbdc0c67a626ef2 b/src/fuzz/server_no_fuzzer_mode_corpus/245c140f4a5800adfa7a6e94ecbdc0c67a626ef2
new file mode 100644
index 0000000..50e8633
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/245c140f4a5800adfa7a6e94ecbdc0c67a626ef2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/246327b4f9198aa302033c73781462e5798efcf5 b/src/fuzz/server_no_fuzzer_mode_corpus/246327b4f9198aa302033c73781462e5798efcf5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/246327b4f9198aa302033c73781462e5798efcf5
rename to src/fuzz/server_no_fuzzer_mode_corpus/246327b4f9198aa302033c73781462e5798efcf5
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/2467263c0f7188169166b0d4347461b5ae058cdd b/src/fuzz/server_no_fuzzer_mode_corpus/2467263c0f7188169166b0d4347461b5ae058cdd
new file mode 100644
index 0000000..3dd528c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/2467263c0f7188169166b0d4347461b5ae058cdd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2504d089c2ba4bbb51f7588f791f95f00617ede1 b/src/fuzz/server_no_fuzzer_mode_corpus/2504d089c2ba4bbb51f7588f791f95f00617ede1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2504d089c2ba4bbb51f7588f791f95f00617ede1
rename to src/fuzz/server_no_fuzzer_mode_corpus/2504d089c2ba4bbb51f7588f791f95f00617ede1
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/27159295d9da1910cc4090c0b90df0bc0a3c065a b/src/fuzz/server_no_fuzzer_mode_corpus/27159295d9da1910cc4090c0b90df0bc0a3c065a
new file mode 100644
index 0000000..3a4392e
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/27159295d9da1910cc4090c0b90df0bc0a3c065a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/284c4ecf66b5d18df255aa441476f3b6f8fd956d b/src/fuzz/server_no_fuzzer_mode_corpus/284c4ecf66b5d18df255aa441476f3b6f8fd956d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/284c4ecf66b5d18df255aa441476f3b6f8fd956d
rename to src/fuzz/server_no_fuzzer_mode_corpus/284c4ecf66b5d18df255aa441476f3b6f8fd956d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/28595fdccec9a49cf650b8841b76c48e367d7ac0 b/src/fuzz/server_no_fuzzer_mode_corpus/28595fdccec9a49cf650b8841b76c48e367d7ac0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/28595fdccec9a49cf650b8841b76c48e367d7ac0
rename to src/fuzz/server_no_fuzzer_mode_corpus/28595fdccec9a49cf650b8841b76c48e367d7ac0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/28d75987bd7855b6f3c04c8d0de4040ae319322c b/src/fuzz/server_no_fuzzer_mode_corpus/28d75987bd7855b6f3c04c8d0de4040ae319322c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/28d75987bd7855b6f3c04c8d0de4040ae319322c
rename to src/fuzz/server_no_fuzzer_mode_corpus/28d75987bd7855b6f3c04c8d0de4040ae319322c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/28daa994ceff3f0cee5702491b93bd14c59383ba b/src/fuzz/server_no_fuzzer_mode_corpus/28daa994ceff3f0cee5702491b93bd14c59383ba
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/28daa994ceff3f0cee5702491b93bd14c59383ba
rename to src/fuzz/server_no_fuzzer_mode_corpus/28daa994ceff3f0cee5702491b93bd14c59383ba
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/297de488559833cfbceb42024f16390fdffb1093 b/src/fuzz/server_no_fuzzer_mode_corpus/297de488559833cfbceb42024f16390fdffb1093
new file mode 100644
index 0000000..7c10af1
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/297de488559833cfbceb42024f16390fdffb1093
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2a21fcec464b8262d6300f8f0c7f3518e146acc4 b/src/fuzz/server_no_fuzzer_mode_corpus/2a21fcec464b8262d6300f8f0c7f3518e146acc4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2a21fcec464b8262d6300f8f0c7f3518e146acc4
rename to src/fuzz/server_no_fuzzer_mode_corpus/2a21fcec464b8262d6300f8f0c7f3518e146acc4
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/2ad583821c1860f52d94c6692faccaed025acfdb b/src/fuzz/server_no_fuzzer_mode_corpus/2ad583821c1860f52d94c6692faccaed025acfdb
new file mode 100644
index 0000000..1decf8e
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/2ad583821c1860f52d94c6692faccaed025acfdb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2ba03e96d467ad75f911b4f55319a56cc3312751 b/src/fuzz/server_no_fuzzer_mode_corpus/2ba03e96d467ad75f911b4f55319a56cc3312751
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2ba03e96d467ad75f911b4f55319a56cc3312751
rename to src/fuzz/server_no_fuzzer_mode_corpus/2ba03e96d467ad75f911b4f55319a56cc3312751
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2bcbc0d023a29bc3bedc22b2b61a1df6737e785d b/src/fuzz/server_no_fuzzer_mode_corpus/2bcbc0d023a29bc3bedc22b2b61a1df6737e785d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2bcbc0d023a29bc3bedc22b2b61a1df6737e785d
rename to src/fuzz/server_no_fuzzer_mode_corpus/2bcbc0d023a29bc3bedc22b2b61a1df6737e785d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2c09301393be1636d0a8cc70b6b75e2dffc10f2e b/src/fuzz/server_no_fuzzer_mode_corpus/2c09301393be1636d0a8cc70b6b75e2dffc10f2e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2c09301393be1636d0a8cc70b6b75e2dffc10f2e
rename to src/fuzz/server_no_fuzzer_mode_corpus/2c09301393be1636d0a8cc70b6b75e2dffc10f2e
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/2c437eed7cb8f2599f1f987eb462e5dfa8b95005 b/src/fuzz/server_no_fuzzer_mode_corpus/2c437eed7cb8f2599f1f987eb462e5dfa8b95005
new file mode 100644
index 0000000..9b6c72e
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/2c437eed7cb8f2599f1f987eb462e5dfa8b95005
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2cc1ef77d85171cf85462d750136e699967c4062 b/src/fuzz/server_no_fuzzer_mode_corpus/2cc1ef77d85171cf85462d750136e699967c4062
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2cc1ef77d85171cf85462d750136e699967c4062
rename to src/fuzz/server_no_fuzzer_mode_corpus/2cc1ef77d85171cf85462d750136e699967c4062
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2cd81aeed696eb0b3a941f1ca8e8ce9b3a7d00b1 b/src/fuzz/server_no_fuzzer_mode_corpus/2cd81aeed696eb0b3a941f1ca8e8ce9b3a7d00b1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2cd81aeed696eb0b3a941f1ca8e8ce9b3a7d00b1
rename to src/fuzz/server_no_fuzzer_mode_corpus/2cd81aeed696eb0b3a941f1ca8e8ce9b3a7d00b1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2cf927e5b4f3db56e90563f6b7b4193298691ebe b/src/fuzz/server_no_fuzzer_mode_corpus/2cf927e5b4f3db56e90563f6b7b4193298691ebe
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2cf927e5b4f3db56e90563f6b7b4193298691ebe
rename to src/fuzz/server_no_fuzzer_mode_corpus/2cf927e5b4f3db56e90563f6b7b4193298691ebe
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2d18b5f4f5f3a0235f499d76f6d9e9db7a5ef0cf b/src/fuzz/server_no_fuzzer_mode_corpus/2d18b5f4f5f3a0235f499d76f6d9e9db7a5ef0cf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2d18b5f4f5f3a0235f499d76f6d9e9db7a5ef0cf
rename to src/fuzz/server_no_fuzzer_mode_corpus/2d18b5f4f5f3a0235f499d76f6d9e9db7a5ef0cf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2da8bdc397014d7f5a1fee1b7d30b1cd28b7e862 b/src/fuzz/server_no_fuzzer_mode_corpus/2da8bdc397014d7f5a1fee1b7d30b1cd28b7e862
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2da8bdc397014d7f5a1fee1b7d30b1cd28b7e862
rename to src/fuzz/server_no_fuzzer_mode_corpus/2da8bdc397014d7f5a1fee1b7d30b1cd28b7e862
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2dc4d57d10664322de1220bb2030e1b3661544b1 b/src/fuzz/server_no_fuzzer_mode_corpus/2dc4d57d10664322de1220bb2030e1b3661544b1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2dc4d57d10664322de1220bb2030e1b3661544b1
rename to src/fuzz/server_no_fuzzer_mode_corpus/2dc4d57d10664322de1220bb2030e1b3661544b1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2ec8ed2f45f5a5b8f66ab3b47f16b235718f0ec6 b/src/fuzz/server_no_fuzzer_mode_corpus/2ec8ed2f45f5a5b8f66ab3b47f16b235718f0ec6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2ec8ed2f45f5a5b8f66ab3b47f16b235718f0ec6
rename to src/fuzz/server_no_fuzzer_mode_corpus/2ec8ed2f45f5a5b8f66ab3b47f16b235718f0ec6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2ede02b70e97de69de384bedcec01813ca769f35 b/src/fuzz/server_no_fuzzer_mode_corpus/2ede02b70e97de69de384bedcec01813ca769f35
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2ede02b70e97de69de384bedcec01813ca769f35
rename to src/fuzz/server_no_fuzzer_mode_corpus/2ede02b70e97de69de384bedcec01813ca769f35
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2f0f63d0a3dbc0410feda2deecd9c7622834f6b5 b/src/fuzz/server_no_fuzzer_mode_corpus/2f0f63d0a3dbc0410feda2deecd9c7622834f6b5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2f0f63d0a3dbc0410feda2deecd9c7622834f6b5
rename to src/fuzz/server_no_fuzzer_mode_corpus/2f0f63d0a3dbc0410feda2deecd9c7622834f6b5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2f30f458e3e2f93c3df539e181427baf43dd8da5 b/src/fuzz/server_no_fuzzer_mode_corpus/2f30f458e3e2f93c3df539e181427baf43dd8da5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2f30f458e3e2f93c3df539e181427baf43dd8da5
rename to src/fuzz/server_no_fuzzer_mode_corpus/2f30f458e3e2f93c3df539e181427baf43dd8da5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/2f44c3b502e4bb0b88a1bf4fa9760540447c74ce b/src/fuzz/server_no_fuzzer_mode_corpus/2f44c3b502e4bb0b88a1bf4fa9760540447c74ce
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/2f44c3b502e4bb0b88a1bf4fa9760540447c74ce
rename to src/fuzz/server_no_fuzzer_mode_corpus/2f44c3b502e4bb0b88a1bf4fa9760540447c74ce
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/306f10d3374c29f86351764870b814f25e96fb00 b/src/fuzz/server_no_fuzzer_mode_corpus/306f10d3374c29f86351764870b814f25e96fb00
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/306f10d3374c29f86351764870b814f25e96fb00
rename to src/fuzz/server_no_fuzzer_mode_corpus/306f10d3374c29f86351764870b814f25e96fb00
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/30cf369f8271fc2e5a363b05727a2b6993a91782 b/src/fuzz/server_no_fuzzer_mode_corpus/30cf369f8271fc2e5a363b05727a2b6993a91782
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/30cf369f8271fc2e5a363b05727a2b6993a91782
rename to src/fuzz/server_no_fuzzer_mode_corpus/30cf369f8271fc2e5a363b05727a2b6993a91782
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/322de7ec5c0671e0fb799996b2d7c30f7ad927bc b/src/fuzz/server_no_fuzzer_mode_corpus/322de7ec5c0671e0fb799996b2d7c30f7ad927bc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/322de7ec5c0671e0fb799996b2d7c30f7ad927bc
rename to src/fuzz/server_no_fuzzer_mode_corpus/322de7ec5c0671e0fb799996b2d7c30f7ad927bc
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/327c35674beb6c067401986360dd7e05234bc31e b/src/fuzz/server_no_fuzzer_mode_corpus/327c35674beb6c067401986360dd7e05234bc31e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/327c35674beb6c067401986360dd7e05234bc31e
rename to src/fuzz/server_no_fuzzer_mode_corpus/327c35674beb6c067401986360dd7e05234bc31e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3399fb5bf14f0340e00828ab18d292f0de51a25e b/src/fuzz/server_no_fuzzer_mode_corpus/3399fb5bf14f0340e00828ab18d292f0de51a25e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3399fb5bf14f0340e00828ab18d292f0de51a25e
rename to src/fuzz/server_no_fuzzer_mode_corpus/3399fb5bf14f0340e00828ab18d292f0de51a25e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/33da2d1bc96d7201287c8a845582ddbf50bcb37a b/src/fuzz/server_no_fuzzer_mode_corpus/33da2d1bc96d7201287c8a845582ddbf50bcb37a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/33da2d1bc96d7201287c8a845582ddbf50bcb37a
rename to src/fuzz/server_no_fuzzer_mode_corpus/33da2d1bc96d7201287c8a845582ddbf50bcb37a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/342abffbd3a33d4b73e54c0675585fcd511f492d b/src/fuzz/server_no_fuzzer_mode_corpus/342abffbd3a33d4b73e54c0675585fcd511f492d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/342abffbd3a33d4b73e54c0675585fcd511f492d
rename to src/fuzz/server_no_fuzzer_mode_corpus/342abffbd3a33d4b73e54c0675585fcd511f492d
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/3434baa9770fe589fc2110be2680d4b0ca7ccc24 b/src/fuzz/server_no_fuzzer_mode_corpus/3434baa9770fe589fc2110be2680d4b0ca7ccc24
new file mode 100644
index 0000000..8c4df48
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/3434baa9770fe589fc2110be2680d4b0ca7ccc24
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/343dea8f3f2a78c7db0dce8a4b5f151176c5d882 b/src/fuzz/server_no_fuzzer_mode_corpus/343dea8f3f2a78c7db0dce8a4b5f151176c5d882
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/343dea8f3f2a78c7db0dce8a4b5f151176c5d882
rename to src/fuzz/server_no_fuzzer_mode_corpus/343dea8f3f2a78c7db0dce8a4b5f151176c5d882
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/34682a590921e907b96b9e3ea4ca81e7a1ddb42a b/src/fuzz/server_no_fuzzer_mode_corpus/34682a590921e907b96b9e3ea4ca81e7a1ddb42a
new file mode 100644
index 0000000..96439b2
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/34682a590921e907b96b9e3ea4ca81e7a1ddb42a
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/357179e5cfeffc0d0a70072d83cb8ebf6c9b567f b/src/fuzz/server_no_fuzzer_mode_corpus/357179e5cfeffc0d0a70072d83cb8ebf6c9b567f
new file mode 100644
index 0000000..91a02be
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/357179e5cfeffc0d0a70072d83cb8ebf6c9b567f
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/35a7bba0e41884293b9c1e91003489563e16163c b/src/fuzz/server_no_fuzzer_mode_corpus/35a7bba0e41884293b9c1e91003489563e16163c
new file mode 100644
index 0000000..efe73e0
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/35a7bba0e41884293b9c1e91003489563e16163c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/35c0efd2c9cbc6f3b4e76cddb8c1d94ee1a44794 b/src/fuzz/server_no_fuzzer_mode_corpus/35c0efd2c9cbc6f3b4e76cddb8c1d94ee1a44794
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/35c0efd2c9cbc6f3b4e76cddb8c1d94ee1a44794
rename to src/fuzz/server_no_fuzzer_mode_corpus/35c0efd2c9cbc6f3b4e76cddb8c1d94ee1a44794
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/35ff95557bc6038f4b3866e8cf5f9529b511b51a b/src/fuzz/server_no_fuzzer_mode_corpus/35ff95557bc6038f4b3866e8cf5f9529b511b51a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/35ff95557bc6038f4b3866e8cf5f9529b511b51a
rename to src/fuzz/server_no_fuzzer_mode_corpus/35ff95557bc6038f4b3866e8cf5f9529b511b51a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/36408aff7c4939c52780f09d2b959a02087009d8 b/src/fuzz/server_no_fuzzer_mode_corpus/36408aff7c4939c52780f09d2b959a02087009d8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/36408aff7c4939c52780f09d2b959a02087009d8
rename to src/fuzz/server_no_fuzzer_mode_corpus/36408aff7c4939c52780f09d2b959a02087009d8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/36eb60784edea2c9e84965e234df7162cf09b472 b/src/fuzz/server_no_fuzzer_mode_corpus/36eb60784edea2c9e84965e234df7162cf09b472
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/36eb60784edea2c9e84965e234df7162cf09b472
rename to src/fuzz/server_no_fuzzer_mode_corpus/36eb60784edea2c9e84965e234df7162cf09b472
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/372dfd3ad38c81697a88f223c61bebe4108d9e7d b/src/fuzz/server_no_fuzzer_mode_corpus/372dfd3ad38c81697a88f223c61bebe4108d9e7d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/372dfd3ad38c81697a88f223c61bebe4108d9e7d
rename to src/fuzz/server_no_fuzzer_mode_corpus/372dfd3ad38c81697a88f223c61bebe4108d9e7d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3797cfedecf9e7abe3c140a8700416cec19e456b b/src/fuzz/server_no_fuzzer_mode_corpus/3797cfedecf9e7abe3c140a8700416cec19e456b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3797cfedecf9e7abe3c140a8700416cec19e456b
rename to src/fuzz/server_no_fuzzer_mode_corpus/3797cfedecf9e7abe3c140a8700416cec19e456b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3815608992bbaf73e9830ed71bc994580aa8b262 b/src/fuzz/server_no_fuzzer_mode_corpus/3815608992bbaf73e9830ed71bc994580aa8b262
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3815608992bbaf73e9830ed71bc994580aa8b262
rename to src/fuzz/server_no_fuzzer_mode_corpus/3815608992bbaf73e9830ed71bc994580aa8b262
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/38782780870efe01276992695144688ed7fc0d0e b/src/fuzz/server_no_fuzzer_mode_corpus/38782780870efe01276992695144688ed7fc0d0e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/38782780870efe01276992695144688ed7fc0d0e
rename to src/fuzz/server_no_fuzzer_mode_corpus/38782780870efe01276992695144688ed7fc0d0e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/390c601ab4fc7955cbc293bdfe06d4596a6a4d1e b/src/fuzz/server_no_fuzzer_mode_corpus/390c601ab4fc7955cbc293bdfe06d4596a6a4d1e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/390c601ab4fc7955cbc293bdfe06d4596a6a4d1e
rename to src/fuzz/server_no_fuzzer_mode_corpus/390c601ab4fc7955cbc293bdfe06d4596a6a4d1e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/393218bd0709e8f01050f972cac5f7943dcc92d0 b/src/fuzz/server_no_fuzzer_mode_corpus/393218bd0709e8f01050f972cac5f7943dcc92d0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/393218bd0709e8f01050f972cac5f7943dcc92d0
rename to src/fuzz/server_no_fuzzer_mode_corpus/393218bd0709e8f01050f972cac5f7943dcc92d0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3a120b8a4862c1bc0beb6a7d5f3fe9538af6fd80 b/src/fuzz/server_no_fuzzer_mode_corpus/3a120b8a4862c1bc0beb6a7d5f3fe9538af6fd80
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3a120b8a4862c1bc0beb6a7d5f3fe9538af6fd80
rename to src/fuzz/server_no_fuzzer_mode_corpus/3a120b8a4862c1bc0beb6a7d5f3fe9538af6fd80
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3a737d30c5a8805fadc8ad37ec97415facd482b2 b/src/fuzz/server_no_fuzzer_mode_corpus/3a737d30c5a8805fadc8ad37ec97415facd482b2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3a737d30c5a8805fadc8ad37ec97415facd482b2
rename to src/fuzz/server_no_fuzzer_mode_corpus/3a737d30c5a8805fadc8ad37ec97415facd482b2
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/3c1b292602bb262917b28348d87e42726a3b4f7f b/src/fuzz/server_no_fuzzer_mode_corpus/3c1b292602bb262917b28348d87e42726a3b4f7f
new file mode 100644
index 0000000..84e16e6
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/3c1b292602bb262917b28348d87e42726a3b4f7f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3c2f22d033ddba01cf6e8cc32a7856c345b8fa39 b/src/fuzz/server_no_fuzzer_mode_corpus/3c2f22d033ddba01cf6e8cc32a7856c345b8fa39
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3c2f22d033ddba01cf6e8cc32a7856c345b8fa39
rename to src/fuzz/server_no_fuzzer_mode_corpus/3c2f22d033ddba01cf6e8cc32a7856c345b8fa39
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3c5f664fd82e10a83df15830bd0ae0b66c3a3a4a b/src/fuzz/server_no_fuzzer_mode_corpus/3c5f664fd82e10a83df15830bd0ae0b66c3a3a4a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3c5f664fd82e10a83df15830bd0ae0b66c3a3a4a
rename to src/fuzz/server_no_fuzzer_mode_corpus/3c5f664fd82e10a83df15830bd0ae0b66c3a3a4a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3cd98577646d22f4af245e2b3cf623e19a63827c b/src/fuzz/server_no_fuzzer_mode_corpus/3cd98577646d22f4af245e2b3cf623e19a63827c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3cd98577646d22f4af245e2b3cf623e19a63827c
rename to src/fuzz/server_no_fuzzer_mode_corpus/3cd98577646d22f4af245e2b3cf623e19a63827c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3cdfdd6097562b00bada1729212b675702ed597b b/src/fuzz/server_no_fuzzer_mode_corpus/3cdfdd6097562b00bada1729212b675702ed597b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3cdfdd6097562b00bada1729212b675702ed597b
rename to src/fuzz/server_no_fuzzer_mode_corpus/3cdfdd6097562b00bada1729212b675702ed597b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3cfac745077d5b35a20306b7370bb75a8ed81385 b/src/fuzz/server_no_fuzzer_mode_corpus/3cfac745077d5b35a20306b7370bb75a8ed81385
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3cfac745077d5b35a20306b7370bb75a8ed81385
rename to src/fuzz/server_no_fuzzer_mode_corpus/3cfac745077d5b35a20306b7370bb75a8ed81385
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3d324da734ed5f9480f251da38869f41e638d617 b/src/fuzz/server_no_fuzzer_mode_corpus/3d324da734ed5f9480f251da38869f41e638d617
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3d324da734ed5f9480f251da38869f41e638d617
rename to src/fuzz/server_no_fuzzer_mode_corpus/3d324da734ed5f9480f251da38869f41e638d617
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/3dfb621c543412bb858fa84ef59323f7bdb2ed36 b/src/fuzz/server_no_fuzzer_mode_corpus/3dfb621c543412bb858fa84ef59323f7bdb2ed36
new file mode 100644
index 0000000..c95350d
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/3dfb621c543412bb858fa84ef59323f7bdb2ed36
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3e452bfb827194370dc64efc2ef5b4a1efde76f0 b/src/fuzz/server_no_fuzzer_mode_corpus/3e452bfb827194370dc64efc2ef5b4a1efde76f0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3e452bfb827194370dc64efc2ef5b4a1efde76f0
rename to src/fuzz/server_no_fuzzer_mode_corpus/3e452bfb827194370dc64efc2ef5b4a1efde76f0
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/3f17b10a71b0f2883378fe9a0aae96e3280140ee b/src/fuzz/server_no_fuzzer_mode_corpus/3f17b10a71b0f2883378fe9a0aae96e3280140ee
new file mode 100644
index 0000000..a661e8c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/3f17b10a71b0f2883378fe9a0aae96e3280140ee
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3f4f571a6306785bd50b8b60274dd533aa1f6f96 b/src/fuzz/server_no_fuzzer_mode_corpus/3f4f571a6306785bd50b8b60274dd533aa1f6f96
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3f4f571a6306785bd50b8b60274dd533aa1f6f96
rename to src/fuzz/server_no_fuzzer_mode_corpus/3f4f571a6306785bd50b8b60274dd533aa1f6f96
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/3fddee660c732806c4cf75c0a535a906adeaf2f8 b/src/fuzz/server_no_fuzzer_mode_corpus/3fddee660c732806c4cf75c0a535a906adeaf2f8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/3fddee660c732806c4cf75c0a535a906adeaf2f8
rename to src/fuzz/server_no_fuzzer_mode_corpus/3fddee660c732806c4cf75c0a535a906adeaf2f8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4119dd280b114874c907a50cbb768e33417fa43f b/src/fuzz/server_no_fuzzer_mode_corpus/4119dd280b114874c907a50cbb768e33417fa43f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4119dd280b114874c907a50cbb768e33417fa43f
rename to src/fuzz/server_no_fuzzer_mode_corpus/4119dd280b114874c907a50cbb768e33417fa43f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4153d1ab2cd0068f9c99eae3748da0e16ea31d3d b/src/fuzz/server_no_fuzzer_mode_corpus/4153d1ab2cd0068f9c99eae3748da0e16ea31d3d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4153d1ab2cd0068f9c99eae3748da0e16ea31d3d
rename to src/fuzz/server_no_fuzzer_mode_corpus/4153d1ab2cd0068f9c99eae3748da0e16ea31d3d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/438d757e41c4964ff23c877038331b62410df122 b/src/fuzz/server_no_fuzzer_mode_corpus/438d757e41c4964ff23c877038331b62410df122
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/438d757e41c4964ff23c877038331b62410df122
rename to src/fuzz/server_no_fuzzer_mode_corpus/438d757e41c4964ff23c877038331b62410df122
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/43b965aebbcddea6c776f56a9ccc67e6617d5d2e b/src/fuzz/server_no_fuzzer_mode_corpus/43b965aebbcddea6c776f56a9ccc67e6617d5d2e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/43b965aebbcddea6c776f56a9ccc67e6617d5d2e
rename to src/fuzz/server_no_fuzzer_mode_corpus/43b965aebbcddea6c776f56a9ccc67e6617d5d2e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/43d1508a5748ed862dbda3a7c5732c756a45371f b/src/fuzz/server_no_fuzzer_mode_corpus/43d1508a5748ed862dbda3a7c5732c756a45371f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/43d1508a5748ed862dbda3a7c5732c756a45371f
rename to src/fuzz/server_no_fuzzer_mode_corpus/43d1508a5748ed862dbda3a7c5732c756a45371f
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/44096b89a066ce2ea3e62dc4f9c4ce68496b1f4b b/src/fuzz/server_no_fuzzer_mode_corpus/44096b89a066ce2ea3e62dc4f9c4ce68496b1f4b
new file mode 100644
index 0000000..d67a0a7
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/44096b89a066ce2ea3e62dc4f9c4ce68496b1f4b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/44b88a54b45e929895e62f0df349d2118fac4926 b/src/fuzz/server_no_fuzzer_mode_corpus/44b88a54b45e929895e62f0df349d2118fac4926
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/44b88a54b45e929895e62f0df349d2118fac4926
rename to src/fuzz/server_no_fuzzer_mode_corpus/44b88a54b45e929895e62f0df349d2118fac4926
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/44e28bf531e394c9652141e0c214ccf7e83c8f49 b/src/fuzz/server_no_fuzzer_mode_corpus/44e28bf531e394c9652141e0c214ccf7e83c8f49
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/44e28bf531e394c9652141e0c214ccf7e83c8f49
rename to src/fuzz/server_no_fuzzer_mode_corpus/44e28bf531e394c9652141e0c214ccf7e83c8f49
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/46d476cec07892045e43fbdec297eefac47d1dcd b/src/fuzz/server_no_fuzzer_mode_corpus/46d476cec07892045e43fbdec297eefac47d1dcd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/46d476cec07892045e43fbdec297eefac47d1dcd
rename to src/fuzz/server_no_fuzzer_mode_corpus/46d476cec07892045e43fbdec297eefac47d1dcd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/46ee49bf71d81db9ec25e63ddd3005c403f3eaff b/src/fuzz/server_no_fuzzer_mode_corpus/46ee49bf71d81db9ec25e63ddd3005c403f3eaff
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/46ee49bf71d81db9ec25e63ddd3005c403f3eaff
rename to src/fuzz/server_no_fuzzer_mode_corpus/46ee49bf71d81db9ec25e63ddd3005c403f3eaff
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4701a996db9f51a3785672a418d817ac918af030 b/src/fuzz/server_no_fuzzer_mode_corpus/4701a996db9f51a3785672a418d817ac918af030
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4701a996db9f51a3785672a418d817ac918af030
rename to src/fuzz/server_no_fuzzer_mode_corpus/4701a996db9f51a3785672a418d817ac918af030
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/472dc3c76762f89ca0b67d4fa9e6a0b80ab96d46 b/src/fuzz/server_no_fuzzer_mode_corpus/472dc3c76762f89ca0b67d4fa9e6a0b80ab96d46
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/472dc3c76762f89ca0b67d4fa9e6a0b80ab96d46
rename to src/fuzz/server_no_fuzzer_mode_corpus/472dc3c76762f89ca0b67d4fa9e6a0b80ab96d46
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4764e1747f76ecd6fd07828c24badb99dbfb4585 b/src/fuzz/server_no_fuzzer_mode_corpus/4764e1747f76ecd6fd07828c24badb99dbfb4585
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4764e1747f76ecd6fd07828c24badb99dbfb4585
rename to src/fuzz/server_no_fuzzer_mode_corpus/4764e1747f76ecd6fd07828c24badb99dbfb4585
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4872d27fdf102f2dfe776a718db33dbc5fb814d0 b/src/fuzz/server_no_fuzzer_mode_corpus/4872d27fdf102f2dfe776a718db33dbc5fb814d0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4872d27fdf102f2dfe776a718db33dbc5fb814d0
rename to src/fuzz/server_no_fuzzer_mode_corpus/4872d27fdf102f2dfe776a718db33dbc5fb814d0
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/497f86b8cf01e8870743bf4ea157834b179a39ce b/src/fuzz/server_no_fuzzer_mode_corpus/497f86b8cf01e8870743bf4ea157834b179a39ce
new file mode 100644
index 0000000..368281d
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/497f86b8cf01e8870743bf4ea157834b179a39ce
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/49b45defe1fbe376e9988bf6c7eb6c1767f0425f b/src/fuzz/server_no_fuzzer_mode_corpus/49b45defe1fbe376e9988bf6c7eb6c1767f0425f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/49b45defe1fbe376e9988bf6c7eb6c1767f0425f
rename to src/fuzz/server_no_fuzzer_mode_corpus/49b45defe1fbe376e9988bf6c7eb6c1767f0425f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4a18136ad23f65ccd751cf307f85010c1f856a24 b/src/fuzz/server_no_fuzzer_mode_corpus/4a18136ad23f65ccd751cf307f85010c1f856a24
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4a18136ad23f65ccd751cf307f85010c1f856a24
rename to src/fuzz/server_no_fuzzer_mode_corpus/4a18136ad23f65ccd751cf307f85010c1f856a24
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/4a550882f9caf933a356463a02f02964ebf587a1 b/src/fuzz/server_no_fuzzer_mode_corpus/4a550882f9caf933a356463a02f02964ebf587a1
new file mode 100644
index 0000000..00b4e6f
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/4a550882f9caf933a356463a02f02964ebf587a1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4aa6ddc122b53afb2aa16f7c51399d75c4b3e79d b/src/fuzz/server_no_fuzzer_mode_corpus/4aa6ddc122b53afb2aa16f7c51399d75c4b3e79d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4aa6ddc122b53afb2aa16f7c51399d75c4b3e79d
rename to src/fuzz/server_no_fuzzer_mode_corpus/4aa6ddc122b53afb2aa16f7c51399d75c4b3e79d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4aa7a3d7dca16a5b125ae3161759a3013a843b4a b/src/fuzz/server_no_fuzzer_mode_corpus/4aa7a3d7dca16a5b125ae3161759a3013a843b4a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4aa7a3d7dca16a5b125ae3161759a3013a843b4a
rename to src/fuzz/server_no_fuzzer_mode_corpus/4aa7a3d7dca16a5b125ae3161759a3013a843b4a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4b80a7e2d86957b1ac8646ee81fb8d549140a0ab b/src/fuzz/server_no_fuzzer_mode_corpus/4b80a7e2d86957b1ac8646ee81fb8d549140a0ab
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4b80a7e2d86957b1ac8646ee81fb8d549140a0ab
rename to src/fuzz/server_no_fuzzer_mode_corpus/4b80a7e2d86957b1ac8646ee81fb8d549140a0ab
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4bf6cf93aad8725818db77fe3681497907b74675 b/src/fuzz/server_no_fuzzer_mode_corpus/4bf6cf93aad8725818db77fe3681497907b74675
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4bf6cf93aad8725818db77fe3681497907b74675
rename to src/fuzz/server_no_fuzzer_mode_corpus/4bf6cf93aad8725818db77fe3681497907b74675
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/4c204fb176ad1966501d0688d9567cdbc89be691 b/src/fuzz/server_no_fuzzer_mode_corpus/4c204fb176ad1966501d0688d9567cdbc89be691
new file mode 100644
index 0000000..53796e6
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/4c204fb176ad1966501d0688d9567cdbc89be691
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4c2f75a07df986496c0124e82a0daf53ef5733ef b/src/fuzz/server_no_fuzzer_mode_corpus/4c2f75a07df986496c0124e82a0daf53ef5733ef
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4c2f75a07df986496c0124e82a0daf53ef5733ef
rename to src/fuzz/server_no_fuzzer_mode_corpus/4c2f75a07df986496c0124e82a0daf53ef5733ef
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4d326efc3fdfe62eb1aa6d32baa5bba49875737c b/src/fuzz/server_no_fuzzer_mode_corpus/4d326efc3fdfe62eb1aa6d32baa5bba49875737c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4d326efc3fdfe62eb1aa6d32baa5bba49875737c
rename to src/fuzz/server_no_fuzzer_mode_corpus/4d326efc3fdfe62eb1aa6d32baa5bba49875737c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4d4b32eecde94edf651c64ff66ade2a3e51ea2db b/src/fuzz/server_no_fuzzer_mode_corpus/4d4b32eecde94edf651c64ff66ade2a3e51ea2db
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4d4b32eecde94edf651c64ff66ade2a3e51ea2db
rename to src/fuzz/server_no_fuzzer_mode_corpus/4d4b32eecde94edf651c64ff66ade2a3e51ea2db
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4dd5ef15636fee27ab973b4235656a48fb0dbee4 b/src/fuzz/server_no_fuzzer_mode_corpus/4dd5ef15636fee27ab973b4235656a48fb0dbee4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4dd5ef15636fee27ab973b4235656a48fb0dbee4
rename to src/fuzz/server_no_fuzzer_mode_corpus/4dd5ef15636fee27ab973b4235656a48fb0dbee4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4e37ca19e3ad4c3239b7b8f14063b7357d3bee47 b/src/fuzz/server_no_fuzzer_mode_corpus/4e37ca19e3ad4c3239b7b8f14063b7357d3bee47
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4e37ca19e3ad4c3239b7b8f14063b7357d3bee47
rename to src/fuzz/server_no_fuzzer_mode_corpus/4e37ca19e3ad4c3239b7b8f14063b7357d3bee47
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4e8b0f090c6d4c3e7cf44bd0c0b5c5cb6f190960 b/src/fuzz/server_no_fuzzer_mode_corpus/4e8b0f090c6d4c3e7cf44bd0c0b5c5cb6f190960
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4e8b0f090c6d4c3e7cf44bd0c0b5c5cb6f190960
rename to src/fuzz/server_no_fuzzer_mode_corpus/4e8b0f090c6d4c3e7cf44bd0c0b5c5cb6f190960
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4eea539ee813b43f3242b7a30f5f8fd67fd4bd8d b/src/fuzz/server_no_fuzzer_mode_corpus/4eea539ee813b43f3242b7a30f5f8fd67fd4bd8d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4eea539ee813b43f3242b7a30f5f8fd67fd4bd8d
rename to src/fuzz/server_no_fuzzer_mode_corpus/4eea539ee813b43f3242b7a30f5f8fd67fd4bd8d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/4f49b84d412e0fa3280cf182506aa44b42a89e29 b/src/fuzz/server_no_fuzzer_mode_corpus/4f49b84d412e0fa3280cf182506aa44b42a89e29
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/4f49b84d412e0fa3280cf182506aa44b42a89e29
rename to src/fuzz/server_no_fuzzer_mode_corpus/4f49b84d412e0fa3280cf182506aa44b42a89e29
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/51dd3eb54f8b7b8440b4f6f46c579c227012a0b2 b/src/fuzz/server_no_fuzzer_mode_corpus/51dd3eb54f8b7b8440b4f6f46c579c227012a0b2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/51dd3eb54f8b7b8440b4f6f46c579c227012a0b2
rename to src/fuzz/server_no_fuzzer_mode_corpus/51dd3eb54f8b7b8440b4f6f46c579c227012a0b2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5251f7fcfde5023989abd4694a23271fdd7f3f82 b/src/fuzz/server_no_fuzzer_mode_corpus/5251f7fcfde5023989abd4694a23271fdd7f3f82
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5251f7fcfde5023989abd4694a23271fdd7f3f82
rename to src/fuzz/server_no_fuzzer_mode_corpus/5251f7fcfde5023989abd4694a23271fdd7f3f82
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5518f546d6c1e9b013e66dd0e3dc86af95bf15fa b/src/fuzz/server_no_fuzzer_mode_corpus/5518f546d6c1e9b013e66dd0e3dc86af95bf15fa
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5518f546d6c1e9b013e66dd0e3dc86af95bf15fa
rename to src/fuzz/server_no_fuzzer_mode_corpus/5518f546d6c1e9b013e66dd0e3dc86af95bf15fa
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/55ccbe8e02901ab3e0f009d73befd2c2a59aa48b b/src/fuzz/server_no_fuzzer_mode_corpus/55ccbe8e02901ab3e0f009d73befd2c2a59aa48b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/55ccbe8e02901ab3e0f009d73befd2c2a59aa48b
rename to src/fuzz/server_no_fuzzer_mode_corpus/55ccbe8e02901ab3e0f009d73befd2c2a59aa48b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/562d3a9f84f5304c2fe84e9cf0f522a5316ccf6c b/src/fuzz/server_no_fuzzer_mode_corpus/562d3a9f84f5304c2fe84e9cf0f522a5316ccf6c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/562d3a9f84f5304c2fe84e9cf0f522a5316ccf6c
rename to src/fuzz/server_no_fuzzer_mode_corpus/562d3a9f84f5304c2fe84e9cf0f522a5316ccf6c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/568bc0da595603a2412d0d182f1996f5c8af4e44 b/src/fuzz/server_no_fuzzer_mode_corpus/568bc0da595603a2412d0d182f1996f5c8af4e44
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/568bc0da595603a2412d0d182f1996f5c8af4e44
rename to src/fuzz/server_no_fuzzer_mode_corpus/568bc0da595603a2412d0d182f1996f5c8af4e44
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/56988b521baeb78522bba750bb94b5024b2e80e0 b/src/fuzz/server_no_fuzzer_mode_corpus/56988b521baeb78522bba750bb94b5024b2e80e0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/56988b521baeb78522bba750bb94b5024b2e80e0
rename to src/fuzz/server_no_fuzzer_mode_corpus/56988b521baeb78522bba750bb94b5024b2e80e0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/57a71e5204de5c8ef78a112b0be71bc621e0d79a b/src/fuzz/server_no_fuzzer_mode_corpus/57a71e5204de5c8ef78a112b0be71bc621e0d79a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/57a71e5204de5c8ef78a112b0be71bc621e0d79a
rename to src/fuzz/server_no_fuzzer_mode_corpus/57a71e5204de5c8ef78a112b0be71bc621e0d79a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/583154d034eac68a265654797c9dea99b6ffb8c8 b/src/fuzz/server_no_fuzzer_mode_corpus/583154d034eac68a265654797c9dea99b6ffb8c8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/583154d034eac68a265654797c9dea99b6ffb8c8
rename to src/fuzz/server_no_fuzzer_mode_corpus/583154d034eac68a265654797c9dea99b6ffb8c8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/595b8d5661597a065ef843bc241f46d1026a8c60 b/src/fuzz/server_no_fuzzer_mode_corpus/595b8d5661597a065ef843bc241f46d1026a8c60
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/595b8d5661597a065ef843bc241f46d1026a8c60
rename to src/fuzz/server_no_fuzzer_mode_corpus/595b8d5661597a065ef843bc241f46d1026a8c60
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/5a04e5bec40de8728cf12fd7662a8654b377003e b/src/fuzz/server_no_fuzzer_mode_corpus/5a04e5bec40de8728cf12fd7662a8654b377003e
new file mode 100644
index 0000000..b3c84a0
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/5a04e5bec40de8728cf12fd7662a8654b377003e
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/5b893cbfdd4d524e091ec66bb2e35bf477a7e5f3 b/src/fuzz/server_no_fuzzer_mode_corpus/5b893cbfdd4d524e091ec66bb2e35bf477a7e5f3
new file mode 100644
index 0000000..acc5e3f
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/5b893cbfdd4d524e091ec66bb2e35bf477a7e5f3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5b8bdf3f7553868f91403a49bdc32e18d56540a0 b/src/fuzz/server_no_fuzzer_mode_corpus/5b8bdf3f7553868f91403a49bdc32e18d56540a0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5b8bdf3f7553868f91403a49bdc32e18d56540a0
rename to src/fuzz/server_no_fuzzer_mode_corpus/5b8bdf3f7553868f91403a49bdc32e18d56540a0
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/5b945b8aba17cf37de8da44246482397bb653370 b/src/fuzz/server_no_fuzzer_mode_corpus/5b945b8aba17cf37de8da44246482397bb653370
new file mode 100644
index 0000000..a70af8a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/5b945b8aba17cf37de8da44246482397bb653370
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/5bad4f224133c1189a9f68840fc80b55d0fcec09 b/src/fuzz/server_no_fuzzer_mode_corpus/5bad4f224133c1189a9f68840fc80b55d0fcec09
new file mode 100644
index 0000000..e553a7d
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/5bad4f224133c1189a9f68840fc80b55d0fcec09
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/5bf4694cf0e2eb094a3a437b4d33e2f8d94b83c0 b/src/fuzz/server_no_fuzzer_mode_corpus/5bf4694cf0e2eb094a3a437b4d33e2f8d94b83c0
new file mode 100644
index 0000000..4bb77af
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/5bf4694cf0e2eb094a3a437b4d33e2f8d94b83c0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5c09923b5d854ea172edd91e245737ee1da84f97 b/src/fuzz/server_no_fuzzer_mode_corpus/5c09923b5d854ea172edd91e245737ee1da84f97
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5c09923b5d854ea172edd91e245737ee1da84f97
rename to src/fuzz/server_no_fuzzer_mode_corpus/5c09923b5d854ea172edd91e245737ee1da84f97
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5ca590cabb6eff12e445b3a46f7723636f3f383d b/src/fuzz/server_no_fuzzer_mode_corpus/5ca590cabb6eff12e445b3a46f7723636f3f383d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5ca590cabb6eff12e445b3a46f7723636f3f383d
rename to src/fuzz/server_no_fuzzer_mode_corpus/5ca590cabb6eff12e445b3a46f7723636f3f383d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5cdc5e563f563076d78d1c152ecad8868e4ebb40 b/src/fuzz/server_no_fuzzer_mode_corpus/5cdc5e563f563076d78d1c152ecad8868e4ebb40
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5cdc5e563f563076d78d1c152ecad8868e4ebb40
rename to src/fuzz/server_no_fuzzer_mode_corpus/5cdc5e563f563076d78d1c152ecad8868e4ebb40
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5cea68d5e95c3b3002eb3038ece431e32cf620b0 b/src/fuzz/server_no_fuzzer_mode_corpus/5cea68d5e95c3b3002eb3038ece431e32cf620b0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5cea68d5e95c3b3002eb3038ece431e32cf620b0
rename to src/fuzz/server_no_fuzzer_mode_corpus/5cea68d5e95c3b3002eb3038ece431e32cf620b0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5d04402a860b737a6f12e8d5e86a3247f2c9444f b/src/fuzz/server_no_fuzzer_mode_corpus/5d04402a860b737a6f12e8d5e86a3247f2c9444f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5d04402a860b737a6f12e8d5e86a3247f2c9444f
rename to src/fuzz/server_no_fuzzer_mode_corpus/5d04402a860b737a6f12e8d5e86a3247f2c9444f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5d6384b5248f87e4ef42af56a4ee44de9c9b80b8 b/src/fuzz/server_no_fuzzer_mode_corpus/5d6384b5248f87e4ef42af56a4ee44de9c9b80b8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5d6384b5248f87e4ef42af56a4ee44de9c9b80b8
rename to src/fuzz/server_no_fuzzer_mode_corpus/5d6384b5248f87e4ef42af56a4ee44de9c9b80b8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5d6f2716b2dae48229e5f459b1d2d591c44a6d53 b/src/fuzz/server_no_fuzzer_mode_corpus/5d6f2716b2dae48229e5f459b1d2d591c44a6d53
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5d6f2716b2dae48229e5f459b1d2d591c44a6d53
rename to src/fuzz/server_no_fuzzer_mode_corpus/5d6f2716b2dae48229e5f459b1d2d591c44a6d53
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5d8b9c2f571f945a671465f9d707532342c707d0 b/src/fuzz/server_no_fuzzer_mode_corpus/5d8b9c2f571f945a671465f9d707532342c707d0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5d8b9c2f571f945a671465f9d707532342c707d0
rename to src/fuzz/server_no_fuzzer_mode_corpus/5d8b9c2f571f945a671465f9d707532342c707d0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5d9d829821ed03338ab892d38b4479dfeeee663d b/src/fuzz/server_no_fuzzer_mode_corpus/5d9d829821ed03338ab892d38b4479dfeeee663d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5d9d829821ed03338ab892d38b4479dfeeee663d
rename to src/fuzz/server_no_fuzzer_mode_corpus/5d9d829821ed03338ab892d38b4479dfeeee663d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5dc9d42eb49d3223281248ac3d6d0f7ba3037dce b/src/fuzz/server_no_fuzzer_mode_corpus/5dc9d42eb49d3223281248ac3d6d0f7ba3037dce
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5dc9d42eb49d3223281248ac3d6d0f7ba3037dce
rename to src/fuzz/server_no_fuzzer_mode_corpus/5dc9d42eb49d3223281248ac3d6d0f7ba3037dce
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5dd145b1b92c4f903e7d75b24e9b452743205e9f b/src/fuzz/server_no_fuzzer_mode_corpus/5dd145b1b92c4f903e7d75b24e9b452743205e9f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5dd145b1b92c4f903e7d75b24e9b452743205e9f
rename to src/fuzz/server_no_fuzzer_mode_corpus/5dd145b1b92c4f903e7d75b24e9b452743205e9f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5e1cf62ca22f839bbc2c61e2e1bb2e7e81ed7bee b/src/fuzz/server_no_fuzzer_mode_corpus/5e1cf62ca22f839bbc2c61e2e1bb2e7e81ed7bee
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5e1cf62ca22f839bbc2c61e2e1bb2e7e81ed7bee
rename to src/fuzz/server_no_fuzzer_mode_corpus/5e1cf62ca22f839bbc2c61e2e1bb2e7e81ed7bee
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5e57a0141d2b14d0739ac0b8a02db9da1cda661d b/src/fuzz/server_no_fuzzer_mode_corpus/5e57a0141d2b14d0739ac0b8a02db9da1cda661d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5e57a0141d2b14d0739ac0b8a02db9da1cda661d
rename to src/fuzz/server_no_fuzzer_mode_corpus/5e57a0141d2b14d0739ac0b8a02db9da1cda661d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5ee0835e4c227fb2e2a9d83a4197c04bf80a34bb b/src/fuzz/server_no_fuzzer_mode_corpus/5ee0835e4c227fb2e2a9d83a4197c04bf80a34bb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5ee0835e4c227fb2e2a9d83a4197c04bf80a34bb
rename to src/fuzz/server_no_fuzzer_mode_corpus/5ee0835e4c227fb2e2a9d83a4197c04bf80a34bb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5ef8b90c3ef4ffb0e87ad987f5ce573e3650e68e b/src/fuzz/server_no_fuzzer_mode_corpus/5ef8b90c3ef4ffb0e87ad987f5ce573e3650e68e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5ef8b90c3ef4ffb0e87ad987f5ce573e3650e68e
rename to src/fuzz/server_no_fuzzer_mode_corpus/5ef8b90c3ef4ffb0e87ad987f5ce573e3650e68e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/5f46dd35ce756a42da7e301b0f85df2e533cc422 b/src/fuzz/server_no_fuzzer_mode_corpus/5f46dd35ce756a42da7e301b0f85df2e533cc422
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/5f46dd35ce756a42da7e301b0f85df2e533cc422
rename to src/fuzz/server_no_fuzzer_mode_corpus/5f46dd35ce756a42da7e301b0f85df2e533cc422
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6074ec8f2be2b2a160055368337aa9c88445b8cc b/src/fuzz/server_no_fuzzer_mode_corpus/6074ec8f2be2b2a160055368337aa9c88445b8cc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6074ec8f2be2b2a160055368337aa9c88445b8cc
rename to src/fuzz/server_no_fuzzer_mode_corpus/6074ec8f2be2b2a160055368337aa9c88445b8cc
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6088101bb24a4f3215d8cd54ce65c98ac25b2a4a b/src/fuzz/server_no_fuzzer_mode_corpus/6088101bb24a4f3215d8cd54ce65c98ac25b2a4a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6088101bb24a4f3215d8cd54ce65c98ac25b2a4a
rename to src/fuzz/server_no_fuzzer_mode_corpus/6088101bb24a4f3215d8cd54ce65c98ac25b2a4a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/60e32d6e31df066ecf0f393014c52b788f6810ba b/src/fuzz/server_no_fuzzer_mode_corpus/60e32d6e31df066ecf0f393014c52b788f6810ba
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/60e32d6e31df066ecf0f393014c52b788f6810ba
rename to src/fuzz/server_no_fuzzer_mode_corpus/60e32d6e31df066ecf0f393014c52b788f6810ba
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/611bff1395d37cfebe40961126bcada5aeb9a3ef b/src/fuzz/server_no_fuzzer_mode_corpus/611bff1395d37cfebe40961126bcada5aeb9a3ef
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/611bff1395d37cfebe40961126bcada5aeb9a3ef
rename to src/fuzz/server_no_fuzzer_mode_corpus/611bff1395d37cfebe40961126bcada5aeb9a3ef
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/618bdf7184839285341c130bc68eaf3f87ef03cb b/src/fuzz/server_no_fuzzer_mode_corpus/618bdf7184839285341c130bc68eaf3f87ef03cb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/618bdf7184839285341c130bc68eaf3f87ef03cb
rename to src/fuzz/server_no_fuzzer_mode_corpus/618bdf7184839285341c130bc68eaf3f87ef03cb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/626996d0b8bc362a6f8a538516f373eb1a771482 b/src/fuzz/server_no_fuzzer_mode_corpus/626996d0b8bc362a6f8a538516f373eb1a771482
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/626996d0b8bc362a6f8a538516f373eb1a771482
rename to src/fuzz/server_no_fuzzer_mode_corpus/626996d0b8bc362a6f8a538516f373eb1a771482
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/64a901854f4211fdc0be06215ff1bdb427e22d27 b/src/fuzz/server_no_fuzzer_mode_corpus/64a901854f4211fdc0be06215ff1bdb427e22d27
new file mode 100644
index 0000000..8f3d617
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/64a901854f4211fdc0be06215ff1bdb427e22d27
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/660d46a5e4194cd5c80bc4f5b30ca23708dc727a b/src/fuzz/server_no_fuzzer_mode_corpus/660d46a5e4194cd5c80bc4f5b30ca23708dc727a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/660d46a5e4194cd5c80bc4f5b30ca23708dc727a
rename to src/fuzz/server_no_fuzzer_mode_corpus/660d46a5e4194cd5c80bc4f5b30ca23708dc727a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/669e7413977900e1a1611c9c941989c765c4e236 b/src/fuzz/server_no_fuzzer_mode_corpus/669e7413977900e1a1611c9c941989c765c4e236
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/669e7413977900e1a1611c9c941989c765c4e236
rename to src/fuzz/server_no_fuzzer_mode_corpus/669e7413977900e1a1611c9c941989c765c4e236
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b b/src/fuzz/server_no_fuzzer_mode_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b
new file mode 100644
index 0000000..9fa4a3a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/676c8a4f39c2bef17ec5bfb80ef128c22325953b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/67816ae7bf8c7c76cb2fcd60c2cea995f2f85c29 b/src/fuzz/server_no_fuzzer_mode_corpus/67816ae7bf8c7c76cb2fcd60c2cea995f2f85c29
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/67816ae7bf8c7c76cb2fcd60c2cea995f2f85c29
rename to src/fuzz/server_no_fuzzer_mode_corpus/67816ae7bf8c7c76cb2fcd60c2cea995f2f85c29
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6795fbbd10b982336bc6fdf18fedd5540e1cdb5e b/src/fuzz/server_no_fuzzer_mode_corpus/6795fbbd10b982336bc6fdf18fedd5540e1cdb5e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6795fbbd10b982336bc6fdf18fedd5540e1cdb5e
rename to src/fuzz/server_no_fuzzer_mode_corpus/6795fbbd10b982336bc6fdf18fedd5540e1cdb5e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/67f9f9f0c5dc571443548dee3eaa43e5da943ed5 b/src/fuzz/server_no_fuzzer_mode_corpus/67f9f9f0c5dc571443548dee3eaa43e5da943ed5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/67f9f9f0c5dc571443548dee3eaa43e5da943ed5
rename to src/fuzz/server_no_fuzzer_mode_corpus/67f9f9f0c5dc571443548dee3eaa43e5da943ed5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6a46272294a3c8cb305211f0e4897521f4fd0396 b/src/fuzz/server_no_fuzzer_mode_corpus/6a46272294a3c8cb305211f0e4897521f4fd0396
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6a46272294a3c8cb305211f0e4897521f4fd0396
rename to src/fuzz/server_no_fuzzer_mode_corpus/6a46272294a3c8cb305211f0e4897521f4fd0396
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6a5610536c842736fa7f3582504f10f3c2218ab2 b/src/fuzz/server_no_fuzzer_mode_corpus/6a5610536c842736fa7f3582504f10f3c2218ab2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6a5610536c842736fa7f3582504f10f3c2218ab2
rename to src/fuzz/server_no_fuzzer_mode_corpus/6a5610536c842736fa7f3582504f10f3c2218ab2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6adf86bf945a72fcca8ef6b7bd182703c941ec58 b/src/fuzz/server_no_fuzzer_mode_corpus/6adf86bf945a72fcca8ef6b7bd182703c941ec58
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6adf86bf945a72fcca8ef6b7bd182703c941ec58
rename to src/fuzz/server_no_fuzzer_mode_corpus/6adf86bf945a72fcca8ef6b7bd182703c941ec58
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6b7e5431e0a8f9d8e3db01c42bcdb7caef5579b5 b/src/fuzz/server_no_fuzzer_mode_corpus/6b7e5431e0a8f9d8e3db01c42bcdb7caef5579b5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6b7e5431e0a8f9d8e3db01c42bcdb7caef5579b5
rename to src/fuzz/server_no_fuzzer_mode_corpus/6b7e5431e0a8f9d8e3db01c42bcdb7caef5579b5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6dc59cee133378570b955b045aae46d189bfede9 b/src/fuzz/server_no_fuzzer_mode_corpus/6dc59cee133378570b955b045aae46d189bfede9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6dc59cee133378570b955b045aae46d189bfede9
rename to src/fuzz/server_no_fuzzer_mode_corpus/6dc59cee133378570b955b045aae46d189bfede9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6f72491711e69a5ede3650b189f27c8e0e51c6dc b/src/fuzz/server_no_fuzzer_mode_corpus/6f72491711e69a5ede3650b189f27c8e0e51c6dc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6f72491711e69a5ede3650b189f27c8e0e51c6dc
rename to src/fuzz/server_no_fuzzer_mode_corpus/6f72491711e69a5ede3650b189f27c8e0e51c6dc
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/6f89bf28647f655108d51837b98bf20821497a31 b/src/fuzz/server_no_fuzzer_mode_corpus/6f89bf28647f655108d51837b98bf20821497a31
new file mode 100644
index 0000000..16f2a13
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/6f89bf28647f655108d51837b98bf20821497a31
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/6fe2a9faf86292a05c8ef3ae87dddce4b59366b0 b/src/fuzz/server_no_fuzzer_mode_corpus/6fe2a9faf86292a05c8ef3ae87dddce4b59366b0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/6fe2a9faf86292a05c8ef3ae87dddce4b59366b0
rename to src/fuzz/server_no_fuzzer_mode_corpus/6fe2a9faf86292a05c8ef3ae87dddce4b59366b0
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/7055ce13e1f6c1841168aa8a33655fae1c703ef3 b/src/fuzz/server_no_fuzzer_mode_corpus/7055ce13e1f6c1841168aa8a33655fae1c703ef3
new file mode 100644
index 0000000..fee91a0
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/7055ce13e1f6c1841168aa8a33655fae1c703ef3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/707b0f1ccd8a88377f0fa0d4feb395c662a0a120 b/src/fuzz/server_no_fuzzer_mode_corpus/707b0f1ccd8a88377f0fa0d4feb395c662a0a120
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/707b0f1ccd8a88377f0fa0d4feb395c662a0a120
rename to src/fuzz/server_no_fuzzer_mode_corpus/707b0f1ccd8a88377f0fa0d4feb395c662a0a120
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/71178ffc0f7263e9825d6a6fc402fe1e37df8f9b b/src/fuzz/server_no_fuzzer_mode_corpus/71178ffc0f7263e9825d6a6fc402fe1e37df8f9b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/71178ffc0f7263e9825d6a6fc402fe1e37df8f9b
rename to src/fuzz/server_no_fuzzer_mode_corpus/71178ffc0f7263e9825d6a6fc402fe1e37df8f9b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/718403e68916dc47ab71e8546465e3e8a0cb09c1 b/src/fuzz/server_no_fuzzer_mode_corpus/718403e68916dc47ab71e8546465e3e8a0cb09c1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/718403e68916dc47ab71e8546465e3e8a0cb09c1
rename to src/fuzz/server_no_fuzzer_mode_corpus/718403e68916dc47ab71e8546465e3e8a0cb09c1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/718487afa1d377f123c6756bd3251b181b0b5879 b/src/fuzz/server_no_fuzzer_mode_corpus/718487afa1d377f123c6756bd3251b181b0b5879
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/718487afa1d377f123c6756bd3251b181b0b5879
rename to src/fuzz/server_no_fuzzer_mode_corpus/718487afa1d377f123c6756bd3251b181b0b5879
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/736e50c5689e7cbb2f0b380a6748a0c7cc080dfa b/src/fuzz/server_no_fuzzer_mode_corpus/736e50c5689e7cbb2f0b380a6748a0c7cc080dfa
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/736e50c5689e7cbb2f0b380a6748a0c7cc080dfa
rename to src/fuzz/server_no_fuzzer_mode_corpus/736e50c5689e7cbb2f0b380a6748a0c7cc080dfa
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/756cae31cc203e8b73481e667ce714f794413526 b/src/fuzz/server_no_fuzzer_mode_corpus/756cae31cc203e8b73481e667ce714f794413526
new file mode 100644
index 0000000..2011b8a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/756cae31cc203e8b73481e667ce714f794413526
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b b/src/fuzz/server_no_fuzzer_mode_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b
new file mode 100644
index 0000000..21688ed
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/75d0c720e59ff8e03c3b506c5e17a4845c88464b
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/75ebf6152695e8160a9765b8f3f23349f34bef7d b/src/fuzz/server_no_fuzzer_mode_corpus/75ebf6152695e8160a9765b8f3f23349f34bef7d
new file mode 100644
index 0000000..a2f3c3c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/75ebf6152695e8160a9765b8f3f23349f34bef7d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/76004034fcbe63d7e8a6a75770d437995b8237cf b/src/fuzz/server_no_fuzzer_mode_corpus/76004034fcbe63d7e8a6a75770d437995b8237cf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/76004034fcbe63d7e8a6a75770d437995b8237cf
rename to src/fuzz/server_no_fuzzer_mode_corpus/76004034fcbe63d7e8a6a75770d437995b8237cf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/766c3f823846075e032780a90c901b1ca9f34b33 b/src/fuzz/server_no_fuzzer_mode_corpus/766c3f823846075e032780a90c901b1ca9f34b33
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/766c3f823846075e032780a90c901b1ca9f34b33
rename to src/fuzz/server_no_fuzzer_mode_corpus/766c3f823846075e032780a90c901b1ca9f34b33
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7805d9a0fcc60059aa961104b53631df4baded7d b/src/fuzz/server_no_fuzzer_mode_corpus/7805d9a0fcc60059aa961104b53631df4baded7d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7805d9a0fcc60059aa961104b53631df4baded7d
rename to src/fuzz/server_no_fuzzer_mode_corpus/7805d9a0fcc60059aa961104b53631df4baded7d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/78453b23ede1f62b308ebf6330c999304c0fa50c b/src/fuzz/server_no_fuzzer_mode_corpus/78453b23ede1f62b308ebf6330c999304c0fa50c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/78453b23ede1f62b308ebf6330c999304c0fa50c
rename to src/fuzz/server_no_fuzzer_mode_corpus/78453b23ede1f62b308ebf6330c999304c0fa50c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/79c21d4627814845abb47f422f55dce52396e471 b/src/fuzz/server_no_fuzzer_mode_corpus/79c21d4627814845abb47f422f55dce52396e471
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/79c21d4627814845abb47f422f55dce52396e471
rename to src/fuzz/server_no_fuzzer_mode_corpus/79c21d4627814845abb47f422f55dce52396e471
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7b976de73f25c7fde1bdf9a7e1b1d690c90eac8c b/src/fuzz/server_no_fuzzer_mode_corpus/7b976de73f25c7fde1bdf9a7e1b1d690c90eac8c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7b976de73f25c7fde1bdf9a7e1b1d690c90eac8c
rename to src/fuzz/server_no_fuzzer_mode_corpus/7b976de73f25c7fde1bdf9a7e1b1d690c90eac8c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7d432b7e92184ce59d40f0980b6519878076c0bf b/src/fuzz/server_no_fuzzer_mode_corpus/7d432b7e92184ce59d40f0980b6519878076c0bf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7d432b7e92184ce59d40f0980b6519878076c0bf
rename to src/fuzz/server_no_fuzzer_mode_corpus/7d432b7e92184ce59d40f0980b6519878076c0bf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7d943509937db131b9d406715007444de7dfa0e0 b/src/fuzz/server_no_fuzzer_mode_corpus/7d943509937db131b9d406715007444de7dfa0e0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7d943509937db131b9d406715007444de7dfa0e0
rename to src/fuzz/server_no_fuzzer_mode_corpus/7d943509937db131b9d406715007444de7dfa0e0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7dc5dbb29d21ff78bb6816b3abc638251aa025a8 b/src/fuzz/server_no_fuzzer_mode_corpus/7dc5dbb29d21ff78bb6816b3abc638251aa025a8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7dc5dbb29d21ff78bb6816b3abc638251aa025a8
rename to src/fuzz/server_no_fuzzer_mode_corpus/7dc5dbb29d21ff78bb6816b3abc638251aa025a8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7e717339a399dd1ab377076e6fbd3ae53bd0533b b/src/fuzz/server_no_fuzzer_mode_corpus/7e717339a399dd1ab377076e6fbd3ae53bd0533b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7e717339a399dd1ab377076e6fbd3ae53bd0533b
rename to src/fuzz/server_no_fuzzer_mode_corpus/7e717339a399dd1ab377076e6fbd3ae53bd0533b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7e8ece78856f6d3d8e7dbf93dcc607615954f806 b/src/fuzz/server_no_fuzzer_mode_corpus/7e8ece78856f6d3d8e7dbf93dcc607615954f806
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7e8ece78856f6d3d8e7dbf93dcc607615954f806
rename to src/fuzz/server_no_fuzzer_mode_corpus/7e8ece78856f6d3d8e7dbf93dcc607615954f806
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/7f6cb4c8c0aa983b6d4d92738e7725a314ccf21e b/src/fuzz/server_no_fuzzer_mode_corpus/7f6cb4c8c0aa983b6d4d92738e7725a314ccf21e
new file mode 100644
index 0000000..8a0a900
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/7f6cb4c8c0aa983b6d4d92738e7725a314ccf21e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/7fbbd3611f4745dd11326b9aa98789fdd5317226 b/src/fuzz/server_no_fuzzer_mode_corpus/7fbbd3611f4745dd11326b9aa98789fdd5317226
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/7fbbd3611f4745dd11326b9aa98789fdd5317226
rename to src/fuzz/server_no_fuzzer_mode_corpus/7fbbd3611f4745dd11326b9aa98789fdd5317226
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/80b0fd23e419bc63185b219828876a0a799e9292 b/src/fuzz/server_no_fuzzer_mode_corpus/80b0fd23e419bc63185b219828876a0a799e9292
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/80b0fd23e419bc63185b219828876a0a799e9292
rename to src/fuzz/server_no_fuzzer_mode_corpus/80b0fd23e419bc63185b219828876a0a799e9292
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/80b62afd604052f368219c4ecf68cb13b5949e8e b/src/fuzz/server_no_fuzzer_mode_corpus/80b62afd604052f368219c4ecf68cb13b5949e8e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/80b62afd604052f368219c4ecf68cb13b5949e8e
rename to src/fuzz/server_no_fuzzer_mode_corpus/80b62afd604052f368219c4ecf68cb13b5949e8e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/821fbdcc1dae7f2e165d8612c216cb9f87c993b9 b/src/fuzz/server_no_fuzzer_mode_corpus/821fbdcc1dae7f2e165d8612c216cb9f87c993b9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/821fbdcc1dae7f2e165d8612c216cb9f87c993b9
rename to src/fuzz/server_no_fuzzer_mode_corpus/821fbdcc1dae7f2e165d8612c216cb9f87c993b9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/822842ea89615192b041877e7a75fd41c2e82790 b/src/fuzz/server_no_fuzzer_mode_corpus/822842ea89615192b041877e7a75fd41c2e82790
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/822842ea89615192b041877e7a75fd41c2e82790
rename to src/fuzz/server_no_fuzzer_mode_corpus/822842ea89615192b041877e7a75fd41c2e82790
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/83127908faab278f20ab9bb6187c3a7de9141bb2 b/src/fuzz/server_no_fuzzer_mode_corpus/83127908faab278f20ab9bb6187c3a7de9141bb2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/83127908faab278f20ab9bb6187c3a7de9141bb2
rename to src/fuzz/server_no_fuzzer_mode_corpus/83127908faab278f20ab9bb6187c3a7de9141bb2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/83de936cbeff0cf860fdcfb2977d79e8475a47a1 b/src/fuzz/server_no_fuzzer_mode_corpus/83de936cbeff0cf860fdcfb2977d79e8475a47a1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/83de936cbeff0cf860fdcfb2977d79e8475a47a1
rename to src/fuzz/server_no_fuzzer_mode_corpus/83de936cbeff0cf860fdcfb2977d79e8475a47a1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/843ae2ae8e64013b78ae489cd8223e3576e73453 b/src/fuzz/server_no_fuzzer_mode_corpus/843ae2ae8e64013b78ae489cd8223e3576e73453
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/843ae2ae8e64013b78ae489cd8223e3576e73453
rename to src/fuzz/server_no_fuzzer_mode_corpus/843ae2ae8e64013b78ae489cd8223e3576e73453
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/854e7723cc5226072b5b9353200431a9cca34f1c b/src/fuzz/server_no_fuzzer_mode_corpus/854e7723cc5226072b5b9353200431a9cca34f1c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/854e7723cc5226072b5b9353200431a9cca34f1c
rename to src/fuzz/server_no_fuzzer_mode_corpus/854e7723cc5226072b5b9353200431a9cca34f1c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/856717f6e978ed5dc06d3e98f819becf360a0c8f b/src/fuzz/server_no_fuzzer_mode_corpus/856717f6e978ed5dc06d3e98f819becf360a0c8f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/856717f6e978ed5dc06d3e98f819becf360a0c8f
rename to src/fuzz/server_no_fuzzer_mode_corpus/856717f6e978ed5dc06d3e98f819becf360a0c8f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/85f12f993c076a451c8a93b4d83ca01acb2784dd b/src/fuzz/server_no_fuzzer_mode_corpus/85f12f993c076a451c8a93b4d83ca01acb2784dd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/85f12f993c076a451c8a93b4d83ca01acb2784dd
rename to src/fuzz/server_no_fuzzer_mode_corpus/85f12f993c076a451c8a93b4d83ca01acb2784dd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/860fa3d88cc39d5a9c008c5e451e746238ac1bdd b/src/fuzz/server_no_fuzzer_mode_corpus/860fa3d88cc39d5a9c008c5e451e746238ac1bdd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/860fa3d88cc39d5a9c008c5e451e746238ac1bdd
rename to src/fuzz/server_no_fuzzer_mode_corpus/860fa3d88cc39d5a9c008c5e451e746238ac1bdd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/86274c56c95f710d955eecf162f466e7ee48dde6 b/src/fuzz/server_no_fuzzer_mode_corpus/86274c56c95f710d955eecf162f466e7ee48dde6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/86274c56c95f710d955eecf162f466e7ee48dde6
rename to src/fuzz/server_no_fuzzer_mode_corpus/86274c56c95f710d955eecf162f466e7ee48dde6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8721de4079859692cfb630adc2ebb1d93affdf67 b/src/fuzz/server_no_fuzzer_mode_corpus/8721de4079859692cfb630adc2ebb1d93affdf67
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8721de4079859692cfb630adc2ebb1d93affdf67
rename to src/fuzz/server_no_fuzzer_mode_corpus/8721de4079859692cfb630adc2ebb1d93affdf67
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/877acade5135a842fa32414c9de11e39e62276bd b/src/fuzz/server_no_fuzzer_mode_corpus/877acade5135a842fa32414c9de11e39e62276bd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/877acade5135a842fa32414c9de11e39e62276bd
rename to src/fuzz/server_no_fuzzer_mode_corpus/877acade5135a842fa32414c9de11e39e62276bd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/879869086d669960666b14d379affcc3acedc3c7 b/src/fuzz/server_no_fuzzer_mode_corpus/879869086d669960666b14d379affcc3acedc3c7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/879869086d669960666b14d379affcc3acedc3c7
rename to src/fuzz/server_no_fuzzer_mode_corpus/879869086d669960666b14d379affcc3acedc3c7
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/88e3c6bbe38fe2359327308f3492ac1902d35c1b b/src/fuzz/server_no_fuzzer_mode_corpus/88e3c6bbe38fe2359327308f3492ac1902d35c1b
new file mode 100644
index 0000000..cb95f91
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/88e3c6bbe38fe2359327308f3492ac1902d35c1b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/88fbadaa4011de66b7de55d7f1a5ac92f7f9ad5e b/src/fuzz/server_no_fuzzer_mode_corpus/88fbadaa4011de66b7de55d7f1a5ac92f7f9ad5e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/88fbadaa4011de66b7de55d7f1a5ac92f7f9ad5e
rename to src/fuzz/server_no_fuzzer_mode_corpus/88fbadaa4011de66b7de55d7f1a5ac92f7f9ad5e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8a046e8af539745b3fa115d1332db059da5228bf b/src/fuzz/server_no_fuzzer_mode_corpus/8a046e8af539745b3fa115d1332db059da5228bf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8a046e8af539745b3fa115d1332db059da5228bf
rename to src/fuzz/server_no_fuzzer_mode_corpus/8a046e8af539745b3fa115d1332db059da5228bf
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/8a06ce6fc9fb00b63dd1920d9d443c5ebc6f6b3d b/src/fuzz/server_no_fuzzer_mode_corpus/8a06ce6fc9fb00b63dd1920d9d443c5ebc6f6b3d
new file mode 100644
index 0000000..a7b3efc
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/8a06ce6fc9fb00b63dd1920d9d443c5ebc6f6b3d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8a19f558c0b396a1772c85d64fb6c6f5bd8f269e b/src/fuzz/server_no_fuzzer_mode_corpus/8a19f558c0b396a1772c85d64fb6c6f5bd8f269e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8a19f558c0b396a1772c85d64fb6c6f5bd8f269e
rename to src/fuzz/server_no_fuzzer_mode_corpus/8a19f558c0b396a1772c85d64fb6c6f5bd8f269e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8a1a7fa937593cb98656fb6ea85d2619237cb0c2 b/src/fuzz/server_no_fuzzer_mode_corpus/8a1a7fa937593cb98656fb6ea85d2619237cb0c2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8a1a7fa937593cb98656fb6ea85d2619237cb0c2
rename to src/fuzz/server_no_fuzzer_mode_corpus/8a1a7fa937593cb98656fb6ea85d2619237cb0c2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8b41db3a58cfcc484be4b1eacd8cc9f1264090ab b/src/fuzz/server_no_fuzzer_mode_corpus/8b41db3a58cfcc484be4b1eacd8cc9f1264090ab
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8b41db3a58cfcc484be4b1eacd8cc9f1264090ab
rename to src/fuzz/server_no_fuzzer_mode_corpus/8b41db3a58cfcc484be4b1eacd8cc9f1264090ab
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8ba3ad4f520f6fbfeb1fda66fb312f92b5e52d37 b/src/fuzz/server_no_fuzzer_mode_corpus/8ba3ad4f520f6fbfeb1fda66fb312f92b5e52d37
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8ba3ad4f520f6fbfeb1fda66fb312f92b5e52d37
rename to src/fuzz/server_no_fuzzer_mode_corpus/8ba3ad4f520f6fbfeb1fda66fb312f92b5e52d37
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8bc2ed3ea8079724e11704db483b5fd627b2340c b/src/fuzz/server_no_fuzzer_mode_corpus/8bc2ed3ea8079724e11704db483b5fd627b2340c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8bc2ed3ea8079724e11704db483b5fd627b2340c
rename to src/fuzz/server_no_fuzzer_mode_corpus/8bc2ed3ea8079724e11704db483b5fd627b2340c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8c0a2f5793f148ca0782f2ba9c3f6633f7d99806 b/src/fuzz/server_no_fuzzer_mode_corpus/8c0a2f5793f148ca0782f2ba9c3f6633f7d99806
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8c0a2f5793f148ca0782f2ba9c3f6633f7d99806
rename to src/fuzz/server_no_fuzzer_mode_corpus/8c0a2f5793f148ca0782f2ba9c3f6633f7d99806
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8c79943f1258629438d0f2e7a596a53f9fa4714a b/src/fuzz/server_no_fuzzer_mode_corpus/8c79943f1258629438d0f2e7a596a53f9fa4714a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8c79943f1258629438d0f2e7a596a53f9fa4714a
rename to src/fuzz/server_no_fuzzer_mode_corpus/8c79943f1258629438d0f2e7a596a53f9fa4714a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8d2143c6d4bd2ce07101389222acc1f39be47f3f b/src/fuzz/server_no_fuzzer_mode_corpus/8d2143c6d4bd2ce07101389222acc1f39be47f3f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8d2143c6d4bd2ce07101389222acc1f39be47f3f
rename to src/fuzz/server_no_fuzzer_mode_corpus/8d2143c6d4bd2ce07101389222acc1f39be47f3f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8e99da49c383818a60e748d408303bed43812a12 b/src/fuzz/server_no_fuzzer_mode_corpus/8e99da49c383818a60e748d408303bed43812a12
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8e99da49c383818a60e748d408303bed43812a12
rename to src/fuzz/server_no_fuzzer_mode_corpus/8e99da49c383818a60e748d408303bed43812a12
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/8eb4f628da35d5bdd81e927d30d1143e9a05d35b b/src/fuzz/server_no_fuzzer_mode_corpus/8eb4f628da35d5bdd81e927d30d1143e9a05d35b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/8eb4f628da35d5bdd81e927d30d1143e9a05d35b
rename to src/fuzz/server_no_fuzzer_mode_corpus/8eb4f628da35d5bdd81e927d30d1143e9a05d35b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9016681d920295065e90ff3cfc2d7f17bb54222d b/src/fuzz/server_no_fuzzer_mode_corpus/9016681d920295065e90ff3cfc2d7f17bb54222d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9016681d920295065e90ff3cfc2d7f17bb54222d
rename to src/fuzz/server_no_fuzzer_mode_corpus/9016681d920295065e90ff3cfc2d7f17bb54222d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9072ecf76bc288e26aa74c1ca5118a73563fe219 b/src/fuzz/server_no_fuzzer_mode_corpus/9072ecf76bc288e26aa74c1ca5118a73563fe219
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9072ecf76bc288e26aa74c1ca5118a73563fe219
rename to src/fuzz/server_no_fuzzer_mode_corpus/9072ecf76bc288e26aa74c1ca5118a73563fe219
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/90d7ff2d7fd456c8126226f41b65a84e0a1d7d33 b/src/fuzz/server_no_fuzzer_mode_corpus/90d7ff2d7fd456c8126226f41b65a84e0a1d7d33
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/90d7ff2d7fd456c8126226f41b65a84e0a1d7d33
rename to src/fuzz/server_no_fuzzer_mode_corpus/90d7ff2d7fd456c8126226f41b65a84e0a1d7d33
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/91187d13c0deebb8ac9a3f6f8aac183e37b74ad6 b/src/fuzz/server_no_fuzzer_mode_corpus/91187d13c0deebb8ac9a3f6f8aac183e37b74ad6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/91187d13c0deebb8ac9a3f6f8aac183e37b74ad6
rename to src/fuzz/server_no_fuzzer_mode_corpus/91187d13c0deebb8ac9a3f6f8aac183e37b74ad6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/912c06b53d4e9fd7c1d2c97b1dcdd1a1144a5566 b/src/fuzz/server_no_fuzzer_mode_corpus/912c06b53d4e9fd7c1d2c97b1dcdd1a1144a5566
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/912c06b53d4e9fd7c1d2c97b1dcdd1a1144a5566
rename to src/fuzz/server_no_fuzzer_mode_corpus/912c06b53d4e9fd7c1d2c97b1dcdd1a1144a5566
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/91429029b2a72dd8a669720e5744413e5885613f b/src/fuzz/server_no_fuzzer_mode_corpus/91429029b2a72dd8a669720e5744413e5885613f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/91429029b2a72dd8a669720e5744413e5885613f
rename to src/fuzz/server_no_fuzzer_mode_corpus/91429029b2a72dd8a669720e5744413e5885613f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/920eae0f62f4e7e9315ec2c04133d6f7a9b5d94b b/src/fuzz/server_no_fuzzer_mode_corpus/920eae0f62f4e7e9315ec2c04133d6f7a9b5d94b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/920eae0f62f4e7e9315ec2c04133d6f7a9b5d94b
rename to src/fuzz/server_no_fuzzer_mode_corpus/920eae0f62f4e7e9315ec2c04133d6f7a9b5d94b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/92dc5d17326a519fdf94b4cf940533f428dbf03b b/src/fuzz/server_no_fuzzer_mode_corpus/92dc5d17326a519fdf94b4cf940533f428dbf03b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/92dc5d17326a519fdf94b4cf940533f428dbf03b
rename to src/fuzz/server_no_fuzzer_mode_corpus/92dc5d17326a519fdf94b4cf940533f428dbf03b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/932e116423a150bd4040058c62ae81b943e8c850 b/src/fuzz/server_no_fuzzer_mode_corpus/932e116423a150bd4040058c62ae81b943e8c850
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/932e116423a150bd4040058c62ae81b943e8c850
rename to src/fuzz/server_no_fuzzer_mode_corpus/932e116423a150bd4040058c62ae81b943e8c850
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/93414030e49fca198d8f7260e62a469f4be07376 b/src/fuzz/server_no_fuzzer_mode_corpus/93414030e49fca198d8f7260e62a469f4be07376
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/93414030e49fca198d8f7260e62a469f4be07376
rename to src/fuzz/server_no_fuzzer_mode_corpus/93414030e49fca198d8f7260e62a469f4be07376
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/93b6cf4454b478278eb8eaf0d160cebea6f8d79b b/src/fuzz/server_no_fuzzer_mode_corpus/93b6cf4454b478278eb8eaf0d160cebea6f8d79b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/93b6cf4454b478278eb8eaf0d160cebea6f8d79b
rename to src/fuzz/server_no_fuzzer_mode_corpus/93b6cf4454b478278eb8eaf0d160cebea6f8d79b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9471e688d7bb3e3551645a38d3bb8efa89c599a6 b/src/fuzz/server_no_fuzzer_mode_corpus/9471e688d7bb3e3551645a38d3bb8efa89c599a6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9471e688d7bb3e3551645a38d3bb8efa89c599a6
rename to src/fuzz/server_no_fuzzer_mode_corpus/9471e688d7bb3e3551645a38d3bb8efa89c599a6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9489ab5adbb97ee605d3a85762347f259076616e b/src/fuzz/server_no_fuzzer_mode_corpus/9489ab5adbb97ee605d3a85762347f259076616e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9489ab5adbb97ee605d3a85762347f259076616e
rename to src/fuzz/server_no_fuzzer_mode_corpus/9489ab5adbb97ee605d3a85762347f259076616e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/94e110cf70bf139a282897fb2b33ccc7fcc72752 b/src/fuzz/server_no_fuzzer_mode_corpus/94e110cf70bf139a282897fb2b33ccc7fcc72752
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/94e110cf70bf139a282897fb2b33ccc7fcc72752
rename to src/fuzz/server_no_fuzzer_mode_corpus/94e110cf70bf139a282897fb2b33ccc7fcc72752
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/94fb12e2eeef46140ca841bcfa45ffcbacc7362e b/src/fuzz/server_no_fuzzer_mode_corpus/94fb12e2eeef46140ca841bcfa45ffcbacc7362e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/94fb12e2eeef46140ca841bcfa45ffcbacc7362e
rename to src/fuzz/server_no_fuzzer_mode_corpus/94fb12e2eeef46140ca841bcfa45ffcbacc7362e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9642dd10833e6e823fef684f682dfe196956ca9d b/src/fuzz/server_no_fuzzer_mode_corpus/9642dd10833e6e823fef684f682dfe196956ca9d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9642dd10833e6e823fef684f682dfe196956ca9d
rename to src/fuzz/server_no_fuzzer_mode_corpus/9642dd10833e6e823fef684f682dfe196956ca9d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/970fa798580d6f587d100df8d82a8a14045d04f3 b/src/fuzz/server_no_fuzzer_mode_corpus/970fa798580d6f587d100df8d82a8a14045d04f3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/970fa798580d6f587d100df8d82a8a14045d04f3
rename to src/fuzz/server_no_fuzzer_mode_corpus/970fa798580d6f587d100df8d82a8a14045d04f3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/97c24fc64a94260d54d427e731dd671d6ef1c87a b/src/fuzz/server_no_fuzzer_mode_corpus/97c24fc64a94260d54d427e731dd671d6ef1c87a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/97c24fc64a94260d54d427e731dd671d6ef1c87a
rename to src/fuzz/server_no_fuzzer_mode_corpus/97c24fc64a94260d54d427e731dd671d6ef1c87a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9811a62726742b957e45b31b4ac7813b69256cde b/src/fuzz/server_no_fuzzer_mode_corpus/9811a62726742b957e45b31b4ac7813b69256cde
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9811a62726742b957e45b31b4ac7813b69256cde
rename to src/fuzz/server_no_fuzzer_mode_corpus/9811a62726742b957e45b31b4ac7813b69256cde
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/981c0aa863e36f30c68b0e1515304e2e46fda0ae b/src/fuzz/server_no_fuzzer_mode_corpus/981c0aa863e36f30c68b0e1515304e2e46fda0ae
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/981c0aa863e36f30c68b0e1515304e2e46fda0ae
rename to src/fuzz/server_no_fuzzer_mode_corpus/981c0aa863e36f30c68b0e1515304e2e46fda0ae
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/987f62cdf4de7b4305821ca6b364e12ff6d2024e b/src/fuzz/server_no_fuzzer_mode_corpus/987f62cdf4de7b4305821ca6b364e12ff6d2024e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/987f62cdf4de7b4305821ca6b364e12ff6d2024e
rename to src/fuzz/server_no_fuzzer_mode_corpus/987f62cdf4de7b4305821ca6b364e12ff6d2024e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/997311e3ae79c132057c98a6d166deebdab69c71 b/src/fuzz/server_no_fuzzer_mode_corpus/997311e3ae79c132057c98a6d166deebdab69c71
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/997311e3ae79c132057c98a6d166deebdab69c71
rename to src/fuzz/server_no_fuzzer_mode_corpus/997311e3ae79c132057c98a6d166deebdab69c71
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/99862d97d721139bf4510838cc6ba6f88965f35f b/src/fuzz/server_no_fuzzer_mode_corpus/99862d97d721139bf4510838cc6ba6f88965f35f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/99862d97d721139bf4510838cc6ba6f88965f35f
rename to src/fuzz/server_no_fuzzer_mode_corpus/99862d97d721139bf4510838cc6ba6f88965f35f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9987df311d7c30432c4df8d14193c8f5236f58a2 b/src/fuzz/server_no_fuzzer_mode_corpus/9987df311d7c30432c4df8d14193c8f5236f58a2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9987df311d7c30432c4df8d14193c8f5236f58a2
rename to src/fuzz/server_no_fuzzer_mode_corpus/9987df311d7c30432c4df8d14193c8f5236f58a2
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/9a9fe018246f72cc3fd6692605e4fe534e168240 b/src/fuzz/server_no_fuzzer_mode_corpus/9a9fe018246f72cc3fd6692605e4fe534e168240
new file mode 100644
index 0000000..afae401
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/9a9fe018246f72cc3fd6692605e4fe534e168240
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9bc3038b0a30d90868ba599f7e44417e3dec7dfb b/src/fuzz/server_no_fuzzer_mode_corpus/9bc3038b0a30d90868ba599f7e44417e3dec7dfb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9bc3038b0a30d90868ba599f7e44417e3dec7dfb
rename to src/fuzz/server_no_fuzzer_mode_corpus/9bc3038b0a30d90868ba599f7e44417e3dec7dfb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9c34981b88a050357ca2db56e4062d73caf117f0 b/src/fuzz/server_no_fuzzer_mode_corpus/9c34981b88a050357ca2db56e4062d73caf117f0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9c34981b88a050357ca2db56e4062d73caf117f0
rename to src/fuzz/server_no_fuzzer_mode_corpus/9c34981b88a050357ca2db56e4062d73caf117f0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9c5fa0fc7080a2990f85ef48ec9c2d22f6e3af60 b/src/fuzz/server_no_fuzzer_mode_corpus/9c5fa0fc7080a2990f85ef48ec9c2d22f6e3af60
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9c5fa0fc7080a2990f85ef48ec9c2d22f6e3af60
rename to src/fuzz/server_no_fuzzer_mode_corpus/9c5fa0fc7080a2990f85ef48ec9c2d22f6e3af60
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9c922a546a18b59d7f4cf8bc5171ba10a66cd700 b/src/fuzz/server_no_fuzzer_mode_corpus/9c922a546a18b59d7f4cf8bc5171ba10a66cd700
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9c922a546a18b59d7f4cf8bc5171ba10a66cd700
rename to src/fuzz/server_no_fuzzer_mode_corpus/9c922a546a18b59d7f4cf8bc5171ba10a66cd700
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9d6fa1090c493ac01361927414ac0a49535c92ee b/src/fuzz/server_no_fuzzer_mode_corpus/9d6fa1090c493ac01361927414ac0a49535c92ee
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9d6fa1090c493ac01361927414ac0a49535c92ee
rename to src/fuzz/server_no_fuzzer_mode_corpus/9d6fa1090c493ac01361927414ac0a49535c92ee
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9d735b723b0ed2d4d433c00b613e14c28921f0f4 b/src/fuzz/server_no_fuzzer_mode_corpus/9d735b723b0ed2d4d433c00b613e14c28921f0f4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9d735b723b0ed2d4d433c00b613e14c28921f0f4
rename to src/fuzz/server_no_fuzzer_mode_corpus/9d735b723b0ed2d4d433c00b613e14c28921f0f4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/9e9c00e8f297955206b62ecd77638fd241b5da3a b/src/fuzz/server_no_fuzzer_mode_corpus/9e9c00e8f297955206b62ecd77638fd241b5da3a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/9e9c00e8f297955206b62ecd77638fd241b5da3a
rename to src/fuzz/server_no_fuzzer_mode_corpus/9e9c00e8f297955206b62ecd77638fd241b5da3a
Binary files differ
diff --git a/src/fuzz/server_corpus/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a b/src/fuzz/server_no_fuzzer_mode_corpus/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a
similarity index 100%
rename from src/fuzz/server_corpus/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a
rename to src/fuzz/server_no_fuzzer_mode_corpus/9eff0be6355a0c6c70e2e4aec16a6f0e17ef5b2a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a131c62b37efa169925184ed88dc9d7c886cf590 b/src/fuzz/server_no_fuzzer_mode_corpus/a131c62b37efa169925184ed88dc9d7c886cf590
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a131c62b37efa169925184ed88dc9d7c886cf590
rename to src/fuzz/server_no_fuzzer_mode_corpus/a131c62b37efa169925184ed88dc9d7c886cf590
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a159c0b29640bd5e21a9b82b2c38b5173d0e1f7a b/src/fuzz/server_no_fuzzer_mode_corpus/a159c0b29640bd5e21a9b82b2c38b5173d0e1f7a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a159c0b29640bd5e21a9b82b2c38b5173d0e1f7a
rename to src/fuzz/server_no_fuzzer_mode_corpus/a159c0b29640bd5e21a9b82b2c38b5173d0e1f7a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a1c0be5740d5410c8b35639b2bdd033f208168a9 b/src/fuzz/server_no_fuzzer_mode_corpus/a1c0be5740d5410c8b35639b2bdd033f208168a9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a1c0be5740d5410c8b35639b2bdd033f208168a9
rename to src/fuzz/server_no_fuzzer_mode_corpus/a1c0be5740d5410c8b35639b2bdd033f208168a9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a1fbaaac6d6560a1f3c4ca79062b6ace5c67e6cd b/src/fuzz/server_no_fuzzer_mode_corpus/a1fbaaac6d6560a1f3c4ca79062b6ace5c67e6cd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a1fbaaac6d6560a1f3c4ca79062b6ace5c67e6cd
rename to src/fuzz/server_no_fuzzer_mode_corpus/a1fbaaac6d6560a1f3c4ca79062b6ace5c67e6cd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a2c824d536d09f292644d246e16c4a02b4d57786 b/src/fuzz/server_no_fuzzer_mode_corpus/a2c824d536d09f292644d246e16c4a02b4d57786
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a2c824d536d09f292644d246e16c4a02b4d57786
rename to src/fuzz/server_no_fuzzer_mode_corpus/a2c824d536d09f292644d246e16c4a02b4d57786
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a3808ef364037ff1ad87b1134f0730e3b0e88c22 b/src/fuzz/server_no_fuzzer_mode_corpus/a3808ef364037ff1ad87b1134f0730e3b0e88c22
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a3808ef364037ff1ad87b1134f0730e3b0e88c22
rename to src/fuzz/server_no_fuzzer_mode_corpus/a3808ef364037ff1ad87b1134f0730e3b0e88c22
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a4025775158a7947f004d5c14d976cbb07f15ed8 b/src/fuzz/server_no_fuzzer_mode_corpus/a4025775158a7947f004d5c14d976cbb07f15ed8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a4025775158a7947f004d5c14d976cbb07f15ed8
rename to src/fuzz/server_no_fuzzer_mode_corpus/a4025775158a7947f004d5c14d976cbb07f15ed8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a4722ffec3db2c312ac095f50b356e25bfd65728 b/src/fuzz/server_no_fuzzer_mode_corpus/a4722ffec3db2c312ac095f50b356e25bfd65728
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a4722ffec3db2c312ac095f50b356e25bfd65728
rename to src/fuzz/server_no_fuzzer_mode_corpus/a4722ffec3db2c312ac095f50b356e25bfd65728
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a4e9e8471ce156a8b3fbfd6b6b87c42e2f164e33 b/src/fuzz/server_no_fuzzer_mode_corpus/a4e9e8471ce156a8b3fbfd6b6b87c42e2f164e33
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a4e9e8471ce156a8b3fbfd6b6b87c42e2f164e33
rename to src/fuzz/server_no_fuzzer_mode_corpus/a4e9e8471ce156a8b3fbfd6b6b87c42e2f164e33
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a5470fb0945d46ab47bbb42b9df384ea7a9f741b b/src/fuzz/server_no_fuzzer_mode_corpus/a5470fb0945d46ab47bbb42b9df384ea7a9f741b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a5470fb0945d46ab47bbb42b9df384ea7a9f741b
rename to src/fuzz/server_no_fuzzer_mode_corpus/a5470fb0945d46ab47bbb42b9df384ea7a9f741b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a6c3849c4b77bc0766159ccfb5c9c4f967670150 b/src/fuzz/server_no_fuzzer_mode_corpus/a6c3849c4b77bc0766159ccfb5c9c4f967670150
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a6c3849c4b77bc0766159ccfb5c9c4f967670150
rename to src/fuzz/server_no_fuzzer_mode_corpus/a6c3849c4b77bc0766159ccfb5c9c4f967670150
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a6e5bfddcb943a4bfa3b8824a9acdc259521bccf b/src/fuzz/server_no_fuzzer_mode_corpus/a6e5bfddcb943a4bfa3b8824a9acdc259521bccf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a6e5bfddcb943a4bfa3b8824a9acdc259521bccf
rename to src/fuzz/server_no_fuzzer_mode_corpus/a6e5bfddcb943a4bfa3b8824a9acdc259521bccf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a76e8b2f1ef5ca89e6467dbd4e3e4bd8ac7d11b7 b/src/fuzz/server_no_fuzzer_mode_corpus/a76e8b2f1ef5ca89e6467dbd4e3e4bd8ac7d11b7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a76e8b2f1ef5ca89e6467dbd4e3e4bd8ac7d11b7
rename to src/fuzz/server_no_fuzzer_mode_corpus/a76e8b2f1ef5ca89e6467dbd4e3e4bd8ac7d11b7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a79b0ea6d8a869a01aa80ae52485c0e2d004853f b/src/fuzz/server_no_fuzzer_mode_corpus/a79b0ea6d8a869a01aa80ae52485c0e2d004853f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a79b0ea6d8a869a01aa80ae52485c0e2d004853f
rename to src/fuzz/server_no_fuzzer_mode_corpus/a79b0ea6d8a869a01aa80ae52485c0e2d004853f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a8049a59d608040e0d15895c4c58b1580d384f3e b/src/fuzz/server_no_fuzzer_mode_corpus/a8049a59d608040e0d15895c4c58b1580d384f3e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a8049a59d608040e0d15895c4c58b1580d384f3e
rename to src/fuzz/server_no_fuzzer_mode_corpus/a8049a59d608040e0d15895c4c58b1580d384f3e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a84eb2e5d64ab8b2277af470ce5548d8f33722f7 b/src/fuzz/server_no_fuzzer_mode_corpus/a84eb2e5d64ab8b2277af470ce5548d8f33722f7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a84eb2e5d64ab8b2277af470ce5548d8f33722f7
rename to src/fuzz/server_no_fuzzer_mode_corpus/a84eb2e5d64ab8b2277af470ce5548d8f33722f7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a884770432b51fa684eef92319cecb96be224c4c b/src/fuzz/server_no_fuzzer_mode_corpus/a884770432b51fa684eef92319cecb96be224c4c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a884770432b51fa684eef92319cecb96be224c4c
rename to src/fuzz/server_no_fuzzer_mode_corpus/a884770432b51fa684eef92319cecb96be224c4c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a92fd79c824d9d8cf151e3849da62d4feb3fcb56 b/src/fuzz/server_no_fuzzer_mode_corpus/a92fd79c824d9d8cf151e3849da62d4feb3fcb56
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a92fd79c824d9d8cf151e3849da62d4feb3fcb56
rename to src/fuzz/server_no_fuzzer_mode_corpus/a92fd79c824d9d8cf151e3849da62d4feb3fcb56
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/a95da87ecdf14770236874bd0705cd24e19ecf7c b/src/fuzz/server_no_fuzzer_mode_corpus/a95da87ecdf14770236874bd0705cd24e19ecf7c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/a95da87ecdf14770236874bd0705cd24e19ecf7c
rename to src/fuzz/server_no_fuzzer_mode_corpus/a95da87ecdf14770236874bd0705cd24e19ecf7c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/aa31df42a5d6865fc19a31ddad7b5f2822ff0f5e b/src/fuzz/server_no_fuzzer_mode_corpus/aa31df42a5d6865fc19a31ddad7b5f2822ff0f5e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/aa31df42a5d6865fc19a31ddad7b5f2822ff0f5e
rename to src/fuzz/server_no_fuzzer_mode_corpus/aa31df42a5d6865fc19a31ddad7b5f2822ff0f5e
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/aa363a2f7e23c854b829b5b63d9edb43ad070510 b/src/fuzz/server_no_fuzzer_mode_corpus/aa363a2f7e23c854b829b5b63d9edb43ad070510
new file mode 100644
index 0000000..c9c454e
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/aa363a2f7e23c854b829b5b63d9edb43ad070510
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/aa3bafdc5f2dfe86fcae30c5efacc3fc2e34ce6f b/src/fuzz/server_no_fuzzer_mode_corpus/aa3bafdc5f2dfe86fcae30c5efacc3fc2e34ce6f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/aa3bafdc5f2dfe86fcae30c5efacc3fc2e34ce6f
rename to src/fuzz/server_no_fuzzer_mode_corpus/aa3bafdc5f2dfe86fcae30c5efacc3fc2e34ce6f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/aaee3d02c5b40e6ca1954304f60b20a07c3918b9 b/src/fuzz/server_no_fuzzer_mode_corpus/aaee3d02c5b40e6ca1954304f60b20a07c3918b9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/aaee3d02c5b40e6ca1954304f60b20a07c3918b9
rename to src/fuzz/server_no_fuzzer_mode_corpus/aaee3d02c5b40e6ca1954304f60b20a07c3918b9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ab6845efd4c4de05cb349cfd1d2ad5edd1bae8ad b/src/fuzz/server_no_fuzzer_mode_corpus/ab6845efd4c4de05cb349cfd1d2ad5edd1bae8ad
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ab6845efd4c4de05cb349cfd1d2ad5edd1bae8ad
rename to src/fuzz/server_no_fuzzer_mode_corpus/ab6845efd4c4de05cb349cfd1d2ad5edd1bae8ad
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/abb86edc3eec24f266067adc33248e914e2d2703 b/src/fuzz/server_no_fuzzer_mode_corpus/abb86edc3eec24f266067adc33248e914e2d2703
new file mode 100644
index 0000000..f3e775c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/abb86edc3eec24f266067adc33248e914e2d2703
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ac91a6d718ec3af5036ed496ee7d851d3838675a b/src/fuzz/server_no_fuzzer_mode_corpus/ac91a6d718ec3af5036ed496ee7d851d3838675a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ac91a6d718ec3af5036ed496ee7d851d3838675a
rename to src/fuzz/server_no_fuzzer_mode_corpus/ac91a6d718ec3af5036ed496ee7d851d3838675a
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/acb085d551ffef796cc44723a630581b275b6584 b/src/fuzz/server_no_fuzzer_mode_corpus/acb085d551ffef796cc44723a630581b275b6584
new file mode 100644
index 0000000..76ec4b9
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/acb085d551ffef796cc44723a630581b275b6584
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/acf9c9f7d279236c0b41bcf169ff787626cb2ee9 b/src/fuzz/server_no_fuzzer_mode_corpus/acf9c9f7d279236c0b41bcf169ff787626cb2ee9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/acf9c9f7d279236c0b41bcf169ff787626cb2ee9
rename to src/fuzz/server_no_fuzzer_mode_corpus/acf9c9f7d279236c0b41bcf169ff787626cb2ee9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ad2ea836613b670a12f09185e17b6b79a395076d b/src/fuzz/server_no_fuzzer_mode_corpus/ad2ea836613b670a12f09185e17b6b79a395076d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ad2ea836613b670a12f09185e17b6b79a395076d
rename to src/fuzz/server_no_fuzzer_mode_corpus/ad2ea836613b670a12f09185e17b6b79a395076d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ae895315f4117a892c308b5aa700b4ec317703d7 b/src/fuzz/server_no_fuzzer_mode_corpus/ae895315f4117a892c308b5aa700b4ec317703d7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ae895315f4117a892c308b5aa700b4ec317703d7
rename to src/fuzz/server_no_fuzzer_mode_corpus/ae895315f4117a892c308b5aa700b4ec317703d7
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/af3768615dac960bf89e461cfbbd87e96dd7bb64 b/src/fuzz/server_no_fuzzer_mode_corpus/af3768615dac960bf89e461cfbbd87e96dd7bb64
new file mode 100644
index 0000000..97193e9
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/af3768615dac960bf89e461cfbbd87e96dd7bb64
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/af8d9905d8361d3d52ce3b9a7ec948c317b64950 b/src/fuzz/server_no_fuzzer_mode_corpus/af8d9905d8361d3d52ce3b9a7ec948c317b64950
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/af8d9905d8361d3d52ce3b9a7ec948c317b64950
rename to src/fuzz/server_no_fuzzer_mode_corpus/af8d9905d8361d3d52ce3b9a7ec948c317b64950
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/afc79c287b8a0d903b27ed1e5784224c75b6b7f2 b/src/fuzz/server_no_fuzzer_mode_corpus/afc79c287b8a0d903b27ed1e5784224c75b6b7f2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/afc79c287b8a0d903b27ed1e5784224c75b6b7f2
rename to src/fuzz/server_no_fuzzer_mode_corpus/afc79c287b8a0d903b27ed1e5784224c75b6b7f2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b08dc0f49074c6bf20d9c2e259c97b3f2e67aad4 b/src/fuzz/server_no_fuzzer_mode_corpus/b08dc0f49074c6bf20d9c2e259c97b3f2e67aad4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b08dc0f49074c6bf20d9c2e259c97b3f2e67aad4
rename to src/fuzz/server_no_fuzzer_mode_corpus/b08dc0f49074c6bf20d9c2e259c97b3f2e67aad4
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b09d11ffd2373cbc36cfce836e7e4ceff3ac4f1a b/src/fuzz/server_no_fuzzer_mode_corpus/b09d11ffd2373cbc36cfce836e7e4ceff3ac4f1a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b09d11ffd2373cbc36cfce836e7e4ceff3ac4f1a
rename to src/fuzz/server_no_fuzzer_mode_corpus/b09d11ffd2373cbc36cfce836e7e4ceff3ac4f1a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b11d38272bc4d0437a8eacdff7f205af3432ca71 b/src/fuzz/server_no_fuzzer_mode_corpus/b11d38272bc4d0437a8eacdff7f205af3432ca71
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b11d38272bc4d0437a8eacdff7f205af3432ca71
rename to src/fuzz/server_no_fuzzer_mode_corpus/b11d38272bc4d0437a8eacdff7f205af3432ca71
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12 b/src/fuzz/server_no_fuzzer_mode_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12
new file mode 100644
index 0000000..209948a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/b14bf9b60379f6fde0224ba7256042e113e17c12
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b19c2fd0d8801fec4f7cb840a2153cdf6e78901d b/src/fuzz/server_no_fuzzer_mode_corpus/b19c2fd0d8801fec4f7cb840a2153cdf6e78901d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b19c2fd0d8801fec4f7cb840a2153cdf6e78901d
rename to src/fuzz/server_no_fuzzer_mode_corpus/b19c2fd0d8801fec4f7cb840a2153cdf6e78901d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b1f0922757222a821b46f1651a929f32d6d15a1d b/src/fuzz/server_no_fuzzer_mode_corpus/b1f0922757222a821b46f1651a929f32d6d15a1d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b1f0922757222a821b46f1651a929f32d6d15a1d
rename to src/fuzz/server_no_fuzzer_mode_corpus/b1f0922757222a821b46f1651a929f32d6d15a1d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b29c8b64b36839d22537bd5780b1195a2d795482 b/src/fuzz/server_no_fuzzer_mode_corpus/b29c8b64b36839d22537bd5780b1195a2d795482
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b29c8b64b36839d22537bd5780b1195a2d795482
rename to src/fuzz/server_no_fuzzer_mode_corpus/b29c8b64b36839d22537bd5780b1195a2d795482
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b2f7450588592354c260f5fc07f7ed2205d89d36 b/src/fuzz/server_no_fuzzer_mode_corpus/b2f7450588592354c260f5fc07f7ed2205d89d36
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b2f7450588592354c260f5fc07f7ed2205d89d36
rename to src/fuzz/server_no_fuzzer_mode_corpus/b2f7450588592354c260f5fc07f7ed2205d89d36
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b376633f3ef4a2ea1007e91ca0c298b6a143f730 b/src/fuzz/server_no_fuzzer_mode_corpus/b376633f3ef4a2ea1007e91ca0c298b6a143f730
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b376633f3ef4a2ea1007e91ca0c298b6a143f730
rename to src/fuzz/server_no_fuzzer_mode_corpus/b376633f3ef4a2ea1007e91ca0c298b6a143f730
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/b4776e4299c0668615623599cfb17e179f0c8c41 b/src/fuzz/server_no_fuzzer_mode_corpus/b4776e4299c0668615623599cfb17e179f0c8c41
new file mode 100644
index 0000000..d1b3b74
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/b4776e4299c0668615623599cfb17e179f0c8c41
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b48a9014bcef59e5b812bf107116b3469ca6e738 b/src/fuzz/server_no_fuzzer_mode_corpus/b48a9014bcef59e5b812bf107116b3469ca6e738
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b48a9014bcef59e5b812bf107116b3469ca6e738
rename to src/fuzz/server_no_fuzzer_mode_corpus/b48a9014bcef59e5b812bf107116b3469ca6e738
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b5aca9463efda591b9415e7e68d35e82ff6e9a4f b/src/fuzz/server_no_fuzzer_mode_corpus/b5aca9463efda591b9415e7e68d35e82ff6e9a4f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b5aca9463efda591b9415e7e68d35e82ff6e9a4f
rename to src/fuzz/server_no_fuzzer_mode_corpus/b5aca9463efda591b9415e7e68d35e82ff6e9a4f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b645eadfe63851bbbff943332b9164675489fdea b/src/fuzz/server_no_fuzzer_mode_corpus/b645eadfe63851bbbff943332b9164675489fdea
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b645eadfe63851bbbff943332b9164675489fdea
rename to src/fuzz/server_no_fuzzer_mode_corpus/b645eadfe63851bbbff943332b9164675489fdea
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b659359f3cf3802af64e4eb666012e3ce7ff17bc b/src/fuzz/server_no_fuzzer_mode_corpus/b659359f3cf3802af64e4eb666012e3ce7ff17bc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b659359f3cf3802af64e4eb666012e3ce7ff17bc
rename to src/fuzz/server_no_fuzzer_mode_corpus/b659359f3cf3802af64e4eb666012e3ce7ff17bc
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b6d09b9ab245323fd1991b3d7cc69ef3127b3b69 b/src/fuzz/server_no_fuzzer_mode_corpus/b6d09b9ab245323fd1991b3d7cc69ef3127b3b69
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b6d09b9ab245323fd1991b3d7cc69ef3127b3b69
rename to src/fuzz/server_no_fuzzer_mode_corpus/b6d09b9ab245323fd1991b3d7cc69ef3127b3b69
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b73a8f60a8a5ef12759bef41079da3353ead032b b/src/fuzz/server_no_fuzzer_mode_corpus/b73a8f60a8a5ef12759bef41079da3353ead032b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b73a8f60a8a5ef12759bef41079da3353ead032b
rename to src/fuzz/server_no_fuzzer_mode_corpus/b73a8f60a8a5ef12759bef41079da3353ead032b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b73b25c98ffd9c07a6a7452e27ec03a1a519cd47 b/src/fuzz/server_no_fuzzer_mode_corpus/b73b25c98ffd9c07a6a7452e27ec03a1a519cd47
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b73b25c98ffd9c07a6a7452e27ec03a1a519cd47
rename to src/fuzz/server_no_fuzzer_mode_corpus/b73b25c98ffd9c07a6a7452e27ec03a1a519cd47
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b7548fce385bfb9cca56d02b2bc3d08299c3ef88 b/src/fuzz/server_no_fuzzer_mode_corpus/b7548fce385bfb9cca56d02b2bc3d08299c3ef88
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b7548fce385bfb9cca56d02b2bc3d08299c3ef88
rename to src/fuzz/server_no_fuzzer_mode_corpus/b7548fce385bfb9cca56d02b2bc3d08299c3ef88
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/b8b5b4c31fe1515f6b0f6aae3405c9150ba8b927 b/src/fuzz/server_no_fuzzer_mode_corpus/b8b5b4c31fe1515f6b0f6aae3405c9150ba8b927
new file mode 100644
index 0000000..879d696
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/b8b5b4c31fe1515f6b0f6aae3405c9150ba8b927
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/b9b3467169abe938b54aa4844d2d50ca50c7b67a b/src/fuzz/server_no_fuzzer_mode_corpus/b9b3467169abe938b54aa4844d2d50ca50c7b67a
new file mode 100644
index 0000000..298c697
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/b9b3467169abe938b54aa4844d2d50ca50c7b67a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/b9dc258d38fef14c3ad2302abd27c6f582c3b0ba b/src/fuzz/server_no_fuzzer_mode_corpus/b9dc258d38fef14c3ad2302abd27c6f582c3b0ba
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/b9dc258d38fef14c3ad2302abd27c6f582c3b0ba
rename to src/fuzz/server_no_fuzzer_mode_corpus/b9dc258d38fef14c3ad2302abd27c6f582c3b0ba
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ba3775f513ea972e0baa17c247da85706064d873 b/src/fuzz/server_no_fuzzer_mode_corpus/ba3775f513ea972e0baa17c247da85706064d873
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ba3775f513ea972e0baa17c247da85706064d873
rename to src/fuzz/server_no_fuzzer_mode_corpus/ba3775f513ea972e0baa17c247da85706064d873
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/baa81ef9575f23fe76c884b3ec1cec00142fd3de b/src/fuzz/server_no_fuzzer_mode_corpus/baa81ef9575f23fe76c884b3ec1cec00142fd3de
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/baa81ef9575f23fe76c884b3ec1cec00142fd3de
rename to src/fuzz/server_no_fuzzer_mode_corpus/baa81ef9575f23fe76c884b3ec1cec00142fd3de
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/baf5151de4a778a04a21a2ab59d8822529f5f1aa b/src/fuzz/server_no_fuzzer_mode_corpus/baf5151de4a778a04a21a2ab59d8822529f5f1aa
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/baf5151de4a778a04a21a2ab59d8822529f5f1aa
rename to src/fuzz/server_no_fuzzer_mode_corpus/baf5151de4a778a04a21a2ab59d8822529f5f1aa
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bb76ae9d433dd50e2d6848a4e34517cb6fa57a29 b/src/fuzz/server_no_fuzzer_mode_corpus/bb76ae9d433dd50e2d6848a4e34517cb6fa57a29
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bb76ae9d433dd50e2d6848a4e34517cb6fa57a29
rename to src/fuzz/server_no_fuzzer_mode_corpus/bb76ae9d433dd50e2d6848a4e34517cb6fa57a29
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/bbb583fc45fc784cdb3772e038bba8fb462cfa7b b/src/fuzz/server_no_fuzzer_mode_corpus/bbb583fc45fc784cdb3772e038bba8fb462cfa7b
new file mode 100644
index 0000000..a0dd14c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/bbb583fc45fc784cdb3772e038bba8fb462cfa7b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bc33a1a7556a073237bb66ff9091234b0b7b6bde b/src/fuzz/server_no_fuzzer_mode_corpus/bc33a1a7556a073237bb66ff9091234b0b7b6bde
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bc33a1a7556a073237bb66ff9091234b0b7b6bde
rename to src/fuzz/server_no_fuzzer_mode_corpus/bc33a1a7556a073237bb66ff9091234b0b7b6bde
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bc65bf3746a64d9d8345618d8bf788f0841ce42a b/src/fuzz/server_no_fuzzer_mode_corpus/bc65bf3746a64d9d8345618d8bf788f0841ce42a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bc65bf3746a64d9d8345618d8bf788f0841ce42a
rename to src/fuzz/server_no_fuzzer_mode_corpus/bc65bf3746a64d9d8345618d8bf788f0841ce42a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bd37abc58cfee26c5c3f678e8f4296b2ca7e9458 b/src/fuzz/server_no_fuzzer_mode_corpus/bd37abc58cfee26c5c3f678e8f4296b2ca7e9458
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bd37abc58cfee26c5c3f678e8f4296b2ca7e9458
rename to src/fuzz/server_no_fuzzer_mode_corpus/bd37abc58cfee26c5c3f678e8f4296b2ca7e9458
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bd44b1a9e99f819110f901c2862527d7cb73d0d3 b/src/fuzz/server_no_fuzzer_mode_corpus/bd44b1a9e99f819110f901c2862527d7cb73d0d3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bd44b1a9e99f819110f901c2862527d7cb73d0d3
rename to src/fuzz/server_no_fuzzer_mode_corpus/bd44b1a9e99f819110f901c2862527d7cb73d0d3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/be07a269336d9884734a35679b3fd12a7c83b1cd b/src/fuzz/server_no_fuzzer_mode_corpus/be07a269336d9884734a35679b3fd12a7c83b1cd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/be07a269336d9884734a35679b3fd12a7c83b1cd
rename to src/fuzz/server_no_fuzzer_mode_corpus/be07a269336d9884734a35679b3fd12a7c83b1cd
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/be746ae50e9847503828cd685f5419e703ba08c7 b/src/fuzz/server_no_fuzzer_mode_corpus/be746ae50e9847503828cd685f5419e703ba08c7
new file mode 100644
index 0000000..2df1b0a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/be746ae50e9847503828cd685f5419e703ba08c7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bec6a7bd83f7ef6e2f611427b335a8885ed1a79e b/src/fuzz/server_no_fuzzer_mode_corpus/bec6a7bd83f7ef6e2f611427b335a8885ed1a79e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bec6a7bd83f7ef6e2f611427b335a8885ed1a79e
rename to src/fuzz/server_no_fuzzer_mode_corpus/bec6a7bd83f7ef6e2f611427b335a8885ed1a79e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/befc181804f18716d0997986f889e25d0296173b b/src/fuzz/server_no_fuzzer_mode_corpus/befc181804f18716d0997986f889e25d0296173b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/befc181804f18716d0997986f889e25d0296173b
rename to src/fuzz/server_no_fuzzer_mode_corpus/befc181804f18716d0997986f889e25d0296173b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/bf75767d1269f7227835e8a70e4ba5607daae8e4 b/src/fuzz/server_no_fuzzer_mode_corpus/bf75767d1269f7227835e8a70e4ba5607daae8e4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/bf75767d1269f7227835e8a70e4ba5607daae8e4
rename to src/fuzz/server_no_fuzzer_mode_corpus/bf75767d1269f7227835e8a70e4ba5607daae8e4
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/bfdf4e74388014a68a4ef7970508afc15115fd3f b/src/fuzz/server_no_fuzzer_mode_corpus/bfdf4e74388014a68a4ef7970508afc15115fd3f
new file mode 100644
index 0000000..932a526
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/bfdf4e74388014a68a4ef7970508afc15115fd3f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c0e817e8bacedd33d014b949a05750bd020dbdc9 b/src/fuzz/server_no_fuzzer_mode_corpus/c0e817e8bacedd33d014b949a05750bd020dbdc9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c0e817e8bacedd33d014b949a05750bd020dbdc9
rename to src/fuzz/server_no_fuzzer_mode_corpus/c0e817e8bacedd33d014b949a05750bd020dbdc9
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c115e4ea913845d3b933d40abaf730d17fdecbe8 b/src/fuzz/server_no_fuzzer_mode_corpus/c115e4ea913845d3b933d40abaf730d17fdecbe8
new file mode 100644
index 0000000..a7065da
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c115e4ea913845d3b933d40abaf730d17fdecbe8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c19f831d1043ca4bbf9d68ce89b2883f840748f7 b/src/fuzz/server_no_fuzzer_mode_corpus/c19f831d1043ca4bbf9d68ce89b2883f840748f7
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c19f831d1043ca4bbf9d68ce89b2883f840748f7
rename to src/fuzz/server_no_fuzzer_mode_corpus/c19f831d1043ca4bbf9d68ce89b2883f840748f7
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c1c1ef9aed717efc942fb8b33049f39c7b98d938 b/src/fuzz/server_no_fuzzer_mode_corpus/c1c1ef9aed717efc942fb8b33049f39c7b98d938
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c1c1ef9aed717efc942fb8b33049f39c7b98d938
rename to src/fuzz/server_no_fuzzer_mode_corpus/c1c1ef9aed717efc942fb8b33049f39c7b98d938
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c1f28bebad1f86668e77d71e61d47e92afcddf51 b/src/fuzz/server_no_fuzzer_mode_corpus/c1f28bebad1f86668e77d71e61d47e92afcddf51
new file mode 100644
index 0000000..56e18ea
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c1f28bebad1f86668e77d71e61d47e92afcddf51
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c21cd9a0d7cb4ca1739505aba5dc1a8ebbbeb1be b/src/fuzz/server_no_fuzzer_mode_corpus/c21cd9a0d7cb4ca1739505aba5dc1a8ebbbeb1be
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c21cd9a0d7cb4ca1739505aba5dc1a8ebbbeb1be
rename to src/fuzz/server_no_fuzzer_mode_corpus/c21cd9a0d7cb4ca1739505aba5dc1a8ebbbeb1be
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c27abf4967e683747d82c46aa53a0e911e9f4cdf b/src/fuzz/server_no_fuzzer_mode_corpus/c27abf4967e683747d82c46aa53a0e911e9f4cdf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c27abf4967e683747d82c46aa53a0e911e9f4cdf
rename to src/fuzz/server_no_fuzzer_mode_corpus/c27abf4967e683747d82c46aa53a0e911e9f4cdf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c2cab2cd536db692b7389b5264696579792ff141 b/src/fuzz/server_no_fuzzer_mode_corpus/c2cab2cd536db692b7389b5264696579792ff141
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c2cab2cd536db692b7389b5264696579792ff141
rename to src/fuzz/server_no_fuzzer_mode_corpus/c2cab2cd536db692b7389b5264696579792ff141
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c2d82516b4e32beaed4a4d5069a7c3822c08db34 b/src/fuzz/server_no_fuzzer_mode_corpus/c2d82516b4e32beaed4a4d5069a7c3822c08db34
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c2d82516b4e32beaed4a4d5069a7c3822c08db34
rename to src/fuzz/server_no_fuzzer_mode_corpus/c2d82516b4e32beaed4a4d5069a7c3822c08db34
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c3431a06f4342fe5ad23f4b45c4ddaa59c18ad4f b/src/fuzz/server_no_fuzzer_mode_corpus/c3431a06f4342fe5ad23f4b45c4ddaa59c18ad4f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c3431a06f4342fe5ad23f4b45c4ddaa59c18ad4f
rename to src/fuzz/server_no_fuzzer_mode_corpus/c3431a06f4342fe5ad23f4b45c4ddaa59c18ad4f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c349dbdf689b7afda2cef864284a189e350372d2 b/src/fuzz/server_no_fuzzer_mode_corpus/c349dbdf689b7afda2cef864284a189e350372d2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c349dbdf689b7afda2cef864284a189e350372d2
rename to src/fuzz/server_no_fuzzer_mode_corpus/c349dbdf689b7afda2cef864284a189e350372d2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c36cb7e24270125a95ef26167b03817d1ac03ab4 b/src/fuzz/server_no_fuzzer_mode_corpus/c36cb7e24270125a95ef26167b03817d1ac03ab4
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c36cb7e24270125a95ef26167b03817d1ac03ab4
rename to src/fuzz/server_no_fuzzer_mode_corpus/c36cb7e24270125a95ef26167b03817d1ac03ab4
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c3ad01a4290838318265b3bb2ab427c321c80e77 b/src/fuzz/server_no_fuzzer_mode_corpus/c3ad01a4290838318265b3bb2ab427c321c80e77
new file mode 100644
index 0000000..e9e9270
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c3ad01a4290838318265b3bb2ab427c321c80e77
Binary files differ
diff --git a/src/fuzz/server_corpus/c40f822fff3902d4f6361cb1636e2054d7e09611 b/src/fuzz/server_no_fuzzer_mode_corpus/c40f822fff3902d4f6361cb1636e2054d7e09611
similarity index 100%
rename from src/fuzz/server_corpus/c40f822fff3902d4f6361cb1636e2054d7e09611
rename to src/fuzz/server_no_fuzzer_mode_corpus/c40f822fff3902d4f6361cb1636e2054d7e09611
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c45e7923ea5c985d8af12865cdeba48ff9876dae b/src/fuzz/server_no_fuzzer_mode_corpus/c45e7923ea5c985d8af12865cdeba48ff9876dae
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c45e7923ea5c985d8af12865cdeba48ff9876dae
rename to src/fuzz/server_no_fuzzer_mode_corpus/c45e7923ea5c985d8af12865cdeba48ff9876dae
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c466d73dc7e37acb845d1e233099a788eee5de73 b/src/fuzz/server_no_fuzzer_mode_corpus/c466d73dc7e37acb845d1e233099a788eee5de73
new file mode 100644
index 0000000..4e69e16
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c466d73dc7e37acb845d1e233099a788eee5de73
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c46ea3f769cb11459f92d47fec8a8195b7f48023 b/src/fuzz/server_no_fuzzer_mode_corpus/c46ea3f769cb11459f92d47fec8a8195b7f48023
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c46ea3f769cb11459f92d47fec8a8195b7f48023
rename to src/fuzz/server_no_fuzzer_mode_corpus/c46ea3f769cb11459f92d47fec8a8195b7f48023
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c4f6653a8eb82a9584a75167c788add431c72180 b/src/fuzz/server_no_fuzzer_mode_corpus/c4f6653a8eb82a9584a75167c788add431c72180
new file mode 100644
index 0000000..2aa95b1
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c4f6653a8eb82a9584a75167c788add431c72180
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/c5a62b826b99d9a9bfdb8c256152580b350b340d b/src/fuzz/server_no_fuzzer_mode_corpus/c5a62b826b99d9a9bfdb8c256152580b350b340d
new file mode 100644
index 0000000..bf9a411
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/c5a62b826b99d9a9bfdb8c256152580b350b340d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c659fd53cd0aba5228a3f123dfc4931eac5ceef2 b/src/fuzz/server_no_fuzzer_mode_corpus/c659fd53cd0aba5228a3f123dfc4931eac5ceef2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c659fd53cd0aba5228a3f123dfc4931eac5ceef2
rename to src/fuzz/server_no_fuzzer_mode_corpus/c659fd53cd0aba5228a3f123dfc4931eac5ceef2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c6c48658dbe7d3aa286c31684309396127239acd b/src/fuzz/server_no_fuzzer_mode_corpus/c6c48658dbe7d3aa286c31684309396127239acd
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c6c48658dbe7d3aa286c31684309396127239acd
rename to src/fuzz/server_no_fuzzer_mode_corpus/c6c48658dbe7d3aa286c31684309396127239acd
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c7e8a64c99fb8bfbb300b3b2a4c488d404083223 b/src/fuzz/server_no_fuzzer_mode_corpus/c7e8a64c99fb8bfbb300b3b2a4c488d404083223
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c7e8a64c99fb8bfbb300b3b2a4c488d404083223
rename to src/fuzz/server_no_fuzzer_mode_corpus/c7e8a64c99fb8bfbb300b3b2a4c488d404083223
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c8bb9ed0433460f95bbfb4d1a1e8a63219e5794c b/src/fuzz/server_no_fuzzer_mode_corpus/c8bb9ed0433460f95bbfb4d1a1e8a63219e5794c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c8bb9ed0433460f95bbfb4d1a1e8a63219e5794c
rename to src/fuzz/server_no_fuzzer_mode_corpus/c8bb9ed0433460f95bbfb4d1a1e8a63219e5794c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c8e49f9f721f228a9298571601943c821141f98c b/src/fuzz/server_no_fuzzer_mode_corpus/c8e49f9f721f228a9298571601943c821141f98c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c8e49f9f721f228a9298571601943c821141f98c
rename to src/fuzz/server_no_fuzzer_mode_corpus/c8e49f9f721f228a9298571601943c821141f98c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/c95f0d1eefff062578a679ac816a67aa2b3adb1b b/src/fuzz/server_no_fuzzer_mode_corpus/c95f0d1eefff062578a679ac816a67aa2b3adb1b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/c95f0d1eefff062578a679ac816a67aa2b3adb1b
rename to src/fuzz/server_no_fuzzer_mode_corpus/c95f0d1eefff062578a679ac816a67aa2b3adb1b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ca9f8e76c8c58ec6e701745612f63e6b4648304a b/src/fuzz/server_no_fuzzer_mode_corpus/ca9f8e76c8c58ec6e701745612f63e6b4648304a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ca9f8e76c8c58ec6e701745612f63e6b4648304a
rename to src/fuzz/server_no_fuzzer_mode_corpus/ca9f8e76c8c58ec6e701745612f63e6b4648304a
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/caac485cb7b8c10526b13bfbde98bf1d0abc7fe5 b/src/fuzz/server_no_fuzzer_mode_corpus/caac485cb7b8c10526b13bfbde98bf1d0abc7fe5
new file mode 100644
index 0000000..f8efed5
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/caac485cb7b8c10526b13bfbde98bf1d0abc7fe5
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cad39b590237acb48b7326e9cb42ffd4d5f7f63a b/src/fuzz/server_no_fuzzer_mode_corpus/cad39b590237acb48b7326e9cb42ffd4d5f7f63a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/cad39b590237acb48b7326e9cb42ffd4d5f7f63a
rename to src/fuzz/server_no_fuzzer_mode_corpus/cad39b590237acb48b7326e9cb42ffd4d5f7f63a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cae2e0f7d7bc254a7a48a4dade13884a886b3efc b/src/fuzz/server_no_fuzzer_mode_corpus/cae2e0f7d7bc254a7a48a4dade13884a886b3efc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/cae2e0f7d7bc254a7a48a4dade13884a886b3efc
rename to src/fuzz/server_no_fuzzer_mode_corpus/cae2e0f7d7bc254a7a48a4dade13884a886b3efc
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cc0f546418b16ca1a34acdfc04fc5ba3daff3837 b/src/fuzz/server_no_fuzzer_mode_corpus/cc0f546418b16ca1a34acdfc04fc5ba3daff3837
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/cc0f546418b16ca1a34acdfc04fc5ba3daff3837
rename to src/fuzz/server_no_fuzzer_mode_corpus/cc0f546418b16ca1a34acdfc04fc5ba3daff3837
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cca0e7c364566ea16f60e61378f3ad2c6d606743 b/src/fuzz/server_no_fuzzer_mode_corpus/cca0e7c364566ea16f60e61378f3ad2c6d606743
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/cca0e7c364566ea16f60e61378f3ad2c6d606743
rename to src/fuzz/server_no_fuzzer_mode_corpus/cca0e7c364566ea16f60e61378f3ad2c6d606743
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/ccfc53fa2579b5c9179127d6d151e67b48ab0a61 b/src/fuzz/server_no_fuzzer_mode_corpus/ccfc53fa2579b5c9179127d6d151e67b48ab0a61
new file mode 100644
index 0000000..ef31fca
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/ccfc53fa2579b5c9179127d6d151e67b48ab0a61
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/cd84cc6ac0083b7b62628e3bfb5dfa943f7633d6 b/src/fuzz/server_no_fuzzer_mode_corpus/cd84cc6ac0083b7b62628e3bfb5dfa943f7633d6
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/cd84cc6ac0083b7b62628e3bfb5dfa943f7633d6
rename to src/fuzz/server_no_fuzzer_mode_corpus/cd84cc6ac0083b7b62628e3bfb5dfa943f7633d6
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ce4102e7e196f7e395bbc7ee62231d482a3d25ca b/src/fuzz/server_no_fuzzer_mode_corpus/ce4102e7e196f7e395bbc7ee62231d482a3d25ca
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ce4102e7e196f7e395bbc7ee62231d482a3d25ca
rename to src/fuzz/server_no_fuzzer_mode_corpus/ce4102e7e196f7e395bbc7ee62231d482a3d25ca
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ce453e5752209c3938b132a781b652b70fb02548 b/src/fuzz/server_no_fuzzer_mode_corpus/ce453e5752209c3938b132a781b652b70fb02548
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ce453e5752209c3938b132a781b652b70fb02548
rename to src/fuzz/server_no_fuzzer_mode_corpus/ce453e5752209c3938b132a781b652b70fb02548
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ce922e8c3a49bcc46ebdb6f34c19c2914127fe94 b/src/fuzz/server_no_fuzzer_mode_corpus/ce922e8c3a49bcc46ebdb6f34c19c2914127fe94
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ce922e8c3a49bcc46ebdb6f34c19c2914127fe94
rename to src/fuzz/server_no_fuzzer_mode_corpus/ce922e8c3a49bcc46ebdb6f34c19c2914127fe94
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ce9db526fea8914002423911d3936ba49d182ecf b/src/fuzz/server_no_fuzzer_mode_corpus/ce9db526fea8914002423911d3936ba49d182ecf
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ce9db526fea8914002423911d3936ba49d182ecf
rename to src/fuzz/server_no_fuzzer_mode_corpus/ce9db526fea8914002423911d3936ba49d182ecf
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d0b3efe8a7595f32ae87ac63d679f59542f2feeb b/src/fuzz/server_no_fuzzer_mode_corpus/d0b3efe8a7595f32ae87ac63d679f59542f2feeb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d0b3efe8a7595f32ae87ac63d679f59542f2feeb
rename to src/fuzz/server_no_fuzzer_mode_corpus/d0b3efe8a7595f32ae87ac63d679f59542f2feeb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d174b16da23fd30f9a003a64af4a0f07166acbca b/src/fuzz/server_no_fuzzer_mode_corpus/d174b16da23fd30f9a003a64af4a0f07166acbca
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d174b16da23fd30f9a003a64af4a0f07166acbca
rename to src/fuzz/server_no_fuzzer_mode_corpus/d174b16da23fd30f9a003a64af4a0f07166acbca
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d2c1dc8d69d60114e8e0a186ecbb4d9bcf811933 b/src/fuzz/server_no_fuzzer_mode_corpus/d2c1dc8d69d60114e8e0a186ecbb4d9bcf811933
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d2c1dc8d69d60114e8e0a186ecbb4d9bcf811933
rename to src/fuzz/server_no_fuzzer_mode_corpus/d2c1dc8d69d60114e8e0a186ecbb4d9bcf811933
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d2c40217ae5014d03aa83c867da14c53bc1d4a35 b/src/fuzz/server_no_fuzzer_mode_corpus/d2c40217ae5014d03aa83c867da14c53bc1d4a35
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d2c40217ae5014d03aa83c867da14c53bc1d4a35
rename to src/fuzz/server_no_fuzzer_mode_corpus/d2c40217ae5014d03aa83c867da14c53bc1d4a35
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d439784e7e3ef0aae959b44d909cb2c4c3a9bed3 b/src/fuzz/server_no_fuzzer_mode_corpus/d439784e7e3ef0aae959b44d909cb2c4c3a9bed3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d439784e7e3ef0aae959b44d909cb2c4c3a9bed3
rename to src/fuzz/server_no_fuzzer_mode_corpus/d439784e7e3ef0aae959b44d909cb2c4c3a9bed3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d4f1c55856461a99d65a88882925c2d8fb61cdc8 b/src/fuzz/server_no_fuzzer_mode_corpus/d4f1c55856461a99d65a88882925c2d8fb61cdc8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d4f1c55856461a99d65a88882925c2d8fb61cdc8
rename to src/fuzz/server_no_fuzzer_mode_corpus/d4f1c55856461a99d65a88882925c2d8fb61cdc8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d56e6b76f1f1196bcbdab3d1e9329398f02cbfd3 b/src/fuzz/server_no_fuzzer_mode_corpus/d56e6b76f1f1196bcbdab3d1e9329398f02cbfd3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d56e6b76f1f1196bcbdab3d1e9329398f02cbfd3
rename to src/fuzz/server_no_fuzzer_mode_corpus/d56e6b76f1f1196bcbdab3d1e9329398f02cbfd3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d7c0581e009c8e4bb05263c28081918aede18f36 b/src/fuzz/server_no_fuzzer_mode_corpus/d7c0581e009c8e4bb05263c28081918aede18f36
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d7c0581e009c8e4bb05263c28081918aede18f36
rename to src/fuzz/server_no_fuzzer_mode_corpus/d7c0581e009c8e4bb05263c28081918aede18f36
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d7d6ffe7ab1d18c754f71bde4d0436c50f80f80e b/src/fuzz/server_no_fuzzer_mode_corpus/d7d6ffe7ab1d18c754f71bde4d0436c50f80f80e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d7d6ffe7ab1d18c754f71bde4d0436c50f80f80e
rename to src/fuzz/server_no_fuzzer_mode_corpus/d7d6ffe7ab1d18c754f71bde4d0436c50f80f80e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d7dbda60702a2b2bdefa84383fb955f92b1c0552 b/src/fuzz/server_no_fuzzer_mode_corpus/d7dbda60702a2b2bdefa84383fb955f92b1c0552
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d7dbda60702a2b2bdefa84383fb955f92b1c0552
rename to src/fuzz/server_no_fuzzer_mode_corpus/d7dbda60702a2b2bdefa84383fb955f92b1c0552
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d85642b9eac7fc349903a3648ac6cee7f18e9987 b/src/fuzz/server_no_fuzzer_mode_corpus/d85642b9eac7fc349903a3648ac6cee7f18e9987
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d85642b9eac7fc349903a3648ac6cee7f18e9987
rename to src/fuzz/server_no_fuzzer_mode_corpus/d85642b9eac7fc349903a3648ac6cee7f18e9987
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/d8ca9b84d438ebb40dc29606af5658686e5e4b19 b/src/fuzz/server_no_fuzzer_mode_corpus/d8ca9b84d438ebb40dc29606af5658686e5e4b19
new file mode 100644
index 0000000..168418c
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/d8ca9b84d438ebb40dc29606af5658686e5e4b19
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/d90061e9ff6cab9f4e5a99c1a39004457b34bc7e b/src/fuzz/server_no_fuzzer_mode_corpus/d90061e9ff6cab9f4e5a99c1a39004457b34bc7e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/d90061e9ff6cab9f4e5a99c1a39004457b34bc7e
rename to src/fuzz/server_no_fuzzer_mode_corpus/d90061e9ff6cab9f4e5a99c1a39004457b34bc7e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/da27b4c7d48c40380f200b1ae505dc3069b3346a b/src/fuzz/server_no_fuzzer_mode_corpus/da27b4c7d48c40380f200b1ae505dc3069b3346a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/da27b4c7d48c40380f200b1ae505dc3069b3346a
rename to src/fuzz/server_no_fuzzer_mode_corpus/da27b4c7d48c40380f200b1ae505dc3069b3346a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/db0364479b679e607b6bd082626bb64555a7a171 b/src/fuzz/server_no_fuzzer_mode_corpus/db0364479b679e607b6bd082626bb64555a7a171
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/db0364479b679e607b6bd082626bb64555a7a171
rename to src/fuzz/server_no_fuzzer_mode_corpus/db0364479b679e607b6bd082626bb64555a7a171
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/db5c028cb8265147379470a3240c635672eca685 b/src/fuzz/server_no_fuzzer_mode_corpus/db5c028cb8265147379470a3240c635672eca685
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/db5c028cb8265147379470a3240c635672eca685
rename to src/fuzz/server_no_fuzzer_mode_corpus/db5c028cb8265147379470a3240c635672eca685
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/dbc5cec15023e17b1e75d6aa75e76ade5fe779ca b/src/fuzz/server_no_fuzzer_mode_corpus/dbc5cec15023e17b1e75d6aa75e76ade5fe779ca
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/dbc5cec15023e17b1e75d6aa75e76ade5fe779ca
rename to src/fuzz/server_no_fuzzer_mode_corpus/dbc5cec15023e17b1e75d6aa75e76ade5fe779ca
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/dbda59a2ecb988a37bab285203f85ddf8e71f73f b/src/fuzz/server_no_fuzzer_mode_corpus/dbda59a2ecb988a37bab285203f85ddf8e71f73f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/dbda59a2ecb988a37bab285203f85ddf8e71f73f
rename to src/fuzz/server_no_fuzzer_mode_corpus/dbda59a2ecb988a37bab285203f85ddf8e71f73f
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/dbf6a36e96e0afe83dffa0a8cc9bb179a69dc1e3 b/src/fuzz/server_no_fuzzer_mode_corpus/dbf6a36e96e0afe83dffa0a8cc9bb179a69dc1e3
new file mode 100644
index 0000000..8eff5ba
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/dbf6a36e96e0afe83dffa0a8cc9bb179a69dc1e3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/dd27b92eed552fb3bd5c379a7ab7939d52add722 b/src/fuzz/server_no_fuzzer_mode_corpus/dd27b92eed552fb3bd5c379a7ab7939d52add722
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/dd27b92eed552fb3bd5c379a7ab7939d52add722
rename to src/fuzz/server_no_fuzzer_mode_corpus/dd27b92eed552fb3bd5c379a7ab7939d52add722
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/de5307331f1c7f97aab5f3a4f530686436661e47 b/src/fuzz/server_no_fuzzer_mode_corpus/de5307331f1c7f97aab5f3a4f530686436661e47
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/de5307331f1c7f97aab5f3a4f530686436661e47
rename to src/fuzz/server_no_fuzzer_mode_corpus/de5307331f1c7f97aab5f3a4f530686436661e47
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/df916f86637758402c0159b523cf6fa7d5e8c17f b/src/fuzz/server_no_fuzzer_mode_corpus/df916f86637758402c0159b523cf6fa7d5e8c17f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/df916f86637758402c0159b523cf6fa7d5e8c17f
rename to src/fuzz/server_no_fuzzer_mode_corpus/df916f86637758402c0159b523cf6fa7d5e8c17f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/dfb715d146ff04d4cf17d5860cf7b0370ae51dba b/src/fuzz/server_no_fuzzer_mode_corpus/dfb715d146ff04d4cf17d5860cf7b0370ae51dba
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/dfb715d146ff04d4cf17d5860cf7b0370ae51dba
rename to src/fuzz/server_no_fuzzer_mode_corpus/dfb715d146ff04d4cf17d5860cf7b0370ae51dba
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e08ffba2acb6f49749a55cdd8c093d8024cd6aeb b/src/fuzz/server_no_fuzzer_mode_corpus/e08ffba2acb6f49749a55cdd8c093d8024cd6aeb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e08ffba2acb6f49749a55cdd8c093d8024cd6aeb
rename to src/fuzz/server_no_fuzzer_mode_corpus/e08ffba2acb6f49749a55cdd8c093d8024cd6aeb
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/e109fd0e9edf89f25f92b61af5e11d6f5d13647f b/src/fuzz/server_no_fuzzer_mode_corpus/e109fd0e9edf89f25f92b61af5e11d6f5d13647f
new file mode 100644
index 0000000..ab193df
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/e109fd0e9edf89f25f92b61af5e11d6f5d13647f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e19613e61a7e3dfa632b99e1b86003262ccbe3da b/src/fuzz/server_no_fuzzer_mode_corpus/e19613e61a7e3dfa632b99e1b86003262ccbe3da
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e19613e61a7e3dfa632b99e1b86003262ccbe3da
rename to src/fuzz/server_no_fuzzer_mode_corpus/e19613e61a7e3dfa632b99e1b86003262ccbe3da
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e1ec1a35da4ef5886739f5955a83454189a5806e b/src/fuzz/server_no_fuzzer_mode_corpus/e1ec1a35da4ef5886739f5955a83454189a5806e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e1ec1a35da4ef5886739f5955a83454189a5806e
rename to src/fuzz/server_no_fuzzer_mode_corpus/e1ec1a35da4ef5886739f5955a83454189a5806e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e2740e51814a2531daae9e2a153d904644ebbf66 b/src/fuzz/server_no_fuzzer_mode_corpus/e2740e51814a2531daae9e2a153d904644ebbf66
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e2740e51814a2531daae9e2a153d904644ebbf66
rename to src/fuzz/server_no_fuzzer_mode_corpus/e2740e51814a2531daae9e2a153d904644ebbf66
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e27a5d318166e706e0331dd39f48a946da831da1 b/src/fuzz/server_no_fuzzer_mode_corpus/e27a5d318166e706e0331dd39f48a946da831da1
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e27a5d318166e706e0331dd39f48a946da831da1
rename to src/fuzz/server_no_fuzzer_mode_corpus/e27a5d318166e706e0331dd39f48a946da831da1
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e37dcb9edb9406613ab058b52109cff6e5eb7373 b/src/fuzz/server_no_fuzzer_mode_corpus/e37dcb9edb9406613ab058b52109cff6e5eb7373
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e37dcb9edb9406613ab058b52109cff6e5eb7373
rename to src/fuzz/server_no_fuzzer_mode_corpus/e37dcb9edb9406613ab058b52109cff6e5eb7373
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e4ca779155a2ac65415a30eee6a9a4aa1c07b35b b/src/fuzz/server_no_fuzzer_mode_corpus/e4ca779155a2ac65415a30eee6a9a4aa1c07b35b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e4ca779155a2ac65415a30eee6a9a4aa1c07b35b
rename to src/fuzz/server_no_fuzzer_mode_corpus/e4ca779155a2ac65415a30eee6a9a4aa1c07b35b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e4cce0a0ca9071cf023358688fad05f18bc5e4fe b/src/fuzz/server_no_fuzzer_mode_corpus/e4cce0a0ca9071cf023358688fad05f18bc5e4fe
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e4cce0a0ca9071cf023358688fad05f18bc5e4fe
rename to src/fuzz/server_no_fuzzer_mode_corpus/e4cce0a0ca9071cf023358688fad05f18bc5e4fe
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/e4db629559cb7b8b0036f4d1ee4c4bc947b10564 b/src/fuzz/server_no_fuzzer_mode_corpus/e4db629559cb7b8b0036f4d1ee4c4bc947b10564
new file mode 100644
index 0000000..4ad48f2
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/e4db629559cb7b8b0036f4d1ee4c4bc947b10564
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e5aaef377b5b77a2365ae18b743cc6603a252a34 b/src/fuzz/server_no_fuzzer_mode_corpus/e5aaef377b5b77a2365ae18b743cc6603a252a34
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e5aaef377b5b77a2365ae18b743cc6603a252a34
rename to src/fuzz/server_no_fuzzer_mode_corpus/e5aaef377b5b77a2365ae18b743cc6603a252a34
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e5b1d6a4dbd2161a4fe4d9a7454ddbaae0aae52a b/src/fuzz/server_no_fuzzer_mode_corpus/e5b1d6a4dbd2161a4fe4d9a7454ddbaae0aae52a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e5b1d6a4dbd2161a4fe4d9a7454ddbaae0aae52a
rename to src/fuzz/server_no_fuzzer_mode_corpus/e5b1d6a4dbd2161a4fe4d9a7454ddbaae0aae52a
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/e721d03081c16f89aabe228e2d491f10ebd7d4f0 b/src/fuzz/server_no_fuzzer_mode_corpus/e721d03081c16f89aabe228e2d491f10ebd7d4f0
new file mode 100644
index 0000000..878b88a
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/e721d03081c16f89aabe228e2d491f10ebd7d4f0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e7812858b0e60a4949b8e51bd2abc314f934ad44 b/src/fuzz/server_no_fuzzer_mode_corpus/e7812858b0e60a4949b8e51bd2abc314f934ad44
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e7812858b0e60a4949b8e51bd2abc314f934ad44
rename to src/fuzz/server_no_fuzzer_mode_corpus/e7812858b0e60a4949b8e51bd2abc314f934ad44
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e79894801828ab2c84ce83aabef5762365e9531b b/src/fuzz/server_no_fuzzer_mode_corpus/e79894801828ab2c84ce83aabef5762365e9531b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e79894801828ab2c84ce83aabef5762365e9531b
rename to src/fuzz/server_no_fuzzer_mode_corpus/e79894801828ab2c84ce83aabef5762365e9531b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e7dc9378b96b825749873eb5b2ceac26f9ec4d0e b/src/fuzz/server_no_fuzzer_mode_corpus/e7dc9378b96b825749873eb5b2ceac26f9ec4d0e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e7dc9378b96b825749873eb5b2ceac26f9ec4d0e
rename to src/fuzz/server_no_fuzzer_mode_corpus/e7dc9378b96b825749873eb5b2ceac26f9ec4d0e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e80074d9c02fb8bb7e38fbd3436f521fea618f7b b/src/fuzz/server_no_fuzzer_mode_corpus/e80074d9c02fb8bb7e38fbd3436f521fea618f7b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e80074d9c02fb8bb7e38fbd3436f521fea618f7b
rename to src/fuzz/server_no_fuzzer_mode_corpus/e80074d9c02fb8bb7e38fbd3436f521fea618f7b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e841dee2ac5ce35147ecd19ffaca010ca2b2b0b5 b/src/fuzz/server_no_fuzzer_mode_corpus/e841dee2ac5ce35147ecd19ffaca010ca2b2b0b5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e841dee2ac5ce35147ecd19ffaca010ca2b2b0b5
rename to src/fuzz/server_no_fuzzer_mode_corpus/e841dee2ac5ce35147ecd19ffaca010ca2b2b0b5
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/e8592060c38e29df3b6f64e0076f46afd36e6988 b/src/fuzz/server_no_fuzzer_mode_corpus/e8592060c38e29df3b6f64e0076f46afd36e6988
new file mode 100644
index 0000000..0760d82
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/e8592060c38e29df3b6f64e0076f46afd36e6988
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e85e807eb8b5c8c7b3264fb3cdfb3951e7079dfe b/src/fuzz/server_no_fuzzer_mode_corpus/e85e807eb8b5c8c7b3264fb3cdfb3951e7079dfe
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e85e807eb8b5c8c7b3264fb3cdfb3951e7079dfe
rename to src/fuzz/server_no_fuzzer_mode_corpus/e85e807eb8b5c8c7b3264fb3cdfb3951e7079dfe
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/e877e2afa34c81aba949338cc8292df7c66d2e52 b/src/fuzz/server_no_fuzzer_mode_corpus/e877e2afa34c81aba949338cc8292df7c66d2e52
new file mode 100644
index 0000000..7745629
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/e877e2afa34c81aba949338cc8292df7c66d2e52
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e886760f57e697fd4a080bc7a813ab4cc22d98de b/src/fuzz/server_no_fuzzer_mode_corpus/e886760f57e697fd4a080bc7a813ab4cc22d98de
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e886760f57e697fd4a080bc7a813ab4cc22d98de
rename to src/fuzz/server_no_fuzzer_mode_corpus/e886760f57e697fd4a080bc7a813ab4cc22d98de
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/e958885558605789e1d5b2ebb389ea8595d8ae9f b/src/fuzz/server_no_fuzzer_mode_corpus/e958885558605789e1d5b2ebb389ea8595d8ae9f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/e958885558605789e1d5b2ebb389ea8595d8ae9f
rename to src/fuzz/server_no_fuzzer_mode_corpus/e958885558605789e1d5b2ebb389ea8595d8ae9f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ea2c8ae59f99ce50ae99e036782202aa990779a8 b/src/fuzz/server_no_fuzzer_mode_corpus/ea2c8ae59f99ce50ae99e036782202aa990779a8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ea2c8ae59f99ce50ae99e036782202aa990779a8
rename to src/fuzz/server_no_fuzzer_mode_corpus/ea2c8ae59f99ce50ae99e036782202aa990779a8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ea7f6b81047b4f8def57d225ed7890763738f2e2 b/src/fuzz/server_no_fuzzer_mode_corpus/ea7f6b81047b4f8def57d225ed7890763738f2e2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ea7f6b81047b4f8def57d225ed7890763738f2e2
rename to src/fuzz/server_no_fuzzer_mode_corpus/ea7f6b81047b4f8def57d225ed7890763738f2e2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ebe8291cee2dc491b8817396a8258ea9ae2381ab b/src/fuzz/server_no_fuzzer_mode_corpus/ebe8291cee2dc491b8817396a8258ea9ae2381ab
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ebe8291cee2dc491b8817396a8258ea9ae2381ab
rename to src/fuzz/server_no_fuzzer_mode_corpus/ebe8291cee2dc491b8817396a8258ea9ae2381ab
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ec59163f9e5197161e6cf27a9420f88dca993f2a b/src/fuzz/server_no_fuzzer_mode_corpus/ec59163f9e5197161e6cf27a9420f88dca993f2a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ec59163f9e5197161e6cf27a9420f88dca993f2a
rename to src/fuzz/server_no_fuzzer_mode_corpus/ec59163f9e5197161e6cf27a9420f88dca993f2a
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ec7f842055ee3eaef1836efdf1bf0684d90ffc6f b/src/fuzz/server_no_fuzzer_mode_corpus/ec7f842055ee3eaef1836efdf1bf0684d90ffc6f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ec7f842055ee3eaef1836efdf1bf0684d90ffc6f
rename to src/fuzz/server_no_fuzzer_mode_corpus/ec7f842055ee3eaef1836efdf1bf0684d90ffc6f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ec8c7f4b7156a184596c73c9d1c2c2a736456cb2 b/src/fuzz/server_no_fuzzer_mode_corpus/ec8c7f4b7156a184596c73c9d1c2c2a736456cb2
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ec8c7f4b7156a184596c73c9d1c2c2a736456cb2
rename to src/fuzz/server_no_fuzzer_mode_corpus/ec8c7f4b7156a184596c73c9d1c2c2a736456cb2
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/eca05ae2db4db1b8fb60240e0b50efead7507bd9 b/src/fuzz/server_no_fuzzer_mode_corpus/eca05ae2db4db1b8fb60240e0b50efead7507bd9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/eca05ae2db4db1b8fb60240e0b50efead7507bd9
rename to src/fuzz/server_no_fuzzer_mode_corpus/eca05ae2db4db1b8fb60240e0b50efead7507bd9
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ed54e9249f4d5f4a8716a7b178c145eade55894f b/src/fuzz/server_no_fuzzer_mode_corpus/ed54e9249f4d5f4a8716a7b178c145eade55894f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ed54e9249f4d5f4a8716a7b178c145eade55894f
rename to src/fuzz/server_no_fuzzer_mode_corpus/ed54e9249f4d5f4a8716a7b178c145eade55894f
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/edf576bc7f4600ac40b05d204344d0a49915f51c b/src/fuzz/server_no_fuzzer_mode_corpus/edf576bc7f4600ac40b05d204344d0a49915f51c
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/edf576bc7f4600ac40b05d204344d0a49915f51c
rename to src/fuzz/server_no_fuzzer_mode_corpus/edf576bc7f4600ac40b05d204344d0a49915f51c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ee3b4d1718ff90e7869b69c4070424f913830ad8 b/src/fuzz/server_no_fuzzer_mode_corpus/ee3b4d1718ff90e7869b69c4070424f913830ad8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ee3b4d1718ff90e7869b69c4070424f913830ad8
rename to src/fuzz/server_no_fuzzer_mode_corpus/ee3b4d1718ff90e7869b69c4070424f913830ad8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ee6cbe2eca89f970438173aa484acc596fc53289 b/src/fuzz/server_no_fuzzer_mode_corpus/ee6cbe2eca89f970438173aa484acc596fc53289
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ee6cbe2eca89f970438173aa484acc596fc53289
rename to src/fuzz/server_no_fuzzer_mode_corpus/ee6cbe2eca89f970438173aa484acc596fc53289
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/eeac8e5b5fbba5b4afc8af69e7136a0ca3106f58 b/src/fuzz/server_no_fuzzer_mode_corpus/eeac8e5b5fbba5b4afc8af69e7136a0ca3106f58
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/eeac8e5b5fbba5b4afc8af69e7136a0ca3106f58
rename to src/fuzz/server_no_fuzzer_mode_corpus/eeac8e5b5fbba5b4afc8af69e7136a0ca3106f58
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/eec97495ec0176d661aae751faefe3e29c970bf3 b/src/fuzz/server_no_fuzzer_mode_corpus/eec97495ec0176d661aae751faefe3e29c970bf3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/eec97495ec0176d661aae751faefe3e29c970bf3
rename to src/fuzz/server_no_fuzzer_mode_corpus/eec97495ec0176d661aae751faefe3e29c970bf3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ef176236eeff5cd0b8dc1c607d0179083212fc78 b/src/fuzz/server_no_fuzzer_mode_corpus/ef176236eeff5cd0b8dc1c607d0179083212fc78
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ef176236eeff5cd0b8dc1c607d0179083212fc78
rename to src/fuzz/server_no_fuzzer_mode_corpus/ef176236eeff5cd0b8dc1c607d0179083212fc78
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ef534991638836fe68555475e7888aecc4573180 b/src/fuzz/server_no_fuzzer_mode_corpus/ef534991638836fe68555475e7888aecc4573180
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ef534991638836fe68555475e7888aecc4573180
rename to src/fuzz/server_no_fuzzer_mode_corpus/ef534991638836fe68555475e7888aecc4573180
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f05e70506f28f841ed940e8822dd541faf41ba82 b/src/fuzz/server_no_fuzzer_mode_corpus/f05e70506f28f841ed940e8822dd541faf41ba82
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f05e70506f28f841ed940e8822dd541faf41ba82
rename to src/fuzz/server_no_fuzzer_mode_corpus/f05e70506f28f841ed940e8822dd541faf41ba82
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/f078545c63e4592e6b69f061f178b3e2bd2539eb b/src/fuzz/server_no_fuzzer_mode_corpus/f078545c63e4592e6b69f061f178b3e2bd2539eb
new file mode 100644
index 0000000..598f0a3
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/f078545c63e4592e6b69f061f178b3e2bd2539eb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f088ba074ccb35225983c4568512de7631285b2f b/src/fuzz/server_no_fuzzer_mode_corpus/f088ba074ccb35225983c4568512de7631285b2f
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f088ba074ccb35225983c4568512de7631285b2f
rename to src/fuzz/server_no_fuzzer_mode_corpus/f088ba074ccb35225983c4568512de7631285b2f
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/f0ca9d97efe48c3aacfba4667b9e0cbc872715c0 b/src/fuzz/server_no_fuzzer_mode_corpus/f0ca9d97efe48c3aacfba4667b9e0cbc872715c0
new file mode 100644
index 0000000..6ab6652
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/f0ca9d97efe48c3aacfba4667b9e0cbc872715c0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f1dff08c50bc7a2fb07a23579c4d534a834c1fce b/src/fuzz/server_no_fuzzer_mode_corpus/f1dff08c50bc7a2fb07a23579c4d534a834c1fce
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f1dff08c50bc7a2fb07a23579c4d534a834c1fce
rename to src/fuzz/server_no_fuzzer_mode_corpus/f1dff08c50bc7a2fb07a23579c4d534a834c1fce
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f1e2cc634a6ba6db2c3a826f337b635ef340f17d b/src/fuzz/server_no_fuzzer_mode_corpus/f1e2cc634a6ba6db2c3a826f337b635ef340f17d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f1e2cc634a6ba6db2c3a826f337b635ef340f17d
rename to src/fuzz/server_no_fuzzer_mode_corpus/f1e2cc634a6ba6db2c3a826f337b635ef340f17d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f1f9319fec8b3854cebe6886a03ead6a67ad082e b/src/fuzz/server_no_fuzzer_mode_corpus/f1f9319fec8b3854cebe6886a03ead6a67ad082e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f1f9319fec8b3854cebe6886a03ead6a67ad082e
rename to src/fuzz/server_no_fuzzer_mode_corpus/f1f9319fec8b3854cebe6886a03ead6a67ad082e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f264f07f3e1b8e20f775abc608c9cede7a963790 b/src/fuzz/server_no_fuzzer_mode_corpus/f264f07f3e1b8e20f775abc608c9cede7a963790
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f264f07f3e1b8e20f775abc608c9cede7a963790
rename to src/fuzz/server_no_fuzzer_mode_corpus/f264f07f3e1b8e20f775abc608c9cede7a963790
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f2e068164194840d77a9b833bab341a2d01f86c9 b/src/fuzz/server_no_fuzzer_mode_corpus/f2e068164194840d77a9b833bab341a2d01f86c9
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f2e068164194840d77a9b833bab341a2d01f86c9
rename to src/fuzz/server_no_fuzzer_mode_corpus/f2e068164194840d77a9b833bab341a2d01f86c9
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/f2e67d3787a62b80783c411a61244b53c13be69c b/src/fuzz/server_no_fuzzer_mode_corpus/f2e67d3787a62b80783c411a61244b53c13be69c
new file mode 100644
index 0000000..24b1d29
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/f2e67d3787a62b80783c411a61244b53c13be69c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f3593861333a38e2a307963329186d43d1c59cd0 b/src/fuzz/server_no_fuzzer_mode_corpus/f3593861333a38e2a307963329186d43d1c59cd0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f3593861333a38e2a307963329186d43d1c59cd0
rename to src/fuzz/server_no_fuzzer_mode_corpus/f3593861333a38e2a307963329186d43d1c59cd0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f3825d1d3a3a6a59be01b3cdfae1a89d9ac31ad3 b/src/fuzz/server_no_fuzzer_mode_corpus/f3825d1d3a3a6a59be01b3cdfae1a89d9ac31ad3
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f3825d1d3a3a6a59be01b3cdfae1a89d9ac31ad3
rename to src/fuzz/server_no_fuzzer_mode_corpus/f3825d1d3a3a6a59be01b3cdfae1a89d9ac31ad3
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f405f617763ee694f4d2efbb6340595e5b5c7d82 b/src/fuzz/server_no_fuzzer_mode_corpus/f405f617763ee694f4d2efbb6340595e5b5c7d82
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f405f617763ee694f4d2efbb6340595e5b5c7d82
rename to src/fuzz/server_no_fuzzer_mode_corpus/f405f617763ee694f4d2efbb6340595e5b5c7d82
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f4e074ba0c8181a2b96482e29c238b7c174d0f1d b/src/fuzz/server_no_fuzzer_mode_corpus/f4e074ba0c8181a2b96482e29c238b7c174d0f1d
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f4e074ba0c8181a2b96482e29c238b7c174d0f1d
rename to src/fuzz/server_no_fuzzer_mode_corpus/f4e074ba0c8181a2b96482e29c238b7c174d0f1d
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f5703e319cf0627f5886386cd1e04192bdd4fb8b b/src/fuzz/server_no_fuzzer_mode_corpus/f5703e319cf0627f5886386cd1e04192bdd4fb8b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f5703e319cf0627f5886386cd1e04192bdd4fb8b
rename to src/fuzz/server_no_fuzzer_mode_corpus/f5703e319cf0627f5886386cd1e04192bdd4fb8b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f618e090ad5c914a567d94a8bebd732b5d55d3fb b/src/fuzz/server_no_fuzzer_mode_corpus/f618e090ad5c914a567d94a8bebd732b5d55d3fb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f618e090ad5c914a567d94a8bebd732b5d55d3fb
rename to src/fuzz/server_no_fuzzer_mode_corpus/f618e090ad5c914a567d94a8bebd732b5d55d3fb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f63693f3613310448d6ba07f32262196714fddc8 b/src/fuzz/server_no_fuzzer_mode_corpus/f63693f3613310448d6ba07f32262196714fddc8
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f63693f3613310448d6ba07f32262196714fddc8
rename to src/fuzz/server_no_fuzzer_mode_corpus/f63693f3613310448d6ba07f32262196714fddc8
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f655b7a7526edddc8ed006902fcef94bc08a5df0 b/src/fuzz/server_no_fuzzer_mode_corpus/f655b7a7526edddc8ed006902fcef94bc08a5df0
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f655b7a7526edddc8ed006902fcef94bc08a5df0
rename to src/fuzz/server_no_fuzzer_mode_corpus/f655b7a7526edddc8ed006902fcef94bc08a5df0
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f7095fcae0eeea759bb71ace0d4c819f45916813 b/src/fuzz/server_no_fuzzer_mode_corpus/f7095fcae0eeea759bb71ace0d4c819f45916813
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f7095fcae0eeea759bb71ace0d4c819f45916813
rename to src/fuzz/server_no_fuzzer_mode_corpus/f7095fcae0eeea759bb71ace0d4c819f45916813
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f79e5ecfa82f228fc86b3d78cfd66f5f4a91e681 b/src/fuzz/server_no_fuzzer_mode_corpus/f79e5ecfa82f228fc86b3d78cfd66f5f4a91e681
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f79e5ecfa82f228fc86b3d78cfd66f5f4a91e681
rename to src/fuzz/server_no_fuzzer_mode_corpus/f79e5ecfa82f228fc86b3d78cfd66f5f4a91e681
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f7f18e8a4ffb813cf94a7888c2984e0d5d58b967 b/src/fuzz/server_no_fuzzer_mode_corpus/f7f18e8a4ffb813cf94a7888c2984e0d5d58b967
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f7f18e8a4ffb813cf94a7888c2984e0d5d58b967
rename to src/fuzz/server_no_fuzzer_mode_corpus/f7f18e8a4ffb813cf94a7888c2984e0d5d58b967
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f84945893aadcf4422f9f1ef47d4000ff4296892 b/src/fuzz/server_no_fuzzer_mode_corpus/f84945893aadcf4422f9f1ef47d4000ff4296892
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f84945893aadcf4422f9f1ef47d4000ff4296892
rename to src/fuzz/server_no_fuzzer_mode_corpus/f84945893aadcf4422f9f1ef47d4000ff4296892
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/f8e933a802366ba454b5449880db99d7c65dcf21 b/src/fuzz/server_no_fuzzer_mode_corpus/f8e933a802366ba454b5449880db99d7c65dcf21
new file mode 100644
index 0000000..af2f249
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/f8e933a802366ba454b5449880db99d7c65dcf21
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f91ff9b71b566f49b7f455193ece86db7380751b b/src/fuzz/server_no_fuzzer_mode_corpus/f91ff9b71b566f49b7f455193ece86db7380751b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f91ff9b71b566f49b7f455193ece86db7380751b
rename to src/fuzz/server_no_fuzzer_mode_corpus/f91ff9b71b566f49b7f455193ece86db7380751b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f942643bf0edec936a846340f72d5b092a834063 b/src/fuzz/server_no_fuzzer_mode_corpus/f942643bf0edec936a846340f72d5b092a834063
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f942643bf0edec936a846340f72d5b092a834063
rename to src/fuzz/server_no_fuzzer_mode_corpus/f942643bf0edec936a846340f72d5b092a834063
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f98c252bfb626ddbd1f4a206220c939f14cc5249 b/src/fuzz/server_no_fuzzer_mode_corpus/f98c252bfb626ddbd1f4a206220c939f14cc5249
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f98c252bfb626ddbd1f4a206220c939f14cc5249
rename to src/fuzz/server_no_fuzzer_mode_corpus/f98c252bfb626ddbd1f4a206220c939f14cc5249
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/f9d2656776aa01522491e1bdf5cd8851ad15b39b b/src/fuzz/server_no_fuzzer_mode_corpus/f9d2656776aa01522491e1bdf5cd8851ad15b39b
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/f9d2656776aa01522491e1bdf5cd8851ad15b39b
rename to src/fuzz/server_no_fuzzer_mode_corpus/f9d2656776aa01522491e1bdf5cd8851ad15b39b
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fa75e552f36ba9824e6fad71274b384bd4800da5 b/src/fuzz/server_no_fuzzer_mode_corpus/fa75e552f36ba9824e6fad71274b384bd4800da5
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/fa75e552f36ba9824e6fad71274b384bd4800da5
rename to src/fuzz/server_no_fuzzer_mode_corpus/fa75e552f36ba9824e6fad71274b384bd4800da5
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/faff846f97bed687cc0a19fda11f6e6a6e7a1a01 b/src/fuzz/server_no_fuzzer_mode_corpus/faff846f97bed687cc0a19fda11f6e6a6e7a1a01
new file mode 100644
index 0000000..302f46b
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/faff846f97bed687cc0a19fda11f6e6a6e7a1a01
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fbe8018dbcea38eabdaa9a74b5de86b74ea121bb b/src/fuzz/server_no_fuzzer_mode_corpus/fbe8018dbcea38eabdaa9a74b5de86b74ea121bb
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/fbe8018dbcea38eabdaa9a74b5de86b74ea121bb
rename to src/fuzz/server_no_fuzzer_mode_corpus/fbe8018dbcea38eabdaa9a74b5de86b74ea121bb
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fc06fe23281bee455c11b39ef4c4bad0c3363367 b/src/fuzz/server_no_fuzzer_mode_corpus/fc06fe23281bee455c11b39ef4c4bad0c3363367
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/fc06fe23281bee455c11b39ef4c4bad0c3363367
rename to src/fuzz/server_no_fuzzer_mode_corpus/fc06fe23281bee455c11b39ef4c4bad0c3363367
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fc84fd6e18c99133de1b445215c42b46f1a93788 b/src/fuzz/server_no_fuzzer_mode_corpus/fc84fd6e18c99133de1b445215c42b46f1a93788
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/fc84fd6e18c99133de1b445215c42b46f1a93788
rename to src/fuzz/server_no_fuzzer_mode_corpus/fc84fd6e18c99133de1b445215c42b46f1a93788
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/fe63cd927616d11e5210d3e180d699ff8a1d594a b/src/fuzz/server_no_fuzzer_mode_corpus/fe63cd927616d11e5210d3e180d699ff8a1d594a
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/fe63cd927616d11e5210d3e180d699ff8a1d594a
rename to src/fuzz/server_no_fuzzer_mode_corpus/fe63cd927616d11e5210d3e180d699ff8a1d594a
Binary files differ
diff --git a/src/fuzz/server_no_fuzzer_mode_corpus/feeed70cfd0107aed1b812fe78d9d011fcb36d8c b/src/fuzz/server_no_fuzzer_mode_corpus/feeed70cfd0107aed1b812fe78d9d011fcb36d8c
new file mode 100644
index 0000000..adacd89
--- /dev/null
+++ b/src/fuzz/server_no_fuzzer_mode_corpus/feeed70cfd0107aed1b812fe78d9d011fcb36d8c
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ff75d2c084faf0b7c9d39eb304d7ad32dbb4026e b/src/fuzz/server_no_fuzzer_mode_corpus/ff75d2c084faf0b7c9d39eb304d7ad32dbb4026e
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ff75d2c084faf0b7c9d39eb304d7ad32dbb4026e
rename to src/fuzz/server_no_fuzzer_mode_corpus/ff75d2c084faf0b7c9d39eb304d7ad32dbb4026e
Binary files differ
diff --git a/src/fuzz/server_corpus_no_fuzzer_mode/ffa80e2c9aee0b05dfa2ce0c2111862b8d34badc b/src/fuzz/server_no_fuzzer_mode_corpus/ffa80e2c9aee0b05dfa2ce0c2111862b8d34badc
similarity index 100%
rename from src/fuzz/server_corpus_no_fuzzer_mode/ffa80e2c9aee0b05dfa2ce0c2111862b8d34badc
rename to src/fuzz/server_no_fuzzer_mode_corpus/ffa80e2c9aee0b05dfa2ce0c2111862b8d34badc
Binary files differ
diff --git a/src/fuzz/ssl_ctx_api.cc b/src/fuzz/ssl_ctx_api.cc
index 24f4e9f..ca74b05 100644
--- a/src/fuzz/ssl_ctx_api.cc
+++ b/src/fuzz/ssl_ctx_api.cc
@@ -237,8 +237,10 @@
 
 template <typename T>
 static bool GetVector(std::vector<T> *out, CBS *cbs) {
-  static_assert(std::is_pod<T>::value,
-                "GetVector may only be called on POD types");
+  static_assert(
+      std::is_standard_layout<T>::value && std::is_trivially_copyable<T>::value,
+      "GetVector may only be called on standard layout, trivially copyable "
+      "types");
 
   CBS child;
   if (!CBS_get_u8_length_prefixed(cbs, &child)) {
diff --git a/src/gen/bcm/aes-gcm-avx10-x86_64-apple.S b/src/gen/bcm/aes-gcm-avx10-x86_64-apple.S
deleted file mode 100644
index be66605..0000000
--- a/src/gen/bcm/aes-gcm-avx10-x86_64-apple.S
+++ /dev/null
@@ -1,1250 +0,0 @@
-// This file is generated from a similarly-named Perl script in the BoringSSL
-// source tree. Do not edit by hand.
-
-#include <openssl/asm_base.h>
-
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__APPLE__)
-.section	__DATA,__const
-.p2align	6
-
-
-L$bswap_mask:
-.quad	0x08090a0b0c0d0e0f, 0x0001020304050607
-
-
-
-
-
-
-
-
-L$gfpoly:
-.quad	1, 0xc200000000000000
-
-
-L$gfpoly_and_internal_carrybit:
-.quad	1, 0xc200000000000001
-
-
-
-
-
-L$ctr_pattern:
-.quad	0, 0
-.quad	1, 0
-L$inc_2blocks:
-.quad	2, 0
-.quad	3, 0
-L$inc_4blocks:
-.quad	4, 0
-
-.text	
-.globl	_gcm_gmult_vpclmulqdq_avx10
-.private_extern _gcm_gmult_vpclmulqdq_avx10
-
-.p2align	5
-_gcm_gmult_vpclmulqdq_avx10:
-
-
-_CET_ENDBR
-
-
-
-	vmovdqu	(%rdi),%xmm0
-	vmovdqu	L$bswap_mask(%rip),%xmm1
-	vmovdqu	256-16(%rsi),%xmm2
-	vmovdqu	L$gfpoly(%rip),%xmm3
-	vpshufb	%xmm1,%xmm0,%xmm0
-
-	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm4
-	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm5
-	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm6
-	vpxord	%xmm6,%xmm5,%xmm5
-	vpclmulqdq	$0x01,%xmm4,%xmm3,%xmm6
-	vpshufd	$0x4e,%xmm4,%xmm4
-	vpternlogd	$0x96,%xmm6,%xmm4,%xmm5
-	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm0
-	vpclmulqdq	$0x01,%xmm5,%xmm3,%xmm4
-	vpshufd	$0x4e,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm4,%xmm5,%xmm0
-
-
-	vpshufb	%xmm1,%xmm0,%xmm0
-	vmovdqu	%xmm0,(%rdi)
-	ret
-
-
-
-.globl	_gcm_init_vpclmulqdq_avx10_512
-.private_extern _gcm_init_vpclmulqdq_avx10_512
-
-.p2align	5
-_gcm_init_vpclmulqdq_avx10_512:
-
-
-_CET_ENDBR
-
-	leaq	256-64(%rdi),%r8
-
-
-
-	vpshufd	$0x4e,(%rsi),%xmm3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vpshufd	$0xd3,%xmm3,%xmm0
-	vpsrad	$31,%xmm0,%xmm0
-	vpaddq	%xmm3,%xmm3,%xmm3
-
-	vpternlogd	$0x78,L$gfpoly_and_internal_carrybit(%rip),%xmm0,%xmm3
-
-
-	vbroadcasti32x4	L$gfpoly(%rip),%zmm5
-
-
-
-
-
-
-
-
-	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
-	vpclmulqdq	$0x01,%xmm3,%xmm3,%xmm1
-	vpclmulqdq	$0x10,%xmm3,%xmm3,%xmm2
-	vpxord	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm5,%xmm2
-	vpshufd	$0x4e,%xmm0,%xmm0
-	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
-	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm4
-	vpclmulqdq	$0x01,%xmm1,%xmm5,%xmm0
-	vpshufd	$0x4e,%xmm1,%xmm1
-	vpternlogd	$0x96,%xmm0,%xmm1,%xmm4
-
-
-
-	vinserti128	$1,%xmm3,%ymm4,%ymm3
-	vinserti128	$1,%xmm4,%ymm4,%ymm4
-	vpclmulqdq	$0x00,%ymm4,%ymm3,%ymm0
-	vpclmulqdq	$0x01,%ymm4,%ymm3,%ymm1
-	vpclmulqdq	$0x10,%ymm4,%ymm3,%ymm2
-	vpxord	%ymm2,%ymm1,%ymm1
-	vpclmulqdq	$0x01,%ymm0,%ymm5,%ymm2
-	vpshufd	$0x4e,%ymm0,%ymm0
-	vpternlogd	$0x96,%ymm2,%ymm0,%ymm1
-	vpclmulqdq	$0x11,%ymm4,%ymm3,%ymm4
-	vpclmulqdq	$0x01,%ymm1,%ymm5,%ymm0
-	vpshufd	$0x4e,%ymm1,%ymm1
-	vpternlogd	$0x96,%ymm0,%ymm1,%ymm4
-
-	vinserti64x4	$1,%ymm3,%zmm4,%zmm3
-	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
-
-	vmovdqu8	%zmm3,(%r8)
-
-
-
-
-
-	movl	$3,%eax
-L$precompute_next__func1:
-	subq	$64,%r8
-	vpclmulqdq	$0x00,%zmm4,%zmm3,%zmm0
-	vpclmulqdq	$0x01,%zmm4,%zmm3,%zmm1
-	vpclmulqdq	$0x10,%zmm4,%zmm3,%zmm2
-	vpxord	%zmm2,%zmm1,%zmm1
-	vpclmulqdq	$0x01,%zmm0,%zmm5,%zmm2
-	vpshufd	$0x4e,%zmm0,%zmm0
-	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
-	vpclmulqdq	$0x11,%zmm4,%zmm3,%zmm3
-	vpclmulqdq	$0x01,%zmm1,%zmm5,%zmm0
-	vpshufd	$0x4e,%zmm1,%zmm1
-	vpternlogd	$0x96,%zmm0,%zmm1,%zmm3
-
-	vmovdqu8	%zmm3,(%r8)
-	decl	%eax
-	jnz	L$precompute_next__func1
-
-	vzeroupper
-	ret
-
-
-
-.globl	_gcm_ghash_vpclmulqdq_avx10_512
-.private_extern _gcm_ghash_vpclmulqdq_avx10_512
-
-.p2align	5
-_gcm_ghash_vpclmulqdq_avx10_512:
-
-
-_CET_ENDBR
-
-
-
-
-
-
-	vmovdqu	L$bswap_mask(%rip),%xmm4
-	vmovdqu	L$gfpoly(%rip),%xmm10
-
-
-	vmovdqu	(%rdi),%xmm5
-	vpshufb	%xmm4,%xmm5,%xmm5
-
-
-	cmpq	$64,%rcx
-	jb	L$aad_blockbyblock__func1
-
-
-
-	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
-	vshufi64x2	$0,%zmm10,%zmm10,%zmm10
-
-
-	vmovdqu8	256-64(%rsi),%zmm9
-
-	cmpq	$256-1,%rcx
-	jbe	L$aad_loop_1x__func1
-
-
-	vmovdqu8	256-256(%rsi),%zmm6
-	vmovdqu8	256-192(%rsi),%zmm7
-	vmovdqu8	256-128(%rsi),%zmm8
-
-
-L$aad_loop_4x__func1:
-	vmovdqu8	0(%rdx),%zmm0
-	vmovdqu8	64(%rdx),%zmm1
-	vmovdqu8	128(%rdx),%zmm2
-	vmovdqu8	192(%rdx),%zmm3
-	vpshufb	%zmm4,%zmm0,%zmm0
-	vpxord	%zmm5,%zmm0,%zmm0
-	vpshufb	%zmm4,%zmm1,%zmm1
-	vpshufb	%zmm4,%zmm2,%zmm2
-	vpshufb	%zmm4,%zmm3,%zmm3
-	vpclmulqdq	$0x00,%zmm6,%zmm0,%zmm5
-	vpclmulqdq	$0x00,%zmm7,%zmm1,%zmm11
-	vpclmulqdq	$0x00,%zmm8,%zmm2,%zmm12
-	vpxord	%zmm11,%zmm5,%zmm5
-	vpclmulqdq	$0x00,%zmm9,%zmm3,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm5
-	vpclmulqdq	$0x01,%zmm6,%zmm0,%zmm11
-	vpclmulqdq	$0x01,%zmm7,%zmm1,%zmm12
-	vpclmulqdq	$0x01,%zmm8,%zmm2,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x01,%zmm9,%zmm3,%zmm12
-	vpclmulqdq	$0x10,%zmm6,%zmm0,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x10,%zmm7,%zmm1,%zmm12
-	vpclmulqdq	$0x10,%zmm8,%zmm2,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x01,%zmm5,%zmm10,%zmm13
-	vpclmulqdq	$0x10,%zmm9,%zmm3,%zmm12
-	vpxord	%zmm12,%zmm11,%zmm11
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm6,%zmm0,%zmm0
-	vpclmulqdq	$0x11,%zmm7,%zmm1,%zmm1
-	vpclmulqdq	$0x11,%zmm8,%zmm2,%zmm2
-	vpternlogd	$0x96,%zmm13,%zmm5,%zmm11
-	vpclmulqdq	$0x11,%zmm9,%zmm3,%zmm3
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm0
-	vpclmulqdq	$0x01,%zmm11,%zmm10,%zmm12
-	vpxord	%zmm3,%zmm0,%zmm5
-	vpshufd	$0x4e,%zmm11,%zmm11
-	vpternlogd	$0x96,%zmm12,%zmm11,%zmm5
-	vextracti32x4	$1,%zmm5,%xmm0
-	vextracti32x4	$2,%zmm5,%xmm1
-	vextracti32x4	$3,%zmm5,%xmm2
-	vpxord	%xmm0,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
-
-	subq	$-256,%rdx
-	addq	$-256,%rcx
-	cmpq	$256-1,%rcx
-	ja	L$aad_loop_4x__func1
-
-
-	cmpq	$64,%rcx
-	jb	L$aad_large_done__func1
-L$aad_loop_1x__func1:
-	vmovdqu8	(%rdx),%zmm0
-	vpshufb	%zmm4,%zmm0,%zmm0
-	vpxord	%zmm0,%zmm5,%zmm5
-	vpclmulqdq	$0x00,%zmm9,%zmm5,%zmm0
-	vpclmulqdq	$0x01,%zmm9,%zmm5,%zmm1
-	vpclmulqdq	$0x10,%zmm9,%zmm5,%zmm2
-	vpxord	%zmm2,%zmm1,%zmm1
-	vpclmulqdq	$0x01,%zmm0,%zmm10,%zmm2
-	vpshufd	$0x4e,%zmm0,%zmm0
-	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
-	vpclmulqdq	$0x11,%zmm9,%zmm5,%zmm5
-	vpclmulqdq	$0x01,%zmm1,%zmm10,%zmm0
-	vpshufd	$0x4e,%zmm1,%zmm1
-	vpternlogd	$0x96,%zmm0,%zmm1,%zmm5
-
-	vextracti32x4	$1,%zmm5,%xmm0
-	vextracti32x4	$2,%zmm5,%xmm1
-	vextracti32x4	$3,%zmm5,%xmm2
-	vpxord	%xmm0,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
-
-	addq	$64,%rdx
-	subq	$64,%rcx
-	cmpq	$64,%rcx
-	jae	L$aad_loop_1x__func1
-
-L$aad_large_done__func1:
-
-
-	vzeroupper
-
-
-L$aad_blockbyblock__func1:
-	testq	%rcx,%rcx
-	jz	L$aad_done__func1
-	vmovdqu	256-16(%rsi),%xmm9
-L$aad_loop_blockbyblock__func1:
-	vmovdqu	(%rdx),%xmm0
-	vpshufb	%xmm4,%xmm0,%xmm0
-	vpxor	%xmm0,%xmm5,%xmm5
-	vpclmulqdq	$0x00,%xmm9,%xmm5,%xmm0
-	vpclmulqdq	$0x01,%xmm9,%xmm5,%xmm1
-	vpclmulqdq	$0x10,%xmm9,%xmm5,%xmm2
-	vpxord	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm10,%xmm2
-	vpshufd	$0x4e,%xmm0,%xmm0
-	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
-	vpclmulqdq	$0x11,%xmm9,%xmm5,%xmm5
-	vpclmulqdq	$0x01,%xmm1,%xmm10,%xmm0
-	vpshufd	$0x4e,%xmm1,%xmm1
-	vpternlogd	$0x96,%xmm0,%xmm1,%xmm5
-
-	addq	$16,%rdx
-	subq	$16,%rcx
-	jnz	L$aad_loop_blockbyblock__func1
-
-L$aad_done__func1:
-
-	vpshufb	%xmm4,%xmm5,%xmm5
-	vmovdqu	%xmm5,(%rdi)
-	ret
-
-
-
-.globl	_aes_gcm_enc_update_vaes_avx10_512
-.private_extern _aes_gcm_enc_update_vaes_avx10_512
-
-.p2align	5
-_aes_gcm_enc_update_vaes_avx10_512:
-
-
-_CET_ENDBR
-	pushq	%r12
-
-
-	movq	16(%rsp),%r12
-#ifdef BORINGSSL_DISPATCH_TEST
-
-	movb	$1,_BORINGSSL_function_hit+7(%rip)
-#endif
-
-	vbroadcasti32x4	L$bswap_mask(%rip),%zmm8
-	vbroadcasti32x4	L$gfpoly(%rip),%zmm31
-
-
-
-	vmovdqu	(%r12),%xmm10
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vbroadcasti32x4	(%r8),%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm12
-
-
-
-	movl	240(%rcx),%r10d
-	leal	-20(,%r10,4),%r10d
-
-
-
-
-	leaq	96(%rcx,%r10,4),%r11
-	vbroadcasti32x4	(%rcx),%zmm13
-	vbroadcasti32x4	(%r11),%zmm14
-
-
-	vpaddd	L$ctr_pattern(%rip),%zmm12,%zmm12
-
-
-	vbroadcasti32x4	L$inc_4blocks(%rip),%zmm11
-
-
-
-	cmpq	$256-1,%rdx
-	jbe	L$crypt_loop_4x_done__func1
-
-
-	vmovdqu8	256-256(%r9),%zmm27
-	vmovdqu8	256-192(%r9),%zmm28
-	vmovdqu8	256-128(%r9),%zmm29
-	vmovdqu8	256-64(%r9),%zmm30
-
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	leaq	16(%rcx),%rax
-L$vaesenc_loop_first_4_vecs__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	L$vaesenc_loop_first_4_vecs__func1
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	jbe	L$ghash_last_ciphertext_4x__func1
-	vbroadcasti32x4	-144(%r11),%zmm15
-	vbroadcasti32x4	-128(%r11),%zmm16
-	vbroadcasti32x4	-112(%r11),%zmm17
-	vbroadcasti32x4	-96(%r11),%zmm18
-	vbroadcasti32x4	-80(%r11),%zmm19
-	vbroadcasti32x4	-64(%r11),%zmm20
-	vbroadcasti32x4	-48(%r11),%zmm21
-	vbroadcasti32x4	-32(%r11),%zmm22
-	vbroadcasti32x4	-16(%r11),%zmm23
-L$crypt_loop_4x__func1:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	cmpl	$24,%r10d
-	jl	L$aes128__func1
-	je	L$aes192__func1
-
-	vbroadcasti32x4	-208(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-192(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-L$aes192__func1:
-	vbroadcasti32x4	-176(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-160(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-L$aes128__func1:
-	prefetcht0	512+0(%rdi)
-	prefetcht0	512+64(%rdi)
-	prefetcht0	512+128(%rdi)
-	prefetcht0	512+192(%rdi)
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-
-	vaesenc	%zmm15,%zmm0,%zmm0
-	vaesenc	%zmm15,%zmm1,%zmm1
-	vaesenc	%zmm15,%zmm2,%zmm2
-	vaesenc	%zmm15,%zmm3,%zmm3
-
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-
-	vaesenc	%zmm16,%zmm0,%zmm0
-	vaesenc	%zmm16,%zmm1,%zmm1
-	vaesenc	%zmm16,%zmm2,%zmm2
-	vaesenc	%zmm16,%zmm3,%zmm3
-
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-
-	vaesenc	%zmm17,%zmm0,%zmm0
-	vaesenc	%zmm17,%zmm1,%zmm1
-	vaesenc	%zmm17,%zmm2,%zmm2
-	vaesenc	%zmm17,%zmm3,%zmm3
-
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-
-	vaesenc	%zmm18,%zmm0,%zmm0
-	vaesenc	%zmm18,%zmm1,%zmm1
-	vaesenc	%zmm18,%zmm2,%zmm2
-	vaesenc	%zmm18,%zmm3,%zmm3
-
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-
-	vaesenc	%zmm19,%zmm0,%zmm0
-	vaesenc	%zmm19,%zmm1,%zmm1
-	vaesenc	%zmm19,%zmm2,%zmm2
-	vaesenc	%zmm19,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-
-	vaesenc	%zmm20,%zmm0,%zmm0
-	vaesenc	%zmm20,%zmm1,%zmm1
-	vaesenc	%zmm20,%zmm2,%zmm2
-	vaesenc	%zmm20,%zmm3,%zmm3
-
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-
-	vaesenc	%zmm21,%zmm0,%zmm0
-	vaesenc	%zmm21,%zmm1,%zmm1
-	vaesenc	%zmm21,%zmm2,%zmm2
-	vaesenc	%zmm21,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-
-	vaesenc	%zmm22,%zmm0,%zmm0
-	vaesenc	%zmm22,%zmm1,%zmm1
-	vaesenc	%zmm22,%zmm2,%zmm2
-	vaesenc	%zmm22,%zmm3,%zmm3
-
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-
-	vaesenc	%zmm23,%zmm0,%zmm0
-	vaesenc	%zmm23,%zmm1,%zmm1
-	vaesenc	%zmm23,%zmm2,%zmm2
-	vaesenc	%zmm23,%zmm3,%zmm3
-
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	ja	L$crypt_loop_4x__func1
-L$ghash_last_ciphertext_4x__func1:
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-L$crypt_loop_4x_done__func1:
-
-	testq	%rdx,%rdx
-	jz	L$done__func1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	movq	%rdx,%rax
-	negq	%rax
-	andq	$-16,%rax
-	leaq	256(%r9,%rax,1),%r8
-	vpxor	%xmm4,%xmm4,%xmm4
-	vpxor	%xmm5,%xmm5,%xmm5
-	vpxor	%xmm6,%xmm6,%xmm6
-
-	cmpq	$64,%rdx
-	jb	L$partial_vec__func1
-
-L$crypt_loop_1x__func1:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-L$vaesenc_loop_tail_full_vec__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	L$vaesenc_loop_tail_full_vec__func1
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi)
-
-
-	vmovdqu8	(%r8),%zmm30
-	vpshufb	%zmm8,%zmm0,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-	vpxor	%xmm10,%xmm10,%xmm10
-
-	addq	$64,%r8
-	addq	$64,%rdi
-	addq	$64,%rsi
-	subq	$64,%rdx
-	cmpq	$64,%rdx
-	jae	L$crypt_loop_1x__func1
-
-	testq	%rdx,%rdx
-	jz	L$reduce__func1
-
-L$partial_vec__func1:
-
-
-
-
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k1
-	addq	$15,%rdx
-	andq	$-16,%rdx
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k2
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-L$vaesenc_loop_tail_partialvec__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	L$vaesenc_loop_tail_partialvec__func1
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1{%k1}{z}
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi){%k1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	(%r8),%zmm30{%k2}{z}
-	vmovdqu8	%zmm0,%zmm1{%k1}{z}
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-
-L$reduce__func1:
-
-	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
-	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
-
-	vextracti32x4	$1,%zmm6,%xmm0
-	vextracti32x4	$2,%zmm6,%xmm1
-	vextracti32x4	$3,%zmm6,%xmm2
-	vpxord	%xmm0,%xmm6,%xmm10
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
-
-
-L$done__func1:
-
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vmovdqu	%xmm10,(%r12)
-
-	vzeroupper
-	popq	%r12
-
-	ret
-
-
-
-.globl	_aes_gcm_dec_update_vaes_avx10_512
-.private_extern _aes_gcm_dec_update_vaes_avx10_512
-
-.p2align	5
-_aes_gcm_dec_update_vaes_avx10_512:
-
-
-_CET_ENDBR
-	pushq	%r12
-
-
-	movq	16(%rsp),%r12
-
-	vbroadcasti32x4	L$bswap_mask(%rip),%zmm8
-	vbroadcasti32x4	L$gfpoly(%rip),%zmm31
-
-
-
-	vmovdqu	(%r12),%xmm10
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vbroadcasti32x4	(%r8),%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm12
-
-
-
-	movl	240(%rcx),%r10d
-	leal	-20(,%r10,4),%r10d
-
-
-
-
-	leaq	96(%rcx,%r10,4),%r11
-	vbroadcasti32x4	(%rcx),%zmm13
-	vbroadcasti32x4	(%r11),%zmm14
-
-
-	vpaddd	L$ctr_pattern(%rip),%zmm12,%zmm12
-
-
-	vbroadcasti32x4	L$inc_4blocks(%rip),%zmm11
-
-
-
-	cmpq	$256-1,%rdx
-	jbe	L$crypt_loop_4x_done__func2
-
-
-	vmovdqu8	256-256(%r9),%zmm27
-	vmovdqu8	256-192(%r9),%zmm28
-	vmovdqu8	256-128(%r9),%zmm29
-	vmovdqu8	256-64(%r9),%zmm30
-	vbroadcasti32x4	-144(%r11),%zmm15
-	vbroadcasti32x4	-128(%r11),%zmm16
-	vbroadcasti32x4	-112(%r11),%zmm17
-	vbroadcasti32x4	-96(%r11),%zmm18
-	vbroadcasti32x4	-80(%r11),%zmm19
-	vbroadcasti32x4	-64(%r11),%zmm20
-	vbroadcasti32x4	-48(%r11),%zmm21
-	vbroadcasti32x4	-32(%r11),%zmm22
-	vbroadcasti32x4	-16(%r11),%zmm23
-L$crypt_loop_4x__func2:
-	vmovdqu8	0(%rdi),%zmm4
-	vmovdqu8	64(%rdi),%zmm5
-	vmovdqu8	128(%rdi),%zmm6
-	vmovdqu8	192(%rdi),%zmm7
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	cmpl	$24,%r10d
-	jl	L$aes128__func2
-	je	L$aes192__func2
-
-	vbroadcasti32x4	-208(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-192(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-L$aes192__func2:
-	vbroadcasti32x4	-176(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-160(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-L$aes128__func2:
-	prefetcht0	512+0(%rdi)
-	prefetcht0	512+64(%rdi)
-	prefetcht0	512+128(%rdi)
-	prefetcht0	512+192(%rdi)
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-
-	vaesenc	%zmm15,%zmm0,%zmm0
-	vaesenc	%zmm15,%zmm1,%zmm1
-	vaesenc	%zmm15,%zmm2,%zmm2
-	vaesenc	%zmm15,%zmm3,%zmm3
-
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-
-	vaesenc	%zmm16,%zmm0,%zmm0
-	vaesenc	%zmm16,%zmm1,%zmm1
-	vaesenc	%zmm16,%zmm2,%zmm2
-	vaesenc	%zmm16,%zmm3,%zmm3
-
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-
-	vaesenc	%zmm17,%zmm0,%zmm0
-	vaesenc	%zmm17,%zmm1,%zmm1
-	vaesenc	%zmm17,%zmm2,%zmm2
-	vaesenc	%zmm17,%zmm3,%zmm3
-
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-
-	vaesenc	%zmm18,%zmm0,%zmm0
-	vaesenc	%zmm18,%zmm1,%zmm1
-	vaesenc	%zmm18,%zmm2,%zmm2
-	vaesenc	%zmm18,%zmm3,%zmm3
-
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-
-	vaesenc	%zmm19,%zmm0,%zmm0
-	vaesenc	%zmm19,%zmm1,%zmm1
-	vaesenc	%zmm19,%zmm2,%zmm2
-	vaesenc	%zmm19,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-
-	vaesenc	%zmm20,%zmm0,%zmm0
-	vaesenc	%zmm20,%zmm1,%zmm1
-	vaesenc	%zmm20,%zmm2,%zmm2
-	vaesenc	%zmm20,%zmm3,%zmm3
-
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-
-	vaesenc	%zmm21,%zmm0,%zmm0
-	vaesenc	%zmm21,%zmm1,%zmm1
-	vaesenc	%zmm21,%zmm2,%zmm2
-	vaesenc	%zmm21,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-
-	vaesenc	%zmm22,%zmm0,%zmm0
-	vaesenc	%zmm22,%zmm1,%zmm1
-	vaesenc	%zmm22,%zmm2,%zmm2
-	vaesenc	%zmm22,%zmm3,%zmm3
-
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-
-	vaesenc	%zmm23,%zmm0,%zmm0
-	vaesenc	%zmm23,%zmm1,%zmm1
-	vaesenc	%zmm23,%zmm2,%zmm2
-	vaesenc	%zmm23,%zmm3,%zmm3
-
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	ja	L$crypt_loop_4x__func2
-L$crypt_loop_4x_done__func2:
-
-	testq	%rdx,%rdx
-	jz	L$done__func2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	movq	%rdx,%rax
-	negq	%rax
-	andq	$-16,%rax
-	leaq	256(%r9,%rax,1),%r8
-	vpxor	%xmm4,%xmm4,%xmm4
-	vpxor	%xmm5,%xmm5,%xmm5
-	vpxor	%xmm6,%xmm6,%xmm6
-
-	cmpq	$64,%rdx
-	jb	L$partial_vec__func2
-
-L$crypt_loop_1x__func2:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-L$vaesenc_loop_tail_full_vec__func2:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	L$vaesenc_loop_tail_full_vec__func2
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi)
-
-
-	vmovdqu8	(%r8),%zmm30
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-	vpxor	%xmm10,%xmm10,%xmm10
-
-	addq	$64,%r8
-	addq	$64,%rdi
-	addq	$64,%rsi
-	subq	$64,%rdx
-	cmpq	$64,%rdx
-	jae	L$crypt_loop_1x__func2
-
-	testq	%rdx,%rdx
-	jz	L$reduce__func2
-
-L$partial_vec__func2:
-
-
-
-
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k1
-	addq	$15,%rdx
-	andq	$-16,%rdx
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k2
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-L$vaesenc_loop_tail_partialvec__func2:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	L$vaesenc_loop_tail_partialvec__func2
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1{%k1}{z}
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi){%k1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	(%r8),%zmm30{%k2}{z}
-
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-
-L$reduce__func2:
-
-	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
-	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
-
-	vextracti32x4	$1,%zmm6,%xmm0
-	vextracti32x4	$2,%zmm6,%xmm1
-	vextracti32x4	$3,%zmm6,%xmm2
-	vpxord	%xmm0,%xmm6,%xmm10
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
-
-
-L$done__func2:
-
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vmovdqu	%xmm10,(%r12)
-
-	vzeroupper
-	popq	%r12
-
-	ret
-
-
-
-#endif
diff --git a/src/gen/bcm/aes-gcm-avx10-x86_64-linux.S b/src/gen/bcm/aes-gcm-avx10-x86_64-linux.S
deleted file mode 100644
index b525623..0000000
--- a/src/gen/bcm/aes-gcm-avx10-x86_64-linux.S
+++ /dev/null
@@ -1,1255 +0,0 @@
-// This file is generated from a similarly-named Perl script in the BoringSSL
-// source tree. Do not edit by hand.
-
-#include <openssl/asm_base.h>
-
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__ELF__)
-.section	.rodata
-.align	64
-
-
-.Lbswap_mask:
-.quad	0x08090a0b0c0d0e0f, 0x0001020304050607
-
-
-
-
-
-
-
-
-.Lgfpoly:
-.quad	1, 0xc200000000000000
-
-
-.Lgfpoly_and_internal_carrybit:
-.quad	1, 0xc200000000000001
-
-
-
-
-
-.Lctr_pattern:
-.quad	0, 0
-.quad	1, 0
-.Linc_2blocks:
-.quad	2, 0
-.quad	3, 0
-.Linc_4blocks:
-.quad	4, 0
-
-.text	
-.globl	gcm_gmult_vpclmulqdq_avx10
-.hidden gcm_gmult_vpclmulqdq_avx10
-.type	gcm_gmult_vpclmulqdq_avx10,@function
-.align	32
-gcm_gmult_vpclmulqdq_avx10:
-.cfi_startproc	
-
-_CET_ENDBR
-
-
-
-	vmovdqu	(%rdi),%xmm0
-	vmovdqu	.Lbswap_mask(%rip),%xmm1
-	vmovdqu	256-16(%rsi),%xmm2
-	vmovdqu	.Lgfpoly(%rip),%xmm3
-	vpshufb	%xmm1,%xmm0,%xmm0
-
-	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm4
-	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm5
-	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm6
-	vpxord	%xmm6,%xmm5,%xmm5
-	vpclmulqdq	$0x01,%xmm4,%xmm3,%xmm6
-	vpshufd	$0x4e,%xmm4,%xmm4
-	vpternlogd	$0x96,%xmm6,%xmm4,%xmm5
-	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm0
-	vpclmulqdq	$0x01,%xmm5,%xmm3,%xmm4
-	vpshufd	$0x4e,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm4,%xmm5,%xmm0
-
-
-	vpshufb	%xmm1,%xmm0,%xmm0
-	vmovdqu	%xmm0,(%rdi)
-	ret
-
-.cfi_endproc	
-.size	gcm_gmult_vpclmulqdq_avx10, . - gcm_gmult_vpclmulqdq_avx10
-.globl	gcm_init_vpclmulqdq_avx10_512
-.hidden gcm_init_vpclmulqdq_avx10_512
-.type	gcm_init_vpclmulqdq_avx10_512,@function
-.align	32
-gcm_init_vpclmulqdq_avx10_512:
-.cfi_startproc	
-
-_CET_ENDBR
-
-	leaq	256-64(%rdi),%r8
-
-
-
-	vpshufd	$0x4e,(%rsi),%xmm3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vpshufd	$0xd3,%xmm3,%xmm0
-	vpsrad	$31,%xmm0,%xmm0
-	vpaddq	%xmm3,%xmm3,%xmm3
-
-	vpternlogd	$0x78,.Lgfpoly_and_internal_carrybit(%rip),%xmm0,%xmm3
-
-
-	vbroadcasti32x4	.Lgfpoly(%rip),%zmm5
-
-
-
-
-
-
-
-
-	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
-	vpclmulqdq	$0x01,%xmm3,%xmm3,%xmm1
-	vpclmulqdq	$0x10,%xmm3,%xmm3,%xmm2
-	vpxord	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm5,%xmm2
-	vpshufd	$0x4e,%xmm0,%xmm0
-	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
-	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm4
-	vpclmulqdq	$0x01,%xmm1,%xmm5,%xmm0
-	vpshufd	$0x4e,%xmm1,%xmm1
-	vpternlogd	$0x96,%xmm0,%xmm1,%xmm4
-
-
-
-	vinserti128	$1,%xmm3,%ymm4,%ymm3
-	vinserti128	$1,%xmm4,%ymm4,%ymm4
-	vpclmulqdq	$0x00,%ymm4,%ymm3,%ymm0
-	vpclmulqdq	$0x01,%ymm4,%ymm3,%ymm1
-	vpclmulqdq	$0x10,%ymm4,%ymm3,%ymm2
-	vpxord	%ymm2,%ymm1,%ymm1
-	vpclmulqdq	$0x01,%ymm0,%ymm5,%ymm2
-	vpshufd	$0x4e,%ymm0,%ymm0
-	vpternlogd	$0x96,%ymm2,%ymm0,%ymm1
-	vpclmulqdq	$0x11,%ymm4,%ymm3,%ymm4
-	vpclmulqdq	$0x01,%ymm1,%ymm5,%ymm0
-	vpshufd	$0x4e,%ymm1,%ymm1
-	vpternlogd	$0x96,%ymm0,%ymm1,%ymm4
-
-	vinserti64x4	$1,%ymm3,%zmm4,%zmm3
-	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
-
-	vmovdqu8	%zmm3,(%r8)
-
-
-
-
-
-	movl	$3,%eax
-.Lprecompute_next__func1:
-	subq	$64,%r8
-	vpclmulqdq	$0x00,%zmm4,%zmm3,%zmm0
-	vpclmulqdq	$0x01,%zmm4,%zmm3,%zmm1
-	vpclmulqdq	$0x10,%zmm4,%zmm3,%zmm2
-	vpxord	%zmm2,%zmm1,%zmm1
-	vpclmulqdq	$0x01,%zmm0,%zmm5,%zmm2
-	vpshufd	$0x4e,%zmm0,%zmm0
-	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
-	vpclmulqdq	$0x11,%zmm4,%zmm3,%zmm3
-	vpclmulqdq	$0x01,%zmm1,%zmm5,%zmm0
-	vpshufd	$0x4e,%zmm1,%zmm1
-	vpternlogd	$0x96,%zmm0,%zmm1,%zmm3
-
-	vmovdqu8	%zmm3,(%r8)
-	decl	%eax
-	jnz	.Lprecompute_next__func1
-
-	vzeroupper
-	ret
-
-.cfi_endproc	
-.size	gcm_init_vpclmulqdq_avx10_512, . - gcm_init_vpclmulqdq_avx10_512
-.globl	gcm_ghash_vpclmulqdq_avx10_512
-.hidden gcm_ghash_vpclmulqdq_avx10_512
-.type	gcm_ghash_vpclmulqdq_avx10_512,@function
-.align	32
-gcm_ghash_vpclmulqdq_avx10_512:
-.cfi_startproc	
-
-_CET_ENDBR
-
-
-
-
-
-
-	vmovdqu	.Lbswap_mask(%rip),%xmm4
-	vmovdqu	.Lgfpoly(%rip),%xmm10
-
-
-	vmovdqu	(%rdi),%xmm5
-	vpshufb	%xmm4,%xmm5,%xmm5
-
-
-	cmpq	$64,%rcx
-	jb	.Laad_blockbyblock__func1
-
-
-
-	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
-	vshufi64x2	$0,%zmm10,%zmm10,%zmm10
-
-
-	vmovdqu8	256-64(%rsi),%zmm9
-
-	cmpq	$256-1,%rcx
-	jbe	.Laad_loop_1x__func1
-
-
-	vmovdqu8	256-256(%rsi),%zmm6
-	vmovdqu8	256-192(%rsi),%zmm7
-	vmovdqu8	256-128(%rsi),%zmm8
-
-
-.Laad_loop_4x__func1:
-	vmovdqu8	0(%rdx),%zmm0
-	vmovdqu8	64(%rdx),%zmm1
-	vmovdqu8	128(%rdx),%zmm2
-	vmovdqu8	192(%rdx),%zmm3
-	vpshufb	%zmm4,%zmm0,%zmm0
-	vpxord	%zmm5,%zmm0,%zmm0
-	vpshufb	%zmm4,%zmm1,%zmm1
-	vpshufb	%zmm4,%zmm2,%zmm2
-	vpshufb	%zmm4,%zmm3,%zmm3
-	vpclmulqdq	$0x00,%zmm6,%zmm0,%zmm5
-	vpclmulqdq	$0x00,%zmm7,%zmm1,%zmm11
-	vpclmulqdq	$0x00,%zmm8,%zmm2,%zmm12
-	vpxord	%zmm11,%zmm5,%zmm5
-	vpclmulqdq	$0x00,%zmm9,%zmm3,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm5
-	vpclmulqdq	$0x01,%zmm6,%zmm0,%zmm11
-	vpclmulqdq	$0x01,%zmm7,%zmm1,%zmm12
-	vpclmulqdq	$0x01,%zmm8,%zmm2,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x01,%zmm9,%zmm3,%zmm12
-	vpclmulqdq	$0x10,%zmm6,%zmm0,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x10,%zmm7,%zmm1,%zmm12
-	vpclmulqdq	$0x10,%zmm8,%zmm2,%zmm13
-	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
-	vpclmulqdq	$0x01,%zmm5,%zmm10,%zmm13
-	vpclmulqdq	$0x10,%zmm9,%zmm3,%zmm12
-	vpxord	%zmm12,%zmm11,%zmm11
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm6,%zmm0,%zmm0
-	vpclmulqdq	$0x11,%zmm7,%zmm1,%zmm1
-	vpclmulqdq	$0x11,%zmm8,%zmm2,%zmm2
-	vpternlogd	$0x96,%zmm13,%zmm5,%zmm11
-	vpclmulqdq	$0x11,%zmm9,%zmm3,%zmm3
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm0
-	vpclmulqdq	$0x01,%zmm11,%zmm10,%zmm12
-	vpxord	%zmm3,%zmm0,%zmm5
-	vpshufd	$0x4e,%zmm11,%zmm11
-	vpternlogd	$0x96,%zmm12,%zmm11,%zmm5
-	vextracti32x4	$1,%zmm5,%xmm0
-	vextracti32x4	$2,%zmm5,%xmm1
-	vextracti32x4	$3,%zmm5,%xmm2
-	vpxord	%xmm0,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
-
-	subq	$-256,%rdx
-	addq	$-256,%rcx
-	cmpq	$256-1,%rcx
-	ja	.Laad_loop_4x__func1
-
-
-	cmpq	$64,%rcx
-	jb	.Laad_large_done__func1
-.Laad_loop_1x__func1:
-	vmovdqu8	(%rdx),%zmm0
-	vpshufb	%zmm4,%zmm0,%zmm0
-	vpxord	%zmm0,%zmm5,%zmm5
-	vpclmulqdq	$0x00,%zmm9,%zmm5,%zmm0
-	vpclmulqdq	$0x01,%zmm9,%zmm5,%zmm1
-	vpclmulqdq	$0x10,%zmm9,%zmm5,%zmm2
-	vpxord	%zmm2,%zmm1,%zmm1
-	vpclmulqdq	$0x01,%zmm0,%zmm10,%zmm2
-	vpshufd	$0x4e,%zmm0,%zmm0
-	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
-	vpclmulqdq	$0x11,%zmm9,%zmm5,%zmm5
-	vpclmulqdq	$0x01,%zmm1,%zmm10,%zmm0
-	vpshufd	$0x4e,%zmm1,%zmm1
-	vpternlogd	$0x96,%zmm0,%zmm1,%zmm5
-
-	vextracti32x4	$1,%zmm5,%xmm0
-	vextracti32x4	$2,%zmm5,%xmm1
-	vextracti32x4	$3,%zmm5,%xmm2
-	vpxord	%xmm0,%xmm5,%xmm5
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
-
-	addq	$64,%rdx
-	subq	$64,%rcx
-	cmpq	$64,%rcx
-	jae	.Laad_loop_1x__func1
-
-.Laad_large_done__func1:
-
-
-	vzeroupper
-
-
-.Laad_blockbyblock__func1:
-	testq	%rcx,%rcx
-	jz	.Laad_done__func1
-	vmovdqu	256-16(%rsi),%xmm9
-.Laad_loop_blockbyblock__func1:
-	vmovdqu	(%rdx),%xmm0
-	vpshufb	%xmm4,%xmm0,%xmm0
-	vpxor	%xmm0,%xmm5,%xmm5
-	vpclmulqdq	$0x00,%xmm9,%xmm5,%xmm0
-	vpclmulqdq	$0x01,%xmm9,%xmm5,%xmm1
-	vpclmulqdq	$0x10,%xmm9,%xmm5,%xmm2
-	vpxord	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm10,%xmm2
-	vpshufd	$0x4e,%xmm0,%xmm0
-	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
-	vpclmulqdq	$0x11,%xmm9,%xmm5,%xmm5
-	vpclmulqdq	$0x01,%xmm1,%xmm10,%xmm0
-	vpshufd	$0x4e,%xmm1,%xmm1
-	vpternlogd	$0x96,%xmm0,%xmm1,%xmm5
-
-	addq	$16,%rdx
-	subq	$16,%rcx
-	jnz	.Laad_loop_blockbyblock__func1
-
-.Laad_done__func1:
-
-	vpshufb	%xmm4,%xmm5,%xmm5
-	vmovdqu	%xmm5,(%rdi)
-	ret
-
-.cfi_endproc	
-.size	gcm_ghash_vpclmulqdq_avx10_512, . - gcm_ghash_vpclmulqdq_avx10_512
-.globl	aes_gcm_enc_update_vaes_avx10_512
-.hidden aes_gcm_enc_update_vaes_avx10_512
-.type	aes_gcm_enc_update_vaes_avx10_512,@function
-.align	32
-aes_gcm_enc_update_vaes_avx10_512:
-.cfi_startproc	
-
-_CET_ENDBR
-	pushq	%r12
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r12,-16
-
-	movq	16(%rsp),%r12
-#ifdef BORINGSSL_DISPATCH_TEST
-.extern	BORINGSSL_function_hit
-.hidden BORINGSSL_function_hit
-	movb	$1,BORINGSSL_function_hit+7(%rip)
-#endif
-
-	vbroadcasti32x4	.Lbswap_mask(%rip),%zmm8
-	vbroadcasti32x4	.Lgfpoly(%rip),%zmm31
-
-
-
-	vmovdqu	(%r12),%xmm10
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vbroadcasti32x4	(%r8),%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm12
-
-
-
-	movl	240(%rcx),%r10d
-	leal	-20(,%r10,4),%r10d
-
-
-
-
-	leaq	96(%rcx,%r10,4),%r11
-	vbroadcasti32x4	(%rcx),%zmm13
-	vbroadcasti32x4	(%r11),%zmm14
-
-
-	vpaddd	.Lctr_pattern(%rip),%zmm12,%zmm12
-
-
-	vbroadcasti32x4	.Linc_4blocks(%rip),%zmm11
-
-
-
-	cmpq	$256-1,%rdx
-	jbe	.Lcrypt_loop_4x_done__func1
-
-
-	vmovdqu8	256-256(%r9),%zmm27
-	vmovdqu8	256-192(%r9),%zmm28
-	vmovdqu8	256-128(%r9),%zmm29
-	vmovdqu8	256-64(%r9),%zmm30
-
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	leaq	16(%rcx),%rax
-.Lvaesenc_loop_first_4_vecs__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	.Lvaesenc_loop_first_4_vecs__func1
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	jbe	.Lghash_last_ciphertext_4x__func1
-	vbroadcasti32x4	-144(%r11),%zmm15
-	vbroadcasti32x4	-128(%r11),%zmm16
-	vbroadcasti32x4	-112(%r11),%zmm17
-	vbroadcasti32x4	-96(%r11),%zmm18
-	vbroadcasti32x4	-80(%r11),%zmm19
-	vbroadcasti32x4	-64(%r11),%zmm20
-	vbroadcasti32x4	-48(%r11),%zmm21
-	vbroadcasti32x4	-32(%r11),%zmm22
-	vbroadcasti32x4	-16(%r11),%zmm23
-.Lcrypt_loop_4x__func1:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	cmpl	$24,%r10d
-	jl	.Laes128__func1
-	je	.Laes192__func1
-
-	vbroadcasti32x4	-208(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-192(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-.Laes192__func1:
-	vbroadcasti32x4	-176(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-160(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-.Laes128__func1:
-	prefetcht0	512+0(%rdi)
-	prefetcht0	512+64(%rdi)
-	prefetcht0	512+128(%rdi)
-	prefetcht0	512+192(%rdi)
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-
-	vaesenc	%zmm15,%zmm0,%zmm0
-	vaesenc	%zmm15,%zmm1,%zmm1
-	vaesenc	%zmm15,%zmm2,%zmm2
-	vaesenc	%zmm15,%zmm3,%zmm3
-
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-
-	vaesenc	%zmm16,%zmm0,%zmm0
-	vaesenc	%zmm16,%zmm1,%zmm1
-	vaesenc	%zmm16,%zmm2,%zmm2
-	vaesenc	%zmm16,%zmm3,%zmm3
-
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-
-	vaesenc	%zmm17,%zmm0,%zmm0
-	vaesenc	%zmm17,%zmm1,%zmm1
-	vaesenc	%zmm17,%zmm2,%zmm2
-	vaesenc	%zmm17,%zmm3,%zmm3
-
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-
-	vaesenc	%zmm18,%zmm0,%zmm0
-	vaesenc	%zmm18,%zmm1,%zmm1
-	vaesenc	%zmm18,%zmm2,%zmm2
-	vaesenc	%zmm18,%zmm3,%zmm3
-
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-
-	vaesenc	%zmm19,%zmm0,%zmm0
-	vaesenc	%zmm19,%zmm1,%zmm1
-	vaesenc	%zmm19,%zmm2,%zmm2
-	vaesenc	%zmm19,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-
-	vaesenc	%zmm20,%zmm0,%zmm0
-	vaesenc	%zmm20,%zmm1,%zmm1
-	vaesenc	%zmm20,%zmm2,%zmm2
-	vaesenc	%zmm20,%zmm3,%zmm3
-
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-
-	vaesenc	%zmm21,%zmm0,%zmm0
-	vaesenc	%zmm21,%zmm1,%zmm1
-	vaesenc	%zmm21,%zmm2,%zmm2
-	vaesenc	%zmm21,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-
-	vaesenc	%zmm22,%zmm0,%zmm0
-	vaesenc	%zmm22,%zmm1,%zmm1
-	vaesenc	%zmm22,%zmm2,%zmm2
-	vaesenc	%zmm22,%zmm3,%zmm3
-
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-
-	vaesenc	%zmm23,%zmm0,%zmm0
-	vaesenc	%zmm23,%zmm1,%zmm1
-	vaesenc	%zmm23,%zmm2,%zmm2
-	vaesenc	%zmm23,%zmm3,%zmm3
-
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	ja	.Lcrypt_loop_4x__func1
-.Lghash_last_ciphertext_4x__func1:
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-.Lcrypt_loop_4x_done__func1:
-
-	testq	%rdx,%rdx
-	jz	.Ldone__func1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	movq	%rdx,%rax
-	negq	%rax
-	andq	$-16,%rax
-	leaq	256(%r9,%rax,1),%r8
-	vpxor	%xmm4,%xmm4,%xmm4
-	vpxor	%xmm5,%xmm5,%xmm5
-	vpxor	%xmm6,%xmm6,%xmm6
-
-	cmpq	$64,%rdx
-	jb	.Lpartial_vec__func1
-
-.Lcrypt_loop_1x__func1:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-.Lvaesenc_loop_tail_full_vec__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	.Lvaesenc_loop_tail_full_vec__func1
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi)
-
-
-	vmovdqu8	(%r8),%zmm30
-	vpshufb	%zmm8,%zmm0,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-	vpxor	%xmm10,%xmm10,%xmm10
-
-	addq	$64,%r8
-	addq	$64,%rdi
-	addq	$64,%rsi
-	subq	$64,%rdx
-	cmpq	$64,%rdx
-	jae	.Lcrypt_loop_1x__func1
-
-	testq	%rdx,%rdx
-	jz	.Lreduce__func1
-
-.Lpartial_vec__func1:
-
-
-
-
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k1
-	addq	$15,%rdx
-	andq	$-16,%rdx
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k2
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-.Lvaesenc_loop_tail_partialvec__func1:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	.Lvaesenc_loop_tail_partialvec__func1
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1{%k1}{z}
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi){%k1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	(%r8),%zmm30{%k2}{z}
-	vmovdqu8	%zmm0,%zmm1{%k1}{z}
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-
-.Lreduce__func1:
-
-	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
-	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
-
-	vextracti32x4	$1,%zmm6,%xmm0
-	vextracti32x4	$2,%zmm6,%xmm1
-	vextracti32x4	$3,%zmm6,%xmm2
-	vpxord	%xmm0,%xmm6,%xmm10
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
-
-
-.Ldone__func1:
-
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vmovdqu	%xmm10,(%r12)
-
-	vzeroupper
-	popq	%r12
-.cfi_adjust_cfa_offset	-8
-.cfi_restore	%r12
-	ret
-
-.cfi_endproc	
-.size	aes_gcm_enc_update_vaes_avx10_512, . - aes_gcm_enc_update_vaes_avx10_512
-.globl	aes_gcm_dec_update_vaes_avx10_512
-.hidden aes_gcm_dec_update_vaes_avx10_512
-.type	aes_gcm_dec_update_vaes_avx10_512,@function
-.align	32
-aes_gcm_dec_update_vaes_avx10_512:
-.cfi_startproc	
-
-_CET_ENDBR
-	pushq	%r12
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r12,-16
-
-	movq	16(%rsp),%r12
-
-	vbroadcasti32x4	.Lbswap_mask(%rip),%zmm8
-	vbroadcasti32x4	.Lgfpoly(%rip),%zmm31
-
-
-
-	vmovdqu	(%r12),%xmm10
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vbroadcasti32x4	(%r8),%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm12
-
-
-
-	movl	240(%rcx),%r10d
-	leal	-20(,%r10,4),%r10d
-
-
-
-
-	leaq	96(%rcx,%r10,4),%r11
-	vbroadcasti32x4	(%rcx),%zmm13
-	vbroadcasti32x4	(%r11),%zmm14
-
-
-	vpaddd	.Lctr_pattern(%rip),%zmm12,%zmm12
-
-
-	vbroadcasti32x4	.Linc_4blocks(%rip),%zmm11
-
-
-
-	cmpq	$256-1,%rdx
-	jbe	.Lcrypt_loop_4x_done__func2
-
-
-	vmovdqu8	256-256(%r9),%zmm27
-	vmovdqu8	256-192(%r9),%zmm28
-	vmovdqu8	256-128(%r9),%zmm29
-	vmovdqu8	256-64(%r9),%zmm30
-	vbroadcasti32x4	-144(%r11),%zmm15
-	vbroadcasti32x4	-128(%r11),%zmm16
-	vbroadcasti32x4	-112(%r11),%zmm17
-	vbroadcasti32x4	-96(%r11),%zmm18
-	vbroadcasti32x4	-80(%r11),%zmm19
-	vbroadcasti32x4	-64(%r11),%zmm20
-	vbroadcasti32x4	-48(%r11),%zmm21
-	vbroadcasti32x4	-32(%r11),%zmm22
-	vbroadcasti32x4	-16(%r11),%zmm23
-.Lcrypt_loop_4x__func2:
-	vmovdqu8	0(%rdi),%zmm4
-	vmovdqu8	64(%rdi),%zmm5
-	vmovdqu8	128(%rdi),%zmm6
-	vmovdqu8	192(%rdi),%zmm7
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm1
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm2
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpshufb	%zmm8,%zmm12,%zmm3
-	vpaddd	%zmm11,%zmm12,%zmm12
-
-
-	vpxord	%zmm13,%zmm0,%zmm0
-	vpxord	%zmm13,%zmm1,%zmm1
-	vpxord	%zmm13,%zmm2,%zmm2
-	vpxord	%zmm13,%zmm3,%zmm3
-
-	cmpl	$24,%r10d
-	jl	.Laes128__func2
-	je	.Laes192__func2
-
-	vbroadcasti32x4	-208(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-192(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-.Laes192__func2:
-	vbroadcasti32x4	-176(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-	vbroadcasti32x4	-160(%r11),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	vaesenc	%zmm9,%zmm1,%zmm1
-	vaesenc	%zmm9,%zmm2,%zmm2
-	vaesenc	%zmm9,%zmm3,%zmm3
-
-.Laes128__func2:
-	prefetcht0	512+0(%rdi)
-	prefetcht0	512+64(%rdi)
-	prefetcht0	512+128(%rdi)
-	prefetcht0	512+192(%rdi)
-	vpshufb	%zmm8,%zmm4,%zmm4
-	vpxord	%zmm10,%zmm4,%zmm4
-	vpshufb	%zmm8,%zmm5,%zmm5
-	vpshufb	%zmm8,%zmm6,%zmm6
-
-	vaesenc	%zmm15,%zmm0,%zmm0
-	vaesenc	%zmm15,%zmm1,%zmm1
-	vaesenc	%zmm15,%zmm2,%zmm2
-	vaesenc	%zmm15,%zmm3,%zmm3
-
-	vpshufb	%zmm8,%zmm7,%zmm7
-	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
-	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
-	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
-
-	vaesenc	%zmm16,%zmm0,%zmm0
-	vaesenc	%zmm16,%zmm1,%zmm1
-	vaesenc	%zmm16,%zmm2,%zmm2
-	vaesenc	%zmm16,%zmm3,%zmm3
-
-	vpxord	%zmm24,%zmm10,%zmm10
-	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
-	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
-
-	vaesenc	%zmm17,%zmm0,%zmm0
-	vaesenc	%zmm17,%zmm1,%zmm1
-	vaesenc	%zmm17,%zmm2,%zmm2
-	vaesenc	%zmm17,%zmm3,%zmm3
-
-	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
-
-	vaesenc	%zmm18,%zmm0,%zmm0
-	vaesenc	%zmm18,%zmm1,%zmm1
-	vaesenc	%zmm18,%zmm2,%zmm2
-	vaesenc	%zmm18,%zmm3,%zmm3
-
-	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
-	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
-
-	vaesenc	%zmm19,%zmm0,%zmm0
-	vaesenc	%zmm19,%zmm1,%zmm1
-	vaesenc	%zmm19,%zmm2,%zmm2
-	vaesenc	%zmm19,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
-	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
-	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
-	vpxord	%zmm25,%zmm24,%zmm24
-
-	vaesenc	%zmm20,%zmm0,%zmm0
-	vaesenc	%zmm20,%zmm1,%zmm1
-	vaesenc	%zmm20,%zmm2,%zmm2
-	vaesenc	%zmm20,%zmm3,%zmm3
-
-	vpshufd	$0x4e,%zmm10,%zmm10
-	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
-	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
-	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
-
-	vaesenc	%zmm21,%zmm0,%zmm0
-	vaesenc	%zmm21,%zmm1,%zmm1
-	vaesenc	%zmm21,%zmm2,%zmm2
-	vaesenc	%zmm21,%zmm3,%zmm3
-
-	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
-	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
-	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
-	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
-
-	vaesenc	%zmm22,%zmm0,%zmm0
-	vaesenc	%zmm22,%zmm1,%zmm1
-	vaesenc	%zmm22,%zmm2,%zmm2
-	vaesenc	%zmm22,%zmm3,%zmm3
-
-	vpxord	%zmm7,%zmm4,%zmm10
-	vpshufd	$0x4e,%zmm24,%zmm24
-	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
-
-	vaesenc	%zmm23,%zmm0,%zmm0
-	vaesenc	%zmm23,%zmm1,%zmm1
-	vaesenc	%zmm23,%zmm2,%zmm2
-	vaesenc	%zmm23,%zmm3,%zmm3
-
-	vextracti32x4	$1,%zmm10,%xmm4
-	vextracti32x4	$2,%zmm10,%xmm5
-	vextracti32x4	$3,%zmm10,%xmm6
-	vpxord	%xmm4,%xmm10,%xmm10
-	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
-
-
-
-
-	vpxord	0(%rdi),%zmm14,%zmm4
-	vpxord	64(%rdi),%zmm14,%zmm5
-	vpxord	128(%rdi),%zmm14,%zmm6
-	vpxord	192(%rdi),%zmm14,%zmm7
-
-
-
-	vaesenclast	%zmm4,%zmm0,%zmm4
-	vaesenclast	%zmm5,%zmm1,%zmm5
-	vaesenclast	%zmm6,%zmm2,%zmm6
-	vaesenclast	%zmm7,%zmm3,%zmm7
-
-
-	vmovdqu8	%zmm4,0(%rsi)
-	vmovdqu8	%zmm5,64(%rsi)
-	vmovdqu8	%zmm6,128(%rsi)
-	vmovdqu8	%zmm7,192(%rsi)
-
-	subq	$-256,%rdi
-	subq	$-256,%rsi
-	addq	$-256,%rdx
-	cmpq	$256-1,%rdx
-	ja	.Lcrypt_loop_4x__func2
-.Lcrypt_loop_4x_done__func2:
-
-	testq	%rdx,%rdx
-	jz	.Ldone__func2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	movq	%rdx,%rax
-	negq	%rax
-	andq	$-16,%rax
-	leaq	256(%r9,%rax,1),%r8
-	vpxor	%xmm4,%xmm4,%xmm4
-	vpxor	%xmm5,%xmm5,%xmm5
-	vpxor	%xmm6,%xmm6,%xmm6
-
-	cmpq	$64,%rdx
-	jb	.Lpartial_vec__func2
-
-.Lcrypt_loop_1x__func2:
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpaddd	%zmm11,%zmm12,%zmm12
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-.Lvaesenc_loop_tail_full_vec__func2:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	.Lvaesenc_loop_tail_full_vec__func2
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi)
-
-
-	vmovdqu8	(%r8),%zmm30
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-	vpxor	%xmm10,%xmm10,%xmm10
-
-	addq	$64,%r8
-	addq	$64,%rdi
-	addq	$64,%rsi
-	subq	$64,%rdx
-	cmpq	$64,%rdx
-	jae	.Lcrypt_loop_1x__func2
-
-	testq	%rdx,%rdx
-	jz	.Lreduce__func2
-
-.Lpartial_vec__func2:
-
-
-
-
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k1
-	addq	$15,%rdx
-	andq	$-16,%rdx
-	movq	$-1,%rax
-	bzhiq	%rdx,%rax,%rax
-	kmovq	%rax,%k2
-
-
-
-	vpshufb	%zmm8,%zmm12,%zmm0
-	vpxord	%zmm13,%zmm0,%zmm0
-	leaq	16(%rcx),%rax
-.Lvaesenc_loop_tail_partialvec__func2:
-	vbroadcasti32x4	(%rax),%zmm9
-	vaesenc	%zmm9,%zmm0,%zmm0
-	addq	$16,%rax
-	cmpq	%rax,%r11
-	jne	.Lvaesenc_loop_tail_partialvec__func2
-	vaesenclast	%zmm14,%zmm0,%zmm0
-
-
-	vmovdqu8	(%rdi),%zmm1{%k1}{z}
-	vpxord	%zmm1,%zmm0,%zmm0
-	vmovdqu8	%zmm0,(%rsi){%k1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	(%r8),%zmm30{%k2}{z}
-
-	vpshufb	%zmm8,%zmm1,%zmm0
-	vpxord	%zmm10,%zmm0,%zmm0
-	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
-	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
-	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
-	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
-	vpxord	%zmm7,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
-	vpxord	%zmm3,%zmm6,%zmm6
-
-
-.Lreduce__func2:
-
-	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm4,%zmm4
-	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
-	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
-	vpshufd	$0x4e,%zmm5,%zmm5
-	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
-
-	vextracti32x4	$1,%zmm6,%xmm0
-	vextracti32x4	$2,%zmm6,%xmm1
-	vextracti32x4	$3,%zmm6,%xmm2
-	vpxord	%xmm0,%xmm6,%xmm10
-	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
-
-
-.Ldone__func2:
-
-	vpshufb	%xmm8,%xmm10,%xmm10
-	vmovdqu	%xmm10,(%r12)
-
-	vzeroupper
-	popq	%r12
-.cfi_adjust_cfa_offset	-8
-.cfi_restore	%r12
-	ret
-
-.cfi_endproc	
-.size	aes_gcm_dec_update_vaes_avx10_512, . - aes_gcm_dec_update_vaes_avx10_512
-#endif
diff --git a/src/gen/bcm/aes-gcm-avx10-x86_64-win.asm b/src/gen/bcm/aes-gcm-avx10-x86_64-win.asm
deleted file mode 100644
index 733ae72..0000000
--- a/src/gen/bcm/aes-gcm-avx10-x86_64-win.asm
+++ /dev/null
@@ -1,1531 +0,0 @@
-; This file is generated from a similarly-named Perl script in the BoringSSL
-; source tree. Do not edit by hand.
-
-%ifidn __OUTPUT_FORMAT__, win64
-default	rel
-%define XMMWORD
-%define YMMWORD
-%define ZMMWORD
-%define _CET_ENDBR
-
-%ifdef BORINGSSL_PREFIX
-%include "boringssl_prefix_symbols_nasm.inc"
-%endif
-section	.rdata rdata align=8
-ALIGN	64
-
-
-$L$bswap_mask:
-	DQ	0x08090a0b0c0d0e0f,0x0001020304050607
-
-
-
-
-
-
-
-
-$L$gfpoly:
-	DQ	1,0xc200000000000000
-
-
-$L$gfpoly_and_internal_carrybit:
-	DQ	1,0xc200000000000001
-
-
-
-
-
-$L$ctr_pattern:
-	DQ	0,0
-	DQ	1,0
-$L$inc_2blocks:
-	DQ	2,0
-	DQ	3,0
-$L$inc_4blocks:
-	DQ	4,0
-
-section	.text code align=64
-
-global	gcm_gmult_vpclmulqdq_avx10
-
-ALIGN	32
-gcm_gmult_vpclmulqdq_avx10:
-
-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx10_1:
-_CET_ENDBR
-	sub	rsp,24
-$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx10_2:
-	movdqa	XMMWORD[rsp],xmm6
-$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx10_3:
-
-$L$SEH_endprologue_gcm_gmult_vpclmulqdq_avx10_4:
-
-	vmovdqu	xmm0,XMMWORD[rcx]
-	vmovdqu	xmm1,XMMWORD[$L$bswap_mask]
-	vmovdqu	xmm2,XMMWORD[((256-16))+rdx]
-	vmovdqu	xmm3,XMMWORD[$L$gfpoly]
-	vpshufb	xmm0,xmm0,xmm1
-
-	vpclmulqdq	xmm4,xmm0,xmm2,0x00
-	vpclmulqdq	xmm5,xmm0,xmm2,0x01
-	vpclmulqdq	xmm6,xmm0,xmm2,0x10
-	vpxord	xmm5,xmm5,xmm6
-	vpclmulqdq	xmm6,xmm3,xmm4,0x01
-	vpshufd	xmm4,xmm4,0x4e
-	vpternlogd	xmm5,xmm4,xmm6,0x96
-	vpclmulqdq	xmm0,xmm0,xmm2,0x11
-	vpclmulqdq	xmm4,xmm3,xmm5,0x01
-	vpshufd	xmm5,xmm5,0x4e
-	vpternlogd	xmm0,xmm5,xmm4,0x96
-
-
-	vpshufb	xmm0,xmm0,xmm1
-	vmovdqu	XMMWORD[rcx],xmm0
-	movdqa	xmm6,XMMWORD[rsp]
-	add	rsp,24
-	ret
-$L$SEH_end_gcm_gmult_vpclmulqdq_avx10_5:
-
-
-global	gcm_init_vpclmulqdq_avx10_512
-
-ALIGN	32
-gcm_init_vpclmulqdq_avx10_512:
-
-
-_CET_ENDBR
-
-	lea	r8,[((256-64))+rcx]
-
-
-
-	vpshufd	xmm3,XMMWORD[rdx],0x4e
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vpshufd	xmm0,xmm3,0xd3
-	vpsrad	xmm0,xmm0,31
-	vpaddq	xmm3,xmm3,xmm3
-
-	vpternlogd	xmm3,xmm0,XMMWORD[$L$gfpoly_and_internal_carrybit],0x78
-
-
-	vbroadcasti32x4	zmm5,ZMMWORD[$L$gfpoly]
-
-
-
-
-
-
-
-
-	vpclmulqdq	xmm0,xmm3,xmm3,0x00
-	vpclmulqdq	xmm1,xmm3,xmm3,0x01
-	vpclmulqdq	xmm2,xmm3,xmm3,0x10
-	vpxord	xmm1,xmm1,xmm2
-	vpclmulqdq	xmm2,xmm5,xmm0,0x01
-	vpshufd	xmm0,xmm0,0x4e
-	vpternlogd	xmm1,xmm0,xmm2,0x96
-	vpclmulqdq	xmm4,xmm3,xmm3,0x11
-	vpclmulqdq	xmm0,xmm5,xmm1,0x01
-	vpshufd	xmm1,xmm1,0x4e
-	vpternlogd	xmm4,xmm1,xmm0,0x96
-
-
-
-	vinserti128	ymm3,ymm4,xmm3,1
-	vinserti128	ymm4,ymm4,xmm4,1
-	vpclmulqdq	ymm0,ymm3,ymm4,0x00
-	vpclmulqdq	ymm1,ymm3,ymm4,0x01
-	vpclmulqdq	ymm2,ymm3,ymm4,0x10
-	vpxord	ymm1,ymm1,ymm2
-	vpclmulqdq	ymm2,ymm5,ymm0,0x01
-	vpshufd	ymm0,ymm0,0x4e
-	vpternlogd	ymm1,ymm0,ymm2,0x96
-	vpclmulqdq	ymm4,ymm3,ymm4,0x11
-	vpclmulqdq	ymm0,ymm5,ymm1,0x01
-	vpshufd	ymm1,ymm1,0x4e
-	vpternlogd	ymm4,ymm1,ymm0,0x96
-
-	vinserti64x4	zmm3,zmm4,ymm3,1
-	vshufi64x2	zmm4,zmm4,zmm4,0
-
-	vmovdqu8	ZMMWORD[r8],zmm3
-
-
-
-
-
-	mov	eax,3
-$L$precompute_next__func1:
-	sub	r8,64
-	vpclmulqdq	zmm0,zmm3,zmm4,0x00
-	vpclmulqdq	zmm1,zmm3,zmm4,0x01
-	vpclmulqdq	zmm2,zmm3,zmm4,0x10
-	vpxord	zmm1,zmm1,zmm2
-	vpclmulqdq	zmm2,zmm5,zmm0,0x01
-	vpshufd	zmm0,zmm0,0x4e
-	vpternlogd	zmm1,zmm0,zmm2,0x96
-	vpclmulqdq	zmm3,zmm3,zmm4,0x11
-	vpclmulqdq	zmm0,zmm5,zmm1,0x01
-	vpshufd	zmm1,zmm1,0x4e
-	vpternlogd	zmm3,zmm1,zmm0,0x96
-
-	vmovdqu8	ZMMWORD[r8],zmm3
-	dec	eax
-	jnz	NEAR $L$precompute_next__func1
-
-	vzeroupper
-	ret
-
-
-
-global	gcm_ghash_vpclmulqdq_avx10_512
-
-ALIGN	32
-gcm_ghash_vpclmulqdq_avx10_512:
-
-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1:
-_CET_ENDBR
-	sub	rsp,136
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_2:
-	movdqa	XMMWORD[rsp],xmm6
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_3:
-	movdqa	XMMWORD[16+rsp],xmm7
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_4:
-	movdqa	XMMWORD[32+rsp],xmm8
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_5:
-	movdqa	XMMWORD[48+rsp],xmm9
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_6:
-	movdqa	XMMWORD[64+rsp],xmm10
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_7:
-	movdqa	XMMWORD[80+rsp],xmm11
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_8:
-	movdqa	XMMWORD[96+rsp],xmm12
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_9:
-	movdqa	XMMWORD[112+rsp],xmm13
-$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_10:
-
-$L$SEH_endprologue_gcm_ghash_vpclmulqdq_avx10_512_11:
-
-
-
-
-	vmovdqu	xmm4,XMMWORD[$L$bswap_mask]
-	vmovdqu	xmm10,XMMWORD[$L$gfpoly]
-
-
-	vmovdqu	xmm5,XMMWORD[rcx]
-	vpshufb	xmm5,xmm5,xmm4
-
-
-	cmp	r9,64
-	jb	NEAR $L$aad_blockbyblock__func1
-
-
-
-	vshufi64x2	zmm4,zmm4,zmm4,0
-	vshufi64x2	zmm10,zmm10,zmm10,0
-
-
-	vmovdqu8	zmm9,ZMMWORD[((256-64))+rdx]
-
-	cmp	r9,4*64-1
-	jbe	NEAR $L$aad_loop_1x__func1
-
-
-	vmovdqu8	zmm6,ZMMWORD[((256-256))+rdx]
-	vmovdqu8	zmm7,ZMMWORD[((256-192))+rdx]
-	vmovdqu8	zmm8,ZMMWORD[((256-128))+rdx]
-
-
-$L$aad_loop_4x__func1:
-	vmovdqu8	zmm0,ZMMWORD[r8]
-	vmovdqu8	zmm1,ZMMWORD[64+r8]
-	vmovdqu8	zmm2,ZMMWORD[128+r8]
-	vmovdqu8	zmm3,ZMMWORD[192+r8]
-	vpshufb	zmm0,zmm0,zmm4
-	vpxord	zmm0,zmm0,zmm5
-	vpshufb	zmm1,zmm1,zmm4
-	vpshufb	zmm2,zmm2,zmm4
-	vpshufb	zmm3,zmm3,zmm4
-	vpclmulqdq	zmm5,zmm0,zmm6,0x00
-	vpclmulqdq	zmm11,zmm1,zmm7,0x00
-	vpclmulqdq	zmm12,zmm2,zmm8,0x00
-	vpxord	zmm5,zmm5,zmm11
-	vpclmulqdq	zmm13,zmm3,zmm9,0x00
-	vpternlogd	zmm5,zmm12,zmm13,0x96
-	vpclmulqdq	zmm11,zmm0,zmm6,0x01
-	vpclmulqdq	zmm12,zmm1,zmm7,0x01
-	vpclmulqdq	zmm13,zmm2,zmm8,0x01
-	vpternlogd	zmm11,zmm12,zmm13,0x96
-	vpclmulqdq	zmm12,zmm3,zmm9,0x01
-	vpclmulqdq	zmm13,zmm0,zmm6,0x10
-	vpternlogd	zmm11,zmm12,zmm13,0x96
-	vpclmulqdq	zmm12,zmm1,zmm7,0x10
-	vpclmulqdq	zmm13,zmm2,zmm8,0x10
-	vpternlogd	zmm11,zmm12,zmm13,0x96
-	vpclmulqdq	zmm13,zmm10,zmm5,0x01
-	vpclmulqdq	zmm12,zmm3,zmm9,0x10
-	vpxord	zmm11,zmm11,zmm12
-	vpshufd	zmm5,zmm5,0x4e
-	vpclmulqdq	zmm0,zmm0,zmm6,0x11
-	vpclmulqdq	zmm1,zmm1,zmm7,0x11
-	vpclmulqdq	zmm2,zmm2,zmm8,0x11
-	vpternlogd	zmm11,zmm5,zmm13,0x96
-	vpclmulqdq	zmm3,zmm3,zmm9,0x11
-	vpternlogd	zmm0,zmm1,zmm2,0x96
-	vpclmulqdq	zmm12,zmm10,zmm11,0x01
-	vpxord	zmm5,zmm0,zmm3
-	vpshufd	zmm11,zmm11,0x4e
-	vpternlogd	zmm5,zmm11,zmm12,0x96
-	vextracti32x4	xmm0,zmm5,1
-	vextracti32x4	xmm1,zmm5,2
-	vextracti32x4	xmm2,zmm5,3
-	vpxord	xmm5,xmm5,xmm0
-	vpternlogd	xmm5,xmm2,xmm1,0x96
-
-	sub	r8,-4*64
-	add	r9,-4*64
-	cmp	r9,4*64-1
-	ja	NEAR $L$aad_loop_4x__func1
-
-
-	cmp	r9,64
-	jb	NEAR $L$aad_large_done__func1
-$L$aad_loop_1x__func1:
-	vmovdqu8	zmm0,ZMMWORD[r8]
-	vpshufb	zmm0,zmm0,zmm4
-	vpxord	zmm5,zmm5,zmm0
-	vpclmulqdq	zmm0,zmm5,zmm9,0x00
-	vpclmulqdq	zmm1,zmm5,zmm9,0x01
-	vpclmulqdq	zmm2,zmm5,zmm9,0x10
-	vpxord	zmm1,zmm1,zmm2
-	vpclmulqdq	zmm2,zmm10,zmm0,0x01
-	vpshufd	zmm0,zmm0,0x4e
-	vpternlogd	zmm1,zmm0,zmm2,0x96
-	vpclmulqdq	zmm5,zmm5,zmm9,0x11
-	vpclmulqdq	zmm0,zmm10,zmm1,0x01
-	vpshufd	zmm1,zmm1,0x4e
-	vpternlogd	zmm5,zmm1,zmm0,0x96
-
-	vextracti32x4	xmm0,zmm5,1
-	vextracti32x4	xmm1,zmm5,2
-	vextracti32x4	xmm2,zmm5,3
-	vpxord	xmm5,xmm5,xmm0
-	vpternlogd	xmm5,xmm2,xmm1,0x96
-
-	add	r8,64
-	sub	r9,64
-	cmp	r9,64
-	jae	NEAR $L$aad_loop_1x__func1
-
-$L$aad_large_done__func1:
-
-
-	vzeroupper
-
-
-$L$aad_blockbyblock__func1:
-	test	r9,r9
-	jz	NEAR $L$aad_done__func1
-	vmovdqu	xmm9,XMMWORD[((256-16))+rdx]
-$L$aad_loop_blockbyblock__func1:
-	vmovdqu	xmm0,XMMWORD[r8]
-	vpshufb	xmm0,xmm0,xmm4
-	vpxor	xmm5,xmm5,xmm0
-	vpclmulqdq	xmm0,xmm5,xmm9,0x00
-	vpclmulqdq	xmm1,xmm5,xmm9,0x01
-	vpclmulqdq	xmm2,xmm5,xmm9,0x10
-	vpxord	xmm1,xmm1,xmm2
-	vpclmulqdq	xmm2,xmm10,xmm0,0x01
-	vpshufd	xmm0,xmm0,0x4e
-	vpternlogd	xmm1,xmm0,xmm2,0x96
-	vpclmulqdq	xmm5,xmm5,xmm9,0x11
-	vpclmulqdq	xmm0,xmm10,xmm1,0x01
-	vpshufd	xmm1,xmm1,0x4e
-	vpternlogd	xmm5,xmm1,xmm0,0x96
-
-	add	r8,16
-	sub	r9,16
-	jnz	NEAR $L$aad_loop_blockbyblock__func1
-
-$L$aad_done__func1:
-
-	vpshufb	xmm5,xmm5,xmm4
-	vmovdqu	XMMWORD[rcx],xmm5
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
-	movdqa	xmm10,XMMWORD[64+rsp]
-	movdqa	xmm11,XMMWORD[80+rsp]
-	movdqa	xmm12,XMMWORD[96+rsp]
-	movdqa	xmm13,XMMWORD[112+rsp]
-	add	rsp,136
-	ret
-$L$SEH_end_gcm_ghash_vpclmulqdq_avx10_512_12:
-
-
-global	aes_gcm_enc_update_vaes_avx10_512
-
-ALIGN	32
-aes_gcm_enc_update_vaes_avx10_512:
-
-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1:
-_CET_ENDBR
-	push	rsi
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_2:
-	push	rdi
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_3:
-	push	r12
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_4:
-
-	mov	rsi,QWORD[64+rsp]
-	mov	rdi,QWORD[72+rsp]
-	mov	r12,QWORD[80+rsp]
-	sub	rsp,160
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_5:
-	movdqa	XMMWORD[rsp],xmm6
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_6:
-	movdqa	XMMWORD[16+rsp],xmm7
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_7:
-	movdqa	XMMWORD[32+rsp],xmm8
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_8:
-	movdqa	XMMWORD[48+rsp],xmm9
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_9:
-	movdqa	XMMWORD[64+rsp],xmm10
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_10:
-	movdqa	XMMWORD[80+rsp],xmm11
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_11:
-	movdqa	XMMWORD[96+rsp],xmm12
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_12:
-	movdqa	XMMWORD[112+rsp],xmm13
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_13:
-	movdqa	XMMWORD[128+rsp],xmm14
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_14:
-	movdqa	XMMWORD[144+rsp],xmm15
-$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_15:
-
-$L$SEH_endprologue_aes_gcm_enc_update_vaes_avx10_512_16:
-%ifdef BORINGSSL_DISPATCH_TEST
-EXTERN	BORINGSSL_function_hit
-	mov	BYTE[((BORINGSSL_function_hit+7))],1
-%endif
-
-	vbroadcasti32x4	zmm8,ZMMWORD[$L$bswap_mask]
-	vbroadcasti32x4	zmm31,ZMMWORD[$L$gfpoly]
-
-
-
-	vmovdqu	xmm10,XMMWORD[r12]
-	vpshufb	xmm10,xmm10,xmm8
-	vbroadcasti32x4	zmm12,ZMMWORD[rsi]
-	vpshufb	zmm12,zmm12,zmm8
-
-
-
-	mov	r10d,DWORD[240+r9]
-	lea	r10d,[((-20))+r10*4]
-
-
-
-
-	lea	r11,[96+r10*4+r9]
-	vbroadcasti32x4	zmm13,ZMMWORD[r9]
-	vbroadcasti32x4	zmm14,ZMMWORD[r11]
-
-
-	vpaddd	zmm12,zmm12,ZMMWORD[$L$ctr_pattern]
-
-
-	vbroadcasti32x4	zmm11,ZMMWORD[$L$inc_4blocks]
-
-
-
-	cmp	r8,4*64-1
-	jbe	NEAR $L$crypt_loop_4x_done__func1
-
-
-	vmovdqu8	zmm27,ZMMWORD[((256-256))+rdi]
-	vmovdqu8	zmm28,ZMMWORD[((256-192))+rdi]
-	vmovdqu8	zmm29,ZMMWORD[((256-128))+rdi]
-	vmovdqu8	zmm30,ZMMWORD[((256-64))+rdi]
-
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm1,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm2,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm3,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-
-
-	vpxord	zmm0,zmm0,zmm13
-	vpxord	zmm1,zmm1,zmm13
-	vpxord	zmm2,zmm2,zmm13
-	vpxord	zmm3,zmm3,zmm13
-
-	lea	rax,[16+r9]
-$L$vaesenc_loop_first_4_vecs__func1:
-	vbroadcasti32x4	zmm9,ZMMWORD[rax]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-	add	rax,16
-	cmp	r11,rax
-	jne	NEAR $L$vaesenc_loop_first_4_vecs__func1
-
-
-
-	vpxord	zmm4,zmm14,ZMMWORD[rcx]
-	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
-	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
-	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
-
-
-
-	vaesenclast	zmm4,zmm0,zmm4
-	vaesenclast	zmm5,zmm1,zmm5
-	vaesenclast	zmm6,zmm2,zmm6
-	vaesenclast	zmm7,zmm3,zmm7
-
-
-	vmovdqu8	ZMMWORD[rdx],zmm4
-	vmovdqu8	ZMMWORD[64+rdx],zmm5
-	vmovdqu8	ZMMWORD[128+rdx],zmm6
-	vmovdqu8	ZMMWORD[192+rdx],zmm7
-
-	sub	rcx,-4*64
-	sub	rdx,-4*64
-	add	r8,-4*64
-	cmp	r8,4*64-1
-	jbe	NEAR $L$ghash_last_ciphertext_4x__func1
-	vbroadcasti32x4	zmm15,ZMMWORD[((-144))+r11]
-	vbroadcasti32x4	zmm16,ZMMWORD[((-128))+r11]
-	vbroadcasti32x4	zmm17,ZMMWORD[((-112))+r11]
-	vbroadcasti32x4	zmm18,ZMMWORD[((-96))+r11]
-	vbroadcasti32x4	zmm19,ZMMWORD[((-80))+r11]
-	vbroadcasti32x4	zmm20,ZMMWORD[((-64))+r11]
-	vbroadcasti32x4	zmm21,ZMMWORD[((-48))+r11]
-	vbroadcasti32x4	zmm22,ZMMWORD[((-32))+r11]
-	vbroadcasti32x4	zmm23,ZMMWORD[((-16))+r11]
-$L$crypt_loop_4x__func1:
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm1,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm2,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm3,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-
-
-	vpxord	zmm0,zmm0,zmm13
-	vpxord	zmm1,zmm1,zmm13
-	vpxord	zmm2,zmm2,zmm13
-	vpxord	zmm3,zmm3,zmm13
-
-	cmp	r10d,24
-	jl	NEAR $L$aes128__func1
-	je	NEAR $L$aes192__func1
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-208))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-192))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-$L$aes192__func1:
-	vbroadcasti32x4	zmm9,ZMMWORD[((-176))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-160))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-$L$aes128__func1:
-	prefetcht0	[((512+0))+rcx]
-	prefetcht0	[((512+64))+rcx]
-	prefetcht0	[((512+128))+rcx]
-	prefetcht0	[((512+192))+rcx]
-	vpshufb	zmm4,zmm4,zmm8
-	vpxord	zmm4,zmm4,zmm10
-	vpshufb	zmm5,zmm5,zmm8
-	vpshufb	zmm6,zmm6,zmm8
-
-	vaesenc	zmm0,zmm0,zmm15
-	vaesenc	zmm1,zmm1,zmm15
-	vaesenc	zmm2,zmm2,zmm15
-	vaesenc	zmm3,zmm3,zmm15
-
-	vpshufb	zmm7,zmm7,zmm8
-	vpclmulqdq	zmm10,zmm4,zmm27,0x00
-	vpclmulqdq	zmm24,zmm5,zmm28,0x00
-	vpclmulqdq	zmm25,zmm6,zmm29,0x00
-
-	vaesenc	zmm0,zmm0,zmm16
-	vaesenc	zmm1,zmm1,zmm16
-	vaesenc	zmm2,zmm2,zmm16
-	vaesenc	zmm3,zmm3,zmm16
-
-	vpxord	zmm10,zmm10,zmm24
-	vpclmulqdq	zmm26,zmm7,zmm30,0x00
-	vpternlogd	zmm10,zmm25,zmm26,0x96
-	vpclmulqdq	zmm24,zmm4,zmm27,0x01
-
-	vaesenc	zmm0,zmm0,zmm17
-	vaesenc	zmm1,zmm1,zmm17
-	vaesenc	zmm2,zmm2,zmm17
-	vaesenc	zmm3,zmm3,zmm17
-
-	vpclmulqdq	zmm25,zmm5,zmm28,0x01
-	vpclmulqdq	zmm26,zmm6,zmm29,0x01
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm7,zmm30,0x01
-
-	vaesenc	zmm0,zmm0,zmm18
-	vaesenc	zmm1,zmm1,zmm18
-	vaesenc	zmm2,zmm2,zmm18
-	vaesenc	zmm3,zmm3,zmm18
-
-	vpclmulqdq	zmm26,zmm4,zmm27,0x10
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm5,zmm28,0x10
-	vpclmulqdq	zmm26,zmm6,zmm29,0x10
-
-	vaesenc	zmm0,zmm0,zmm19
-	vaesenc	zmm1,zmm1,zmm19
-	vaesenc	zmm2,zmm2,zmm19
-	vaesenc	zmm3,zmm3,zmm19
-
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm26,zmm31,zmm10,0x01
-	vpclmulqdq	zmm25,zmm7,zmm30,0x10
-	vpxord	zmm24,zmm24,zmm25
-
-	vaesenc	zmm0,zmm0,zmm20
-	vaesenc	zmm1,zmm1,zmm20
-	vaesenc	zmm2,zmm2,zmm20
-	vaesenc	zmm3,zmm3,zmm20
-
-	vpshufd	zmm10,zmm10,0x4e
-	vpclmulqdq	zmm4,zmm4,zmm27,0x11
-	vpclmulqdq	zmm5,zmm5,zmm28,0x11
-	vpclmulqdq	zmm6,zmm6,zmm29,0x11
-
-	vaesenc	zmm0,zmm0,zmm21
-	vaesenc	zmm1,zmm1,zmm21
-	vaesenc	zmm2,zmm2,zmm21
-	vaesenc	zmm3,zmm3,zmm21
-
-	vpternlogd	zmm24,zmm10,zmm26,0x96
-	vpclmulqdq	zmm7,zmm7,zmm30,0x11
-	vpternlogd	zmm4,zmm5,zmm6,0x96
-	vpclmulqdq	zmm25,zmm31,zmm24,0x01
-
-	vaesenc	zmm0,zmm0,zmm22
-	vaesenc	zmm1,zmm1,zmm22
-	vaesenc	zmm2,zmm2,zmm22
-	vaesenc	zmm3,zmm3,zmm22
-
-	vpxord	zmm10,zmm4,zmm7
-	vpshufd	zmm24,zmm24,0x4e
-	vpternlogd	zmm10,zmm24,zmm25,0x96
-
-	vaesenc	zmm0,zmm0,zmm23
-	vaesenc	zmm1,zmm1,zmm23
-	vaesenc	zmm2,zmm2,zmm23
-	vaesenc	zmm3,zmm3,zmm23
-
-	vextracti32x4	xmm4,zmm10,1
-	vextracti32x4	xmm5,zmm10,2
-	vextracti32x4	xmm6,zmm10,3
-	vpxord	xmm10,xmm10,xmm4
-	vpternlogd	xmm10,xmm6,xmm5,0x96
-
-
-
-
-	vpxord	zmm4,zmm14,ZMMWORD[rcx]
-	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
-	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
-	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
-
-
-
-	vaesenclast	zmm4,zmm0,zmm4
-	vaesenclast	zmm5,zmm1,zmm5
-	vaesenclast	zmm6,zmm2,zmm6
-	vaesenclast	zmm7,zmm3,zmm7
-
-
-	vmovdqu8	ZMMWORD[rdx],zmm4
-	vmovdqu8	ZMMWORD[64+rdx],zmm5
-	vmovdqu8	ZMMWORD[128+rdx],zmm6
-	vmovdqu8	ZMMWORD[192+rdx],zmm7
-
-	sub	rcx,-4*64
-	sub	rdx,-4*64
-	add	r8,-4*64
-	cmp	r8,4*64-1
-	ja	NEAR $L$crypt_loop_4x__func1
-$L$ghash_last_ciphertext_4x__func1:
-	vpshufb	zmm4,zmm4,zmm8
-	vpxord	zmm4,zmm4,zmm10
-	vpshufb	zmm5,zmm5,zmm8
-	vpshufb	zmm6,zmm6,zmm8
-	vpshufb	zmm7,zmm7,zmm8
-	vpclmulqdq	zmm10,zmm4,zmm27,0x00
-	vpclmulqdq	zmm24,zmm5,zmm28,0x00
-	vpclmulqdq	zmm25,zmm6,zmm29,0x00
-	vpxord	zmm10,zmm10,zmm24
-	vpclmulqdq	zmm26,zmm7,zmm30,0x00
-	vpternlogd	zmm10,zmm25,zmm26,0x96
-	vpclmulqdq	zmm24,zmm4,zmm27,0x01
-	vpclmulqdq	zmm25,zmm5,zmm28,0x01
-	vpclmulqdq	zmm26,zmm6,zmm29,0x01
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm7,zmm30,0x01
-	vpclmulqdq	zmm26,zmm4,zmm27,0x10
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm5,zmm28,0x10
-	vpclmulqdq	zmm26,zmm6,zmm29,0x10
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm26,zmm31,zmm10,0x01
-	vpclmulqdq	zmm25,zmm7,zmm30,0x10
-	vpxord	zmm24,zmm24,zmm25
-	vpshufd	zmm10,zmm10,0x4e
-	vpclmulqdq	zmm4,zmm4,zmm27,0x11
-	vpclmulqdq	zmm5,zmm5,zmm28,0x11
-	vpclmulqdq	zmm6,zmm6,zmm29,0x11
-	vpternlogd	zmm24,zmm10,zmm26,0x96
-	vpclmulqdq	zmm7,zmm7,zmm30,0x11
-	vpternlogd	zmm4,zmm5,zmm6,0x96
-	vpclmulqdq	zmm25,zmm31,zmm24,0x01
-	vpxord	zmm10,zmm4,zmm7
-	vpshufd	zmm24,zmm24,0x4e
-	vpternlogd	zmm10,zmm24,zmm25,0x96
-	vextracti32x4	xmm4,zmm10,1
-	vextracti32x4	xmm5,zmm10,2
-	vextracti32x4	xmm6,zmm10,3
-	vpxord	xmm10,xmm10,xmm4
-	vpternlogd	xmm10,xmm6,xmm5,0x96
-
-$L$crypt_loop_4x_done__func1:
-
-	test	r8,r8
-	jz	NEAR $L$done__func1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	mov	rax,r8
-	neg	rax
-	and	rax,-16
-	lea	rsi,[256+rax*1+rdi]
-	vpxor	xmm4,xmm4,xmm4
-	vpxor	xmm5,xmm5,xmm5
-	vpxor	xmm6,xmm6,xmm6
-
-	cmp	r8,64
-	jb	NEAR $L$partial_vec__func1
-
-$L$crypt_loop_1x__func1:
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpxord	zmm0,zmm0,zmm13
-	lea	rax,[16+r9]
-$L$vaesenc_loop_tail_full_vec__func1:
-	vbroadcasti32x4	zmm9,ZMMWORD[rax]
-	vaesenc	zmm0,zmm0,zmm9
-	add	rax,16
-	cmp	r11,rax
-	jne	NEAR $L$vaesenc_loop_tail_full_vec__func1
-	vaesenclast	zmm0,zmm0,zmm14
-
-
-	vmovdqu8	zmm1,ZMMWORD[rcx]
-	vpxord	zmm0,zmm0,zmm1
-	vmovdqu8	ZMMWORD[rdx],zmm0
-
-
-	vmovdqu8	zmm30,ZMMWORD[rsi]
-	vpshufb	zmm0,zmm0,zmm8
-	vpxord	zmm0,zmm0,zmm10
-	vpclmulqdq	zmm7,zmm0,zmm30,0x00
-	vpclmulqdq	zmm1,zmm0,zmm30,0x01
-	vpclmulqdq	zmm2,zmm0,zmm30,0x10
-	vpclmulqdq	zmm3,zmm0,zmm30,0x11
-	vpxord	zmm4,zmm4,zmm7
-	vpternlogd	zmm5,zmm1,zmm2,0x96
-	vpxord	zmm6,zmm6,zmm3
-
-	vpxor	xmm10,xmm10,xmm10
-
-	add	rsi,64
-	add	rcx,64
-	add	rdx,64
-	sub	r8,64
-	cmp	r8,64
-	jae	NEAR $L$crypt_loop_1x__func1
-
-	test	r8,r8
-	jz	NEAR $L$reduce__func1
-
-$L$partial_vec__func1:
-
-
-
-
-	mov	rax,-1
-	bzhi	rax,rax,r8
-	kmovq	k1,rax
-	add	r8,15
-	and	r8,-16
-	mov	rax,-1
-	bzhi	rax,rax,r8
-	kmovq	k2,rax
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpxord	zmm0,zmm0,zmm13
-	lea	rax,[16+r9]
-$L$vaesenc_loop_tail_partialvec__func1:
-	vbroadcasti32x4	zmm9,ZMMWORD[rax]
-	vaesenc	zmm0,zmm0,zmm9
-	add	rax,16
-	cmp	r11,rax
-	jne	NEAR $L$vaesenc_loop_tail_partialvec__func1
-	vaesenclast	zmm0,zmm0,zmm14
-
-
-	vmovdqu8	zmm1{k1}{z},[rcx]
-	vpxord	zmm0,zmm0,zmm1
-	vmovdqu8	ZMMWORD[rdx]{k1},zmm0
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	zmm30{k2}{z},[rsi]
-	vmovdqu8	zmm1{k1}{z},zmm0
-	vpshufb	zmm0,zmm1,zmm8
-	vpxord	zmm0,zmm0,zmm10
-	vpclmulqdq	zmm7,zmm0,zmm30,0x00
-	vpclmulqdq	zmm1,zmm0,zmm30,0x01
-	vpclmulqdq	zmm2,zmm0,zmm30,0x10
-	vpclmulqdq	zmm3,zmm0,zmm30,0x11
-	vpxord	zmm4,zmm4,zmm7
-	vpternlogd	zmm5,zmm1,zmm2,0x96
-	vpxord	zmm6,zmm6,zmm3
-
-
-$L$reduce__func1:
-
-	vpclmulqdq	zmm0,zmm31,zmm4,0x01
-	vpshufd	zmm4,zmm4,0x4e
-	vpternlogd	zmm5,zmm4,zmm0,0x96
-	vpclmulqdq	zmm0,zmm31,zmm5,0x01
-	vpshufd	zmm5,zmm5,0x4e
-	vpternlogd	zmm6,zmm5,zmm0,0x96
-
-	vextracti32x4	xmm0,zmm6,1
-	vextracti32x4	xmm1,zmm6,2
-	vextracti32x4	xmm2,zmm6,3
-	vpxord	xmm10,xmm6,xmm0
-	vpternlogd	xmm10,xmm2,xmm1,0x96
-
-
-$L$done__func1:
-
-	vpshufb	xmm10,xmm10,xmm8
-	vmovdqu	XMMWORD[r12],xmm10
-
-	vzeroupper
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
-	movdqa	xmm10,XMMWORD[64+rsp]
-	movdqa	xmm11,XMMWORD[80+rsp]
-	movdqa	xmm12,XMMWORD[96+rsp]
-	movdqa	xmm13,XMMWORD[112+rsp]
-	movdqa	xmm14,XMMWORD[128+rsp]
-	movdqa	xmm15,XMMWORD[144+rsp]
-	add	rsp,160
-	pop	r12
-	pop	rdi
-	pop	rsi
-	ret
-$L$SEH_end_aes_gcm_enc_update_vaes_avx10_512_17:
-
-
-global	aes_gcm_dec_update_vaes_avx10_512
-
-ALIGN	32
-aes_gcm_dec_update_vaes_avx10_512:
-
-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1:
-_CET_ENDBR
-	push	rsi
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_2:
-	push	rdi
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_3:
-	push	r12
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_4:
-
-	mov	rsi,QWORD[64+rsp]
-	mov	rdi,QWORD[72+rsp]
-	mov	r12,QWORD[80+rsp]
-	sub	rsp,160
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_5:
-	movdqa	XMMWORD[rsp],xmm6
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_6:
-	movdqa	XMMWORD[16+rsp],xmm7
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_7:
-	movdqa	XMMWORD[32+rsp],xmm8
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_8:
-	movdqa	XMMWORD[48+rsp],xmm9
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_9:
-	movdqa	XMMWORD[64+rsp],xmm10
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_10:
-	movdqa	XMMWORD[80+rsp],xmm11
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_11:
-	movdqa	XMMWORD[96+rsp],xmm12
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_12:
-	movdqa	XMMWORD[112+rsp],xmm13
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_13:
-	movdqa	XMMWORD[128+rsp],xmm14
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_14:
-	movdqa	XMMWORD[144+rsp],xmm15
-$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_15:
-
-$L$SEH_endprologue_aes_gcm_dec_update_vaes_avx10_512_16:
-
-	vbroadcasti32x4	zmm8,ZMMWORD[$L$bswap_mask]
-	vbroadcasti32x4	zmm31,ZMMWORD[$L$gfpoly]
-
-
-
-	vmovdqu	xmm10,XMMWORD[r12]
-	vpshufb	xmm10,xmm10,xmm8
-	vbroadcasti32x4	zmm12,ZMMWORD[rsi]
-	vpshufb	zmm12,zmm12,zmm8
-
-
-
-	mov	r10d,DWORD[240+r9]
-	lea	r10d,[((-20))+r10*4]
-
-
-
-
-	lea	r11,[96+r10*4+r9]
-	vbroadcasti32x4	zmm13,ZMMWORD[r9]
-	vbroadcasti32x4	zmm14,ZMMWORD[r11]
-
-
-	vpaddd	zmm12,zmm12,ZMMWORD[$L$ctr_pattern]
-
-
-	vbroadcasti32x4	zmm11,ZMMWORD[$L$inc_4blocks]
-
-
-
-	cmp	r8,4*64-1
-	jbe	NEAR $L$crypt_loop_4x_done__func2
-
-
-	vmovdqu8	zmm27,ZMMWORD[((256-256))+rdi]
-	vmovdqu8	zmm28,ZMMWORD[((256-192))+rdi]
-	vmovdqu8	zmm29,ZMMWORD[((256-128))+rdi]
-	vmovdqu8	zmm30,ZMMWORD[((256-64))+rdi]
-	vbroadcasti32x4	zmm15,ZMMWORD[((-144))+r11]
-	vbroadcasti32x4	zmm16,ZMMWORD[((-128))+r11]
-	vbroadcasti32x4	zmm17,ZMMWORD[((-112))+r11]
-	vbroadcasti32x4	zmm18,ZMMWORD[((-96))+r11]
-	vbroadcasti32x4	zmm19,ZMMWORD[((-80))+r11]
-	vbroadcasti32x4	zmm20,ZMMWORD[((-64))+r11]
-	vbroadcasti32x4	zmm21,ZMMWORD[((-48))+r11]
-	vbroadcasti32x4	zmm22,ZMMWORD[((-32))+r11]
-	vbroadcasti32x4	zmm23,ZMMWORD[((-16))+r11]
-$L$crypt_loop_4x__func2:
-	vmovdqu8	zmm4,ZMMWORD[rcx]
-	vmovdqu8	zmm5,ZMMWORD[64+rcx]
-	vmovdqu8	zmm6,ZMMWORD[128+rcx]
-	vmovdqu8	zmm7,ZMMWORD[192+rcx]
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm1,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm2,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpshufb	zmm3,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-
-
-	vpxord	zmm0,zmm0,zmm13
-	vpxord	zmm1,zmm1,zmm13
-	vpxord	zmm2,zmm2,zmm13
-	vpxord	zmm3,zmm3,zmm13
-
-	cmp	r10d,24
-	jl	NEAR $L$aes128__func2
-	je	NEAR $L$aes192__func2
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-208))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-192))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-$L$aes192__func2:
-	vbroadcasti32x4	zmm9,ZMMWORD[((-176))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-	vbroadcasti32x4	zmm9,ZMMWORD[((-160))+r11]
-	vaesenc	zmm0,zmm0,zmm9
-	vaesenc	zmm1,zmm1,zmm9
-	vaesenc	zmm2,zmm2,zmm9
-	vaesenc	zmm3,zmm3,zmm9
-
-$L$aes128__func2:
-	prefetcht0	[((512+0))+rcx]
-	prefetcht0	[((512+64))+rcx]
-	prefetcht0	[((512+128))+rcx]
-	prefetcht0	[((512+192))+rcx]
-	vpshufb	zmm4,zmm4,zmm8
-	vpxord	zmm4,zmm4,zmm10
-	vpshufb	zmm5,zmm5,zmm8
-	vpshufb	zmm6,zmm6,zmm8
-
-	vaesenc	zmm0,zmm0,zmm15
-	vaesenc	zmm1,zmm1,zmm15
-	vaesenc	zmm2,zmm2,zmm15
-	vaesenc	zmm3,zmm3,zmm15
-
-	vpshufb	zmm7,zmm7,zmm8
-	vpclmulqdq	zmm10,zmm4,zmm27,0x00
-	vpclmulqdq	zmm24,zmm5,zmm28,0x00
-	vpclmulqdq	zmm25,zmm6,zmm29,0x00
-
-	vaesenc	zmm0,zmm0,zmm16
-	vaesenc	zmm1,zmm1,zmm16
-	vaesenc	zmm2,zmm2,zmm16
-	vaesenc	zmm3,zmm3,zmm16
-
-	vpxord	zmm10,zmm10,zmm24
-	vpclmulqdq	zmm26,zmm7,zmm30,0x00
-	vpternlogd	zmm10,zmm25,zmm26,0x96
-	vpclmulqdq	zmm24,zmm4,zmm27,0x01
-
-	vaesenc	zmm0,zmm0,zmm17
-	vaesenc	zmm1,zmm1,zmm17
-	vaesenc	zmm2,zmm2,zmm17
-	vaesenc	zmm3,zmm3,zmm17
-
-	vpclmulqdq	zmm25,zmm5,zmm28,0x01
-	vpclmulqdq	zmm26,zmm6,zmm29,0x01
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm7,zmm30,0x01
-
-	vaesenc	zmm0,zmm0,zmm18
-	vaesenc	zmm1,zmm1,zmm18
-	vaesenc	zmm2,zmm2,zmm18
-	vaesenc	zmm3,zmm3,zmm18
-
-	vpclmulqdq	zmm26,zmm4,zmm27,0x10
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm25,zmm5,zmm28,0x10
-	vpclmulqdq	zmm26,zmm6,zmm29,0x10
-
-	vaesenc	zmm0,zmm0,zmm19
-	vaesenc	zmm1,zmm1,zmm19
-	vaesenc	zmm2,zmm2,zmm19
-	vaesenc	zmm3,zmm3,zmm19
-
-	vpternlogd	zmm24,zmm25,zmm26,0x96
-	vpclmulqdq	zmm26,zmm31,zmm10,0x01
-	vpclmulqdq	zmm25,zmm7,zmm30,0x10
-	vpxord	zmm24,zmm24,zmm25
-
-	vaesenc	zmm0,zmm0,zmm20
-	vaesenc	zmm1,zmm1,zmm20
-	vaesenc	zmm2,zmm2,zmm20
-	vaesenc	zmm3,zmm3,zmm20
-
-	vpshufd	zmm10,zmm10,0x4e
-	vpclmulqdq	zmm4,zmm4,zmm27,0x11
-	vpclmulqdq	zmm5,zmm5,zmm28,0x11
-	vpclmulqdq	zmm6,zmm6,zmm29,0x11
-
-	vaesenc	zmm0,zmm0,zmm21
-	vaesenc	zmm1,zmm1,zmm21
-	vaesenc	zmm2,zmm2,zmm21
-	vaesenc	zmm3,zmm3,zmm21
-
-	vpternlogd	zmm24,zmm10,zmm26,0x96
-	vpclmulqdq	zmm7,zmm7,zmm30,0x11
-	vpternlogd	zmm4,zmm5,zmm6,0x96
-	vpclmulqdq	zmm25,zmm31,zmm24,0x01
-
-	vaesenc	zmm0,zmm0,zmm22
-	vaesenc	zmm1,zmm1,zmm22
-	vaesenc	zmm2,zmm2,zmm22
-	vaesenc	zmm3,zmm3,zmm22
-
-	vpxord	zmm10,zmm4,zmm7
-	vpshufd	zmm24,zmm24,0x4e
-	vpternlogd	zmm10,zmm24,zmm25,0x96
-
-	vaesenc	zmm0,zmm0,zmm23
-	vaesenc	zmm1,zmm1,zmm23
-	vaesenc	zmm2,zmm2,zmm23
-	vaesenc	zmm3,zmm3,zmm23
-
-	vextracti32x4	xmm4,zmm10,1
-	vextracti32x4	xmm5,zmm10,2
-	vextracti32x4	xmm6,zmm10,3
-	vpxord	xmm10,xmm10,xmm4
-	vpternlogd	xmm10,xmm6,xmm5,0x96
-
-
-
-
-	vpxord	zmm4,zmm14,ZMMWORD[rcx]
-	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
-	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
-	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
-
-
-
-	vaesenclast	zmm4,zmm0,zmm4
-	vaesenclast	zmm5,zmm1,zmm5
-	vaesenclast	zmm6,zmm2,zmm6
-	vaesenclast	zmm7,zmm3,zmm7
-
-
-	vmovdqu8	ZMMWORD[rdx],zmm4
-	vmovdqu8	ZMMWORD[64+rdx],zmm5
-	vmovdqu8	ZMMWORD[128+rdx],zmm6
-	vmovdqu8	ZMMWORD[192+rdx],zmm7
-
-	sub	rcx,-4*64
-	sub	rdx,-4*64
-	add	r8,-4*64
-	cmp	r8,4*64-1
-	ja	NEAR $L$crypt_loop_4x__func2
-$L$crypt_loop_4x_done__func2:
-
-	test	r8,r8
-	jz	NEAR $L$done__func2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	mov	rax,r8
-	neg	rax
-	and	rax,-16
-	lea	rsi,[256+rax*1+rdi]
-	vpxor	xmm4,xmm4,xmm4
-	vpxor	xmm5,xmm5,xmm5
-	vpxor	xmm6,xmm6,xmm6
-
-	cmp	r8,64
-	jb	NEAR $L$partial_vec__func2
-
-$L$crypt_loop_1x__func2:
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpaddd	zmm12,zmm12,zmm11
-	vpxord	zmm0,zmm0,zmm13
-	lea	rax,[16+r9]
-$L$vaesenc_loop_tail_full_vec__func2:
-	vbroadcasti32x4	zmm9,ZMMWORD[rax]
-	vaesenc	zmm0,zmm0,zmm9
-	add	rax,16
-	cmp	r11,rax
-	jne	NEAR $L$vaesenc_loop_tail_full_vec__func2
-	vaesenclast	zmm0,zmm0,zmm14
-
-
-	vmovdqu8	zmm1,ZMMWORD[rcx]
-	vpxord	zmm0,zmm0,zmm1
-	vmovdqu8	ZMMWORD[rdx],zmm0
-
-
-	vmovdqu8	zmm30,ZMMWORD[rsi]
-	vpshufb	zmm0,zmm1,zmm8
-	vpxord	zmm0,zmm0,zmm10
-	vpclmulqdq	zmm7,zmm0,zmm30,0x00
-	vpclmulqdq	zmm1,zmm0,zmm30,0x01
-	vpclmulqdq	zmm2,zmm0,zmm30,0x10
-	vpclmulqdq	zmm3,zmm0,zmm30,0x11
-	vpxord	zmm4,zmm4,zmm7
-	vpternlogd	zmm5,zmm1,zmm2,0x96
-	vpxord	zmm6,zmm6,zmm3
-
-	vpxor	xmm10,xmm10,xmm10
-
-	add	rsi,64
-	add	rcx,64
-	add	rdx,64
-	sub	r8,64
-	cmp	r8,64
-	jae	NEAR $L$crypt_loop_1x__func2
-
-	test	r8,r8
-	jz	NEAR $L$reduce__func2
-
-$L$partial_vec__func2:
-
-
-
-
-	mov	rax,-1
-	bzhi	rax,rax,r8
-	kmovq	k1,rax
-	add	r8,15
-	and	r8,-16
-	mov	rax,-1
-	bzhi	rax,rax,r8
-	kmovq	k2,rax
-
-
-
-	vpshufb	zmm0,zmm12,zmm8
-	vpxord	zmm0,zmm0,zmm13
-	lea	rax,[16+r9]
-$L$vaesenc_loop_tail_partialvec__func2:
-	vbroadcasti32x4	zmm9,ZMMWORD[rax]
-	vaesenc	zmm0,zmm0,zmm9
-	add	rax,16
-	cmp	r11,rax
-	jne	NEAR $L$vaesenc_loop_tail_partialvec__func2
-	vaesenclast	zmm0,zmm0,zmm14
-
-
-	vmovdqu8	zmm1{k1}{z},[rcx]
-	vpxord	zmm0,zmm0,zmm1
-	vmovdqu8	ZMMWORD[rdx]{k1},zmm0
-
-
-
-
-
-
-
-
-
-
-
-
-
-	vmovdqu8	zmm30{k2}{z},[rsi]
-
-	vpshufb	zmm0,zmm1,zmm8
-	vpxord	zmm0,zmm0,zmm10
-	vpclmulqdq	zmm7,zmm0,zmm30,0x00
-	vpclmulqdq	zmm1,zmm0,zmm30,0x01
-	vpclmulqdq	zmm2,zmm0,zmm30,0x10
-	vpclmulqdq	zmm3,zmm0,zmm30,0x11
-	vpxord	zmm4,zmm4,zmm7
-	vpternlogd	zmm5,zmm1,zmm2,0x96
-	vpxord	zmm6,zmm6,zmm3
-
-
-$L$reduce__func2:
-
-	vpclmulqdq	zmm0,zmm31,zmm4,0x01
-	vpshufd	zmm4,zmm4,0x4e
-	vpternlogd	zmm5,zmm4,zmm0,0x96
-	vpclmulqdq	zmm0,zmm31,zmm5,0x01
-	vpshufd	zmm5,zmm5,0x4e
-	vpternlogd	zmm6,zmm5,zmm0,0x96
-
-	vextracti32x4	xmm0,zmm6,1
-	vextracti32x4	xmm1,zmm6,2
-	vextracti32x4	xmm2,zmm6,3
-	vpxord	xmm10,xmm6,xmm0
-	vpternlogd	xmm10,xmm2,xmm1,0x96
-
-
-$L$done__func2:
-
-	vpshufb	xmm10,xmm10,xmm8
-	vmovdqu	XMMWORD[r12],xmm10
-
-	vzeroupper
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
-	movdqa	xmm10,XMMWORD[64+rsp]
-	movdqa	xmm11,XMMWORD[80+rsp]
-	movdqa	xmm12,XMMWORD[96+rsp]
-	movdqa	xmm13,XMMWORD[112+rsp]
-	movdqa	xmm14,XMMWORD[128+rsp]
-	movdqa	xmm15,XMMWORD[144+rsp]
-	add	rsp,160
-	pop	r12
-	pop	rdi
-	pop	rsi
-	ret
-$L$SEH_end_aes_gcm_dec_update_vaes_avx10_512_17:
-
-
-section	.pdata rdata align=4
-ALIGN	4
-	DD	$L$SEH_begin_gcm_gmult_vpclmulqdq_avx10_1 wrt ..imagebase
-	DD	$L$SEH_end_gcm_gmult_vpclmulqdq_avx10_5 wrt ..imagebase
-	DD	$L$SEH_info_gcm_gmult_vpclmulqdq_avx10_0 wrt ..imagebase
-
-	DD	$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1 wrt ..imagebase
-	DD	$L$SEH_end_gcm_ghash_vpclmulqdq_avx10_512_12 wrt ..imagebase
-	DD	$L$SEH_info_gcm_ghash_vpclmulqdq_avx10_512_0 wrt ..imagebase
-
-	DD	$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1 wrt ..imagebase
-	DD	$L$SEH_end_aes_gcm_enc_update_vaes_avx10_512_17 wrt ..imagebase
-	DD	$L$SEH_info_aes_gcm_enc_update_vaes_avx10_512_0 wrt ..imagebase
-
-	DD	$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1 wrt ..imagebase
-	DD	$L$SEH_end_aes_gcm_dec_update_vaes_avx10_512_17 wrt ..imagebase
-	DD	$L$SEH_info_aes_gcm_dec_update_vaes_avx10_512_0 wrt ..imagebase
-
-
-section	.xdata rdata align=8
-ALIGN	4
-$L$SEH_info_gcm_gmult_vpclmulqdq_avx10_0:
-	DB	1
-	DB	$L$SEH_endprologue_gcm_gmult_vpclmulqdq_avx10_4-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx10_1
-	DB	3
-	DB	0
-	DB	$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx10_3-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx10_1
-	DB	104
-	DW	0
-	DB	$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx10_2-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx10_1
-	DB	34
-
-	DW	0
-$L$SEH_info_gcm_ghash_vpclmulqdq_avx10_512_0:
-	DB	1
-	DB	$L$SEH_endprologue_gcm_ghash_vpclmulqdq_avx10_512_11-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	18
-	DB	0
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_10-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	216
-	DW	7
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_9-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	200
-	DW	6
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_8-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	184
-	DW	5
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_7-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	168
-	DW	4
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_6-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	152
-	DW	3
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_5-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	136
-	DW	2
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_4-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	120
-	DW	1
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_3-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	104
-	DW	0
-	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx10_512_2-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx10_512_1
-	DB	1
-	DW	17
-
-$L$SEH_info_aes_gcm_enc_update_vaes_avx10_512_0:
-	DB	1
-	DB	$L$SEH_endprologue_aes_gcm_enc_update_vaes_avx10_512_16-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	25
-	DB	0
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_15-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	248
-	DW	9
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_14-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	232
-	DW	8
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_13-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	216
-	DW	7
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_12-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	200
-	DW	6
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_11-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	184
-	DW	5
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_10-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	168
-	DW	4
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_9-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	152
-	DW	3
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_8-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	136
-	DW	2
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_7-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	120
-	DW	1
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_6-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	104
-	DW	0
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_5-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	1
-	DW	20
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_4-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	192
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_3-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	112
-	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx10_512_2-$L$SEH_begin_aes_gcm_enc_update_vaes_avx10_512_1
-	DB	96
-
-	DW	0
-$L$SEH_info_aes_gcm_dec_update_vaes_avx10_512_0:
-	DB	1
-	DB	$L$SEH_endprologue_aes_gcm_dec_update_vaes_avx10_512_16-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	25
-	DB	0
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_15-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	248
-	DW	9
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_14-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	232
-	DW	8
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_13-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	216
-	DW	7
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_12-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	200
-	DW	6
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_11-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	184
-	DW	5
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_10-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	168
-	DW	4
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_9-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	152
-	DW	3
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_8-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	136
-	DW	2
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_7-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	120
-	DW	1
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_6-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	104
-	DW	0
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_5-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	1
-	DW	20
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_4-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	192
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_3-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	112
-	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx10_512_2-$L$SEH_begin_aes_gcm_dec_update_vaes_avx10_512_1
-	DB	96
-
-	DW	0
-%else
-; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738
-ret
-%endif
diff --git a/src/gen/bcm/aes-gcm-avx2-x86_64-apple.S b/src/gen/bcm/aes-gcm-avx2-x86_64-apple.S
index d896f2a..eb2ac3b 100644
--- a/src/gen/bcm/aes-gcm-avx2-x86_64-apple.S
+++ b/src/gen/bcm/aes-gcm-avx2-x86_64-apple.S
@@ -64,14 +64,10 @@
 
 
 	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
-	vpclmulqdq	$0x01,%xmm3,%xmm3,%xmm1
-	vpclmulqdq	$0x10,%xmm3,%xmm3,%xmm2
-	vpxor	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm6,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm5
+	vpclmulqdq	$0x01,%xmm0,%xmm6,%xmm1
 	vpshufd	$0x4e,%xmm0,%xmm0
 	vpxor	%xmm0,%xmm1,%xmm1
-	vpxor	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm5
 	vpclmulqdq	$0x01,%xmm1,%xmm6,%xmm0
 	vpshufd	$0x4e,%xmm1,%xmm1
 	vpxor	%xmm1,%xmm5,%xmm5
@@ -187,6 +183,8 @@
 
 	vpshufb	%xmm1,%xmm0,%xmm0
 	vmovdqu	%xmm0,(%rdi)
+
+
 	ret
 
 
@@ -202,15 +200,25 @@
 
 
 
-	vbroadcasti128	L$bswap_mask(%rip),%ymm6
+
+
+
+	vmovdqu	L$bswap_mask(%rip),%xmm6
+	vmovdqu	L$gfpoly(%rip),%xmm7
+
+
 	vmovdqu	(%rdi),%xmm5
 	vpshufb	%xmm6,%xmm5,%xmm5
-	vbroadcasti128	L$gfpoly(%rip),%ymm7
 
 
 	cmpq	$32,%rcx
 	jb	L$ghash_lastblock
 
+
+
+	vinserti128	$1,%xmm6,%ymm6,%ymm6
+	vinserti128	$1,%xmm7,%ymm7,%ymm7
+
 	cmpq	$127,%rcx
 	jbe	L$ghash_loop_1x
 
@@ -319,9 +327,6 @@
 L$ghash_loop_1x_done:
 
 
-	vzeroupper
-
-
 L$ghash_lastblock:
 	testq	%rcx,%rcx
 	jz	L$ghash_done
@@ -348,6 +353,8 @@
 
 	vpshufb	%xmm6,%xmm5,%xmm5
 	vmovdqu	%xmm5,(%rdi)
+
+	vzeroupper
 	ret
 
 
@@ -366,7 +373,7 @@
 	movq	16(%rsp),%r12
 #ifdef BORINGSSL_DISPATCH_TEST
 
-	movb	$1,_BORINGSSL_function_hit+8(%rip)
+	movb	$1,_BORINGSSL_function_hit+6(%rip)
 #endif
 	vbroadcasti128	L$bswap_mask(%rip),%ymm0
 
diff --git a/src/gen/bcm/aes-gcm-avx2-x86_64-linux.S b/src/gen/bcm/aes-gcm-avx2-x86_64-linux.S
index 583f02f..018397a 100644
--- a/src/gen/bcm/aes-gcm-avx2-x86_64-linux.S
+++ b/src/gen/bcm/aes-gcm-avx2-x86_64-linux.S
@@ -64,14 +64,10 @@
 
 
 	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
-	vpclmulqdq	$0x01,%xmm3,%xmm3,%xmm1
-	vpclmulqdq	$0x10,%xmm3,%xmm3,%xmm2
-	vpxor	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x01,%xmm0,%xmm6,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm5
+	vpclmulqdq	$0x01,%xmm0,%xmm6,%xmm1
 	vpshufd	$0x4e,%xmm0,%xmm0
 	vpxor	%xmm0,%xmm1,%xmm1
-	vpxor	%xmm2,%xmm1,%xmm1
-	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm5
 	vpclmulqdq	$0x01,%xmm1,%xmm6,%xmm0
 	vpshufd	$0x4e,%xmm1,%xmm1
 	vpxor	%xmm1,%xmm5,%xmm5
@@ -187,6 +183,8 @@
 
 	vpshufb	%xmm1,%xmm0,%xmm0
 	vmovdqu	%xmm0,(%rdi)
+
+
 	ret
 
 .cfi_endproc	
@@ -202,15 +200,25 @@
 
 
 
-	vbroadcasti128	.Lbswap_mask(%rip),%ymm6
+
+
+
+	vmovdqu	.Lbswap_mask(%rip),%xmm6
+	vmovdqu	.Lgfpoly(%rip),%xmm7
+
+
 	vmovdqu	(%rdi),%xmm5
 	vpshufb	%xmm6,%xmm5,%xmm5
-	vbroadcasti128	.Lgfpoly(%rip),%ymm7
 
 
 	cmpq	$32,%rcx
 	jb	.Lghash_lastblock
 
+
+
+	vinserti128	$1,%xmm6,%ymm6,%ymm6
+	vinserti128	$1,%xmm7,%ymm7,%ymm7
+
 	cmpq	$127,%rcx
 	jbe	.Lghash_loop_1x
 
@@ -319,9 +327,6 @@
 .Lghash_loop_1x_done:
 
 
-	vzeroupper
-
-
 .Lghash_lastblock:
 	testq	%rcx,%rcx
 	jz	.Lghash_done
@@ -348,6 +353,8 @@
 
 	vpshufb	%xmm6,%xmm5,%xmm5
 	vmovdqu	%xmm5,(%rdi)
+
+	vzeroupper
 	ret
 
 .cfi_endproc	
@@ -368,7 +375,7 @@
 #ifdef BORINGSSL_DISPATCH_TEST
 .extern	BORINGSSL_function_hit
 .hidden BORINGSSL_function_hit
-	movb	$1,BORINGSSL_function_hit+8(%rip)
+	movb	$1,BORINGSSL_function_hit+6(%rip)
 #endif
 	vbroadcasti128	.Lbswap_mask(%rip),%ymm0
 
diff --git a/src/gen/bcm/aes-gcm-avx2-x86_64-win.asm b/src/gen/bcm/aes-gcm-avx2-x86_64-win.asm
index 00e2a2b..ca1d28b 100644
--- a/src/gen/bcm/aes-gcm-avx2-x86_64-win.asm
+++ b/src/gen/bcm/aes-gcm-avx2-x86_64-win.asm
@@ -52,7 +52,7 @@
 _CET_ENDBR
 	sub	rsp,24
 $L$SEH_prologue_gcm_init_vpclmulqdq_avx2_2:
-	movdqa	XMMWORD[rsp],xmm6
+	vmovdqa	XMMWORD[rsp],xmm6
 $L$SEH_prologue_gcm_init_vpclmulqdq_avx2_3:
 
 $L$SEH_endprologue_gcm_init_vpclmulqdq_avx2_4:
@@ -75,14 +75,10 @@
 
 
 	vpclmulqdq	xmm0,xmm3,xmm3,0x00
-	vpclmulqdq	xmm1,xmm3,xmm3,0x01
-	vpclmulqdq	xmm2,xmm3,xmm3,0x10
-	vpxor	xmm1,xmm1,xmm2
-	vpclmulqdq	xmm2,xmm6,xmm0,0x01
+	vpclmulqdq	xmm5,xmm3,xmm3,0x11
+	vpclmulqdq	xmm1,xmm6,xmm0,0x01
 	vpshufd	xmm0,xmm0,0x4e
 	vpxor	xmm1,xmm1,xmm0
-	vpxor	xmm1,xmm1,xmm2
-	vpclmulqdq	xmm5,xmm3,xmm3,0x11
 	vpclmulqdq	xmm0,xmm6,xmm1,0x01
 	vpshufd	xmm1,xmm1,0x4e
 	vpxor	xmm5,xmm5,xmm1
@@ -160,7 +156,7 @@
 	vmovdqu	YMMWORD[128+rcx],ymm0
 
 	vzeroupper
-	movdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm6,XMMWORD[rsp]
 	add	rsp,24
 	ret
 $L$SEH_end_gcm_init_vpclmulqdq_avx2_5:
@@ -175,7 +171,7 @@
 _CET_ENDBR
 	sub	rsp,24
 $L$SEH_prologue_gcm_gmult_vpclmulqdq_avx2_2:
-	movdqa	XMMWORD[rsp],xmm6
+	vmovdqa	XMMWORD[rsp],xmm6
 $L$SEH_prologue_gcm_gmult_vpclmulqdq_avx2_3:
 
 $L$SEH_endprologue_gcm_gmult_vpclmulqdq_avx2_4:
@@ -203,7 +199,9 @@
 
 	vpshufb	xmm0,xmm0,xmm1
 	vmovdqu	XMMWORD[rcx],xmm0
-	movdqa	xmm6,XMMWORD[rsp]
+
+
+	vmovdqa	xmm6,XMMWORD[rsp]
 	add	rsp,24
 	ret
 $L$SEH_end_gcm_gmult_vpclmulqdq_avx2_5:
@@ -218,26 +216,36 @@
 _CET_ENDBR
 	sub	rsp,72
 $L$SEH_prologue_gcm_ghash_vpclmulqdq_avx2_2:
-	movdqa	XMMWORD[rsp],xmm6
+	vmovdqa	XMMWORD[rsp],xmm6
 $L$SEH_prologue_gcm_ghash_vpclmulqdq_avx2_3:
-	movdqa	XMMWORD[16+rsp],xmm7
+	vmovdqa	XMMWORD[16+rsp],xmm7
 $L$SEH_prologue_gcm_ghash_vpclmulqdq_avx2_4:
-	movdqa	XMMWORD[32+rsp],xmm8
+	vmovdqa	XMMWORD[32+rsp],xmm8
 $L$SEH_prologue_gcm_ghash_vpclmulqdq_avx2_5:
-	movdqa	XMMWORD[48+rsp],xmm9
+	vmovdqa	XMMWORD[48+rsp],xmm9
 $L$SEH_prologue_gcm_ghash_vpclmulqdq_avx2_6:
 
 $L$SEH_endprologue_gcm_ghash_vpclmulqdq_avx2_7:
 
-	vbroadcasti128	ymm6,XMMWORD[$L$bswap_mask]
+
+
+
+	vmovdqu	xmm6,XMMWORD[$L$bswap_mask]
+	vmovdqu	xmm7,XMMWORD[$L$gfpoly]
+
+
 	vmovdqu	xmm5,XMMWORD[rcx]
 	vpshufb	xmm5,xmm5,xmm6
-	vbroadcasti128	ymm7,XMMWORD[$L$gfpoly]
 
 
 	cmp	r9,32
 	jb	NEAR $L$ghash_lastblock
 
+
+
+	vinserti128	ymm6,ymm6,xmm6,1
+	vinserti128	ymm7,ymm7,xmm7,1
+
 	cmp	r9,127
 	jbe	NEAR $L$ghash_loop_1x
 
@@ -346,9 +354,6 @@
 $L$ghash_loop_1x_done:
 
 
-	vzeroupper
-
-
 $L$ghash_lastblock:
 	test	r9,r9
 	jz	NEAR $L$ghash_done
@@ -375,10 +380,12 @@
 
 	vpshufb	xmm5,xmm5,xmm6
 	vmovdqu	XMMWORD[rcx],xmm5
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
+
+	vzeroupper
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
 	add	rsp,72
 	ret
 $L$SEH_end_gcm_ghash_vpclmulqdq_avx2_8:
@@ -403,31 +410,31 @@
 	mov	r12,QWORD[80+rsp]
 	sub	rsp,160
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_5:
-	movdqa	XMMWORD[rsp],xmm6
+	vmovdqa	XMMWORD[rsp],xmm6
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_6:
-	movdqa	XMMWORD[16+rsp],xmm7
+	vmovdqa	XMMWORD[16+rsp],xmm7
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_7:
-	movdqa	XMMWORD[32+rsp],xmm8
+	vmovdqa	XMMWORD[32+rsp],xmm8
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_8:
-	movdqa	XMMWORD[48+rsp],xmm9
+	vmovdqa	XMMWORD[48+rsp],xmm9
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_9:
-	movdqa	XMMWORD[64+rsp],xmm10
+	vmovdqa	XMMWORD[64+rsp],xmm10
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_10:
-	movdqa	XMMWORD[80+rsp],xmm11
+	vmovdqa	XMMWORD[80+rsp],xmm11
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_11:
-	movdqa	XMMWORD[96+rsp],xmm12
+	vmovdqa	XMMWORD[96+rsp],xmm12
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_12:
-	movdqa	XMMWORD[112+rsp],xmm13
+	vmovdqa	XMMWORD[112+rsp],xmm13
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_13:
-	movdqa	XMMWORD[128+rsp],xmm14
+	vmovdqa	XMMWORD[128+rsp],xmm14
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_14:
-	movdqa	XMMWORD[144+rsp],xmm15
+	vmovdqa	XMMWORD[144+rsp],xmm15
 $L$SEH_prologue_aes_gcm_enc_update_vaes_avx2_15:
 
 $L$SEH_endprologue_aes_gcm_enc_update_vaes_avx2_16:
 %ifdef BORINGSSL_DISPATCH_TEST
 EXTERN	BORINGSSL_function_hit
-	mov	BYTE[((BORINGSSL_function_hit+8))],1
+	mov	BYTE[((BORINGSSL_function_hit+6))],1
 %endif
 	vbroadcasti128	ymm0,XMMWORD[$L$bswap_mask]
 
@@ -945,16 +952,16 @@
 	vmovdqu	XMMWORD[r12],xmm1
 
 	vzeroupper
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
-	movdqa	xmm10,XMMWORD[64+rsp]
-	movdqa	xmm11,XMMWORD[80+rsp]
-	movdqa	xmm12,XMMWORD[96+rsp]
-	movdqa	xmm13,XMMWORD[112+rsp]
-	movdqa	xmm14,XMMWORD[128+rsp]
-	movdqa	xmm15,XMMWORD[144+rsp]
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
+	vmovdqa	xmm10,XMMWORD[64+rsp]
+	vmovdqa	xmm11,XMMWORD[80+rsp]
+	vmovdqa	xmm12,XMMWORD[96+rsp]
+	vmovdqa	xmm13,XMMWORD[112+rsp]
+	vmovdqa	xmm14,XMMWORD[128+rsp]
+	vmovdqa	xmm15,XMMWORD[144+rsp]
 	add	rsp,160
 	pop	r12
 	pop	rdi
@@ -982,25 +989,25 @@
 	mov	r12,QWORD[80+rsp]
 	sub	rsp,160
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_5:
-	movdqa	XMMWORD[rsp],xmm6
+	vmovdqa	XMMWORD[rsp],xmm6
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_6:
-	movdqa	XMMWORD[16+rsp],xmm7
+	vmovdqa	XMMWORD[16+rsp],xmm7
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_7:
-	movdqa	XMMWORD[32+rsp],xmm8
+	vmovdqa	XMMWORD[32+rsp],xmm8
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_8:
-	movdqa	XMMWORD[48+rsp],xmm9
+	vmovdqa	XMMWORD[48+rsp],xmm9
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_9:
-	movdqa	XMMWORD[64+rsp],xmm10
+	vmovdqa	XMMWORD[64+rsp],xmm10
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_10:
-	movdqa	XMMWORD[80+rsp],xmm11
+	vmovdqa	XMMWORD[80+rsp],xmm11
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_11:
-	movdqa	XMMWORD[96+rsp],xmm12
+	vmovdqa	XMMWORD[96+rsp],xmm12
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_12:
-	movdqa	XMMWORD[112+rsp],xmm13
+	vmovdqa	XMMWORD[112+rsp],xmm13
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_13:
-	movdqa	XMMWORD[128+rsp],xmm14
+	vmovdqa	XMMWORD[128+rsp],xmm14
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_14:
-	movdqa	XMMWORD[144+rsp],xmm15
+	vmovdqa	XMMWORD[144+rsp],xmm15
 $L$SEH_prologue_aes_gcm_dec_update_vaes_avx2_15:
 
 $L$SEH_endprologue_aes_gcm_dec_update_vaes_avx2_16:
@@ -1406,16 +1413,16 @@
 	vmovdqu	XMMWORD[r12],xmm1
 
 	vzeroupper
-	movdqa	xmm6,XMMWORD[rsp]
-	movdqa	xmm7,XMMWORD[16+rsp]
-	movdqa	xmm8,XMMWORD[32+rsp]
-	movdqa	xmm9,XMMWORD[48+rsp]
-	movdqa	xmm10,XMMWORD[64+rsp]
-	movdqa	xmm11,XMMWORD[80+rsp]
-	movdqa	xmm12,XMMWORD[96+rsp]
-	movdqa	xmm13,XMMWORD[112+rsp]
-	movdqa	xmm14,XMMWORD[128+rsp]
-	movdqa	xmm15,XMMWORD[144+rsp]
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
+	vmovdqa	xmm10,XMMWORD[64+rsp]
+	vmovdqa	xmm11,XMMWORD[80+rsp]
+	vmovdqa	xmm12,XMMWORD[96+rsp]
+	vmovdqa	xmm13,XMMWORD[112+rsp]
+	vmovdqa	xmm14,XMMWORD[128+rsp]
+	vmovdqa	xmm15,XMMWORD[144+rsp]
 	add	rsp,160
 	pop	r12
 	pop	rdi
diff --git a/src/gen/bcm/aes-gcm-avx512-x86_64-apple.S b/src/gen/bcm/aes-gcm-avx512-x86_64-apple.S
new file mode 100644
index 0000000..874ec0a
--- /dev/null
+++ b/src/gen/bcm/aes-gcm-avx512-x86_64-apple.S
@@ -0,0 +1,1246 @@
+// This file is generated from a similarly-named Perl script in the BoringSSL
+// source tree. Do not edit by hand.
+
+#include <openssl/asm_base.h>
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__APPLE__)
+.section	__DATA,__const
+.p2align	6
+
+
+L$bswap_mask:
+.quad	0x08090a0b0c0d0e0f, 0x0001020304050607
+
+
+
+
+
+
+
+
+L$gfpoly:
+.quad	1, 0xc200000000000000
+
+
+L$gfpoly_and_internal_carrybit:
+.quad	1, 0xc200000000000001
+
+
+L$ctr_pattern:
+.quad	0, 0
+.quad	1, 0
+.quad	2, 0
+.quad	3, 0
+
+
+L$inc_4blocks:
+.quad	4, 0
+
+.text	
+.globl	_gcm_init_vpclmulqdq_avx512
+.private_extern _gcm_init_vpclmulqdq_avx512
+
+.p2align	5
+_gcm_init_vpclmulqdq_avx512:
+
+
+_CET_ENDBR
+
+	leaq	256-64(%rdi),%r8
+
+
+
+	vpshufd	$0x4e,(%rsi),%xmm3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vpshufd	$0xd3,%xmm3,%xmm0
+	vpsrad	$31,%xmm0,%xmm0
+	vpaddq	%xmm3,%xmm3,%xmm3
+
+	vpternlogd	$0x78,L$gfpoly_and_internal_carrybit(%rip),%xmm0,%xmm3
+
+
+	vbroadcasti32x4	L$gfpoly(%rip),%zmm5
+
+
+
+
+
+
+
+
+	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
+	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm4
+	vpclmulqdq	$0x01,%xmm0,%xmm5,%xmm1
+	vpshufd	$0x4e,%xmm0,%xmm0
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpclmulqdq	$0x01,%xmm1,%xmm5,%xmm0
+	vpshufd	$0x4e,%xmm1,%xmm1
+	vpternlogd	$0x96,%xmm0,%xmm1,%xmm4
+
+
+
+	vinserti128	$1,%xmm3,%ymm4,%ymm3
+	vinserti128	$1,%xmm4,%ymm4,%ymm4
+
+
+	vpclmulqdq	$0x00,%ymm4,%ymm3,%ymm0
+	vpclmulqdq	$0x01,%ymm4,%ymm3,%ymm1
+	vpclmulqdq	$0x10,%ymm4,%ymm3,%ymm2
+	vpxord	%ymm2,%ymm1,%ymm1
+	vpclmulqdq	$0x01,%ymm0,%ymm5,%ymm2
+	vpshufd	$0x4e,%ymm0,%ymm0
+	vpternlogd	$0x96,%ymm2,%ymm0,%ymm1
+	vpclmulqdq	$0x11,%ymm4,%ymm3,%ymm4
+	vpclmulqdq	$0x01,%ymm1,%ymm5,%ymm0
+	vpshufd	$0x4e,%ymm1,%ymm1
+	vpternlogd	$0x96,%ymm0,%ymm1,%ymm4
+
+	vinserti64x4	$1,%ymm3,%zmm4,%zmm3
+	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
+
+
+	vmovdqu8	%zmm3,(%r8)
+
+
+
+
+	movl	$3,%eax
+L$precompute_next:
+	subq	$64,%r8
+	vpclmulqdq	$0x00,%zmm4,%zmm3,%zmm0
+	vpclmulqdq	$0x01,%zmm4,%zmm3,%zmm1
+	vpclmulqdq	$0x10,%zmm4,%zmm3,%zmm2
+	vpxord	%zmm2,%zmm1,%zmm1
+	vpclmulqdq	$0x01,%zmm0,%zmm5,%zmm2
+	vpshufd	$0x4e,%zmm0,%zmm0
+	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
+	vpclmulqdq	$0x11,%zmm4,%zmm3,%zmm3
+	vpclmulqdq	$0x01,%zmm1,%zmm5,%zmm0
+	vpshufd	$0x4e,%zmm1,%zmm1
+	vpternlogd	$0x96,%zmm0,%zmm1,%zmm3
+
+	vmovdqu8	%zmm3,(%r8)
+	decl	%eax
+	jnz	L$precompute_next
+
+	vzeroupper
+	ret
+
+
+
+.globl	_gcm_gmult_vpclmulqdq_avx512
+.private_extern _gcm_gmult_vpclmulqdq_avx512
+
+.p2align	5
+_gcm_gmult_vpclmulqdq_avx512:
+
+
+_CET_ENDBR
+
+
+
+	vmovdqu	(%rdi),%xmm0
+	vmovdqu	L$bswap_mask(%rip),%xmm1
+	vmovdqu	256-16(%rsi),%xmm2
+	vmovdqu	L$gfpoly(%rip),%xmm3
+	vpshufb	%xmm1,%xmm0,%xmm0
+
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm4
+	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm5
+	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm6
+	vpxord	%xmm6,%xmm5,%xmm5
+	vpclmulqdq	$0x01,%xmm4,%xmm3,%xmm6
+	vpshufd	$0x4e,%xmm4,%xmm4
+	vpternlogd	$0x96,%xmm6,%xmm4,%xmm5
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x01,%xmm5,%xmm3,%xmm4
+	vpshufd	$0x4e,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm4,%xmm5,%xmm0
+
+
+	vpshufb	%xmm1,%xmm0,%xmm0
+	vmovdqu	%xmm0,(%rdi)
+
+
+	ret
+
+
+
+.globl	_gcm_ghash_vpclmulqdq_avx512
+.private_extern _gcm_ghash_vpclmulqdq_avx512
+
+.p2align	5
+_gcm_ghash_vpclmulqdq_avx512:
+
+
+_CET_ENDBR
+
+
+
+
+
+
+	vmovdqu	L$bswap_mask(%rip),%xmm4
+	vmovdqu	L$gfpoly(%rip),%xmm10
+
+
+	vmovdqu	(%rdi),%xmm5
+	vpshufb	%xmm4,%xmm5,%xmm5
+
+
+	cmpq	$64,%rcx
+	jb	L$aad_blockbyblock
+
+
+
+	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
+	vshufi64x2	$0,%zmm10,%zmm10,%zmm10
+
+
+	vmovdqu8	256-64(%rsi),%zmm9
+
+	cmpq	$256,%rcx
+	jb	L$aad_loop_1x
+
+
+	vmovdqu8	256-256(%rsi),%zmm6
+	vmovdqu8	256-192(%rsi),%zmm7
+	vmovdqu8	256-128(%rsi),%zmm8
+
+
+L$aad_loop_4x:
+	vmovdqu8	0(%rdx),%zmm0
+	vmovdqu8	64(%rdx),%zmm1
+	vmovdqu8	128(%rdx),%zmm2
+	vmovdqu8	192(%rdx),%zmm3
+	vpshufb	%zmm4,%zmm0,%zmm0
+	vpxord	%zmm5,%zmm0,%zmm0
+	vpshufb	%zmm4,%zmm1,%zmm1
+	vpshufb	%zmm4,%zmm2,%zmm2
+	vpshufb	%zmm4,%zmm3,%zmm3
+	vpclmulqdq	$0x00,%zmm6,%zmm0,%zmm5
+	vpclmulqdq	$0x00,%zmm7,%zmm1,%zmm11
+	vpclmulqdq	$0x00,%zmm8,%zmm2,%zmm12
+	vpxord	%zmm11,%zmm5,%zmm5
+	vpclmulqdq	$0x00,%zmm9,%zmm3,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm5
+	vpclmulqdq	$0x01,%zmm6,%zmm0,%zmm11
+	vpclmulqdq	$0x01,%zmm7,%zmm1,%zmm12
+	vpclmulqdq	$0x01,%zmm8,%zmm2,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x01,%zmm9,%zmm3,%zmm12
+	vpclmulqdq	$0x10,%zmm6,%zmm0,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x10,%zmm7,%zmm1,%zmm12
+	vpclmulqdq	$0x10,%zmm8,%zmm2,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x01,%zmm5,%zmm10,%zmm13
+	vpclmulqdq	$0x10,%zmm9,%zmm3,%zmm12
+	vpxord	%zmm12,%zmm11,%zmm11
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm6,%zmm0,%zmm0
+	vpclmulqdq	$0x11,%zmm7,%zmm1,%zmm1
+	vpclmulqdq	$0x11,%zmm8,%zmm2,%zmm2
+	vpternlogd	$0x96,%zmm13,%zmm5,%zmm11
+	vpclmulqdq	$0x11,%zmm9,%zmm3,%zmm3
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm0
+	vpclmulqdq	$0x01,%zmm11,%zmm10,%zmm12
+	vpxord	%zmm3,%zmm0,%zmm5
+	vpshufd	$0x4e,%zmm11,%zmm11
+	vpternlogd	$0x96,%zmm12,%zmm11,%zmm5
+	vextracti32x4	$1,%zmm5,%xmm0
+	vextracti32x4	$2,%zmm5,%xmm1
+	vextracti32x4	$3,%zmm5,%xmm2
+	vpxord	%xmm0,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
+
+	addq	$256,%rdx
+	subq	$256,%rcx
+	cmpq	$256,%rcx
+	jae	L$aad_loop_4x
+
+
+	cmpq	$64,%rcx
+	jb	L$aad_large_done
+L$aad_loop_1x:
+	vmovdqu8	(%rdx),%zmm0
+	vpshufb	%zmm4,%zmm0,%zmm0
+	vpxord	%zmm0,%zmm5,%zmm5
+	vpclmulqdq	$0x00,%zmm9,%zmm5,%zmm0
+	vpclmulqdq	$0x01,%zmm9,%zmm5,%zmm1
+	vpclmulqdq	$0x10,%zmm9,%zmm5,%zmm2
+	vpxord	%zmm2,%zmm1,%zmm1
+	vpclmulqdq	$0x01,%zmm0,%zmm10,%zmm2
+	vpshufd	$0x4e,%zmm0,%zmm0
+	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
+	vpclmulqdq	$0x11,%zmm9,%zmm5,%zmm5
+	vpclmulqdq	$0x01,%zmm1,%zmm10,%zmm0
+	vpshufd	$0x4e,%zmm1,%zmm1
+	vpternlogd	$0x96,%zmm0,%zmm1,%zmm5
+
+	vextracti32x4	$1,%zmm5,%xmm0
+	vextracti32x4	$2,%zmm5,%xmm1
+	vextracti32x4	$3,%zmm5,%xmm2
+	vpxord	%xmm0,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
+
+	addq	$64,%rdx
+	subq	$64,%rcx
+	cmpq	$64,%rcx
+	jae	L$aad_loop_1x
+
+L$aad_large_done:
+
+
+L$aad_blockbyblock:
+	testq	%rcx,%rcx
+	jz	L$aad_done
+	vmovdqu	256-16(%rsi),%xmm9
+L$aad_loop_blockbyblock:
+	vmovdqu	(%rdx),%xmm0
+	vpshufb	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm0,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm9,%xmm5,%xmm0
+	vpclmulqdq	$0x01,%xmm9,%xmm5,%xmm1
+	vpclmulqdq	$0x10,%xmm9,%xmm5,%xmm2
+	vpxord	%xmm2,%xmm1,%xmm1
+	vpclmulqdq	$0x01,%xmm0,%xmm10,%xmm2
+	vpshufd	$0x4e,%xmm0,%xmm0
+	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x11,%xmm9,%xmm5,%xmm5
+	vpclmulqdq	$0x01,%xmm1,%xmm10,%xmm0
+	vpshufd	$0x4e,%xmm1,%xmm1
+	vpternlogd	$0x96,%xmm0,%xmm1,%xmm5
+
+	addq	$16,%rdx
+	subq	$16,%rcx
+	jnz	L$aad_loop_blockbyblock
+
+L$aad_done:
+
+	vpshufb	%xmm4,%xmm5,%xmm5
+	vmovdqu	%xmm5,(%rdi)
+
+	vzeroupper
+	ret
+
+
+
+.globl	_aes_gcm_enc_update_vaes_avx512
+.private_extern _aes_gcm_enc_update_vaes_avx512
+
+.p2align	5
+_aes_gcm_enc_update_vaes_avx512:
+
+
+_CET_ENDBR
+	pushq	%r12
+
+
+	movq	16(%rsp),%r12
+#ifdef BORINGSSL_DISPATCH_TEST
+
+	movb	$1,_BORINGSSL_function_hit+7(%rip)
+#endif
+
+	vbroadcasti32x4	L$bswap_mask(%rip),%zmm8
+	vbroadcasti32x4	L$gfpoly(%rip),%zmm31
+
+
+
+	vmovdqu	(%r12),%xmm10
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vbroadcasti32x4	(%r8),%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm12
+
+
+
+	movl	240(%rcx),%r10d
+	leal	-20(,%r10,4),%r10d
+
+
+
+
+	leaq	96(%rcx,%r10,4),%r11
+	vbroadcasti32x4	(%rcx),%zmm13
+	vbroadcasti32x4	(%r11),%zmm14
+
+
+	vpaddd	L$ctr_pattern(%rip),%zmm12,%zmm12
+
+
+	vbroadcasti32x4	L$inc_4blocks(%rip),%zmm11
+
+
+
+	cmpq	$256,%rdx
+	jb	L$crypt_loop_4x_done__func1
+
+
+	vmovdqu8	256-256(%r9),%zmm27
+	vmovdqu8	256-192(%r9),%zmm28
+	vmovdqu8	256-128(%r9),%zmm29
+	vmovdqu8	256-64(%r9),%zmm30
+
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	leaq	16(%rcx),%rax
+L$vaesenc_loop_first_4_vecs__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	L$vaesenc_loop_first_4_vecs__func1
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jb	L$ghash_last_ciphertext_4x__func1
+
+	vbroadcasti32x4	-144(%r11),%zmm15
+	vbroadcasti32x4	-128(%r11),%zmm16
+	vbroadcasti32x4	-112(%r11),%zmm17
+	vbroadcasti32x4	-96(%r11),%zmm18
+	vbroadcasti32x4	-80(%r11),%zmm19
+	vbroadcasti32x4	-64(%r11),%zmm20
+	vbroadcasti32x4	-48(%r11),%zmm21
+	vbroadcasti32x4	-32(%r11),%zmm22
+	vbroadcasti32x4	-16(%r11),%zmm23
+
+L$crypt_loop_4x__func1:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	cmpl	$24,%r10d
+	jl	L$aes128__func1
+	je	L$aes192__func1
+
+	vbroadcasti32x4	-208(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-192(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+L$aes192__func1:
+	vbroadcasti32x4	-176(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-160(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+L$aes128__func1:
+
+
+
+
+	prefetcht0	512+0(%rdi)
+	prefetcht0	512+64(%rdi)
+	prefetcht0	512+128(%rdi)
+	prefetcht0	512+192(%rdi)
+
+
+
+
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+
+	vaesenc	%zmm15,%zmm0,%zmm0
+	vaesenc	%zmm15,%zmm1,%zmm1
+	vaesenc	%zmm15,%zmm2,%zmm2
+	vaesenc	%zmm15,%zmm3,%zmm3
+
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+
+	vaesenc	%zmm16,%zmm0,%zmm0
+	vaesenc	%zmm16,%zmm1,%zmm1
+	vaesenc	%zmm16,%zmm2,%zmm2
+	vaesenc	%zmm16,%zmm3,%zmm3
+
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+
+	vaesenc	%zmm17,%zmm0,%zmm0
+	vaesenc	%zmm17,%zmm1,%zmm1
+	vaesenc	%zmm17,%zmm2,%zmm2
+	vaesenc	%zmm17,%zmm3,%zmm3
+
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+
+	vaesenc	%zmm18,%zmm0,%zmm0
+	vaesenc	%zmm18,%zmm1,%zmm1
+	vaesenc	%zmm18,%zmm2,%zmm2
+	vaesenc	%zmm18,%zmm3,%zmm3
+
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+
+	vaesenc	%zmm19,%zmm0,%zmm0
+	vaesenc	%zmm19,%zmm1,%zmm1
+	vaesenc	%zmm19,%zmm2,%zmm2
+	vaesenc	%zmm19,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+
+	vaesenc	%zmm20,%zmm0,%zmm0
+	vaesenc	%zmm20,%zmm1,%zmm1
+	vaesenc	%zmm20,%zmm2,%zmm2
+	vaesenc	%zmm20,%zmm3,%zmm3
+
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+
+	vaesenc	%zmm21,%zmm0,%zmm0
+	vaesenc	%zmm21,%zmm1,%zmm1
+	vaesenc	%zmm21,%zmm2,%zmm2
+	vaesenc	%zmm21,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+
+	vaesenc	%zmm22,%zmm0,%zmm0
+	vaesenc	%zmm22,%zmm1,%zmm1
+	vaesenc	%zmm22,%zmm2,%zmm2
+	vaesenc	%zmm22,%zmm3,%zmm3
+
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+
+	vaesenc	%zmm23,%zmm0,%zmm0
+	vaesenc	%zmm23,%zmm1,%zmm1
+	vaesenc	%zmm23,%zmm2,%zmm2
+	vaesenc	%zmm23,%zmm3,%zmm3
+
+
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jae	L$crypt_loop_4x__func1
+L$ghash_last_ciphertext_4x__func1:
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+L$crypt_loop_4x_done__func1:
+
+	testq	%rdx,%rdx
+	jz	L$done__func1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdx,%rax
+	negq	%rax
+	andq	$-16,%rax
+	leaq	256(%r9,%rax,1),%r8
+	vpxor	%xmm4,%xmm4,%xmm4
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpxor	%xmm6,%xmm6,%xmm6
+
+	cmpq	$64,%rdx
+	jb	L$partial_vec__func1
+
+L$crypt_loop_1x__func1:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+L$vaesenc_loop_tail_full_vec__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	L$vaesenc_loop_tail_full_vec__func1
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi)
+
+
+	vmovdqu8	(%r8),%zmm30
+	vpshufb	%zmm8,%zmm0,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+	vpxor	%xmm10,%xmm10,%xmm10
+
+	addq	$64,%r8
+	addq	$64,%rdi
+	addq	$64,%rsi
+	subq	$64,%rdx
+	cmpq	$64,%rdx
+	jae	L$crypt_loop_1x__func1
+
+	testq	%rdx,%rdx
+	jz	L$reduce__func1
+
+L$partial_vec__func1:
+
+
+
+
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k1
+	addq	$15,%rdx
+	andq	$-16,%rdx
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k2
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+L$vaesenc_loop_tail_partialvec__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	L$vaesenc_loop_tail_partialvec__func1
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1{%k1}{z}
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi){%k1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	(%r8),%zmm30{%k2}{z}
+	vmovdqu8	%zmm0,%zmm1{%k1}{z}
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+
+L$reduce__func1:
+
+	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
+	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
+
+	vextracti32x4	$1,%zmm6,%xmm0
+	vextracti32x4	$2,%zmm6,%xmm1
+	vextracti32x4	$3,%zmm6,%xmm2
+	vpxord	%xmm0,%xmm6,%xmm10
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
+
+
+L$done__func1:
+
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%r12)
+
+	vzeroupper
+	popq	%r12
+
+	ret
+
+
+
+.globl	_aes_gcm_dec_update_vaes_avx512
+.private_extern _aes_gcm_dec_update_vaes_avx512
+
+.p2align	5
+_aes_gcm_dec_update_vaes_avx512:
+
+
+_CET_ENDBR
+	pushq	%r12
+
+
+	movq	16(%rsp),%r12
+
+	vbroadcasti32x4	L$bswap_mask(%rip),%zmm8
+	vbroadcasti32x4	L$gfpoly(%rip),%zmm31
+
+
+
+	vmovdqu	(%r12),%xmm10
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vbroadcasti32x4	(%r8),%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm12
+
+
+
+	movl	240(%rcx),%r10d
+	leal	-20(,%r10,4),%r10d
+
+
+
+
+	leaq	96(%rcx,%r10,4),%r11
+	vbroadcasti32x4	(%rcx),%zmm13
+	vbroadcasti32x4	(%r11),%zmm14
+
+
+	vpaddd	L$ctr_pattern(%rip),%zmm12,%zmm12
+
+
+	vbroadcasti32x4	L$inc_4blocks(%rip),%zmm11
+
+
+
+	cmpq	$256,%rdx
+	jb	L$crypt_loop_4x_done__func2
+
+
+	vmovdqu8	256-256(%r9),%zmm27
+	vmovdqu8	256-192(%r9),%zmm28
+	vmovdqu8	256-128(%r9),%zmm29
+	vmovdqu8	256-64(%r9),%zmm30
+
+	vbroadcasti32x4	-144(%r11),%zmm15
+	vbroadcasti32x4	-128(%r11),%zmm16
+	vbroadcasti32x4	-112(%r11),%zmm17
+	vbroadcasti32x4	-96(%r11),%zmm18
+	vbroadcasti32x4	-80(%r11),%zmm19
+	vbroadcasti32x4	-64(%r11),%zmm20
+	vbroadcasti32x4	-48(%r11),%zmm21
+	vbroadcasti32x4	-32(%r11),%zmm22
+	vbroadcasti32x4	-16(%r11),%zmm23
+
+L$crypt_loop_4x__func2:
+	vmovdqu8	0(%rdi),%zmm4
+	vmovdqu8	64(%rdi),%zmm5
+	vmovdqu8	128(%rdi),%zmm6
+	vmovdqu8	192(%rdi),%zmm7
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	cmpl	$24,%r10d
+	jl	L$aes128__func2
+	je	L$aes192__func2
+
+	vbroadcasti32x4	-208(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-192(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+L$aes192__func2:
+	vbroadcasti32x4	-176(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-160(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+L$aes128__func2:
+
+
+
+
+	prefetcht0	512+0(%rdi)
+	prefetcht0	512+64(%rdi)
+	prefetcht0	512+128(%rdi)
+	prefetcht0	512+192(%rdi)
+
+
+
+
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+
+	vaesenc	%zmm15,%zmm0,%zmm0
+	vaesenc	%zmm15,%zmm1,%zmm1
+	vaesenc	%zmm15,%zmm2,%zmm2
+	vaesenc	%zmm15,%zmm3,%zmm3
+
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+
+	vaesenc	%zmm16,%zmm0,%zmm0
+	vaesenc	%zmm16,%zmm1,%zmm1
+	vaesenc	%zmm16,%zmm2,%zmm2
+	vaesenc	%zmm16,%zmm3,%zmm3
+
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+
+	vaesenc	%zmm17,%zmm0,%zmm0
+	vaesenc	%zmm17,%zmm1,%zmm1
+	vaesenc	%zmm17,%zmm2,%zmm2
+	vaesenc	%zmm17,%zmm3,%zmm3
+
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+
+	vaesenc	%zmm18,%zmm0,%zmm0
+	vaesenc	%zmm18,%zmm1,%zmm1
+	vaesenc	%zmm18,%zmm2,%zmm2
+	vaesenc	%zmm18,%zmm3,%zmm3
+
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+
+	vaesenc	%zmm19,%zmm0,%zmm0
+	vaesenc	%zmm19,%zmm1,%zmm1
+	vaesenc	%zmm19,%zmm2,%zmm2
+	vaesenc	%zmm19,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+
+	vaesenc	%zmm20,%zmm0,%zmm0
+	vaesenc	%zmm20,%zmm1,%zmm1
+	vaesenc	%zmm20,%zmm2,%zmm2
+	vaesenc	%zmm20,%zmm3,%zmm3
+
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+
+	vaesenc	%zmm21,%zmm0,%zmm0
+	vaesenc	%zmm21,%zmm1,%zmm1
+	vaesenc	%zmm21,%zmm2,%zmm2
+	vaesenc	%zmm21,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+
+	vaesenc	%zmm22,%zmm0,%zmm0
+	vaesenc	%zmm22,%zmm1,%zmm1
+	vaesenc	%zmm22,%zmm2,%zmm2
+	vaesenc	%zmm22,%zmm3,%zmm3
+
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+
+	vaesenc	%zmm23,%zmm0,%zmm0
+	vaesenc	%zmm23,%zmm1,%zmm1
+	vaesenc	%zmm23,%zmm2,%zmm2
+	vaesenc	%zmm23,%zmm3,%zmm3
+
+
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jae	L$crypt_loop_4x__func2
+L$crypt_loop_4x_done__func2:
+
+	testq	%rdx,%rdx
+	jz	L$done__func2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdx,%rax
+	negq	%rax
+	andq	$-16,%rax
+	leaq	256(%r9,%rax,1),%r8
+	vpxor	%xmm4,%xmm4,%xmm4
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpxor	%xmm6,%xmm6,%xmm6
+
+	cmpq	$64,%rdx
+	jb	L$partial_vec__func2
+
+L$crypt_loop_1x__func2:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+L$vaesenc_loop_tail_full_vec__func2:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	L$vaesenc_loop_tail_full_vec__func2
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi)
+
+
+	vmovdqu8	(%r8),%zmm30
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+	vpxor	%xmm10,%xmm10,%xmm10
+
+	addq	$64,%r8
+	addq	$64,%rdi
+	addq	$64,%rsi
+	subq	$64,%rdx
+	cmpq	$64,%rdx
+	jae	L$crypt_loop_1x__func2
+
+	testq	%rdx,%rdx
+	jz	L$reduce__func2
+
+L$partial_vec__func2:
+
+
+
+
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k1
+	addq	$15,%rdx
+	andq	$-16,%rdx
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k2
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+L$vaesenc_loop_tail_partialvec__func2:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	L$vaesenc_loop_tail_partialvec__func2
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1{%k1}{z}
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi){%k1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	(%r8),%zmm30{%k2}{z}
+
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+
+L$reduce__func2:
+
+	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
+	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
+
+	vextracti32x4	$1,%zmm6,%xmm0
+	vextracti32x4	$2,%zmm6,%xmm1
+	vextracti32x4	$3,%zmm6,%xmm2
+	vpxord	%xmm0,%xmm6,%xmm10
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
+
+
+L$done__func2:
+
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%r12)
+
+	vzeroupper
+	popq	%r12
+
+	ret
+
+
+
+#endif
diff --git a/src/gen/bcm/aes-gcm-avx512-x86_64-linux.S b/src/gen/bcm/aes-gcm-avx512-x86_64-linux.S
new file mode 100644
index 0000000..bec5e88
--- /dev/null
+++ b/src/gen/bcm/aes-gcm-avx512-x86_64-linux.S
@@ -0,0 +1,1251 @@
+// This file is generated from a similarly-named Perl script in the BoringSSL
+// source tree. Do not edit by hand.
+
+#include <openssl/asm_base.h>
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__ELF__)
+.section	.rodata
+.align	64
+
+
+.Lbswap_mask:
+.quad	0x08090a0b0c0d0e0f, 0x0001020304050607
+
+
+
+
+
+
+
+
+.Lgfpoly:
+.quad	1, 0xc200000000000000
+
+
+.Lgfpoly_and_internal_carrybit:
+.quad	1, 0xc200000000000001
+
+
+.Lctr_pattern:
+.quad	0, 0
+.quad	1, 0
+.quad	2, 0
+.quad	3, 0
+
+
+.Linc_4blocks:
+.quad	4, 0
+
+.text	
+.globl	gcm_init_vpclmulqdq_avx512
+.hidden gcm_init_vpclmulqdq_avx512
+.type	gcm_init_vpclmulqdq_avx512,@function
+.align	32
+gcm_init_vpclmulqdq_avx512:
+.cfi_startproc	
+
+_CET_ENDBR
+
+	leaq	256-64(%rdi),%r8
+
+
+
+	vpshufd	$0x4e,(%rsi),%xmm3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vpshufd	$0xd3,%xmm3,%xmm0
+	vpsrad	$31,%xmm0,%xmm0
+	vpaddq	%xmm3,%xmm3,%xmm3
+
+	vpternlogd	$0x78,.Lgfpoly_and_internal_carrybit(%rip),%xmm0,%xmm3
+
+
+	vbroadcasti32x4	.Lgfpoly(%rip),%zmm5
+
+
+
+
+
+
+
+
+	vpclmulqdq	$0x00,%xmm3,%xmm3,%xmm0
+	vpclmulqdq	$0x11,%xmm3,%xmm3,%xmm4
+	vpclmulqdq	$0x01,%xmm0,%xmm5,%xmm1
+	vpshufd	$0x4e,%xmm0,%xmm0
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpclmulqdq	$0x01,%xmm1,%xmm5,%xmm0
+	vpshufd	$0x4e,%xmm1,%xmm1
+	vpternlogd	$0x96,%xmm0,%xmm1,%xmm4
+
+
+
+	vinserti128	$1,%xmm3,%ymm4,%ymm3
+	vinserti128	$1,%xmm4,%ymm4,%ymm4
+
+
+	vpclmulqdq	$0x00,%ymm4,%ymm3,%ymm0
+	vpclmulqdq	$0x01,%ymm4,%ymm3,%ymm1
+	vpclmulqdq	$0x10,%ymm4,%ymm3,%ymm2
+	vpxord	%ymm2,%ymm1,%ymm1
+	vpclmulqdq	$0x01,%ymm0,%ymm5,%ymm2
+	vpshufd	$0x4e,%ymm0,%ymm0
+	vpternlogd	$0x96,%ymm2,%ymm0,%ymm1
+	vpclmulqdq	$0x11,%ymm4,%ymm3,%ymm4
+	vpclmulqdq	$0x01,%ymm1,%ymm5,%ymm0
+	vpshufd	$0x4e,%ymm1,%ymm1
+	vpternlogd	$0x96,%ymm0,%ymm1,%ymm4
+
+	vinserti64x4	$1,%ymm3,%zmm4,%zmm3
+	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
+
+
+	vmovdqu8	%zmm3,(%r8)
+
+
+
+
+	movl	$3,%eax
+.Lprecompute_next:
+	subq	$64,%r8
+	vpclmulqdq	$0x00,%zmm4,%zmm3,%zmm0
+	vpclmulqdq	$0x01,%zmm4,%zmm3,%zmm1
+	vpclmulqdq	$0x10,%zmm4,%zmm3,%zmm2
+	vpxord	%zmm2,%zmm1,%zmm1
+	vpclmulqdq	$0x01,%zmm0,%zmm5,%zmm2
+	vpshufd	$0x4e,%zmm0,%zmm0
+	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
+	vpclmulqdq	$0x11,%zmm4,%zmm3,%zmm3
+	vpclmulqdq	$0x01,%zmm1,%zmm5,%zmm0
+	vpshufd	$0x4e,%zmm1,%zmm1
+	vpternlogd	$0x96,%zmm0,%zmm1,%zmm3
+
+	vmovdqu8	%zmm3,(%r8)
+	decl	%eax
+	jnz	.Lprecompute_next
+
+	vzeroupper
+	ret
+
+.cfi_endproc	
+.size	gcm_init_vpclmulqdq_avx512, . - gcm_init_vpclmulqdq_avx512
+.globl	gcm_gmult_vpclmulqdq_avx512
+.hidden gcm_gmult_vpclmulqdq_avx512
+.type	gcm_gmult_vpclmulqdq_avx512,@function
+.align	32
+gcm_gmult_vpclmulqdq_avx512:
+.cfi_startproc	
+
+_CET_ENDBR
+
+
+
+	vmovdqu	(%rdi),%xmm0
+	vmovdqu	.Lbswap_mask(%rip),%xmm1
+	vmovdqu	256-16(%rsi),%xmm2
+	vmovdqu	.Lgfpoly(%rip),%xmm3
+	vpshufb	%xmm1,%xmm0,%xmm0
+
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm4
+	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm5
+	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm6
+	vpxord	%xmm6,%xmm5,%xmm5
+	vpclmulqdq	$0x01,%xmm4,%xmm3,%xmm6
+	vpshufd	$0x4e,%xmm4,%xmm4
+	vpternlogd	$0x96,%xmm6,%xmm4,%xmm5
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x01,%xmm5,%xmm3,%xmm4
+	vpshufd	$0x4e,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm4,%xmm5,%xmm0
+
+
+	vpshufb	%xmm1,%xmm0,%xmm0
+	vmovdqu	%xmm0,(%rdi)
+
+
+	ret
+
+.cfi_endproc	
+.size	gcm_gmult_vpclmulqdq_avx512, . - gcm_gmult_vpclmulqdq_avx512
+.globl	gcm_ghash_vpclmulqdq_avx512
+.hidden gcm_ghash_vpclmulqdq_avx512
+.type	gcm_ghash_vpclmulqdq_avx512,@function
+.align	32
+gcm_ghash_vpclmulqdq_avx512:
+.cfi_startproc	
+
+_CET_ENDBR
+
+
+
+
+
+
+	vmovdqu	.Lbswap_mask(%rip),%xmm4
+	vmovdqu	.Lgfpoly(%rip),%xmm10
+
+
+	vmovdqu	(%rdi),%xmm5
+	vpshufb	%xmm4,%xmm5,%xmm5
+
+
+	cmpq	$64,%rcx
+	jb	.Laad_blockbyblock
+
+
+
+	vshufi64x2	$0,%zmm4,%zmm4,%zmm4
+	vshufi64x2	$0,%zmm10,%zmm10,%zmm10
+
+
+	vmovdqu8	256-64(%rsi),%zmm9
+
+	cmpq	$256,%rcx
+	jb	.Laad_loop_1x
+
+
+	vmovdqu8	256-256(%rsi),%zmm6
+	vmovdqu8	256-192(%rsi),%zmm7
+	vmovdqu8	256-128(%rsi),%zmm8
+
+
+.Laad_loop_4x:
+	vmovdqu8	0(%rdx),%zmm0
+	vmovdqu8	64(%rdx),%zmm1
+	vmovdqu8	128(%rdx),%zmm2
+	vmovdqu8	192(%rdx),%zmm3
+	vpshufb	%zmm4,%zmm0,%zmm0
+	vpxord	%zmm5,%zmm0,%zmm0
+	vpshufb	%zmm4,%zmm1,%zmm1
+	vpshufb	%zmm4,%zmm2,%zmm2
+	vpshufb	%zmm4,%zmm3,%zmm3
+	vpclmulqdq	$0x00,%zmm6,%zmm0,%zmm5
+	vpclmulqdq	$0x00,%zmm7,%zmm1,%zmm11
+	vpclmulqdq	$0x00,%zmm8,%zmm2,%zmm12
+	vpxord	%zmm11,%zmm5,%zmm5
+	vpclmulqdq	$0x00,%zmm9,%zmm3,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm5
+	vpclmulqdq	$0x01,%zmm6,%zmm0,%zmm11
+	vpclmulqdq	$0x01,%zmm7,%zmm1,%zmm12
+	vpclmulqdq	$0x01,%zmm8,%zmm2,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x01,%zmm9,%zmm3,%zmm12
+	vpclmulqdq	$0x10,%zmm6,%zmm0,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x10,%zmm7,%zmm1,%zmm12
+	vpclmulqdq	$0x10,%zmm8,%zmm2,%zmm13
+	vpternlogd	$0x96,%zmm13,%zmm12,%zmm11
+	vpclmulqdq	$0x01,%zmm5,%zmm10,%zmm13
+	vpclmulqdq	$0x10,%zmm9,%zmm3,%zmm12
+	vpxord	%zmm12,%zmm11,%zmm11
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm6,%zmm0,%zmm0
+	vpclmulqdq	$0x11,%zmm7,%zmm1,%zmm1
+	vpclmulqdq	$0x11,%zmm8,%zmm2,%zmm2
+	vpternlogd	$0x96,%zmm13,%zmm5,%zmm11
+	vpclmulqdq	$0x11,%zmm9,%zmm3,%zmm3
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm0
+	vpclmulqdq	$0x01,%zmm11,%zmm10,%zmm12
+	vpxord	%zmm3,%zmm0,%zmm5
+	vpshufd	$0x4e,%zmm11,%zmm11
+	vpternlogd	$0x96,%zmm12,%zmm11,%zmm5
+	vextracti32x4	$1,%zmm5,%xmm0
+	vextracti32x4	$2,%zmm5,%xmm1
+	vextracti32x4	$3,%zmm5,%xmm2
+	vpxord	%xmm0,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
+
+	addq	$256,%rdx
+	subq	$256,%rcx
+	cmpq	$256,%rcx
+	jae	.Laad_loop_4x
+
+
+	cmpq	$64,%rcx
+	jb	.Laad_large_done
+.Laad_loop_1x:
+	vmovdqu8	(%rdx),%zmm0
+	vpshufb	%zmm4,%zmm0,%zmm0
+	vpxord	%zmm0,%zmm5,%zmm5
+	vpclmulqdq	$0x00,%zmm9,%zmm5,%zmm0
+	vpclmulqdq	$0x01,%zmm9,%zmm5,%zmm1
+	vpclmulqdq	$0x10,%zmm9,%zmm5,%zmm2
+	vpxord	%zmm2,%zmm1,%zmm1
+	vpclmulqdq	$0x01,%zmm0,%zmm10,%zmm2
+	vpshufd	$0x4e,%zmm0,%zmm0
+	vpternlogd	$0x96,%zmm2,%zmm0,%zmm1
+	vpclmulqdq	$0x11,%zmm9,%zmm5,%zmm5
+	vpclmulqdq	$0x01,%zmm1,%zmm10,%zmm0
+	vpshufd	$0x4e,%zmm1,%zmm1
+	vpternlogd	$0x96,%zmm0,%zmm1,%zmm5
+
+	vextracti32x4	$1,%zmm5,%xmm0
+	vextracti32x4	$2,%zmm5,%xmm1
+	vextracti32x4	$3,%zmm5,%xmm2
+	vpxord	%xmm0,%xmm5,%xmm5
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm5
+
+	addq	$64,%rdx
+	subq	$64,%rcx
+	cmpq	$64,%rcx
+	jae	.Laad_loop_1x
+
+.Laad_large_done:
+
+
+.Laad_blockbyblock:
+	testq	%rcx,%rcx
+	jz	.Laad_done
+	vmovdqu	256-16(%rsi),%xmm9
+.Laad_loop_blockbyblock:
+	vmovdqu	(%rdx),%xmm0
+	vpshufb	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm0,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm9,%xmm5,%xmm0
+	vpclmulqdq	$0x01,%xmm9,%xmm5,%xmm1
+	vpclmulqdq	$0x10,%xmm9,%xmm5,%xmm2
+	vpxord	%xmm2,%xmm1,%xmm1
+	vpclmulqdq	$0x01,%xmm0,%xmm10,%xmm2
+	vpshufd	$0x4e,%xmm0,%xmm0
+	vpternlogd	$0x96,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x11,%xmm9,%xmm5,%xmm5
+	vpclmulqdq	$0x01,%xmm1,%xmm10,%xmm0
+	vpshufd	$0x4e,%xmm1,%xmm1
+	vpternlogd	$0x96,%xmm0,%xmm1,%xmm5
+
+	addq	$16,%rdx
+	subq	$16,%rcx
+	jnz	.Laad_loop_blockbyblock
+
+.Laad_done:
+
+	vpshufb	%xmm4,%xmm5,%xmm5
+	vmovdqu	%xmm5,(%rdi)
+
+	vzeroupper
+	ret
+
+.cfi_endproc	
+.size	gcm_ghash_vpclmulqdq_avx512, . - gcm_ghash_vpclmulqdq_avx512
+.globl	aes_gcm_enc_update_vaes_avx512
+.hidden aes_gcm_enc_update_vaes_avx512
+.type	aes_gcm_enc_update_vaes_avx512,@function
+.align	32
+aes_gcm_enc_update_vaes_avx512:
+.cfi_startproc	
+
+_CET_ENDBR
+	pushq	%r12
+.cfi_adjust_cfa_offset	8
+.cfi_offset	%r12,-16
+
+	movq	16(%rsp),%r12
+#ifdef BORINGSSL_DISPATCH_TEST
+.extern	BORINGSSL_function_hit
+.hidden BORINGSSL_function_hit
+	movb	$1,BORINGSSL_function_hit+7(%rip)
+#endif
+
+	vbroadcasti32x4	.Lbswap_mask(%rip),%zmm8
+	vbroadcasti32x4	.Lgfpoly(%rip),%zmm31
+
+
+
+	vmovdqu	(%r12),%xmm10
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vbroadcasti32x4	(%r8),%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm12
+
+
+
+	movl	240(%rcx),%r10d
+	leal	-20(,%r10,4),%r10d
+
+
+
+
+	leaq	96(%rcx,%r10,4),%r11
+	vbroadcasti32x4	(%rcx),%zmm13
+	vbroadcasti32x4	(%r11),%zmm14
+
+
+	vpaddd	.Lctr_pattern(%rip),%zmm12,%zmm12
+
+
+	vbroadcasti32x4	.Linc_4blocks(%rip),%zmm11
+
+
+
+	cmpq	$256,%rdx
+	jb	.Lcrypt_loop_4x_done__func1
+
+
+	vmovdqu8	256-256(%r9),%zmm27
+	vmovdqu8	256-192(%r9),%zmm28
+	vmovdqu8	256-128(%r9),%zmm29
+	vmovdqu8	256-64(%r9),%zmm30
+
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	leaq	16(%rcx),%rax
+.Lvaesenc_loop_first_4_vecs__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	.Lvaesenc_loop_first_4_vecs__func1
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jb	.Lghash_last_ciphertext_4x__func1
+
+	vbroadcasti32x4	-144(%r11),%zmm15
+	vbroadcasti32x4	-128(%r11),%zmm16
+	vbroadcasti32x4	-112(%r11),%zmm17
+	vbroadcasti32x4	-96(%r11),%zmm18
+	vbroadcasti32x4	-80(%r11),%zmm19
+	vbroadcasti32x4	-64(%r11),%zmm20
+	vbroadcasti32x4	-48(%r11),%zmm21
+	vbroadcasti32x4	-32(%r11),%zmm22
+	vbroadcasti32x4	-16(%r11),%zmm23
+
+.Lcrypt_loop_4x__func1:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	cmpl	$24,%r10d
+	jl	.Laes128__func1
+	je	.Laes192__func1
+
+	vbroadcasti32x4	-208(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-192(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+.Laes192__func1:
+	vbroadcasti32x4	-176(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-160(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+.Laes128__func1:
+
+
+
+
+	prefetcht0	512+0(%rdi)
+	prefetcht0	512+64(%rdi)
+	prefetcht0	512+128(%rdi)
+	prefetcht0	512+192(%rdi)
+
+
+
+
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+
+	vaesenc	%zmm15,%zmm0,%zmm0
+	vaesenc	%zmm15,%zmm1,%zmm1
+	vaesenc	%zmm15,%zmm2,%zmm2
+	vaesenc	%zmm15,%zmm3,%zmm3
+
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+
+	vaesenc	%zmm16,%zmm0,%zmm0
+	vaesenc	%zmm16,%zmm1,%zmm1
+	vaesenc	%zmm16,%zmm2,%zmm2
+	vaesenc	%zmm16,%zmm3,%zmm3
+
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+
+	vaesenc	%zmm17,%zmm0,%zmm0
+	vaesenc	%zmm17,%zmm1,%zmm1
+	vaesenc	%zmm17,%zmm2,%zmm2
+	vaesenc	%zmm17,%zmm3,%zmm3
+
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+
+	vaesenc	%zmm18,%zmm0,%zmm0
+	vaesenc	%zmm18,%zmm1,%zmm1
+	vaesenc	%zmm18,%zmm2,%zmm2
+	vaesenc	%zmm18,%zmm3,%zmm3
+
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+
+	vaesenc	%zmm19,%zmm0,%zmm0
+	vaesenc	%zmm19,%zmm1,%zmm1
+	vaesenc	%zmm19,%zmm2,%zmm2
+	vaesenc	%zmm19,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+
+	vaesenc	%zmm20,%zmm0,%zmm0
+	vaesenc	%zmm20,%zmm1,%zmm1
+	vaesenc	%zmm20,%zmm2,%zmm2
+	vaesenc	%zmm20,%zmm3,%zmm3
+
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+
+	vaesenc	%zmm21,%zmm0,%zmm0
+	vaesenc	%zmm21,%zmm1,%zmm1
+	vaesenc	%zmm21,%zmm2,%zmm2
+	vaesenc	%zmm21,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+
+	vaesenc	%zmm22,%zmm0,%zmm0
+	vaesenc	%zmm22,%zmm1,%zmm1
+	vaesenc	%zmm22,%zmm2,%zmm2
+	vaesenc	%zmm22,%zmm3,%zmm3
+
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+
+	vaesenc	%zmm23,%zmm0,%zmm0
+	vaesenc	%zmm23,%zmm1,%zmm1
+	vaesenc	%zmm23,%zmm2,%zmm2
+	vaesenc	%zmm23,%zmm3,%zmm3
+
+
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jae	.Lcrypt_loop_4x__func1
+.Lghash_last_ciphertext_4x__func1:
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+.Lcrypt_loop_4x_done__func1:
+
+	testq	%rdx,%rdx
+	jz	.Ldone__func1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdx,%rax
+	negq	%rax
+	andq	$-16,%rax
+	leaq	256(%r9,%rax,1),%r8
+	vpxor	%xmm4,%xmm4,%xmm4
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpxor	%xmm6,%xmm6,%xmm6
+
+	cmpq	$64,%rdx
+	jb	.Lpartial_vec__func1
+
+.Lcrypt_loop_1x__func1:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+.Lvaesenc_loop_tail_full_vec__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	.Lvaesenc_loop_tail_full_vec__func1
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi)
+
+
+	vmovdqu8	(%r8),%zmm30
+	vpshufb	%zmm8,%zmm0,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+	vpxor	%xmm10,%xmm10,%xmm10
+
+	addq	$64,%r8
+	addq	$64,%rdi
+	addq	$64,%rsi
+	subq	$64,%rdx
+	cmpq	$64,%rdx
+	jae	.Lcrypt_loop_1x__func1
+
+	testq	%rdx,%rdx
+	jz	.Lreduce__func1
+
+.Lpartial_vec__func1:
+
+
+
+
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k1
+	addq	$15,%rdx
+	andq	$-16,%rdx
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k2
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+.Lvaesenc_loop_tail_partialvec__func1:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	.Lvaesenc_loop_tail_partialvec__func1
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1{%k1}{z}
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi){%k1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	(%r8),%zmm30{%k2}{z}
+	vmovdqu8	%zmm0,%zmm1{%k1}{z}
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+
+.Lreduce__func1:
+
+	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
+	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
+
+	vextracti32x4	$1,%zmm6,%xmm0
+	vextracti32x4	$2,%zmm6,%xmm1
+	vextracti32x4	$3,%zmm6,%xmm2
+	vpxord	%xmm0,%xmm6,%xmm10
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
+
+
+.Ldone__func1:
+
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%r12)
+
+	vzeroupper
+	popq	%r12
+.cfi_adjust_cfa_offset	-8
+.cfi_restore	%r12
+	ret
+
+.cfi_endproc	
+.size	aes_gcm_enc_update_vaes_avx512, . - aes_gcm_enc_update_vaes_avx512
+.globl	aes_gcm_dec_update_vaes_avx512
+.hidden aes_gcm_dec_update_vaes_avx512
+.type	aes_gcm_dec_update_vaes_avx512,@function
+.align	32
+aes_gcm_dec_update_vaes_avx512:
+.cfi_startproc	
+
+_CET_ENDBR
+	pushq	%r12
+.cfi_adjust_cfa_offset	8
+.cfi_offset	%r12,-16
+
+	movq	16(%rsp),%r12
+
+	vbroadcasti32x4	.Lbswap_mask(%rip),%zmm8
+	vbroadcasti32x4	.Lgfpoly(%rip),%zmm31
+
+
+
+	vmovdqu	(%r12),%xmm10
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vbroadcasti32x4	(%r8),%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm12
+
+
+
+	movl	240(%rcx),%r10d
+	leal	-20(,%r10,4),%r10d
+
+
+
+
+	leaq	96(%rcx,%r10,4),%r11
+	vbroadcasti32x4	(%rcx),%zmm13
+	vbroadcasti32x4	(%r11),%zmm14
+
+
+	vpaddd	.Lctr_pattern(%rip),%zmm12,%zmm12
+
+
+	vbroadcasti32x4	.Linc_4blocks(%rip),%zmm11
+
+
+
+	cmpq	$256,%rdx
+	jb	.Lcrypt_loop_4x_done__func2
+
+
+	vmovdqu8	256-256(%r9),%zmm27
+	vmovdqu8	256-192(%r9),%zmm28
+	vmovdqu8	256-128(%r9),%zmm29
+	vmovdqu8	256-64(%r9),%zmm30
+
+	vbroadcasti32x4	-144(%r11),%zmm15
+	vbroadcasti32x4	-128(%r11),%zmm16
+	vbroadcasti32x4	-112(%r11),%zmm17
+	vbroadcasti32x4	-96(%r11),%zmm18
+	vbroadcasti32x4	-80(%r11),%zmm19
+	vbroadcasti32x4	-64(%r11),%zmm20
+	vbroadcasti32x4	-48(%r11),%zmm21
+	vbroadcasti32x4	-32(%r11),%zmm22
+	vbroadcasti32x4	-16(%r11),%zmm23
+
+.Lcrypt_loop_4x__func2:
+	vmovdqu8	0(%rdi),%zmm4
+	vmovdqu8	64(%rdi),%zmm5
+	vmovdqu8	128(%rdi),%zmm6
+	vmovdqu8	192(%rdi),%zmm7
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm1
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm2
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpshufb	%zmm8,%zmm12,%zmm3
+	vpaddd	%zmm11,%zmm12,%zmm12
+
+
+	vpxord	%zmm13,%zmm0,%zmm0
+	vpxord	%zmm13,%zmm1,%zmm1
+	vpxord	%zmm13,%zmm2,%zmm2
+	vpxord	%zmm13,%zmm3,%zmm3
+
+	cmpl	$24,%r10d
+	jl	.Laes128__func2
+	je	.Laes192__func2
+
+	vbroadcasti32x4	-208(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-192(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+.Laes192__func2:
+	vbroadcasti32x4	-176(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+	vbroadcasti32x4	-160(%r11),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	vaesenc	%zmm9,%zmm1,%zmm1
+	vaesenc	%zmm9,%zmm2,%zmm2
+	vaesenc	%zmm9,%zmm3,%zmm3
+
+.Laes128__func2:
+
+
+
+
+	prefetcht0	512+0(%rdi)
+	prefetcht0	512+64(%rdi)
+	prefetcht0	512+128(%rdi)
+	prefetcht0	512+192(%rdi)
+
+
+
+
+	vpshufb	%zmm8,%zmm4,%zmm4
+	vpxord	%zmm10,%zmm4,%zmm4
+	vpshufb	%zmm8,%zmm5,%zmm5
+	vpshufb	%zmm8,%zmm6,%zmm6
+
+	vaesenc	%zmm15,%zmm0,%zmm0
+	vaesenc	%zmm15,%zmm1,%zmm1
+	vaesenc	%zmm15,%zmm2,%zmm2
+	vaesenc	%zmm15,%zmm3,%zmm3
+
+	vpshufb	%zmm8,%zmm7,%zmm7
+	vpclmulqdq	$0x00,%zmm27,%zmm4,%zmm10
+	vpclmulqdq	$0x00,%zmm28,%zmm5,%zmm24
+	vpclmulqdq	$0x00,%zmm29,%zmm6,%zmm25
+
+	vaesenc	%zmm16,%zmm0,%zmm0
+	vaesenc	%zmm16,%zmm1,%zmm1
+	vaesenc	%zmm16,%zmm2,%zmm2
+	vaesenc	%zmm16,%zmm3,%zmm3
+
+	vpxord	%zmm24,%zmm10,%zmm10
+	vpclmulqdq	$0x00,%zmm30,%zmm7,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm10
+	vpclmulqdq	$0x01,%zmm27,%zmm4,%zmm24
+
+	vaesenc	%zmm17,%zmm0,%zmm0
+	vaesenc	%zmm17,%zmm1,%zmm1
+	vaesenc	%zmm17,%zmm2,%zmm2
+	vaesenc	%zmm17,%zmm3,%zmm3
+
+	vpclmulqdq	$0x01,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x01,%zmm29,%zmm6,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm30,%zmm7,%zmm25
+
+	vaesenc	%zmm18,%zmm0,%zmm0
+	vaesenc	%zmm18,%zmm1,%zmm1
+	vaesenc	%zmm18,%zmm2,%zmm2
+	vaesenc	%zmm18,%zmm3,%zmm3
+
+	vpclmulqdq	$0x10,%zmm27,%zmm4,%zmm26
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x10,%zmm28,%zmm5,%zmm25
+	vpclmulqdq	$0x10,%zmm29,%zmm6,%zmm26
+
+	vaesenc	%zmm19,%zmm0,%zmm0
+	vaesenc	%zmm19,%zmm1,%zmm1
+	vaesenc	%zmm19,%zmm2,%zmm2
+	vaesenc	%zmm19,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm25,%zmm24
+	vpclmulqdq	$0x01,%zmm10,%zmm31,%zmm26
+	vpclmulqdq	$0x10,%zmm30,%zmm7,%zmm25
+	vpxord	%zmm25,%zmm24,%zmm24
+
+	vaesenc	%zmm20,%zmm0,%zmm0
+	vaesenc	%zmm20,%zmm1,%zmm1
+	vaesenc	%zmm20,%zmm2,%zmm2
+	vaesenc	%zmm20,%zmm3,%zmm3
+
+	vpshufd	$0x4e,%zmm10,%zmm10
+	vpclmulqdq	$0x11,%zmm27,%zmm4,%zmm4
+	vpclmulqdq	$0x11,%zmm28,%zmm5,%zmm5
+	vpclmulqdq	$0x11,%zmm29,%zmm6,%zmm6
+
+	vaesenc	%zmm21,%zmm0,%zmm0
+	vaesenc	%zmm21,%zmm1,%zmm1
+	vaesenc	%zmm21,%zmm2,%zmm2
+	vaesenc	%zmm21,%zmm3,%zmm3
+
+	vpternlogd	$0x96,%zmm26,%zmm10,%zmm24
+	vpclmulqdq	$0x11,%zmm30,%zmm7,%zmm7
+	vpternlogd	$0x96,%zmm6,%zmm5,%zmm4
+	vpclmulqdq	$0x01,%zmm24,%zmm31,%zmm25
+
+	vaesenc	%zmm22,%zmm0,%zmm0
+	vaesenc	%zmm22,%zmm1,%zmm1
+	vaesenc	%zmm22,%zmm2,%zmm2
+	vaesenc	%zmm22,%zmm3,%zmm3
+
+	vpxord	%zmm7,%zmm4,%zmm10
+	vpshufd	$0x4e,%zmm24,%zmm24
+	vpternlogd	$0x96,%zmm25,%zmm24,%zmm10
+
+	vaesenc	%zmm23,%zmm0,%zmm0
+	vaesenc	%zmm23,%zmm1,%zmm1
+	vaesenc	%zmm23,%zmm2,%zmm2
+	vaesenc	%zmm23,%zmm3,%zmm3
+
+
+	vextracti32x4	$1,%zmm10,%xmm4
+	vextracti32x4	$2,%zmm10,%xmm5
+	vextracti32x4	$3,%zmm10,%xmm6
+	vpxord	%xmm4,%xmm10,%xmm10
+	vpternlogd	$0x96,%xmm5,%xmm6,%xmm10
+
+	vpxord	0(%rdi),%zmm14,%zmm4
+	vpxord	64(%rdi),%zmm14,%zmm5
+	vpxord	128(%rdi),%zmm14,%zmm6
+	vpxord	192(%rdi),%zmm14,%zmm7
+	vaesenclast	%zmm4,%zmm0,%zmm4
+	vaesenclast	%zmm5,%zmm1,%zmm5
+	vaesenclast	%zmm6,%zmm2,%zmm6
+	vaesenclast	%zmm7,%zmm3,%zmm7
+	vmovdqu8	%zmm4,0(%rsi)
+	vmovdqu8	%zmm5,64(%rsi)
+	vmovdqu8	%zmm6,128(%rsi)
+	vmovdqu8	%zmm7,192(%rsi)
+
+	addq	$256,%rdi
+	addq	$256,%rsi
+	subq	$256,%rdx
+	cmpq	$256,%rdx
+	jae	.Lcrypt_loop_4x__func2
+.Lcrypt_loop_4x_done__func2:
+
+	testq	%rdx,%rdx
+	jz	.Ldone__func2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdx,%rax
+	negq	%rax
+	andq	$-16,%rax
+	leaq	256(%r9,%rax,1),%r8
+	vpxor	%xmm4,%xmm4,%xmm4
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpxor	%xmm6,%xmm6,%xmm6
+
+	cmpq	$64,%rdx
+	jb	.Lpartial_vec__func2
+
+.Lcrypt_loop_1x__func2:
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpaddd	%zmm11,%zmm12,%zmm12
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+.Lvaesenc_loop_tail_full_vec__func2:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	.Lvaesenc_loop_tail_full_vec__func2
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi)
+
+
+	vmovdqu8	(%r8),%zmm30
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+	vpxor	%xmm10,%xmm10,%xmm10
+
+	addq	$64,%r8
+	addq	$64,%rdi
+	addq	$64,%rsi
+	subq	$64,%rdx
+	cmpq	$64,%rdx
+	jae	.Lcrypt_loop_1x__func2
+
+	testq	%rdx,%rdx
+	jz	.Lreduce__func2
+
+.Lpartial_vec__func2:
+
+
+
+
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k1
+	addq	$15,%rdx
+	andq	$-16,%rdx
+	movq	$-1,%rax
+	bzhiq	%rdx,%rax,%rax
+	kmovq	%rax,%k2
+
+
+
+	vpshufb	%zmm8,%zmm12,%zmm0
+	vpxord	%zmm13,%zmm0,%zmm0
+	leaq	16(%rcx),%rax
+.Lvaesenc_loop_tail_partialvec__func2:
+	vbroadcasti32x4	(%rax),%zmm9
+	vaesenc	%zmm9,%zmm0,%zmm0
+	addq	$16,%rax
+	cmpq	%rax,%r11
+	jne	.Lvaesenc_loop_tail_partialvec__func2
+	vaesenclast	%zmm14,%zmm0,%zmm0
+
+
+	vmovdqu8	(%rdi),%zmm1{%k1}{z}
+	vpxord	%zmm1,%zmm0,%zmm0
+	vmovdqu8	%zmm0,(%rsi){%k1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	(%r8),%zmm30{%k2}{z}
+
+	vpshufb	%zmm8,%zmm1,%zmm0
+	vpxord	%zmm10,%zmm0,%zmm0
+	vpclmulqdq	$0x00,%zmm30,%zmm0,%zmm7
+	vpclmulqdq	$0x01,%zmm30,%zmm0,%zmm1
+	vpclmulqdq	$0x10,%zmm30,%zmm0,%zmm2
+	vpclmulqdq	$0x11,%zmm30,%zmm0,%zmm3
+	vpxord	%zmm7,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm2,%zmm1,%zmm5
+	vpxord	%zmm3,%zmm6,%zmm6
+
+
+.Lreduce__func2:
+
+	vpclmulqdq	$0x01,%zmm4,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm4,%zmm4
+	vpternlogd	$0x96,%zmm0,%zmm4,%zmm5
+	vpclmulqdq	$0x01,%zmm5,%zmm31,%zmm0
+	vpshufd	$0x4e,%zmm5,%zmm5
+	vpternlogd	$0x96,%zmm0,%zmm5,%zmm6
+
+	vextracti32x4	$1,%zmm6,%xmm0
+	vextracti32x4	$2,%zmm6,%xmm1
+	vextracti32x4	$3,%zmm6,%xmm2
+	vpxord	%xmm0,%xmm6,%xmm10
+	vpternlogd	$0x96,%xmm1,%xmm2,%xmm10
+
+
+.Ldone__func2:
+
+	vpshufb	%xmm8,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%r12)
+
+	vzeroupper
+	popq	%r12
+.cfi_adjust_cfa_offset	-8
+.cfi_restore	%r12
+	ret
+
+.cfi_endproc	
+.size	aes_gcm_dec_update_vaes_avx512, . - aes_gcm_dec_update_vaes_avx512
+#endif
diff --git a/src/gen/bcm/aes-gcm-avx512-x86_64-win.asm b/src/gen/bcm/aes-gcm-avx512-x86_64-win.asm
new file mode 100644
index 0000000..3a86e3a
--- /dev/null
+++ b/src/gen/bcm/aes-gcm-avx512-x86_64-win.asm
@@ -0,0 +1,1527 @@
+; This file is generated from a similarly-named Perl script in the BoringSSL
+; source tree. Do not edit by hand.
+
+%ifidn __OUTPUT_FORMAT__, win64
+default	rel
+%define XMMWORD
+%define YMMWORD
+%define ZMMWORD
+%define _CET_ENDBR
+
+%ifdef BORINGSSL_PREFIX
+%include "boringssl_prefix_symbols_nasm.inc"
+%endif
+section	.rdata rdata align=8
+ALIGN	64
+
+
+$L$bswap_mask:
+	DQ	0x08090a0b0c0d0e0f,0x0001020304050607
+
+
+
+
+
+
+
+
+$L$gfpoly:
+	DQ	1,0xc200000000000000
+
+
+$L$gfpoly_and_internal_carrybit:
+	DQ	1,0xc200000000000001
+
+
+$L$ctr_pattern:
+	DQ	0,0
+	DQ	1,0
+	DQ	2,0
+	DQ	3,0
+
+
+$L$inc_4blocks:
+	DQ	4,0
+
+section	.text code align=64
+
+global	gcm_init_vpclmulqdq_avx512
+
+ALIGN	32
+gcm_init_vpclmulqdq_avx512:
+
+
+_CET_ENDBR
+
+	lea	r8,[((256-64))+rcx]
+
+
+
+	vpshufd	xmm3,XMMWORD[rdx],0x4e
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vpshufd	xmm0,xmm3,0xd3
+	vpsrad	xmm0,xmm0,31
+	vpaddq	xmm3,xmm3,xmm3
+
+	vpternlogd	xmm3,xmm0,XMMWORD[$L$gfpoly_and_internal_carrybit],0x78
+
+
+	vbroadcasti32x4	zmm5,ZMMWORD[$L$gfpoly]
+
+
+
+
+
+
+
+
+	vpclmulqdq	xmm0,xmm3,xmm3,0x00
+	vpclmulqdq	xmm4,xmm3,xmm3,0x11
+	vpclmulqdq	xmm1,xmm5,xmm0,0x01
+	vpshufd	xmm0,xmm0,0x4e
+	vpxor	xmm1,xmm1,xmm0
+	vpclmulqdq	xmm0,xmm5,xmm1,0x01
+	vpshufd	xmm1,xmm1,0x4e
+	vpternlogd	xmm4,xmm1,xmm0,0x96
+
+
+
+	vinserti128	ymm3,ymm4,xmm3,1
+	vinserti128	ymm4,ymm4,xmm4,1
+
+
+	vpclmulqdq	ymm0,ymm3,ymm4,0x00
+	vpclmulqdq	ymm1,ymm3,ymm4,0x01
+	vpclmulqdq	ymm2,ymm3,ymm4,0x10
+	vpxord	ymm1,ymm1,ymm2
+	vpclmulqdq	ymm2,ymm5,ymm0,0x01
+	vpshufd	ymm0,ymm0,0x4e
+	vpternlogd	ymm1,ymm0,ymm2,0x96
+	vpclmulqdq	ymm4,ymm3,ymm4,0x11
+	vpclmulqdq	ymm0,ymm5,ymm1,0x01
+	vpshufd	ymm1,ymm1,0x4e
+	vpternlogd	ymm4,ymm1,ymm0,0x96
+
+	vinserti64x4	zmm3,zmm4,ymm3,1
+	vshufi64x2	zmm4,zmm4,zmm4,0
+
+
+	vmovdqu8	ZMMWORD[r8],zmm3
+
+
+
+
+	mov	eax,3
+$L$precompute_next:
+	sub	r8,64
+	vpclmulqdq	zmm0,zmm3,zmm4,0x00
+	vpclmulqdq	zmm1,zmm3,zmm4,0x01
+	vpclmulqdq	zmm2,zmm3,zmm4,0x10
+	vpxord	zmm1,zmm1,zmm2
+	vpclmulqdq	zmm2,zmm5,zmm0,0x01
+	vpshufd	zmm0,zmm0,0x4e
+	vpternlogd	zmm1,zmm0,zmm2,0x96
+	vpclmulqdq	zmm3,zmm3,zmm4,0x11
+	vpclmulqdq	zmm0,zmm5,zmm1,0x01
+	vpshufd	zmm1,zmm1,0x4e
+	vpternlogd	zmm3,zmm1,zmm0,0x96
+
+	vmovdqu8	ZMMWORD[r8],zmm3
+	dec	eax
+	jnz	NEAR $L$precompute_next
+
+	vzeroupper
+	ret
+
+
+
+global	gcm_gmult_vpclmulqdq_avx512
+
+ALIGN	32
+gcm_gmult_vpclmulqdq_avx512:
+
+$L$SEH_begin_gcm_gmult_vpclmulqdq_avx512_1:
+_CET_ENDBR
+	sub	rsp,24
+$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx512_2:
+	vmovdqa	XMMWORD[rsp],xmm6
+$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx512_3:
+
+$L$SEH_endprologue_gcm_gmult_vpclmulqdq_avx512_4:
+
+	vmovdqu	xmm0,XMMWORD[rcx]
+	vmovdqu	xmm1,XMMWORD[$L$bswap_mask]
+	vmovdqu	xmm2,XMMWORD[((256-16))+rdx]
+	vmovdqu	xmm3,XMMWORD[$L$gfpoly]
+	vpshufb	xmm0,xmm0,xmm1
+
+	vpclmulqdq	xmm4,xmm0,xmm2,0x00
+	vpclmulqdq	xmm5,xmm0,xmm2,0x01
+	vpclmulqdq	xmm6,xmm0,xmm2,0x10
+	vpxord	xmm5,xmm5,xmm6
+	vpclmulqdq	xmm6,xmm3,xmm4,0x01
+	vpshufd	xmm4,xmm4,0x4e
+	vpternlogd	xmm5,xmm4,xmm6,0x96
+	vpclmulqdq	xmm0,xmm0,xmm2,0x11
+	vpclmulqdq	xmm4,xmm3,xmm5,0x01
+	vpshufd	xmm5,xmm5,0x4e
+	vpternlogd	xmm0,xmm5,xmm4,0x96
+
+
+	vpshufb	xmm0,xmm0,xmm1
+	vmovdqu	XMMWORD[rcx],xmm0
+
+
+	vmovdqa	xmm6,XMMWORD[rsp]
+	add	rsp,24
+	ret
+$L$SEH_end_gcm_gmult_vpclmulqdq_avx512_5:
+
+
+global	gcm_ghash_vpclmulqdq_avx512
+
+ALIGN	32
+gcm_ghash_vpclmulqdq_avx512:
+
+$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1:
+_CET_ENDBR
+	sub	rsp,136
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_2:
+	vmovdqa	XMMWORD[rsp],xmm6
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_3:
+	vmovdqa	XMMWORD[16+rsp],xmm7
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_4:
+	vmovdqa	XMMWORD[32+rsp],xmm8
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_5:
+	vmovdqa	XMMWORD[48+rsp],xmm9
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_6:
+	vmovdqa	XMMWORD[64+rsp],xmm10
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_7:
+	vmovdqa	XMMWORD[80+rsp],xmm11
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_8:
+	vmovdqa	XMMWORD[96+rsp],xmm12
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_9:
+	vmovdqa	XMMWORD[112+rsp],xmm13
+$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_10:
+
+$L$SEH_endprologue_gcm_ghash_vpclmulqdq_avx512_11:
+
+
+
+
+	vmovdqu	xmm4,XMMWORD[$L$bswap_mask]
+	vmovdqu	xmm10,XMMWORD[$L$gfpoly]
+
+
+	vmovdqu	xmm5,XMMWORD[rcx]
+	vpshufb	xmm5,xmm5,xmm4
+
+
+	cmp	r9,64
+	jb	NEAR $L$aad_blockbyblock
+
+
+
+	vshufi64x2	zmm4,zmm4,zmm4,0
+	vshufi64x2	zmm10,zmm10,zmm10,0
+
+
+	vmovdqu8	zmm9,ZMMWORD[((256-64))+rdx]
+
+	cmp	r9,256
+	jb	NEAR $L$aad_loop_1x
+
+
+	vmovdqu8	zmm6,ZMMWORD[((256-256))+rdx]
+	vmovdqu8	zmm7,ZMMWORD[((256-192))+rdx]
+	vmovdqu8	zmm8,ZMMWORD[((256-128))+rdx]
+
+
+$L$aad_loop_4x:
+	vmovdqu8	zmm0,ZMMWORD[r8]
+	vmovdqu8	zmm1,ZMMWORD[64+r8]
+	vmovdqu8	zmm2,ZMMWORD[128+r8]
+	vmovdqu8	zmm3,ZMMWORD[192+r8]
+	vpshufb	zmm0,zmm0,zmm4
+	vpxord	zmm0,zmm0,zmm5
+	vpshufb	zmm1,zmm1,zmm4
+	vpshufb	zmm2,zmm2,zmm4
+	vpshufb	zmm3,zmm3,zmm4
+	vpclmulqdq	zmm5,zmm0,zmm6,0x00
+	vpclmulqdq	zmm11,zmm1,zmm7,0x00
+	vpclmulqdq	zmm12,zmm2,zmm8,0x00
+	vpxord	zmm5,zmm5,zmm11
+	vpclmulqdq	zmm13,zmm3,zmm9,0x00
+	vpternlogd	zmm5,zmm12,zmm13,0x96
+	vpclmulqdq	zmm11,zmm0,zmm6,0x01
+	vpclmulqdq	zmm12,zmm1,zmm7,0x01
+	vpclmulqdq	zmm13,zmm2,zmm8,0x01
+	vpternlogd	zmm11,zmm12,zmm13,0x96
+	vpclmulqdq	zmm12,zmm3,zmm9,0x01
+	vpclmulqdq	zmm13,zmm0,zmm6,0x10
+	vpternlogd	zmm11,zmm12,zmm13,0x96
+	vpclmulqdq	zmm12,zmm1,zmm7,0x10
+	vpclmulqdq	zmm13,zmm2,zmm8,0x10
+	vpternlogd	zmm11,zmm12,zmm13,0x96
+	vpclmulqdq	zmm13,zmm10,zmm5,0x01
+	vpclmulqdq	zmm12,zmm3,zmm9,0x10
+	vpxord	zmm11,zmm11,zmm12
+	vpshufd	zmm5,zmm5,0x4e
+	vpclmulqdq	zmm0,zmm0,zmm6,0x11
+	vpclmulqdq	zmm1,zmm1,zmm7,0x11
+	vpclmulqdq	zmm2,zmm2,zmm8,0x11
+	vpternlogd	zmm11,zmm5,zmm13,0x96
+	vpclmulqdq	zmm3,zmm3,zmm9,0x11
+	vpternlogd	zmm0,zmm1,zmm2,0x96
+	vpclmulqdq	zmm12,zmm10,zmm11,0x01
+	vpxord	zmm5,zmm0,zmm3
+	vpshufd	zmm11,zmm11,0x4e
+	vpternlogd	zmm5,zmm11,zmm12,0x96
+	vextracti32x4	xmm0,zmm5,1
+	vextracti32x4	xmm1,zmm5,2
+	vextracti32x4	xmm2,zmm5,3
+	vpxord	xmm5,xmm5,xmm0
+	vpternlogd	xmm5,xmm2,xmm1,0x96
+
+	add	r8,256
+	sub	r9,256
+	cmp	r9,256
+	jae	NEAR $L$aad_loop_4x
+
+
+	cmp	r9,64
+	jb	NEAR $L$aad_large_done
+$L$aad_loop_1x:
+	vmovdqu8	zmm0,ZMMWORD[r8]
+	vpshufb	zmm0,zmm0,zmm4
+	vpxord	zmm5,zmm5,zmm0
+	vpclmulqdq	zmm0,zmm5,zmm9,0x00
+	vpclmulqdq	zmm1,zmm5,zmm9,0x01
+	vpclmulqdq	zmm2,zmm5,zmm9,0x10
+	vpxord	zmm1,zmm1,zmm2
+	vpclmulqdq	zmm2,zmm10,zmm0,0x01
+	vpshufd	zmm0,zmm0,0x4e
+	vpternlogd	zmm1,zmm0,zmm2,0x96
+	vpclmulqdq	zmm5,zmm5,zmm9,0x11
+	vpclmulqdq	zmm0,zmm10,zmm1,0x01
+	vpshufd	zmm1,zmm1,0x4e
+	vpternlogd	zmm5,zmm1,zmm0,0x96
+
+	vextracti32x4	xmm0,zmm5,1
+	vextracti32x4	xmm1,zmm5,2
+	vextracti32x4	xmm2,zmm5,3
+	vpxord	xmm5,xmm5,xmm0
+	vpternlogd	xmm5,xmm2,xmm1,0x96
+
+	add	r8,64
+	sub	r9,64
+	cmp	r9,64
+	jae	NEAR $L$aad_loop_1x
+
+$L$aad_large_done:
+
+
+$L$aad_blockbyblock:
+	test	r9,r9
+	jz	NEAR $L$aad_done
+	vmovdqu	xmm9,XMMWORD[((256-16))+rdx]
+$L$aad_loop_blockbyblock:
+	vmovdqu	xmm0,XMMWORD[r8]
+	vpshufb	xmm0,xmm0,xmm4
+	vpxor	xmm5,xmm5,xmm0
+	vpclmulqdq	xmm0,xmm5,xmm9,0x00
+	vpclmulqdq	xmm1,xmm5,xmm9,0x01
+	vpclmulqdq	xmm2,xmm5,xmm9,0x10
+	vpxord	xmm1,xmm1,xmm2
+	vpclmulqdq	xmm2,xmm10,xmm0,0x01
+	vpshufd	xmm0,xmm0,0x4e
+	vpternlogd	xmm1,xmm0,xmm2,0x96
+	vpclmulqdq	xmm5,xmm5,xmm9,0x11
+	vpclmulqdq	xmm0,xmm10,xmm1,0x01
+	vpshufd	xmm1,xmm1,0x4e
+	vpternlogd	xmm5,xmm1,xmm0,0x96
+
+	add	r8,16
+	sub	r9,16
+	jnz	NEAR $L$aad_loop_blockbyblock
+
+$L$aad_done:
+
+	vpshufb	xmm5,xmm5,xmm4
+	vmovdqu	XMMWORD[rcx],xmm5
+
+	vzeroupper
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
+	vmovdqa	xmm10,XMMWORD[64+rsp]
+	vmovdqa	xmm11,XMMWORD[80+rsp]
+	vmovdqa	xmm12,XMMWORD[96+rsp]
+	vmovdqa	xmm13,XMMWORD[112+rsp]
+	add	rsp,136
+	ret
+$L$SEH_end_gcm_ghash_vpclmulqdq_avx512_12:
+
+
+global	aes_gcm_enc_update_vaes_avx512
+
+ALIGN	32
+aes_gcm_enc_update_vaes_avx512:
+
+$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1:
+_CET_ENDBR
+	push	rsi
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_2:
+	push	rdi
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_3:
+	push	r12
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_4:
+
+	mov	rsi,QWORD[64+rsp]
+	mov	rdi,QWORD[72+rsp]
+	mov	r12,QWORD[80+rsp]
+	sub	rsp,160
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_5:
+	vmovdqa	XMMWORD[rsp],xmm6
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_6:
+	vmovdqa	XMMWORD[16+rsp],xmm7
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_7:
+	vmovdqa	XMMWORD[32+rsp],xmm8
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_8:
+	vmovdqa	XMMWORD[48+rsp],xmm9
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_9:
+	vmovdqa	XMMWORD[64+rsp],xmm10
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_10:
+	vmovdqa	XMMWORD[80+rsp],xmm11
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_11:
+	vmovdqa	XMMWORD[96+rsp],xmm12
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_12:
+	vmovdqa	XMMWORD[112+rsp],xmm13
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_13:
+	vmovdqa	XMMWORD[128+rsp],xmm14
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_14:
+	vmovdqa	XMMWORD[144+rsp],xmm15
+$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_15:
+
+$L$SEH_endprologue_aes_gcm_enc_update_vaes_avx512_16:
+%ifdef BORINGSSL_DISPATCH_TEST
+EXTERN	BORINGSSL_function_hit
+	mov	BYTE[((BORINGSSL_function_hit+7))],1
+%endif
+
+	vbroadcasti32x4	zmm8,ZMMWORD[$L$bswap_mask]
+	vbroadcasti32x4	zmm31,ZMMWORD[$L$gfpoly]
+
+
+
+	vmovdqu	xmm10,XMMWORD[r12]
+	vpshufb	xmm10,xmm10,xmm8
+	vbroadcasti32x4	zmm12,ZMMWORD[rsi]
+	vpshufb	zmm12,zmm12,zmm8
+
+
+
+	mov	r10d,DWORD[240+r9]
+	lea	r10d,[((-20))+r10*4]
+
+
+
+
+	lea	r11,[96+r10*4+r9]
+	vbroadcasti32x4	zmm13,ZMMWORD[r9]
+	vbroadcasti32x4	zmm14,ZMMWORD[r11]
+
+
+	vpaddd	zmm12,zmm12,ZMMWORD[$L$ctr_pattern]
+
+
+	vbroadcasti32x4	zmm11,ZMMWORD[$L$inc_4blocks]
+
+
+
+	cmp	r8,256
+	jb	NEAR $L$crypt_loop_4x_done__func1
+
+
+	vmovdqu8	zmm27,ZMMWORD[((256-256))+rdi]
+	vmovdqu8	zmm28,ZMMWORD[((256-192))+rdi]
+	vmovdqu8	zmm29,ZMMWORD[((256-128))+rdi]
+	vmovdqu8	zmm30,ZMMWORD[((256-64))+rdi]
+
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm1,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm2,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm3,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+
+
+	vpxord	zmm0,zmm0,zmm13
+	vpxord	zmm1,zmm1,zmm13
+	vpxord	zmm2,zmm2,zmm13
+	vpxord	zmm3,zmm3,zmm13
+
+	lea	rax,[16+r9]
+$L$vaesenc_loop_first_4_vecs__func1:
+	vbroadcasti32x4	zmm9,ZMMWORD[rax]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+	add	rax,16
+	cmp	r11,rax
+	jne	NEAR $L$vaesenc_loop_first_4_vecs__func1
+	vpxord	zmm4,zmm14,ZMMWORD[rcx]
+	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
+	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
+	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
+	vaesenclast	zmm4,zmm0,zmm4
+	vaesenclast	zmm5,zmm1,zmm5
+	vaesenclast	zmm6,zmm2,zmm6
+	vaesenclast	zmm7,zmm3,zmm7
+	vmovdqu8	ZMMWORD[rdx],zmm4
+	vmovdqu8	ZMMWORD[64+rdx],zmm5
+	vmovdqu8	ZMMWORD[128+rdx],zmm6
+	vmovdqu8	ZMMWORD[192+rdx],zmm7
+
+	add	rcx,256
+	add	rdx,256
+	sub	r8,256
+	cmp	r8,256
+	jb	NEAR $L$ghash_last_ciphertext_4x__func1
+
+	vbroadcasti32x4	zmm15,ZMMWORD[((-144))+r11]
+	vbroadcasti32x4	zmm16,ZMMWORD[((-128))+r11]
+	vbroadcasti32x4	zmm17,ZMMWORD[((-112))+r11]
+	vbroadcasti32x4	zmm18,ZMMWORD[((-96))+r11]
+	vbroadcasti32x4	zmm19,ZMMWORD[((-80))+r11]
+	vbroadcasti32x4	zmm20,ZMMWORD[((-64))+r11]
+	vbroadcasti32x4	zmm21,ZMMWORD[((-48))+r11]
+	vbroadcasti32x4	zmm22,ZMMWORD[((-32))+r11]
+	vbroadcasti32x4	zmm23,ZMMWORD[((-16))+r11]
+
+$L$crypt_loop_4x__func1:
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm1,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm2,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm3,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+
+
+	vpxord	zmm0,zmm0,zmm13
+	vpxord	zmm1,zmm1,zmm13
+	vpxord	zmm2,zmm2,zmm13
+	vpxord	zmm3,zmm3,zmm13
+
+	cmp	r10d,24
+	jl	NEAR $L$aes128__func1
+	je	NEAR $L$aes192__func1
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-208))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-192))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+$L$aes192__func1:
+	vbroadcasti32x4	zmm9,ZMMWORD[((-176))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-160))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+$L$aes128__func1:
+
+
+
+
+	prefetcht0	[((512+0))+rcx]
+	prefetcht0	[((512+64))+rcx]
+	prefetcht0	[((512+128))+rcx]
+	prefetcht0	[((512+192))+rcx]
+
+
+
+
+	vpshufb	zmm4,zmm4,zmm8
+	vpxord	zmm4,zmm4,zmm10
+	vpshufb	zmm5,zmm5,zmm8
+	vpshufb	zmm6,zmm6,zmm8
+
+	vaesenc	zmm0,zmm0,zmm15
+	vaesenc	zmm1,zmm1,zmm15
+	vaesenc	zmm2,zmm2,zmm15
+	vaesenc	zmm3,zmm3,zmm15
+
+	vpshufb	zmm7,zmm7,zmm8
+	vpclmulqdq	zmm10,zmm4,zmm27,0x00
+	vpclmulqdq	zmm24,zmm5,zmm28,0x00
+	vpclmulqdq	zmm25,zmm6,zmm29,0x00
+
+	vaesenc	zmm0,zmm0,zmm16
+	vaesenc	zmm1,zmm1,zmm16
+	vaesenc	zmm2,zmm2,zmm16
+	vaesenc	zmm3,zmm3,zmm16
+
+	vpxord	zmm10,zmm10,zmm24
+	vpclmulqdq	zmm26,zmm7,zmm30,0x00
+	vpternlogd	zmm10,zmm25,zmm26,0x96
+	vpclmulqdq	zmm24,zmm4,zmm27,0x01
+
+	vaesenc	zmm0,zmm0,zmm17
+	vaesenc	zmm1,zmm1,zmm17
+	vaesenc	zmm2,zmm2,zmm17
+	vaesenc	zmm3,zmm3,zmm17
+
+	vpclmulqdq	zmm25,zmm5,zmm28,0x01
+	vpclmulqdq	zmm26,zmm6,zmm29,0x01
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm7,zmm30,0x01
+
+	vaesenc	zmm0,zmm0,zmm18
+	vaesenc	zmm1,zmm1,zmm18
+	vaesenc	zmm2,zmm2,zmm18
+	vaesenc	zmm3,zmm3,zmm18
+
+	vpclmulqdq	zmm26,zmm4,zmm27,0x10
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm5,zmm28,0x10
+	vpclmulqdq	zmm26,zmm6,zmm29,0x10
+
+	vaesenc	zmm0,zmm0,zmm19
+	vaesenc	zmm1,zmm1,zmm19
+	vaesenc	zmm2,zmm2,zmm19
+	vaesenc	zmm3,zmm3,zmm19
+
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm26,zmm31,zmm10,0x01
+	vpclmulqdq	zmm25,zmm7,zmm30,0x10
+	vpxord	zmm24,zmm24,zmm25
+
+	vaesenc	zmm0,zmm0,zmm20
+	vaesenc	zmm1,zmm1,zmm20
+	vaesenc	zmm2,zmm2,zmm20
+	vaesenc	zmm3,zmm3,zmm20
+
+	vpshufd	zmm10,zmm10,0x4e
+	vpclmulqdq	zmm4,zmm4,zmm27,0x11
+	vpclmulqdq	zmm5,zmm5,zmm28,0x11
+	vpclmulqdq	zmm6,zmm6,zmm29,0x11
+
+	vaesenc	zmm0,zmm0,zmm21
+	vaesenc	zmm1,zmm1,zmm21
+	vaesenc	zmm2,zmm2,zmm21
+	vaesenc	zmm3,zmm3,zmm21
+
+	vpternlogd	zmm24,zmm10,zmm26,0x96
+	vpclmulqdq	zmm7,zmm7,zmm30,0x11
+	vpternlogd	zmm4,zmm5,zmm6,0x96
+	vpclmulqdq	zmm25,zmm31,zmm24,0x01
+
+	vaesenc	zmm0,zmm0,zmm22
+	vaesenc	zmm1,zmm1,zmm22
+	vaesenc	zmm2,zmm2,zmm22
+	vaesenc	zmm3,zmm3,zmm22
+
+	vpxord	zmm10,zmm4,zmm7
+	vpshufd	zmm24,zmm24,0x4e
+	vpternlogd	zmm10,zmm24,zmm25,0x96
+
+	vaesenc	zmm0,zmm0,zmm23
+	vaesenc	zmm1,zmm1,zmm23
+	vaesenc	zmm2,zmm2,zmm23
+	vaesenc	zmm3,zmm3,zmm23
+
+
+	vextracti32x4	xmm4,zmm10,1
+	vextracti32x4	xmm5,zmm10,2
+	vextracti32x4	xmm6,zmm10,3
+	vpxord	xmm10,xmm10,xmm4
+	vpternlogd	xmm10,xmm6,xmm5,0x96
+
+	vpxord	zmm4,zmm14,ZMMWORD[rcx]
+	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
+	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
+	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
+	vaesenclast	zmm4,zmm0,zmm4
+	vaesenclast	zmm5,zmm1,zmm5
+	vaesenclast	zmm6,zmm2,zmm6
+	vaesenclast	zmm7,zmm3,zmm7
+	vmovdqu8	ZMMWORD[rdx],zmm4
+	vmovdqu8	ZMMWORD[64+rdx],zmm5
+	vmovdqu8	ZMMWORD[128+rdx],zmm6
+	vmovdqu8	ZMMWORD[192+rdx],zmm7
+
+	add	rcx,256
+	add	rdx,256
+	sub	r8,256
+	cmp	r8,256
+	jae	NEAR $L$crypt_loop_4x__func1
+$L$ghash_last_ciphertext_4x__func1:
+	vpshufb	zmm4,zmm4,zmm8
+	vpxord	zmm4,zmm4,zmm10
+	vpshufb	zmm5,zmm5,zmm8
+	vpshufb	zmm6,zmm6,zmm8
+	vpshufb	zmm7,zmm7,zmm8
+	vpclmulqdq	zmm10,zmm4,zmm27,0x00
+	vpclmulqdq	zmm24,zmm5,zmm28,0x00
+	vpclmulqdq	zmm25,zmm6,zmm29,0x00
+	vpxord	zmm10,zmm10,zmm24
+	vpclmulqdq	zmm26,zmm7,zmm30,0x00
+	vpternlogd	zmm10,zmm25,zmm26,0x96
+	vpclmulqdq	zmm24,zmm4,zmm27,0x01
+	vpclmulqdq	zmm25,zmm5,zmm28,0x01
+	vpclmulqdq	zmm26,zmm6,zmm29,0x01
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm7,zmm30,0x01
+	vpclmulqdq	zmm26,zmm4,zmm27,0x10
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm5,zmm28,0x10
+	vpclmulqdq	zmm26,zmm6,zmm29,0x10
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm26,zmm31,zmm10,0x01
+	vpclmulqdq	zmm25,zmm7,zmm30,0x10
+	vpxord	zmm24,zmm24,zmm25
+	vpshufd	zmm10,zmm10,0x4e
+	vpclmulqdq	zmm4,zmm4,zmm27,0x11
+	vpclmulqdq	zmm5,zmm5,zmm28,0x11
+	vpclmulqdq	zmm6,zmm6,zmm29,0x11
+	vpternlogd	zmm24,zmm10,zmm26,0x96
+	vpclmulqdq	zmm7,zmm7,zmm30,0x11
+	vpternlogd	zmm4,zmm5,zmm6,0x96
+	vpclmulqdq	zmm25,zmm31,zmm24,0x01
+	vpxord	zmm10,zmm4,zmm7
+	vpshufd	zmm24,zmm24,0x4e
+	vpternlogd	zmm10,zmm24,zmm25,0x96
+	vextracti32x4	xmm4,zmm10,1
+	vextracti32x4	xmm5,zmm10,2
+	vextracti32x4	xmm6,zmm10,3
+	vpxord	xmm10,xmm10,xmm4
+	vpternlogd	xmm10,xmm6,xmm5,0x96
+
+$L$crypt_loop_4x_done__func1:
+
+	test	r8,r8
+	jz	NEAR $L$done__func1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	mov	rax,r8
+	neg	rax
+	and	rax,-16
+	lea	rsi,[256+rax*1+rdi]
+	vpxor	xmm4,xmm4,xmm4
+	vpxor	xmm5,xmm5,xmm5
+	vpxor	xmm6,xmm6,xmm6
+
+	cmp	r8,64
+	jb	NEAR $L$partial_vec__func1
+
+$L$crypt_loop_1x__func1:
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpxord	zmm0,zmm0,zmm13
+	lea	rax,[16+r9]
+$L$vaesenc_loop_tail_full_vec__func1:
+	vbroadcasti32x4	zmm9,ZMMWORD[rax]
+	vaesenc	zmm0,zmm0,zmm9
+	add	rax,16
+	cmp	r11,rax
+	jne	NEAR $L$vaesenc_loop_tail_full_vec__func1
+	vaesenclast	zmm0,zmm0,zmm14
+
+
+	vmovdqu8	zmm1,ZMMWORD[rcx]
+	vpxord	zmm0,zmm0,zmm1
+	vmovdqu8	ZMMWORD[rdx],zmm0
+
+
+	vmovdqu8	zmm30,ZMMWORD[rsi]
+	vpshufb	zmm0,zmm0,zmm8
+	vpxord	zmm0,zmm0,zmm10
+	vpclmulqdq	zmm7,zmm0,zmm30,0x00
+	vpclmulqdq	zmm1,zmm0,zmm30,0x01
+	vpclmulqdq	zmm2,zmm0,zmm30,0x10
+	vpclmulqdq	zmm3,zmm0,zmm30,0x11
+	vpxord	zmm4,zmm4,zmm7
+	vpternlogd	zmm5,zmm1,zmm2,0x96
+	vpxord	zmm6,zmm6,zmm3
+
+	vpxor	xmm10,xmm10,xmm10
+
+	add	rsi,64
+	add	rcx,64
+	add	rdx,64
+	sub	r8,64
+	cmp	r8,64
+	jae	NEAR $L$crypt_loop_1x__func1
+
+	test	r8,r8
+	jz	NEAR $L$reduce__func1
+
+$L$partial_vec__func1:
+
+
+
+
+	mov	rax,-1
+	bzhi	rax,rax,r8
+	kmovq	k1,rax
+	add	r8,15
+	and	r8,-16
+	mov	rax,-1
+	bzhi	rax,rax,r8
+	kmovq	k2,rax
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpxord	zmm0,zmm0,zmm13
+	lea	rax,[16+r9]
+$L$vaesenc_loop_tail_partialvec__func1:
+	vbroadcasti32x4	zmm9,ZMMWORD[rax]
+	vaesenc	zmm0,zmm0,zmm9
+	add	rax,16
+	cmp	r11,rax
+	jne	NEAR $L$vaesenc_loop_tail_partialvec__func1
+	vaesenclast	zmm0,zmm0,zmm14
+
+
+	vmovdqu8	zmm1{k1}{z},[rcx]
+	vpxord	zmm0,zmm0,zmm1
+	vmovdqu8	ZMMWORD[rdx]{k1},zmm0
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	zmm30{k2}{z},[rsi]
+	vmovdqu8	zmm1{k1}{z},zmm0
+	vpshufb	zmm0,zmm1,zmm8
+	vpxord	zmm0,zmm0,zmm10
+	vpclmulqdq	zmm7,zmm0,zmm30,0x00
+	vpclmulqdq	zmm1,zmm0,zmm30,0x01
+	vpclmulqdq	zmm2,zmm0,zmm30,0x10
+	vpclmulqdq	zmm3,zmm0,zmm30,0x11
+	vpxord	zmm4,zmm4,zmm7
+	vpternlogd	zmm5,zmm1,zmm2,0x96
+	vpxord	zmm6,zmm6,zmm3
+
+
+$L$reduce__func1:
+
+	vpclmulqdq	zmm0,zmm31,zmm4,0x01
+	vpshufd	zmm4,zmm4,0x4e
+	vpternlogd	zmm5,zmm4,zmm0,0x96
+	vpclmulqdq	zmm0,zmm31,zmm5,0x01
+	vpshufd	zmm5,zmm5,0x4e
+	vpternlogd	zmm6,zmm5,zmm0,0x96
+
+	vextracti32x4	xmm0,zmm6,1
+	vextracti32x4	xmm1,zmm6,2
+	vextracti32x4	xmm2,zmm6,3
+	vpxord	xmm10,xmm6,xmm0
+	vpternlogd	xmm10,xmm2,xmm1,0x96
+
+
+$L$done__func1:
+
+	vpshufb	xmm10,xmm10,xmm8
+	vmovdqu	XMMWORD[r12],xmm10
+
+	vzeroupper
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
+	vmovdqa	xmm10,XMMWORD[64+rsp]
+	vmovdqa	xmm11,XMMWORD[80+rsp]
+	vmovdqa	xmm12,XMMWORD[96+rsp]
+	vmovdqa	xmm13,XMMWORD[112+rsp]
+	vmovdqa	xmm14,XMMWORD[128+rsp]
+	vmovdqa	xmm15,XMMWORD[144+rsp]
+	add	rsp,160
+	pop	r12
+	pop	rdi
+	pop	rsi
+	ret
+$L$SEH_end_aes_gcm_enc_update_vaes_avx512_17:
+
+
+global	aes_gcm_dec_update_vaes_avx512
+
+ALIGN	32
+aes_gcm_dec_update_vaes_avx512:
+
+$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1:
+_CET_ENDBR
+	push	rsi
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_2:
+	push	rdi
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_3:
+	push	r12
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_4:
+
+	mov	rsi,QWORD[64+rsp]
+	mov	rdi,QWORD[72+rsp]
+	mov	r12,QWORD[80+rsp]
+	sub	rsp,160
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_5:
+	vmovdqa	XMMWORD[rsp],xmm6
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_6:
+	vmovdqa	XMMWORD[16+rsp],xmm7
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_7:
+	vmovdqa	XMMWORD[32+rsp],xmm8
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_8:
+	vmovdqa	XMMWORD[48+rsp],xmm9
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_9:
+	vmovdqa	XMMWORD[64+rsp],xmm10
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_10:
+	vmovdqa	XMMWORD[80+rsp],xmm11
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_11:
+	vmovdqa	XMMWORD[96+rsp],xmm12
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_12:
+	vmovdqa	XMMWORD[112+rsp],xmm13
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_13:
+	vmovdqa	XMMWORD[128+rsp],xmm14
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_14:
+	vmovdqa	XMMWORD[144+rsp],xmm15
+$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_15:
+
+$L$SEH_endprologue_aes_gcm_dec_update_vaes_avx512_16:
+
+	vbroadcasti32x4	zmm8,ZMMWORD[$L$bswap_mask]
+	vbroadcasti32x4	zmm31,ZMMWORD[$L$gfpoly]
+
+
+
+	vmovdqu	xmm10,XMMWORD[r12]
+	vpshufb	xmm10,xmm10,xmm8
+	vbroadcasti32x4	zmm12,ZMMWORD[rsi]
+	vpshufb	zmm12,zmm12,zmm8
+
+
+
+	mov	r10d,DWORD[240+r9]
+	lea	r10d,[((-20))+r10*4]
+
+
+
+
+	lea	r11,[96+r10*4+r9]
+	vbroadcasti32x4	zmm13,ZMMWORD[r9]
+	vbroadcasti32x4	zmm14,ZMMWORD[r11]
+
+
+	vpaddd	zmm12,zmm12,ZMMWORD[$L$ctr_pattern]
+
+
+	vbroadcasti32x4	zmm11,ZMMWORD[$L$inc_4blocks]
+
+
+
+	cmp	r8,256
+	jb	NEAR $L$crypt_loop_4x_done__func2
+
+
+	vmovdqu8	zmm27,ZMMWORD[((256-256))+rdi]
+	vmovdqu8	zmm28,ZMMWORD[((256-192))+rdi]
+	vmovdqu8	zmm29,ZMMWORD[((256-128))+rdi]
+	vmovdqu8	zmm30,ZMMWORD[((256-64))+rdi]
+
+	vbroadcasti32x4	zmm15,ZMMWORD[((-144))+r11]
+	vbroadcasti32x4	zmm16,ZMMWORD[((-128))+r11]
+	vbroadcasti32x4	zmm17,ZMMWORD[((-112))+r11]
+	vbroadcasti32x4	zmm18,ZMMWORD[((-96))+r11]
+	vbroadcasti32x4	zmm19,ZMMWORD[((-80))+r11]
+	vbroadcasti32x4	zmm20,ZMMWORD[((-64))+r11]
+	vbroadcasti32x4	zmm21,ZMMWORD[((-48))+r11]
+	vbroadcasti32x4	zmm22,ZMMWORD[((-32))+r11]
+	vbroadcasti32x4	zmm23,ZMMWORD[((-16))+r11]
+
+$L$crypt_loop_4x__func2:
+	vmovdqu8	zmm4,ZMMWORD[rcx]
+	vmovdqu8	zmm5,ZMMWORD[64+rcx]
+	vmovdqu8	zmm6,ZMMWORD[128+rcx]
+	vmovdqu8	zmm7,ZMMWORD[192+rcx]
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm1,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm2,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpshufb	zmm3,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+
+
+	vpxord	zmm0,zmm0,zmm13
+	vpxord	zmm1,zmm1,zmm13
+	vpxord	zmm2,zmm2,zmm13
+	vpxord	zmm3,zmm3,zmm13
+
+	cmp	r10d,24
+	jl	NEAR $L$aes128__func2
+	je	NEAR $L$aes192__func2
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-208))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-192))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+$L$aes192__func2:
+	vbroadcasti32x4	zmm9,ZMMWORD[((-176))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+	vbroadcasti32x4	zmm9,ZMMWORD[((-160))+r11]
+	vaesenc	zmm0,zmm0,zmm9
+	vaesenc	zmm1,zmm1,zmm9
+	vaesenc	zmm2,zmm2,zmm9
+	vaesenc	zmm3,zmm3,zmm9
+
+$L$aes128__func2:
+
+
+
+
+	prefetcht0	[((512+0))+rcx]
+	prefetcht0	[((512+64))+rcx]
+	prefetcht0	[((512+128))+rcx]
+	prefetcht0	[((512+192))+rcx]
+
+
+
+
+	vpshufb	zmm4,zmm4,zmm8
+	vpxord	zmm4,zmm4,zmm10
+	vpshufb	zmm5,zmm5,zmm8
+	vpshufb	zmm6,zmm6,zmm8
+
+	vaesenc	zmm0,zmm0,zmm15
+	vaesenc	zmm1,zmm1,zmm15
+	vaesenc	zmm2,zmm2,zmm15
+	vaesenc	zmm3,zmm3,zmm15
+
+	vpshufb	zmm7,zmm7,zmm8
+	vpclmulqdq	zmm10,zmm4,zmm27,0x00
+	vpclmulqdq	zmm24,zmm5,zmm28,0x00
+	vpclmulqdq	zmm25,zmm6,zmm29,0x00
+
+	vaesenc	zmm0,zmm0,zmm16
+	vaesenc	zmm1,zmm1,zmm16
+	vaesenc	zmm2,zmm2,zmm16
+	vaesenc	zmm3,zmm3,zmm16
+
+	vpxord	zmm10,zmm10,zmm24
+	vpclmulqdq	zmm26,zmm7,zmm30,0x00
+	vpternlogd	zmm10,zmm25,zmm26,0x96
+	vpclmulqdq	zmm24,zmm4,zmm27,0x01
+
+	vaesenc	zmm0,zmm0,zmm17
+	vaesenc	zmm1,zmm1,zmm17
+	vaesenc	zmm2,zmm2,zmm17
+	vaesenc	zmm3,zmm3,zmm17
+
+	vpclmulqdq	zmm25,zmm5,zmm28,0x01
+	vpclmulqdq	zmm26,zmm6,zmm29,0x01
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm7,zmm30,0x01
+
+	vaesenc	zmm0,zmm0,zmm18
+	vaesenc	zmm1,zmm1,zmm18
+	vaesenc	zmm2,zmm2,zmm18
+	vaesenc	zmm3,zmm3,zmm18
+
+	vpclmulqdq	zmm26,zmm4,zmm27,0x10
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm25,zmm5,zmm28,0x10
+	vpclmulqdq	zmm26,zmm6,zmm29,0x10
+
+	vaesenc	zmm0,zmm0,zmm19
+	vaesenc	zmm1,zmm1,zmm19
+	vaesenc	zmm2,zmm2,zmm19
+	vaesenc	zmm3,zmm3,zmm19
+
+	vpternlogd	zmm24,zmm25,zmm26,0x96
+	vpclmulqdq	zmm26,zmm31,zmm10,0x01
+	vpclmulqdq	zmm25,zmm7,zmm30,0x10
+	vpxord	zmm24,zmm24,zmm25
+
+	vaesenc	zmm0,zmm0,zmm20
+	vaesenc	zmm1,zmm1,zmm20
+	vaesenc	zmm2,zmm2,zmm20
+	vaesenc	zmm3,zmm3,zmm20
+
+	vpshufd	zmm10,zmm10,0x4e
+	vpclmulqdq	zmm4,zmm4,zmm27,0x11
+	vpclmulqdq	zmm5,zmm5,zmm28,0x11
+	vpclmulqdq	zmm6,zmm6,zmm29,0x11
+
+	vaesenc	zmm0,zmm0,zmm21
+	vaesenc	zmm1,zmm1,zmm21
+	vaesenc	zmm2,zmm2,zmm21
+	vaesenc	zmm3,zmm3,zmm21
+
+	vpternlogd	zmm24,zmm10,zmm26,0x96
+	vpclmulqdq	zmm7,zmm7,zmm30,0x11
+	vpternlogd	zmm4,zmm5,zmm6,0x96
+	vpclmulqdq	zmm25,zmm31,zmm24,0x01
+
+	vaesenc	zmm0,zmm0,zmm22
+	vaesenc	zmm1,zmm1,zmm22
+	vaesenc	zmm2,zmm2,zmm22
+	vaesenc	zmm3,zmm3,zmm22
+
+	vpxord	zmm10,zmm4,zmm7
+	vpshufd	zmm24,zmm24,0x4e
+	vpternlogd	zmm10,zmm24,zmm25,0x96
+
+	vaesenc	zmm0,zmm0,zmm23
+	vaesenc	zmm1,zmm1,zmm23
+	vaesenc	zmm2,zmm2,zmm23
+	vaesenc	zmm3,zmm3,zmm23
+
+
+	vextracti32x4	xmm4,zmm10,1
+	vextracti32x4	xmm5,zmm10,2
+	vextracti32x4	xmm6,zmm10,3
+	vpxord	xmm10,xmm10,xmm4
+	vpternlogd	xmm10,xmm6,xmm5,0x96
+
+	vpxord	zmm4,zmm14,ZMMWORD[rcx]
+	vpxord	zmm5,zmm14,ZMMWORD[64+rcx]
+	vpxord	zmm6,zmm14,ZMMWORD[128+rcx]
+	vpxord	zmm7,zmm14,ZMMWORD[192+rcx]
+	vaesenclast	zmm4,zmm0,zmm4
+	vaesenclast	zmm5,zmm1,zmm5
+	vaesenclast	zmm6,zmm2,zmm6
+	vaesenclast	zmm7,zmm3,zmm7
+	vmovdqu8	ZMMWORD[rdx],zmm4
+	vmovdqu8	ZMMWORD[64+rdx],zmm5
+	vmovdqu8	ZMMWORD[128+rdx],zmm6
+	vmovdqu8	ZMMWORD[192+rdx],zmm7
+
+	add	rcx,256
+	add	rdx,256
+	sub	r8,256
+	cmp	r8,256
+	jae	NEAR $L$crypt_loop_4x__func2
+$L$crypt_loop_4x_done__func2:
+
+	test	r8,r8
+	jz	NEAR $L$done__func2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	mov	rax,r8
+	neg	rax
+	and	rax,-16
+	lea	rsi,[256+rax*1+rdi]
+	vpxor	xmm4,xmm4,xmm4
+	vpxor	xmm5,xmm5,xmm5
+	vpxor	xmm6,xmm6,xmm6
+
+	cmp	r8,64
+	jb	NEAR $L$partial_vec__func2
+
+$L$crypt_loop_1x__func2:
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpaddd	zmm12,zmm12,zmm11
+	vpxord	zmm0,zmm0,zmm13
+	lea	rax,[16+r9]
+$L$vaesenc_loop_tail_full_vec__func2:
+	vbroadcasti32x4	zmm9,ZMMWORD[rax]
+	vaesenc	zmm0,zmm0,zmm9
+	add	rax,16
+	cmp	r11,rax
+	jne	NEAR $L$vaesenc_loop_tail_full_vec__func2
+	vaesenclast	zmm0,zmm0,zmm14
+
+
+	vmovdqu8	zmm1,ZMMWORD[rcx]
+	vpxord	zmm0,zmm0,zmm1
+	vmovdqu8	ZMMWORD[rdx],zmm0
+
+
+	vmovdqu8	zmm30,ZMMWORD[rsi]
+	vpshufb	zmm0,zmm1,zmm8
+	vpxord	zmm0,zmm0,zmm10
+	vpclmulqdq	zmm7,zmm0,zmm30,0x00
+	vpclmulqdq	zmm1,zmm0,zmm30,0x01
+	vpclmulqdq	zmm2,zmm0,zmm30,0x10
+	vpclmulqdq	zmm3,zmm0,zmm30,0x11
+	vpxord	zmm4,zmm4,zmm7
+	vpternlogd	zmm5,zmm1,zmm2,0x96
+	vpxord	zmm6,zmm6,zmm3
+
+	vpxor	xmm10,xmm10,xmm10
+
+	add	rsi,64
+	add	rcx,64
+	add	rdx,64
+	sub	r8,64
+	cmp	r8,64
+	jae	NEAR $L$crypt_loop_1x__func2
+
+	test	r8,r8
+	jz	NEAR $L$reduce__func2
+
+$L$partial_vec__func2:
+
+
+
+
+	mov	rax,-1
+	bzhi	rax,rax,r8
+	kmovq	k1,rax
+	add	r8,15
+	and	r8,-16
+	mov	rax,-1
+	bzhi	rax,rax,r8
+	kmovq	k2,rax
+
+
+
+	vpshufb	zmm0,zmm12,zmm8
+	vpxord	zmm0,zmm0,zmm13
+	lea	rax,[16+r9]
+$L$vaesenc_loop_tail_partialvec__func2:
+	vbroadcasti32x4	zmm9,ZMMWORD[rax]
+	vaesenc	zmm0,zmm0,zmm9
+	add	rax,16
+	cmp	r11,rax
+	jne	NEAR $L$vaesenc_loop_tail_partialvec__func2
+	vaesenclast	zmm0,zmm0,zmm14
+
+
+	vmovdqu8	zmm1{k1}{z},[rcx]
+	vpxord	zmm0,zmm0,zmm1
+	vmovdqu8	ZMMWORD[rdx]{k1},zmm0
+
+
+
+
+
+
+
+
+
+
+
+
+
+	vmovdqu8	zmm30{k2}{z},[rsi]
+
+	vpshufb	zmm0,zmm1,zmm8
+	vpxord	zmm0,zmm0,zmm10
+	vpclmulqdq	zmm7,zmm0,zmm30,0x00
+	vpclmulqdq	zmm1,zmm0,zmm30,0x01
+	vpclmulqdq	zmm2,zmm0,zmm30,0x10
+	vpclmulqdq	zmm3,zmm0,zmm30,0x11
+	vpxord	zmm4,zmm4,zmm7
+	vpternlogd	zmm5,zmm1,zmm2,0x96
+	vpxord	zmm6,zmm6,zmm3
+
+
+$L$reduce__func2:
+
+	vpclmulqdq	zmm0,zmm31,zmm4,0x01
+	vpshufd	zmm4,zmm4,0x4e
+	vpternlogd	zmm5,zmm4,zmm0,0x96
+	vpclmulqdq	zmm0,zmm31,zmm5,0x01
+	vpshufd	zmm5,zmm5,0x4e
+	vpternlogd	zmm6,zmm5,zmm0,0x96
+
+	vextracti32x4	xmm0,zmm6,1
+	vextracti32x4	xmm1,zmm6,2
+	vextracti32x4	xmm2,zmm6,3
+	vpxord	xmm10,xmm6,xmm0
+	vpternlogd	xmm10,xmm2,xmm1,0x96
+
+
+$L$done__func2:
+
+	vpshufb	xmm10,xmm10,xmm8
+	vmovdqu	XMMWORD[r12],xmm10
+
+	vzeroupper
+	vmovdqa	xmm6,XMMWORD[rsp]
+	vmovdqa	xmm7,XMMWORD[16+rsp]
+	vmovdqa	xmm8,XMMWORD[32+rsp]
+	vmovdqa	xmm9,XMMWORD[48+rsp]
+	vmovdqa	xmm10,XMMWORD[64+rsp]
+	vmovdqa	xmm11,XMMWORD[80+rsp]
+	vmovdqa	xmm12,XMMWORD[96+rsp]
+	vmovdqa	xmm13,XMMWORD[112+rsp]
+	vmovdqa	xmm14,XMMWORD[128+rsp]
+	vmovdqa	xmm15,XMMWORD[144+rsp]
+	add	rsp,160
+	pop	r12
+	pop	rdi
+	pop	rsi
+	ret
+$L$SEH_end_aes_gcm_dec_update_vaes_avx512_17:
+
+
+section	.pdata rdata align=4
+ALIGN	4
+	DD	$L$SEH_begin_gcm_gmult_vpclmulqdq_avx512_1 wrt ..imagebase
+	DD	$L$SEH_end_gcm_gmult_vpclmulqdq_avx512_5 wrt ..imagebase
+	DD	$L$SEH_info_gcm_gmult_vpclmulqdq_avx512_0 wrt ..imagebase
+
+	DD	$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1 wrt ..imagebase
+	DD	$L$SEH_end_gcm_ghash_vpclmulqdq_avx512_12 wrt ..imagebase
+	DD	$L$SEH_info_gcm_ghash_vpclmulqdq_avx512_0 wrt ..imagebase
+
+	DD	$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1 wrt ..imagebase
+	DD	$L$SEH_end_aes_gcm_enc_update_vaes_avx512_17 wrt ..imagebase
+	DD	$L$SEH_info_aes_gcm_enc_update_vaes_avx512_0 wrt ..imagebase
+
+	DD	$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1 wrt ..imagebase
+	DD	$L$SEH_end_aes_gcm_dec_update_vaes_avx512_17 wrt ..imagebase
+	DD	$L$SEH_info_aes_gcm_dec_update_vaes_avx512_0 wrt ..imagebase
+
+
+section	.xdata rdata align=8
+ALIGN	4
+$L$SEH_info_gcm_gmult_vpclmulqdq_avx512_0:
+	DB	1
+	DB	$L$SEH_endprologue_gcm_gmult_vpclmulqdq_avx512_4-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx512_1
+	DB	3
+	DB	0
+	DB	$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx512_3-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx512_1
+	DB	104
+	DW	0
+	DB	$L$SEH_prologue_gcm_gmult_vpclmulqdq_avx512_2-$L$SEH_begin_gcm_gmult_vpclmulqdq_avx512_1
+	DB	34
+
+	DW	0
+$L$SEH_info_gcm_ghash_vpclmulqdq_avx512_0:
+	DB	1
+	DB	$L$SEH_endprologue_gcm_ghash_vpclmulqdq_avx512_11-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	18
+	DB	0
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_10-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	216
+	DW	7
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_9-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	200
+	DW	6
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_8-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	184
+	DW	5
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_7-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	168
+	DW	4
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_6-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	152
+	DW	3
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_5-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	136
+	DW	2
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_4-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	120
+	DW	1
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_3-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	104
+	DW	0
+	DB	$L$SEH_prologue_gcm_ghash_vpclmulqdq_avx512_2-$L$SEH_begin_gcm_ghash_vpclmulqdq_avx512_1
+	DB	1
+	DW	17
+
+$L$SEH_info_aes_gcm_enc_update_vaes_avx512_0:
+	DB	1
+	DB	$L$SEH_endprologue_aes_gcm_enc_update_vaes_avx512_16-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	25
+	DB	0
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_15-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	248
+	DW	9
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_14-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	232
+	DW	8
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_13-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	216
+	DW	7
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_12-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	200
+	DW	6
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_11-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	184
+	DW	5
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_10-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	168
+	DW	4
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_9-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	152
+	DW	3
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_8-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	136
+	DW	2
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_7-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	120
+	DW	1
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_6-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	104
+	DW	0
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_5-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	1
+	DW	20
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_4-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	192
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_3-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	112
+	DB	$L$SEH_prologue_aes_gcm_enc_update_vaes_avx512_2-$L$SEH_begin_aes_gcm_enc_update_vaes_avx512_1
+	DB	96
+
+	DW	0
+$L$SEH_info_aes_gcm_dec_update_vaes_avx512_0:
+	DB	1
+	DB	$L$SEH_endprologue_aes_gcm_dec_update_vaes_avx512_16-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	25
+	DB	0
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_15-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	248
+	DW	9
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_14-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	232
+	DW	8
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_13-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	216
+	DW	7
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_12-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	200
+	DW	6
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_11-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	184
+	DW	5
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_10-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	168
+	DW	4
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_9-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	152
+	DW	3
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_8-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	136
+	DW	2
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_7-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	120
+	DW	1
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_6-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	104
+	DW	0
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_5-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	1
+	DW	20
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_4-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	192
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_3-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	112
+	DB	$L$SEH_prologue_aes_gcm_dec_update_vaes_avx512_2-$L$SEH_begin_aes_gcm_dec_update_vaes_avx512_1
+	DB	96
+
+	DW	0
+%else
+; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738
+ret
+%endif
diff --git a/src/gen/bcm/aesni-x86_64-apple.S b/src/gen/bcm/aesni-x86_64-apple.S
index 0247a2d..958cc5a 100644
--- a/src/gen/bcm/aesni-x86_64-apple.S
+++ b/src/gen/bcm/aesni-x86_64-apple.S
@@ -23,12 +23,12 @@
 	leaq	32(%rdx),%rdx
 	xorps	%xmm0,%xmm2
 L$oop_enc1_1:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rdx),%xmm1
 	leaq	16(%rdx),%rdx
 	jnz	L$oop_enc1_1
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm2,(%rsi)
@@ -51,12 +51,12 @@
 	leaq	32(%rdx),%rdx
 	xorps	%xmm0,%xmm2
 L$oop_dec1_2:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rdx),%xmm1
 	leaq	16(%rdx),%rdx
 	jnz	L$oop_dec1_2
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm2,(%rsi)
@@ -79,19 +79,19 @@
 	addq	$16,%rax
 
 L$enc_loop2:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$enc_loop2
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
 	ret
 
 
@@ -110,19 +110,19 @@
 	addq	$16,%rax
 
 L$dec_loop2:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$dec_loop2
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
 	ret
 
 
@@ -142,23 +142,23 @@
 	addq	$16,%rax
 
 L$enc_loop3:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$enc_loop3
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
 	ret
 
 
@@ -178,23 +178,23 @@
 	addq	$16,%rax
 
 L$dec_loop3:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$dec_loop3
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
 	ret
 
 
@@ -216,27 +216,27 @@
 	addq	$16,%rax
 
 L$enc_loop4:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$enc_loop4
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
 	ret
 
 
@@ -258,27 +258,27 @@
 	addq	$16,%rax
 
 L$dec_loop4:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$dec_loop4
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
 	ret
 
 
@@ -292,49 +292,49 @@
 	xorps	%xmm0,%xmm2
 	pxor	%xmm0,%xmm3
 	pxor	%xmm0,%xmm4
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	pxor	%xmm0,%xmm7
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	L$enc_loop6_enter
 .p2align	4
 L$enc_loop6:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 L$enc_loop6_enter:
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$enc_loop6
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
-.byte	102,15,56,221,240
-.byte	102,15,56,221,248
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
 	ret
 
 
@@ -348,49 +348,49 @@
 	xorps	%xmm0,%xmm2
 	pxor	%xmm0,%xmm3
 	pxor	%xmm0,%xmm4
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm4
 	pxor	%xmm0,%xmm7
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	L$dec_loop6_enter
 .p2align	4
 L$dec_loop6:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
 L$dec_loop6_enter:
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$dec_loop6
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
-.byte	102,15,56,223,240
-.byte	102,15,56,223,248
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
 	ret
 
 
@@ -408,55 +408,55 @@
 	pxor	%xmm0,%xmm6
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	pxor	%xmm0,%xmm9
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	L$enc_loop8_inner
 .p2align	4
 L$enc_loop8:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 L$enc_loop8_inner:
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 L$enc_loop8_enter:
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$enc_loop8
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
-.byte	102,15,56,221,240
-.byte	102,15,56,221,248
-.byte	102,68,15,56,221,192
-.byte	102,68,15,56,221,200
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	aesenclast	%xmm0,%xmm8
+	aesenclast	%xmm0,%xmm9
 	ret
 
 
@@ -474,55 +474,55 @@
 	pxor	%xmm0,%xmm6
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm9
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	L$dec_loop8_inner
 .p2align	4
 L$dec_loop8:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 L$dec_loop8_inner:
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 L$dec_loop8_enter:
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	L$dec_loop8
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
-.byte	102,15,56,223,240
-.byte	102,15,56,223,248
-.byte	102,68,15,56,223,192
-.byte	102,68,15,56,223,200
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	aesdeclast	%xmm0,%xmm8
+	aesdeclast	%xmm0,%xmm9
 	ret
 
 
@@ -634,12 +634,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 L$oop_enc1_3:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_enc1_3
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	movups	%xmm2,(%rsi)
 	jmp	L$ecb_ret
 .p2align	4
@@ -795,12 +795,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 L$oop_dec1_4:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_dec1_4
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	movups	%xmm2,(%rsi)
 	pxor	%xmm2,%xmm2
 	jmp	L$ecb_ret
@@ -895,12 +895,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 L$oop_enc1_5:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%edx
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_enc1_5
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	xorps	%xmm3,%xmm2
@@ -943,17 +943,17 @@
 	bswapl	%edx
 	xorl	%ebp,%eax
 	xorl	%ebp,%edx
-.byte	102,15,58,34,216,3
+	pinsrd	$3,%eax,%xmm3
 	leaq	3(%r8),%rax
 	movdqa	%xmm3,16(%rsp)
-.byte	102,15,58,34,226,3
+	pinsrd	$3,%edx,%xmm4
 	bswapl	%eax
 	movq	%r10,%rdx
 	leaq	4(%r8),%r10
 	movdqa	%xmm4,32(%rsp)
 	xorl	%ebp,%eax
 	bswapl	%r10d
-.byte	102,15,58,34,232,3
+	pinsrd	$3,%eax,%xmm5
 	xorl	%ebp,%r10d
 	movdqa	%xmm5,48(%rsp)
 	leaq	5(%r8),%r9
@@ -987,163 +987,163 @@
 L$ctr32_loop8:
 	addl	$8,%r8d
 	movdqa	96(%rsp),%xmm8
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	movl	%r8d,%r9d
 	movdqa	112(%rsp),%xmm9
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	bswapl	%r9d
 	movups	32-128(%rcx),%xmm0
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	xorl	%ebp,%r9d
 	nop
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,0+12(%rsp)
 	leaq	1(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	48-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,16+12(%rsp)
 	leaq	2(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	64-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,32+12(%rsp)
 	leaq	3(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	80-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,48+12(%rsp)
 	leaq	4(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	96-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,64+12(%rsp)
 	leaq	5(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	112-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,80+12(%rsp)
 	leaq	6(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	128-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,96+12(%rsp)
 	leaq	7(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	144-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
 	xorl	%ebp,%r9d
 	movdqu	0(%rdi),%xmm10
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,112+12(%rsp)
 	cmpl	$11,%eax
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	160-128(%rcx),%xmm0
 
 	jb	L$ctr32_enc_done
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	176-128(%rcx),%xmm1
 
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	192-128(%rcx),%xmm0
 	je	L$ctr32_enc_done
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	208-128(%rcx),%xmm1
 
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	224-128(%rcx),%xmm0
 	jmp	L$ctr32_enc_done
 
@@ -1162,35 +1162,35 @@
 	prefetcht0	448(%rdi)
 	prefetcht0	512(%rdi)
 	pxor	%xmm0,%xmm15
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movdqu	96(%rdi),%xmm1
 	leaq	128(%rdi),%rdi
 
-.byte	102,65,15,56,221,210
+	aesenclast	%xmm10,%xmm2
 	pxor	%xmm0,%xmm1
 	movdqu	112-128(%rdi),%xmm10
-.byte	102,65,15,56,221,219
+	aesenclast	%xmm11,%xmm3
 	pxor	%xmm0,%xmm10
 	movdqa	0(%rsp),%xmm11
-.byte	102,65,15,56,221,228
-.byte	102,65,15,56,221,237
+	aesenclast	%xmm12,%xmm4
+	aesenclast	%xmm13,%xmm5
 	movdqa	16(%rsp),%xmm12
 	movdqa	32(%rsp),%xmm13
-.byte	102,65,15,56,221,246
-.byte	102,65,15,56,221,255
+	aesenclast	%xmm14,%xmm6
+	aesenclast	%xmm15,%xmm7
 	movdqa	48(%rsp),%xmm14
 	movdqa	64(%rsp),%xmm15
-.byte	102,68,15,56,221,193
+	aesenclast	%xmm1,%xmm8
 	movdqa	80(%rsp),%xmm0
 	movups	16-128(%rcx),%xmm1
-.byte	102,69,15,56,221,202
+	aesenclast	%xmm10,%xmm9
 
 	movups	%xmm2,(%rsi)
 	movdqa	%xmm11,%xmm2
@@ -1229,19 +1229,19 @@
 	pxor	%xmm9,%xmm9
 
 	movups	16(%rcx),%xmm0
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	leaq	32-16(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	addq	$16,%rax
 	movups	(%rdi),%xmm10
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
 	movups	16(%rdi),%xmm11
 	movups	32(%rdi),%xmm12
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
 
 	call	L$enc_loop8_enter
 
@@ -1272,20 +1272,20 @@
 
 .p2align	5
 L$ctr32_loop4:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	16(%rcx),%rcx
 	decl	%eax
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movups	(%rcx),%xmm1
 	jnz	L$ctr32_loop4
-.byte	102,15,56,221,209
-.byte	102,15,56,221,217
+	aesenclast	%xmm1,%xmm2
+	aesenclast	%xmm1,%xmm3
 	movups	(%rdi),%xmm10
 	movups	16(%rdi),%xmm11
-.byte	102,15,56,221,225
-.byte	102,15,56,221,233
+	aesenclast	%xmm1,%xmm4
+	aesenclast	%xmm1,%xmm5
 	movups	32(%rdi),%xmm12
 	movups	48(%rdi),%xmm13
 
@@ -1301,16 +1301,16 @@
 
 .p2align	5
 L$ctr32_loop3:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	16(%rcx),%rcx
 	decl	%eax
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 	movups	(%rcx),%xmm1
 	jnz	L$ctr32_loop3
-.byte	102,15,56,221,209
-.byte	102,15,56,221,217
-.byte	102,15,56,221,225
+	aesenclast	%xmm1,%xmm2
+	aesenclast	%xmm1,%xmm3
+	aesenclast	%xmm1,%xmm4
 
 	movups	(%rdi),%xmm10
 	xorps	%xmm10,%xmm2
@@ -1393,12 +1393,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm3,%xmm2
 L$oop_enc1_6:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_enc1_6
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	movl	%r10d,%eax
 	movq	%r11,%rcx
 	movups	%xmm2,0(%rsi)
@@ -1444,12 +1444,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 L$oop_dec1_7:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%r10d
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_dec1_7
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movdqu	%xmm4,(%r8)
@@ -1508,166 +1508,166 @@
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
 
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	pxor	%xmm0,%xmm9
 	movups	32-112(%rcx),%xmm0
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
 	adcq	$0,%rbp
 	andq	$128,%rbp
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm9
 	addq	%rdi,%rbp
 	movups	48-112(%rcx),%xmm1
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	64-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	80-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	96-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	112-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	128-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	144-112(%rcx),%xmm1
 	cmpl	$11,%eax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	160-112(%rcx),%xmm0
 	jb	L$cbc_dec_done
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	176-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	192-112(%rcx),%xmm0
 	je	L$cbc_dec_done
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	208-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	224-112(%rcx),%xmm0
 	jmp	L$cbc_dec_done
 .p2align	4
 L$cbc_dec_done:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm10
 	pxor	%xmm0,%xmm11
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
 	pxor	%xmm0,%xmm12
 	pxor	%xmm0,%xmm13
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
 	pxor	%xmm0,%xmm14
 	pxor	%xmm0,%xmm15
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movdqu	80(%rdi),%xmm1
 
-.byte	102,65,15,56,223,210
+	aesdeclast	%xmm10,%xmm2
 	movdqu	96(%rdi),%xmm10
 	pxor	%xmm0,%xmm1
-.byte	102,65,15,56,223,219
+	aesdeclast	%xmm11,%xmm3
 	pxor	%xmm0,%xmm10
 	movdqu	112(%rdi),%xmm0
-.byte	102,65,15,56,223,228
+	aesdeclast	%xmm12,%xmm4
 	leaq	128(%rdi),%rdi
 	movdqu	0(%rbp),%xmm11
-.byte	102,65,15,56,223,237
-.byte	102,65,15,56,223,246
+	aesdeclast	%xmm13,%xmm5
+	aesdeclast	%xmm14,%xmm6
 	movdqu	16(%rbp),%xmm12
 	movdqu	32(%rbp),%xmm13
-.byte	102,65,15,56,223,255
-.byte	102,68,15,56,223,193
+	aesdeclast	%xmm15,%xmm7
+	aesdeclast	%xmm1,%xmm8
 	movdqu	48(%rbp),%xmm14
 	movdqu	64(%rbp),%xmm15
-.byte	102,69,15,56,223,202
+	aesdeclast	%xmm10,%xmm9
 	movdqa	%xmm0,%xmm10
 	movdqu	80(%rbp),%xmm1
 	movups	-112(%rcx),%xmm0
@@ -1811,12 +1811,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 L$oop_dec1_8:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	L$oop_dec1_8
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	xorps	%xmm10,%xmm2
 	movaps	%xmm11,%xmm10
 	jmp	L$cbc_dec_tail_collected
@@ -1927,8 +1927,8 @@
 L$dec_key_inverse:
 	movups	(%rdi),%xmm0
 	movups	(%rdx),%xmm1
-.byte	102,15,56,219,192
-.byte	102,15,56,219,201
+	aesimc	%xmm0,%xmm0
+	aesimc	%xmm1,%xmm1
 	leaq	16(%rdi),%rdi
 	leaq	-16(%rdx),%rdx
 	movups	%xmm0,16(%rdx)
@@ -1937,7 +1937,7 @@
 	ja	L$dec_key_inverse
 
 	movups	(%rdi),%xmm0
-.byte	102,15,56,219,192
+	aesimc	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm0,(%rdx)
 	pxor	%xmm0,%xmm0
@@ -1973,25 +1973,25 @@
 	movl	$9,%esi
 
 	movups	%xmm0,(%rdx)
-.byte	102,15,58,223,200,1
+	aeskeygenassist	$0x1,%xmm0,%xmm1
 	call	L$key_expansion_128_cold
-.byte	102,15,58,223,200,2
+	aeskeygenassist	$0x2,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,4
+	aeskeygenassist	$0x4,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,8
+	aeskeygenassist	$0x8,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,16
+	aeskeygenassist	$0x10,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,32
+	aeskeygenassist	$0x20,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,64
+	aeskeygenassist	$0x40,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,128
+	aeskeygenassist	$0x80,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,27
+	aeskeygenassist	$0x1b,%xmm0,%xmm1
 	call	L$key_expansion_128
-.byte	102,15,58,223,200,54
+	aeskeygenassist	$0x36,%xmm0,%xmm1
 	call	L$key_expansion_128
 	movups	%xmm0,(%rax)
 	movl	%esi,80(%rax)
@@ -2004,21 +2004,21 @@
 	movl	$11,%esi
 
 	movups	%xmm0,(%rdx)
-.byte	102,15,58,223,202,1
+	aeskeygenassist	$0x1,%xmm2,%xmm1
 	call	L$key_expansion_192a_cold
-.byte	102,15,58,223,202,2
+	aeskeygenassist	$0x2,%xmm2,%xmm1
 	call	L$key_expansion_192b
-.byte	102,15,58,223,202,4
+	aeskeygenassist	$0x4,%xmm2,%xmm1
 	call	L$key_expansion_192a
-.byte	102,15,58,223,202,8
+	aeskeygenassist	$0x8,%xmm2,%xmm1
 	call	L$key_expansion_192b
-.byte	102,15,58,223,202,16
+	aeskeygenassist	$0x10,%xmm2,%xmm1
 	call	L$key_expansion_192a
-.byte	102,15,58,223,202,32
+	aeskeygenassist	$0x20,%xmm2,%xmm1
 	call	L$key_expansion_192b
-.byte	102,15,58,223,202,64
+	aeskeygenassist	$0x40,%xmm2,%xmm1
 	call	L$key_expansion_192a
-.byte	102,15,58,223,202,128
+	aeskeygenassist	$0x80,%xmm2,%xmm1
 	call	L$key_expansion_192b
 	movups	%xmm0,(%rax)
 	movl	%esi,48(%rax)
@@ -2033,31 +2033,31 @@
 
 	movups	%xmm0,(%rdx)
 	movups	%xmm2,16(%rdx)
-.byte	102,15,58,223,202,1
+	aeskeygenassist	$0x1,%xmm2,%xmm1
 	call	L$key_expansion_256a_cold
-.byte	102,15,58,223,200,1
+	aeskeygenassist	$0x1,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,2
+	aeskeygenassist	$0x2,%xmm2,%xmm1
 	call	L$key_expansion_256a
-.byte	102,15,58,223,200,2
+	aeskeygenassist	$0x2,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,4
+	aeskeygenassist	$0x4,%xmm2,%xmm1
 	call	L$key_expansion_256a
-.byte	102,15,58,223,200,4
+	aeskeygenassist	$0x4,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,8
+	aeskeygenassist	$0x8,%xmm2,%xmm1
 	call	L$key_expansion_256a
-.byte	102,15,58,223,200,8
+	aeskeygenassist	$0x8,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,16
+	aeskeygenassist	$0x10,%xmm2,%xmm1
 	call	L$key_expansion_256a
-.byte	102,15,58,223,200,16
+	aeskeygenassist	$0x10,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,32
+	aeskeygenassist	$0x20,%xmm2,%xmm1
 	call	L$key_expansion_256a
-.byte	102,15,58,223,200,32
+	aeskeygenassist	$0x20,%xmm0,%xmm1
 	call	L$key_expansion_256b
-.byte	102,15,58,223,202,64
+	aeskeygenassist	$0x40,%xmm2,%xmm1
 	call	L$key_expansion_256a
 	movups	%xmm0,(%rax)
 	movl	%esi,16(%rax)
@@ -2195,8 +2195,8 @@
 
 .p2align	4
 L$oop_key128:
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 	pslld	$1,%xmm4
 	leaq	16(%rax),%rax
 
@@ -2217,8 +2217,8 @@
 
 	movdqa	L$key_rcon1b(%rip),%xmm4
 
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 	pslld	$1,%xmm4
 
 	movdqa	%xmm2,%xmm3
@@ -2233,8 +2233,8 @@
 	movdqu	%xmm0,(%rax)
 
 	movdqa	%xmm0,%xmm2
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 
 	movdqa	%xmm2,%xmm3
 	pslldq	$4,%xmm2
@@ -2265,8 +2265,8 @@
 L$oop_key192:
 	movq	%xmm2,0(%rax)
 	movdqa	%xmm2,%xmm1
-.byte	102,15,56,0,213
-.byte	102,15,56,221,212
+	pshufb	%xmm5,%xmm2
+	aesenclast	%xmm4,%xmm2
 	pslld	$1,%xmm4
 	leaq	24(%rax),%rax
 
@@ -2309,8 +2309,8 @@
 
 .p2align	4
 L$oop_key256:
-.byte	102,15,56,0,213
-.byte	102,15,56,221,212
+	pshufb	%xmm5,%xmm2
+	aesenclast	%xmm4,%xmm2
 
 	movdqa	%xmm0,%xmm3
 	pslldq	$4,%xmm0
@@ -2329,7 +2329,7 @@
 
 	pshufd	$0xff,%xmm0,%xmm2
 	pxor	%xmm3,%xmm3
-.byte	102,15,56,221,211
+	aesenclast	%xmm3,%xmm2
 
 	movdqa	%xmm1,%xmm3
 	pslldq	$4,%xmm1
diff --git a/src/gen/bcm/aesni-x86_64-linux.S b/src/gen/bcm/aesni-x86_64-linux.S
index bedd98b..4bce582 100644
--- a/src/gen/bcm/aesni-x86_64-linux.S
+++ b/src/gen/bcm/aesni-x86_64-linux.S
@@ -24,12 +24,12 @@
 	leaq	32(%rdx),%rdx
 	xorps	%xmm0,%xmm2
 .Loop_enc1_1:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rdx),%xmm1
 	leaq	16(%rdx),%rdx
 	jnz	.Loop_enc1_1
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm2,(%rsi)
@@ -52,12 +52,12 @@
 	leaq	32(%rdx),%rdx
 	xorps	%xmm0,%xmm2
 .Loop_dec1_2:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rdx),%xmm1
 	leaq	16(%rdx),%rdx
 	jnz	.Loop_dec1_2
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm2,(%rsi)
@@ -80,19 +80,19 @@
 	addq	$16,%rax
 
 .Lenc_loop2:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Lenc_loop2
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
 	ret
 .cfi_endproc	
 .size	_aesni_encrypt2,.-_aesni_encrypt2
@@ -111,19 +111,19 @@
 	addq	$16,%rax
 
 .Ldec_loop2:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Ldec_loop2
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
 	ret
 .cfi_endproc	
 .size	_aesni_decrypt2,.-_aesni_decrypt2
@@ -143,23 +143,23 @@
 	addq	$16,%rax
 
 .Lenc_loop3:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Lenc_loop3
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
 	ret
 .cfi_endproc	
 .size	_aesni_encrypt3,.-_aesni_encrypt3
@@ -179,23 +179,23 @@
 	addq	$16,%rax
 
 .Ldec_loop3:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Ldec_loop3
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
 	ret
 .cfi_endproc	
 .size	_aesni_decrypt3,.-_aesni_decrypt3
@@ -217,27 +217,27 @@
 	addq	$16,%rax
 
 .Lenc_loop4:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Lenc_loop4
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
 	ret
 .cfi_endproc	
 .size	_aesni_encrypt4,.-_aesni_encrypt4
@@ -259,27 +259,27 @@
 	addq	$16,%rax
 
 .Ldec_loop4:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Ldec_loop4
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
 	ret
 .cfi_endproc	
 .size	_aesni_decrypt4,.-_aesni_decrypt4
@@ -293,49 +293,49 @@
 	xorps	%xmm0,%xmm2
 	pxor	%xmm0,%xmm3
 	pxor	%xmm0,%xmm4
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	pxor	%xmm0,%xmm7
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	.Lenc_loop6_enter
 .align	16
 .Lenc_loop6:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 .Lenc_loop6_enter:
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Lenc_loop6
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
-.byte	102,15,56,221,240
-.byte	102,15,56,221,248
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
 	ret
 .cfi_endproc	
 .size	_aesni_encrypt6,.-_aesni_encrypt6
@@ -349,49 +349,49 @@
 	xorps	%xmm0,%xmm2
 	pxor	%xmm0,%xmm3
 	pxor	%xmm0,%xmm4
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm4
 	pxor	%xmm0,%xmm7
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	.Ldec_loop6_enter
 .align	16
 .Ldec_loop6:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
 .Ldec_loop6_enter:
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Ldec_loop6
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
-.byte	102,15,56,223,240
-.byte	102,15,56,223,248
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
 	ret
 .cfi_endproc	
 .size	_aesni_decrypt6,.-_aesni_decrypt6
@@ -409,55 +409,55 @@
 	pxor	%xmm0,%xmm6
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	pxor	%xmm0,%xmm9
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	.Lenc_loop8_inner
 .align	16
 .Lenc_loop8:
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 .Lenc_loop8_inner:
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 .Lenc_loop8_enter:
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Lenc_loop8
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
-.byte	102,15,56,221,208
-.byte	102,15,56,221,216
-.byte	102,15,56,221,224
-.byte	102,15,56,221,232
-.byte	102,15,56,221,240
-.byte	102,15,56,221,248
-.byte	102,68,15,56,221,192
-.byte	102,68,15,56,221,200
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	aesenclast	%xmm0,%xmm8
+	aesenclast	%xmm0,%xmm9
 	ret
 .cfi_endproc	
 .size	_aesni_encrypt8,.-_aesni_encrypt8
@@ -475,55 +475,55 @@
 	pxor	%xmm0,%xmm6
 	leaq	32(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm9
 	movups	(%rcx,%rax,1),%xmm0
 	addq	$16,%rax
 	jmp	.Ldec_loop8_inner
 .align	16
 .Ldec_loop8:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 .Ldec_loop8_inner:
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 .Ldec_loop8_enter:
 	movups	(%rcx,%rax,1),%xmm1
 	addq	$32,%rax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	-16(%rcx,%rax,1),%xmm0
 	jnz	.Ldec_loop8
 
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
-.byte	102,15,56,223,208
-.byte	102,15,56,223,216
-.byte	102,15,56,223,224
-.byte	102,15,56,223,232
-.byte	102,15,56,223,240
-.byte	102,15,56,223,248
-.byte	102,68,15,56,223,192
-.byte	102,68,15,56,223,200
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	aesdeclast	%xmm0,%xmm8
+	aesdeclast	%xmm0,%xmm9
 	ret
 .cfi_endproc	
 .size	_aesni_decrypt8,.-_aesni_decrypt8
@@ -635,12 +635,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 .Loop_enc1_3:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_enc1_3
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	movups	%xmm2,(%rsi)
 	jmp	.Lecb_ret
 .align	16
@@ -796,12 +796,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 .Loop_dec1_4:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_dec1_4
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	movups	%xmm2,(%rsi)
 	pxor	%xmm2,%xmm2
 	jmp	.Lecb_ret
@@ -896,12 +896,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 .Loop_enc1_5:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%edx
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_enc1_5
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	xorps	%xmm3,%xmm2
@@ -944,17 +944,17 @@
 	bswapl	%edx
 	xorl	%ebp,%eax
 	xorl	%ebp,%edx
-.byte	102,15,58,34,216,3
+	pinsrd	$3,%eax,%xmm3
 	leaq	3(%r8),%rax
 	movdqa	%xmm3,16(%rsp)
-.byte	102,15,58,34,226,3
+	pinsrd	$3,%edx,%xmm4
 	bswapl	%eax
 	movq	%r10,%rdx
 	leaq	4(%r8),%r10
 	movdqa	%xmm4,32(%rsp)
 	xorl	%ebp,%eax
 	bswapl	%r10d
-.byte	102,15,58,34,232,3
+	pinsrd	$3,%eax,%xmm5
 	xorl	%ebp,%r10d
 	movdqa	%xmm5,48(%rsp)
 	leaq	5(%r8),%r9
@@ -988,163 +988,163 @@
 .Lctr32_loop8:
 	addl	$8,%r8d
 	movdqa	96(%rsp),%xmm8
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	movl	%r8d,%r9d
 	movdqa	112(%rsp),%xmm9
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm3
 	bswapl	%r9d
 	movups	32-128(%rcx),%xmm0
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	xorl	%ebp,%r9d
 	nop
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,0+12(%rsp)
 	leaq	1(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	48-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,16+12(%rsp)
 	leaq	2(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	64-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,32+12(%rsp)
 	leaq	3(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	80-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,48+12(%rsp)
 	leaq	4(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	96-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,64+12(%rsp)
 	leaq	5(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	112-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,80+12(%rsp)
 	leaq	6(%r8),%r9
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	128-128(%rcx),%xmm0
 	bswapl	%r9d
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	xorl	%ebp,%r9d
 .byte	0x66,0x90
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movl	%r9d,96+12(%rsp)
 	leaq	7(%r8),%r9
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	144-128(%rcx),%xmm1
 	bswapl	%r9d
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
 	xorl	%ebp,%r9d
 	movdqu	0(%rdi),%xmm10
-.byte	102,15,56,220,232
+	aesenc	%xmm0,%xmm5
 	movl	%r9d,112+12(%rsp)
 	cmpl	$11,%eax
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	160-128(%rcx),%xmm0
 
 	jb	.Lctr32_enc_done
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	176-128(%rcx),%xmm1
 
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	192-128(%rcx),%xmm0
 	je	.Lctr32_enc_done
 
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movups	208-128(%rcx),%xmm1
 
-.byte	102,15,56,220,208
-.byte	102,15,56,220,216
-.byte	102,15,56,220,224
-.byte	102,15,56,220,232
-.byte	102,15,56,220,240
-.byte	102,15,56,220,248
-.byte	102,68,15,56,220,192
-.byte	102,68,15,56,220,200
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
 	movups	224-128(%rcx),%xmm0
 	jmp	.Lctr32_enc_done
 
@@ -1163,35 +1163,35 @@
 	prefetcht0	448(%rdi)
 	prefetcht0	512(%rdi)
 	pxor	%xmm0,%xmm15
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
-.byte	102,68,15,56,220,201
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
 	movdqu	96(%rdi),%xmm1
 	leaq	128(%rdi),%rdi
 
-.byte	102,65,15,56,221,210
+	aesenclast	%xmm10,%xmm2
 	pxor	%xmm0,%xmm1
 	movdqu	112-128(%rdi),%xmm10
-.byte	102,65,15,56,221,219
+	aesenclast	%xmm11,%xmm3
 	pxor	%xmm0,%xmm10
 	movdqa	0(%rsp),%xmm11
-.byte	102,65,15,56,221,228
-.byte	102,65,15,56,221,237
+	aesenclast	%xmm12,%xmm4
+	aesenclast	%xmm13,%xmm5
 	movdqa	16(%rsp),%xmm12
 	movdqa	32(%rsp),%xmm13
-.byte	102,65,15,56,221,246
-.byte	102,65,15,56,221,255
+	aesenclast	%xmm14,%xmm6
+	aesenclast	%xmm15,%xmm7
 	movdqa	48(%rsp),%xmm14
 	movdqa	64(%rsp),%xmm15
-.byte	102,68,15,56,221,193
+	aesenclast	%xmm1,%xmm8
 	movdqa	80(%rsp),%xmm0
 	movups	16-128(%rcx),%xmm1
-.byte	102,69,15,56,221,202
+	aesenclast	%xmm10,%xmm9
 
 	movups	%xmm2,(%rsi)
 	movdqa	%xmm11,%xmm2
@@ -1230,19 +1230,19 @@
 	pxor	%xmm9,%xmm9
 
 	movups	16(%rcx),%xmm0
-.byte	102,15,56,220,209
-.byte	102,15,56,220,217
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
 	leaq	32-16(%rcx,%rax,1),%rcx
 	negq	%rax
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm4
 	addq	$16,%rax
 	movups	(%rdi),%xmm10
-.byte	102,15,56,220,233
-.byte	102,15,56,220,241
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
 	movups	16(%rdi),%xmm11
 	movups	32(%rdi),%xmm12
-.byte	102,15,56,220,249
-.byte	102,68,15,56,220,193
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
 
 	call	.Lenc_loop8_enter
 
@@ -1273,20 +1273,20 @@
 
 .align	32
 .Lctr32_loop4:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	16(%rcx),%rcx
 	decl	%eax
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
-.byte	102,15,56,220,233
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
 	movups	(%rcx),%xmm1
 	jnz	.Lctr32_loop4
-.byte	102,15,56,221,209
-.byte	102,15,56,221,217
+	aesenclast	%xmm1,%xmm2
+	aesenclast	%xmm1,%xmm3
 	movups	(%rdi),%xmm10
 	movups	16(%rdi),%xmm11
-.byte	102,15,56,221,225
-.byte	102,15,56,221,233
+	aesenclast	%xmm1,%xmm4
+	aesenclast	%xmm1,%xmm5
 	movups	32(%rdi),%xmm12
 	movups	48(%rdi),%xmm13
 
@@ -1302,16 +1302,16 @@
 
 .align	32
 .Lctr32_loop3:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	leaq	16(%rcx),%rcx
 	decl	%eax
-.byte	102,15,56,220,217
-.byte	102,15,56,220,225
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
 	movups	(%rcx),%xmm1
 	jnz	.Lctr32_loop3
-.byte	102,15,56,221,209
-.byte	102,15,56,221,217
-.byte	102,15,56,221,225
+	aesenclast	%xmm1,%xmm2
+	aesenclast	%xmm1,%xmm3
+	aesenclast	%xmm1,%xmm4
 
 	movups	(%rdi),%xmm10
 	xorps	%xmm10,%xmm2
@@ -1394,12 +1394,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm3,%xmm2
 .Loop_enc1_6:
-.byte	102,15,56,220,209
+	aesenc	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_enc1_6
-.byte	102,15,56,221,209
+	aesenclast	%xmm1,%xmm2
 	movl	%r10d,%eax
 	movq	%r11,%rcx
 	movups	%xmm2,0(%rsi)
@@ -1445,12 +1445,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 .Loop_dec1_7:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%r10d
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_dec1_7
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	pxor	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movdqu	%xmm4,(%r8)
@@ -1509,166 +1509,166 @@
 	pxor	%xmm0,%xmm7
 	pxor	%xmm0,%xmm8
 
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	pxor	%xmm0,%xmm9
 	movups	32-112(%rcx),%xmm0
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
 	adcq	$0,%rbp
 	andq	$128,%rbp
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm9
 	addq	%rdi,%rbp
 	movups	48-112(%rcx),%xmm1
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	64-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	80-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	96-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	112-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	128-112(%rcx),%xmm0
 	nop
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	144-112(%rcx),%xmm1
 	cmpl	$11,%eax
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	160-112(%rcx),%xmm0
 	jb	.Lcbc_dec_done
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	176-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	192-112(%rcx),%xmm0
 	je	.Lcbc_dec_done
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movups	208-112(%rcx),%xmm1
 	nop
-.byte	102,15,56,222,208
-.byte	102,15,56,222,216
-.byte	102,15,56,222,224
-.byte	102,15,56,222,232
-.byte	102,15,56,222,240
-.byte	102,15,56,222,248
-.byte	102,68,15,56,222,192
-.byte	102,68,15,56,222,200
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
 	movups	224-112(%rcx),%xmm0
 	jmp	.Lcbc_dec_done
 .align	16
 .Lcbc_dec_done:
-.byte	102,15,56,222,209
-.byte	102,15,56,222,217
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
 	pxor	%xmm0,%xmm10
 	pxor	%xmm0,%xmm11
-.byte	102,15,56,222,225
-.byte	102,15,56,222,233
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
 	pxor	%xmm0,%xmm12
 	pxor	%xmm0,%xmm13
-.byte	102,15,56,222,241
-.byte	102,15,56,222,249
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
 	pxor	%xmm0,%xmm14
 	pxor	%xmm0,%xmm15
-.byte	102,68,15,56,222,193
-.byte	102,68,15,56,222,201
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
 	movdqu	80(%rdi),%xmm1
 
-.byte	102,65,15,56,223,210
+	aesdeclast	%xmm10,%xmm2
 	movdqu	96(%rdi),%xmm10
 	pxor	%xmm0,%xmm1
-.byte	102,65,15,56,223,219
+	aesdeclast	%xmm11,%xmm3
 	pxor	%xmm0,%xmm10
 	movdqu	112(%rdi),%xmm0
-.byte	102,65,15,56,223,228
+	aesdeclast	%xmm12,%xmm4
 	leaq	128(%rdi),%rdi
 	movdqu	0(%rbp),%xmm11
-.byte	102,65,15,56,223,237
-.byte	102,65,15,56,223,246
+	aesdeclast	%xmm13,%xmm5
+	aesdeclast	%xmm14,%xmm6
 	movdqu	16(%rbp),%xmm12
 	movdqu	32(%rbp),%xmm13
-.byte	102,65,15,56,223,255
-.byte	102,68,15,56,223,193
+	aesdeclast	%xmm15,%xmm7
+	aesdeclast	%xmm1,%xmm8
 	movdqu	48(%rbp),%xmm14
 	movdqu	64(%rbp),%xmm15
-.byte	102,69,15,56,223,202
+	aesdeclast	%xmm10,%xmm9
 	movdqa	%xmm0,%xmm10
 	movdqu	80(%rbp),%xmm1
 	movups	-112(%rcx),%xmm0
@@ -1812,12 +1812,12 @@
 	leaq	32(%rcx),%rcx
 	xorps	%xmm0,%xmm2
 .Loop_dec1_8:
-.byte	102,15,56,222,209
+	aesdec	%xmm1,%xmm2
 	decl	%eax
 	movups	(%rcx),%xmm1
 	leaq	16(%rcx),%rcx
 	jnz	.Loop_dec1_8
-.byte	102,15,56,223,209
+	aesdeclast	%xmm1,%xmm2
 	xorps	%xmm10,%xmm2
 	movaps	%xmm11,%xmm10
 	jmp	.Lcbc_dec_tail_collected
@@ -1928,8 +1928,8 @@
 .Ldec_key_inverse:
 	movups	(%rdi),%xmm0
 	movups	(%rdx),%xmm1
-.byte	102,15,56,219,192
-.byte	102,15,56,219,201
+	aesimc	%xmm0,%xmm0
+	aesimc	%xmm1,%xmm1
 	leaq	16(%rdi),%rdi
 	leaq	-16(%rdx),%rdx
 	movups	%xmm0,16(%rdx)
@@ -1938,7 +1938,7 @@
 	ja	.Ldec_key_inverse
 
 	movups	(%rdi),%xmm0
-.byte	102,15,56,219,192
+	aesimc	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
 	movups	%xmm0,(%rdx)
 	pxor	%xmm0,%xmm0
@@ -1974,25 +1974,25 @@
 	movl	$9,%esi
 
 	movups	%xmm0,(%rdx)
-.byte	102,15,58,223,200,1
+	aeskeygenassist	$0x1,%xmm0,%xmm1
 	call	.Lkey_expansion_128_cold
-.byte	102,15,58,223,200,2
+	aeskeygenassist	$0x2,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,4
+	aeskeygenassist	$0x4,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,8
+	aeskeygenassist	$0x8,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,16
+	aeskeygenassist	$0x10,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,32
+	aeskeygenassist	$0x20,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,64
+	aeskeygenassist	$0x40,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,128
+	aeskeygenassist	$0x80,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,27
+	aeskeygenassist	$0x1b,%xmm0,%xmm1
 	call	.Lkey_expansion_128
-.byte	102,15,58,223,200,54
+	aeskeygenassist	$0x36,%xmm0,%xmm1
 	call	.Lkey_expansion_128
 	movups	%xmm0,(%rax)
 	movl	%esi,80(%rax)
@@ -2005,21 +2005,21 @@
 	movl	$11,%esi
 
 	movups	%xmm0,(%rdx)
-.byte	102,15,58,223,202,1
+	aeskeygenassist	$0x1,%xmm2,%xmm1
 	call	.Lkey_expansion_192a_cold
-.byte	102,15,58,223,202,2
+	aeskeygenassist	$0x2,%xmm2,%xmm1
 	call	.Lkey_expansion_192b
-.byte	102,15,58,223,202,4
+	aeskeygenassist	$0x4,%xmm2,%xmm1
 	call	.Lkey_expansion_192a
-.byte	102,15,58,223,202,8
+	aeskeygenassist	$0x8,%xmm2,%xmm1
 	call	.Lkey_expansion_192b
-.byte	102,15,58,223,202,16
+	aeskeygenassist	$0x10,%xmm2,%xmm1
 	call	.Lkey_expansion_192a
-.byte	102,15,58,223,202,32
+	aeskeygenassist	$0x20,%xmm2,%xmm1
 	call	.Lkey_expansion_192b
-.byte	102,15,58,223,202,64
+	aeskeygenassist	$0x40,%xmm2,%xmm1
 	call	.Lkey_expansion_192a
-.byte	102,15,58,223,202,128
+	aeskeygenassist	$0x80,%xmm2,%xmm1
 	call	.Lkey_expansion_192b
 	movups	%xmm0,(%rax)
 	movl	%esi,48(%rax)
@@ -2034,31 +2034,31 @@
 
 	movups	%xmm0,(%rdx)
 	movups	%xmm2,16(%rdx)
-.byte	102,15,58,223,202,1
+	aeskeygenassist	$0x1,%xmm2,%xmm1
 	call	.Lkey_expansion_256a_cold
-.byte	102,15,58,223,200,1
+	aeskeygenassist	$0x1,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,2
+	aeskeygenassist	$0x2,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
-.byte	102,15,58,223,200,2
+	aeskeygenassist	$0x2,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,4
+	aeskeygenassist	$0x4,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
-.byte	102,15,58,223,200,4
+	aeskeygenassist	$0x4,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,8
+	aeskeygenassist	$0x8,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
-.byte	102,15,58,223,200,8
+	aeskeygenassist	$0x8,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,16
+	aeskeygenassist	$0x10,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
-.byte	102,15,58,223,200,16
+	aeskeygenassist	$0x10,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,32
+	aeskeygenassist	$0x20,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
-.byte	102,15,58,223,200,32
+	aeskeygenassist	$0x20,%xmm0,%xmm1
 	call	.Lkey_expansion_256b
-.byte	102,15,58,223,202,64
+	aeskeygenassist	$0x40,%xmm2,%xmm1
 	call	.Lkey_expansion_256a
 	movups	%xmm0,(%rax)
 	movl	%esi,16(%rax)
@@ -2196,8 +2196,8 @@
 
 .align	16
 .Loop_key128:
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 	pslld	$1,%xmm4
 	leaq	16(%rax),%rax
 
@@ -2218,8 +2218,8 @@
 
 	movdqa	.Lkey_rcon1b(%rip),%xmm4
 
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 	pslld	$1,%xmm4
 
 	movdqa	%xmm2,%xmm3
@@ -2234,8 +2234,8 @@
 	movdqu	%xmm0,(%rax)
 
 	movdqa	%xmm0,%xmm2
-.byte	102,15,56,0,197
-.byte	102,15,56,221,196
+	pshufb	%xmm5,%xmm0
+	aesenclast	%xmm4,%xmm0
 
 	movdqa	%xmm2,%xmm3
 	pslldq	$4,%xmm2
@@ -2266,8 +2266,8 @@
 .Loop_key192:
 	movq	%xmm2,0(%rax)
 	movdqa	%xmm2,%xmm1
-.byte	102,15,56,0,213
-.byte	102,15,56,221,212
+	pshufb	%xmm5,%xmm2
+	aesenclast	%xmm4,%xmm2
 	pslld	$1,%xmm4
 	leaq	24(%rax),%rax
 
@@ -2310,8 +2310,8 @@
 
 .align	16
 .Loop_key256:
-.byte	102,15,56,0,213
-.byte	102,15,56,221,212
+	pshufb	%xmm5,%xmm2
+	aesenclast	%xmm4,%xmm2
 
 	movdqa	%xmm0,%xmm3
 	pslldq	$4,%xmm0
@@ -2330,7 +2330,7 @@
 
 	pshufd	$0xff,%xmm0,%xmm2
 	pxor	%xmm3,%xmm3
-.byte	102,15,56,221,211
+	aesenclast	%xmm3,%xmm2
 
 	movdqa	%xmm1,%xmm3
 	pslldq	$4,%xmm1
diff --git a/src/gen/bcm/aesni-x86_64-win.asm b/src/gen/bcm/aesni-x86_64-win.asm
index c585507..8e592cd 100644
--- a/src/gen/bcm/aesni-x86_64-win.asm
+++ b/src/gen/bcm/aesni-x86_64-win.asm
@@ -30,12 +30,12 @@
 	lea	r8,[32+r8]
 	xorps	xmm2,xmm0
 $L$oop_enc1_1:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[r8]
 	lea	r8,[16+r8]
 	jnz	NEAR $L$oop_enc1_1
-	DB	102,15,56,221,209
+	aesenclast	xmm2,xmm1
 	pxor	xmm0,xmm0
 	pxor	xmm1,xmm1
 	movups	XMMWORD[rdx],xmm2
@@ -57,12 +57,12 @@
 	lea	r8,[32+r8]
 	xorps	xmm2,xmm0
 $L$oop_dec1_2:
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[r8]
 	lea	r8,[16+r8]
 	jnz	NEAR $L$oop_dec1_2
-	DB	102,15,56,223,209
+	aesdeclast	xmm2,xmm1
 	pxor	xmm0,xmm0
 	pxor	xmm1,xmm1
 	movups	XMMWORD[rdx],xmm2
@@ -85,19 +85,19 @@
 	add	rax,16
 
 $L$enc_loop2:
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$enc_loop2
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,221,208
-	DB	102,15,56,221,216
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
 	ret
 
 
@@ -116,19 +116,19 @@
 	add	rax,16
 
 $L$dec_loop2:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$dec_loop2
 
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,223,208
-	DB	102,15,56,223,216
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
 	ret
 
 
@@ -148,23 +148,23 @@
 	add	rax,16
 
 $L$enc_loop3:
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$enc_loop3
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,221,208
-	DB	102,15,56,221,216
-	DB	102,15,56,221,224
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
 	ret
 
 
@@ -184,23 +184,23 @@
 	add	rax,16
 
 $L$dec_loop3:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$dec_loop3
 
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,223,208
-	DB	102,15,56,223,216
-	DB	102,15,56,223,224
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
 	ret
 
 
@@ -222,27 +222,27 @@
 	add	rax,16
 
 $L$enc_loop4:
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$enc_loop4
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,221,208
-	DB	102,15,56,221,216
-	DB	102,15,56,221,224
-	DB	102,15,56,221,232
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
 	ret
 
 
@@ -264,27 +264,27 @@
 	add	rax,16
 
 $L$dec_loop4:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$dec_loop4
 
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,223,208
-	DB	102,15,56,223,216
-	DB	102,15,56,223,224
-	DB	102,15,56,223,232
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
 	ret
 
 
@@ -298,49 +298,49 @@
 	xorps	xmm2,xmm0
 	pxor	xmm3,xmm0
 	pxor	xmm4,xmm0
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	lea	rcx,[32+rax*1+rcx]
 	neg	rax
-	DB	102,15,56,220,217
+	aesenc	xmm3,xmm1
 	pxor	xmm5,xmm0
 	pxor	xmm6,xmm0
-	DB	102,15,56,220,225
+	aesenc	xmm4,xmm1
 	pxor	xmm7,xmm0
 	movups	xmm0,XMMWORD[rax*1+rcx]
 	add	rax,16
 	jmp	NEAR $L$enc_loop6_enter
 ALIGN	16
 $L$enc_loop6:
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
 $L$enc_loop6_enter:
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$enc_loop6
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,15,56,221,208
-	DB	102,15,56,221,216
-	DB	102,15,56,221,224
-	DB	102,15,56,221,232
-	DB	102,15,56,221,240
-	DB	102,15,56,221,248
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
+	aesenclast	xmm6,xmm0
+	aesenclast	xmm7,xmm0
 	ret
 
 
@@ -354,49 +354,49 @@
 	xorps	xmm2,xmm0
 	pxor	xmm3,xmm0
 	pxor	xmm4,xmm0
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	lea	rcx,[32+rax*1+rcx]
 	neg	rax
-	DB	102,15,56,222,217
+	aesdec	xmm3,xmm1
 	pxor	xmm5,xmm0
 	pxor	xmm6,xmm0
-	DB	102,15,56,222,225
+	aesdec	xmm4,xmm1
 	pxor	xmm7,xmm0
 	movups	xmm0,XMMWORD[rax*1+rcx]
 	add	rax,16
 	jmp	NEAR $L$dec_loop6_enter
 ALIGN	16
 $L$dec_loop6:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
 $L$dec_loop6_enter:
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$dec_loop6
 
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,15,56,223,208
-	DB	102,15,56,223,216
-	DB	102,15,56,223,224
-	DB	102,15,56,223,232
-	DB	102,15,56,223,240
-	DB	102,15,56,223,248
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
+	aesdeclast	xmm6,xmm0
+	aesdeclast	xmm7,xmm0
 	ret
 
 
@@ -414,55 +414,55 @@
 	pxor	xmm6,xmm0
 	lea	rcx,[32+rax*1+rcx]
 	neg	rax
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	pxor	xmm7,xmm0
 	pxor	xmm8,xmm0
-	DB	102,15,56,220,217
+	aesenc	xmm3,xmm1
 	pxor	xmm9,xmm0
 	movups	xmm0,XMMWORD[rax*1+rcx]
 	add	rax,16
 	jmp	NEAR $L$enc_loop8_inner
 ALIGN	16
 $L$enc_loop8:
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 $L$enc_loop8_inner:
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 $L$enc_loop8_enter:
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$enc_loop8
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
-	DB	102,15,56,221,208
-	DB	102,15,56,221,216
-	DB	102,15,56,221,224
-	DB	102,15,56,221,232
-	DB	102,15,56,221,240
-	DB	102,15,56,221,248
-	DB	102,68,15,56,221,192
-	DB	102,68,15,56,221,200
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
+	aesenclast	xmm6,xmm0
+	aesenclast	xmm7,xmm0
+	aesenclast	xmm8,xmm0
+	aesenclast	xmm9,xmm0
 	ret
 
 
@@ -480,55 +480,55 @@
 	pxor	xmm6,xmm0
 	lea	rcx,[32+rax*1+rcx]
 	neg	rax
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	pxor	xmm7,xmm0
 	pxor	xmm8,xmm0
-	DB	102,15,56,222,217
+	aesdec	xmm3,xmm1
 	pxor	xmm9,xmm0
 	movups	xmm0,XMMWORD[rax*1+rcx]
 	add	rax,16
 	jmp	NEAR $L$dec_loop8_inner
 ALIGN	16
 $L$dec_loop8:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
 $L$dec_loop8_inner:
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 $L$dec_loop8_enter:
 	movups	xmm1,XMMWORD[rax*1+rcx]
 	add	rax,32
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
 	jnz	NEAR $L$dec_loop8
 
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
-	DB	102,15,56,223,208
-	DB	102,15,56,223,216
-	DB	102,15,56,223,224
-	DB	102,15,56,223,232
-	DB	102,15,56,223,240
-	DB	102,15,56,223,248
-	DB	102,68,15,56,223,192
-	DB	102,68,15,56,223,200
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
+	aesdeclast	xmm6,xmm0
+	aesdeclast	xmm7,xmm0
+	aesdeclast	xmm8,xmm0
+	aesdeclast	xmm9,xmm0
 	ret
 
 
@@ -656,12 +656,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm0
 $L$oop_enc1_3:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_enc1_3
-	DB	102,15,56,221,209
+	aesenclast	xmm2,xmm1
 	movups	XMMWORD[rsi],xmm2
 	jmp	NEAR $L$ecb_ret
 ALIGN	16
@@ -817,12 +817,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm0
 $L$oop_dec1_4:
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_dec1_4
-	DB	102,15,56,223,209
+	aesdeclast	xmm2,xmm1
 	movups	XMMWORD[rsi],xmm2
 	pxor	xmm2,xmm2
 	jmp	NEAR $L$ecb_ret
@@ -939,12 +939,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm0
 $L$oop_enc1_5:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	dec	edx
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_enc1_5
-	DB	102,15,56,221,209
+	aesenclast	xmm2,xmm1
 	pxor	xmm0,xmm0
 	pxor	xmm1,xmm1
 	xorps	xmm2,xmm3
@@ -998,17 +998,17 @@
 	bswap	edx
 	xor	eax,ebp
 	xor	edx,ebp
-DB	102,15,58,34,216,3
+	pinsrd	xmm3,eax,3
 	lea	rax,[3+r8]
 	movdqa	XMMWORD[16+rsp],xmm3
-DB	102,15,58,34,226,3
+	pinsrd	xmm4,edx,3
 	bswap	eax
 	mov	rdx,r10
 	lea	r10,[4+r8]
 	movdqa	XMMWORD[32+rsp],xmm4
 	xor	eax,ebp
 	bswap	r10d
-DB	102,15,58,34,232,3
+	pinsrd	xmm5,eax,3
 	xor	r10d,ebp
 	movdqa	XMMWORD[48+rsp],xmm5
 	lea	r9,[5+r8]
@@ -1042,163 +1042,163 @@
 $L$ctr32_loop8:
 	add	r8d,8
 	movdqa	xmm8,XMMWORD[96+rsp]
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	mov	r9d,r8d
 	movdqa	xmm9,XMMWORD[112+rsp]
-	DB	102,15,56,220,217
+	aesenc	xmm3,xmm1
 	bswap	r9d
 	movups	xmm0,XMMWORD[((32-128))+rcx]
-	DB	102,15,56,220,225
+	aesenc	xmm4,xmm1
 	xor	r9d,ebp
 	nop
-	DB	102,15,56,220,233
+	aesenc	xmm5,xmm1
 	mov	DWORD[((0+12))+rsp],r9d
 	lea	r9,[1+r8]
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((48-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
 	mov	DWORD[((16+12))+rsp],r9d
 	lea	r9,[2+r8]
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((64-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
 	mov	DWORD[((32+12))+rsp],r9d
 	lea	r9,[3+r8]
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((80-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
 	mov	DWORD[((48+12))+rsp],r9d
 	lea	r9,[4+r8]
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((96-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
 	mov	DWORD[((64+12))+rsp],r9d
 	lea	r9,[5+r8]
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((112-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
 	mov	DWORD[((80+12))+rsp],r9d
 	lea	r9,[6+r8]
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((128-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 	xor	r9d,ebp
 	DB	0x66,0x90
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
 	mov	DWORD[((96+12))+rsp],r9d
 	lea	r9,[7+r8]
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((144-128))+rcx]
 	bswap	r9d
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
 	xor	r9d,ebp
 	movdqu	xmm10,XMMWORD[rdi]
-	DB	102,15,56,220,232
+	aesenc	xmm5,xmm0
 	mov	DWORD[((112+12))+rsp],r9d
 	cmp	eax,11
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((160-128))+rcx]
 
 	jb	NEAR $L$ctr32_enc_done
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((176-128))+rcx]
 
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((192-128))+rcx]
 	je	NEAR $L$ctr32_enc_done
 
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movups	xmm1,XMMWORD[((208-128))+rcx]
 
-	DB	102,15,56,220,208
-	DB	102,15,56,220,216
-	DB	102,15,56,220,224
-	DB	102,15,56,220,232
-	DB	102,15,56,220,240
-	DB	102,15,56,220,248
-	DB	102,68,15,56,220,192
-	DB	102,68,15,56,220,200
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
 	movups	xmm0,XMMWORD[((224-128))+rcx]
 	jmp	NEAR $L$ctr32_enc_done
 
@@ -1217,35 +1217,35 @@
 	prefetcht0	[448+rdi]
 	prefetcht0	[512+rdi]
 	pxor	xmm15,xmm0
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
-	DB	102,68,15,56,220,201
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
 	movdqu	xmm1,XMMWORD[96+rdi]
 	lea	rdi,[128+rdi]
 
-	DB	102,65,15,56,221,210
+	aesenclast	xmm2,xmm10
 	pxor	xmm1,xmm0
 	movdqu	xmm10,XMMWORD[((112-128))+rdi]
-	DB	102,65,15,56,221,219
+	aesenclast	xmm3,xmm11
 	pxor	xmm10,xmm0
 	movdqa	xmm11,XMMWORD[rsp]
-	DB	102,65,15,56,221,228
-	DB	102,65,15,56,221,237
+	aesenclast	xmm4,xmm12
+	aesenclast	xmm5,xmm13
 	movdqa	xmm12,XMMWORD[16+rsp]
 	movdqa	xmm13,XMMWORD[32+rsp]
-	DB	102,65,15,56,221,246
-	DB	102,65,15,56,221,255
+	aesenclast	xmm6,xmm14
+	aesenclast	xmm7,xmm15
 	movdqa	xmm14,XMMWORD[48+rsp]
 	movdqa	xmm15,XMMWORD[64+rsp]
-	DB	102,68,15,56,221,193
+	aesenclast	xmm8,xmm1
 	movdqa	xmm0,XMMWORD[80+rsp]
 	movups	xmm1,XMMWORD[((16-128))+rcx]
-	DB	102,69,15,56,221,202
+	aesenclast	xmm9,xmm10
 
 	movups	XMMWORD[rsi],xmm2
 	movdqa	xmm2,xmm11
@@ -1284,19 +1284,19 @@
 	pxor	xmm9,xmm9
 
 	movups	xmm0,XMMWORD[16+rcx]
-	DB	102,15,56,220,209
-	DB	102,15,56,220,217
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
 	lea	rcx,[((32-16))+rax*1+rcx]
 	neg	rax
-	DB	102,15,56,220,225
+	aesenc	xmm4,xmm1
 	add	rax,16
 	movups	xmm10,XMMWORD[rdi]
-	DB	102,15,56,220,233
-	DB	102,15,56,220,241
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
 	movups	xmm11,XMMWORD[16+rdi]
 	movups	xmm12,XMMWORD[32+rdi]
-	DB	102,15,56,220,249
-	DB	102,68,15,56,220,193
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
 
 	call	$L$enc_loop8_enter
 
@@ -1327,20 +1327,20 @@
 
 ALIGN	32
 $L$ctr32_loop4:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	lea	rcx,[16+rcx]
 	dec	eax
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
-	DB	102,15,56,220,233
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
 	movups	xmm1,XMMWORD[rcx]
 	jnz	NEAR $L$ctr32_loop4
-	DB	102,15,56,221,209
-	DB	102,15,56,221,217
+	aesenclast	xmm2,xmm1
+	aesenclast	xmm3,xmm1
 	movups	xmm10,XMMWORD[rdi]
 	movups	xmm11,XMMWORD[16+rdi]
-	DB	102,15,56,221,225
-	DB	102,15,56,221,233
+	aesenclast	xmm4,xmm1
+	aesenclast	xmm5,xmm1
 	movups	xmm12,XMMWORD[32+rdi]
 	movups	xmm13,XMMWORD[48+rdi]
 
@@ -1356,16 +1356,16 @@
 
 ALIGN	32
 $L$ctr32_loop3:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	lea	rcx,[16+rcx]
 	dec	eax
-	DB	102,15,56,220,217
-	DB	102,15,56,220,225
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
 	movups	xmm1,XMMWORD[rcx]
 	jnz	NEAR $L$ctr32_loop3
-	DB	102,15,56,221,209
-	DB	102,15,56,221,217
-	DB	102,15,56,221,225
+	aesenclast	xmm2,xmm1
+	aesenclast	xmm3,xmm1
+	aesenclast	xmm4,xmm1
 
 	movups	xmm10,XMMWORD[rdi]
 	xorps	xmm2,xmm10
@@ -1471,12 +1471,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm3
 $L$oop_enc1_6:
-	DB	102,15,56,220,209
+	aesenc	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_enc1_6
-	DB	102,15,56,221,209
+	aesenclast	xmm2,xmm1
 	mov	eax,r10d
 	mov	rcx,r11
 	movups	XMMWORD[rsi],xmm2
@@ -1522,12 +1522,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm0
 $L$oop_dec1_7:
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	dec	r10d
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_dec1_7
-	DB	102,15,56,223,209
+	aesdeclast	xmm2,xmm1
 	pxor	xmm0,xmm0
 	pxor	xmm1,xmm1
 	movdqu	XMMWORD[r8],xmm4
@@ -1597,166 +1597,166 @@
 	pxor	xmm7,xmm0
 	pxor	xmm8,xmm0
 
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	pxor	xmm9,xmm0
 	movups	xmm0,XMMWORD[((32-112))+rcx]
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
 	adc	rbp,0
 	and	rbp,128
-	DB	102,68,15,56,222,201
+	aesdec	xmm9,xmm1
 	add	rbp,rdi
 	movups	xmm1,XMMWORD[((48-112))+rcx]
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((64-112))+rcx]
 	nop
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movups	xmm1,XMMWORD[((80-112))+rcx]
 	nop
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((96-112))+rcx]
 	nop
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movups	xmm1,XMMWORD[((112-112))+rcx]
 	nop
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((128-112))+rcx]
 	nop
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movups	xmm1,XMMWORD[((144-112))+rcx]
 	cmp	eax,11
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((160-112))+rcx]
 	jb	NEAR $L$cbc_dec_done
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movups	xmm1,XMMWORD[((176-112))+rcx]
 	nop
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((192-112))+rcx]
 	je	NEAR $L$cbc_dec_done
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movups	xmm1,XMMWORD[((208-112))+rcx]
 	nop
-	DB	102,15,56,222,208
-	DB	102,15,56,222,216
-	DB	102,15,56,222,224
-	DB	102,15,56,222,232
-	DB	102,15,56,222,240
-	DB	102,15,56,222,248
-	DB	102,68,15,56,222,192
-	DB	102,68,15,56,222,200
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
 	movups	xmm0,XMMWORD[((224-112))+rcx]
 	jmp	NEAR $L$cbc_dec_done
 ALIGN	16
 $L$cbc_dec_done:
-	DB	102,15,56,222,209
-	DB	102,15,56,222,217
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
 	pxor	xmm10,xmm0
 	pxor	xmm11,xmm0
-	DB	102,15,56,222,225
-	DB	102,15,56,222,233
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
 	pxor	xmm12,xmm0
 	pxor	xmm13,xmm0
-	DB	102,15,56,222,241
-	DB	102,15,56,222,249
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
 	pxor	xmm14,xmm0
 	pxor	xmm15,xmm0
-	DB	102,68,15,56,222,193
-	DB	102,68,15,56,222,201
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
 	movdqu	xmm1,XMMWORD[80+rdi]
 
-	DB	102,65,15,56,223,210
+	aesdeclast	xmm2,xmm10
 	movdqu	xmm10,XMMWORD[96+rdi]
 	pxor	xmm1,xmm0
-	DB	102,65,15,56,223,219
+	aesdeclast	xmm3,xmm11
 	pxor	xmm10,xmm0
 	movdqu	xmm0,XMMWORD[112+rdi]
-	DB	102,65,15,56,223,228
+	aesdeclast	xmm4,xmm12
 	lea	rdi,[128+rdi]
 	movdqu	xmm11,XMMWORD[rbp]
-	DB	102,65,15,56,223,237
-	DB	102,65,15,56,223,246
+	aesdeclast	xmm5,xmm13
+	aesdeclast	xmm6,xmm14
 	movdqu	xmm12,XMMWORD[16+rbp]
 	movdqu	xmm13,XMMWORD[32+rbp]
-	DB	102,65,15,56,223,255
-	DB	102,68,15,56,223,193
+	aesdeclast	xmm7,xmm15
+	aesdeclast	xmm8,xmm1
 	movdqu	xmm14,XMMWORD[48+rbp]
 	movdqu	xmm15,XMMWORD[64+rbp]
-	DB	102,69,15,56,223,202
+	aesdeclast	xmm9,xmm10
 	movdqa	xmm10,xmm0
 	movdqu	xmm1,XMMWORD[80+rbp]
 	movups	xmm0,XMMWORD[((-112))+rcx]
@@ -1900,12 +1900,12 @@
 	lea	rcx,[32+rcx]
 	xorps	xmm2,xmm0
 $L$oop_dec1_8:
-	DB	102,15,56,222,209
+	aesdec	xmm2,xmm1
 	dec	eax
 	movups	xmm1,XMMWORD[rcx]
 	lea	rcx,[16+rcx]
 	jnz	NEAR $L$oop_dec1_8
-	DB	102,15,56,223,209
+	aesdeclast	xmm2,xmm1
 	xorps	xmm2,xmm10
 	movaps	xmm10,xmm11
 	jmp	NEAR $L$cbc_dec_tail_collected
@@ -2033,8 +2033,8 @@
 $L$dec_key_inverse:
 	movups	xmm0,XMMWORD[rcx]
 	movups	xmm1,XMMWORD[r8]
-	DB	102,15,56,219,192
-	DB	102,15,56,219,201
+	aesimc	xmm0,xmm0
+	aesimc	xmm1,xmm1
 	lea	rcx,[16+rcx]
 	lea	r8,[((-16))+r8]
 	movups	XMMWORD[16+r8],xmm0
@@ -2043,7 +2043,7 @@
 	ja	NEAR $L$dec_key_inverse
 
 	movups	xmm0,XMMWORD[rcx]
-	DB	102,15,56,219,192
+	aesimc	xmm0,xmm0
 	pxor	xmm1,xmm1
 	movups	XMMWORD[r8],xmm0
 	pxor	xmm0,xmm0
@@ -2078,25 +2078,25 @@
 	mov	edx,9
 
 	movups	XMMWORD[r8],xmm0
-	DB	102,15,58,223,200,1
+	aeskeygenassist	xmm1,xmm0,0x1
 	call	$L$key_expansion_128_cold
-	DB	102,15,58,223,200,2
+	aeskeygenassist	xmm1,xmm0,0x2
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,4
+	aeskeygenassist	xmm1,xmm0,0x4
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,8
+	aeskeygenassist	xmm1,xmm0,0x8
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,16
+	aeskeygenassist	xmm1,xmm0,0x10
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,32
+	aeskeygenassist	xmm1,xmm0,0x20
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,64
+	aeskeygenassist	xmm1,xmm0,0x40
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,128
+	aeskeygenassist	xmm1,xmm0,0x80
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,27
+	aeskeygenassist	xmm1,xmm0,0x1b
 	call	$L$key_expansion_128
-	DB	102,15,58,223,200,54
+	aeskeygenassist	xmm1,xmm0,0x36
 	call	$L$key_expansion_128
 	movups	XMMWORD[rax],xmm0
 	mov	DWORD[80+rax],edx
@@ -2109,21 +2109,21 @@
 	mov	edx,11
 
 	movups	XMMWORD[r8],xmm0
-	DB	102,15,58,223,202,1
+	aeskeygenassist	xmm1,xmm2,0x1
 	call	$L$key_expansion_192a_cold
-	DB	102,15,58,223,202,2
+	aeskeygenassist	xmm1,xmm2,0x2
 	call	$L$key_expansion_192b
-	DB	102,15,58,223,202,4
+	aeskeygenassist	xmm1,xmm2,0x4
 	call	$L$key_expansion_192a
-	DB	102,15,58,223,202,8
+	aeskeygenassist	xmm1,xmm2,0x8
 	call	$L$key_expansion_192b
-	DB	102,15,58,223,202,16
+	aeskeygenassist	xmm1,xmm2,0x10
 	call	$L$key_expansion_192a
-	DB	102,15,58,223,202,32
+	aeskeygenassist	xmm1,xmm2,0x20
 	call	$L$key_expansion_192b
-	DB	102,15,58,223,202,64
+	aeskeygenassist	xmm1,xmm2,0x40
 	call	$L$key_expansion_192a
-	DB	102,15,58,223,202,128
+	aeskeygenassist	xmm1,xmm2,0x80
 	call	$L$key_expansion_192b
 	movups	XMMWORD[rax],xmm0
 	mov	DWORD[48+rax],edx
@@ -2138,31 +2138,31 @@
 
 	movups	XMMWORD[r8],xmm0
 	movups	XMMWORD[16+r8],xmm2
-	DB	102,15,58,223,202,1
+	aeskeygenassist	xmm1,xmm2,0x1
 	call	$L$key_expansion_256a_cold
-	DB	102,15,58,223,200,1
+	aeskeygenassist	xmm1,xmm0,0x1
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,2
+	aeskeygenassist	xmm1,xmm2,0x2
 	call	$L$key_expansion_256a
-	DB	102,15,58,223,200,2
+	aeskeygenassist	xmm1,xmm0,0x2
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,4
+	aeskeygenassist	xmm1,xmm2,0x4
 	call	$L$key_expansion_256a
-	DB	102,15,58,223,200,4
+	aeskeygenassist	xmm1,xmm0,0x4
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,8
+	aeskeygenassist	xmm1,xmm2,0x8
 	call	$L$key_expansion_256a
-	DB	102,15,58,223,200,8
+	aeskeygenassist	xmm1,xmm0,0x8
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,16
+	aeskeygenassist	xmm1,xmm2,0x10
 	call	$L$key_expansion_256a
-	DB	102,15,58,223,200,16
+	aeskeygenassist	xmm1,xmm0,0x10
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,32
+	aeskeygenassist	xmm1,xmm2,0x20
 	call	$L$key_expansion_256a
-	DB	102,15,58,223,200,32
+	aeskeygenassist	xmm1,xmm0,0x20
 	call	$L$key_expansion_256b
-	DB	102,15,58,223,202,64
+	aeskeygenassist	xmm1,xmm2,0x40
 	call	$L$key_expansion_256a
 	movups	XMMWORD[rax],xmm0
 	mov	DWORD[16+rax],edx
@@ -2299,8 +2299,8 @@
 
 ALIGN	16
 $L$oop_key128:
-DB	102,15,56,0,197
-	DB	102,15,56,221,196
+	pshufb	xmm0,xmm5
+	aesenclast	xmm0,xmm4
 	pslld	xmm4,1
 	lea	rax,[16+rax]
 
@@ -2321,8 +2321,8 @@
 
 	movdqa	xmm4,XMMWORD[$L$key_rcon1b]
 
-DB	102,15,56,0,197
-	DB	102,15,56,221,196
+	pshufb	xmm0,xmm5
+	aesenclast	xmm0,xmm4
 	pslld	xmm4,1
 
 	movdqa	xmm3,xmm2
@@ -2337,8 +2337,8 @@
 	movdqu	XMMWORD[rax],xmm0
 
 	movdqa	xmm2,xmm0
-DB	102,15,56,0,197
-	DB	102,15,56,221,196
+	pshufb	xmm0,xmm5
+	aesenclast	xmm0,xmm4
 
 	movdqa	xmm3,xmm2
 	pslldq	xmm2,4
@@ -2369,8 +2369,8 @@
 $L$oop_key192:
 	movq	QWORD[rax],xmm2
 	movdqa	xmm1,xmm2
-DB	102,15,56,0,213
-	DB	102,15,56,221,212
+	pshufb	xmm2,xmm5
+	aesenclast	xmm2,xmm4
 	pslld	xmm4,1
 	lea	rax,[24+rax]
 
@@ -2413,8 +2413,8 @@
 
 ALIGN	16
 $L$oop_key256:
-DB	102,15,56,0,213
-	DB	102,15,56,221,212
+	pshufb	xmm2,xmm5
+	aesenclast	xmm2,xmm4
 
 	movdqa	xmm3,xmm0
 	pslldq	xmm0,4
@@ -2433,7 +2433,7 @@
 
 	pshufd	xmm2,xmm0,0xff
 	pxor	xmm3,xmm3
-	DB	102,15,56,221,211
+	aesenclast	xmm2,xmm3
 
 	movdqa	xmm3,xmm1
 	pslldq	xmm1,4
diff --git a/src/gen/bcm/armv4-mont-linux.S b/src/gen/bcm/armv4-mont-linux.S
index 704f607..73e42b5 100644
--- a/src/gen/bcm/armv4-mont-linux.S
+++ b/src/gen/bcm/armv4-mont-linux.S
@@ -24,14 +24,9 @@
 bn_mul_mont_nohw:
 	ldr	ip,[sp,#4]		@ load num
 	stmdb	sp!,{r0,r2}		@ sp points at argument block
-	cmp	ip,#2
+	@ No return value. Instead, the caller must ensure num >= 2
 	mov	r0,ip			@ load num
-#ifdef	__thumb2__
-	ittt	lt
-#endif
-	movlt	r0,#0
-	addlt	sp,sp,#2*4
-	blt	.Labrt
+	@ No return value
 
 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}		@ save 10 registers
 
@@ -165,8 +160,7 @@
 	add	sp,sp,#4		@ skip over tp[num+1]
 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}		@ restore registers
 	add	sp,sp,#2*4		@ skip over {r0,r2}
-	mov	r0,#1
-.Labrt:
+	@ No return value
 #if __ARM_ARCH>=5
 	bx	lr				@ bx lr
 #else
@@ -929,6 +923,7 @@
 	mov	sp,ip
 	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
+	@ No return value
 	bx	lr						@ bx lr
 .size	bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
 #endif
diff --git a/src/gen/bcm/armv8-mont-apple.S b/src/gen/bcm/armv8-mont-apple.S
index 9e39c1d..6aad968 100644
--- a/src/gen/bcm/armv8-mont-apple.S
+++ b/src/gen/bcm/armv8-mont-apple.S
@@ -206,7 +206,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldr	x29,[sp],#64
 	AARCH64_VALIDATE_LINK_REGISTER
@@ -965,7 +965,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
@@ -1408,7 +1408,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
diff --git a/src/gen/bcm/armv8-mont-linux.S b/src/gen/bcm/armv8-mont-linux.S
index 168162f..e49322b 100644
--- a/src/gen/bcm/armv8-mont-linux.S
+++ b/src/gen/bcm/armv8-mont-linux.S
@@ -206,7 +206,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldr	x29,[sp],#64
 	AARCH64_VALIDATE_LINK_REGISTER
@@ -965,7 +965,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
@@ -1408,7 +1408,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
diff --git a/src/gen/bcm/armv8-mont-win.S b/src/gen/bcm/armv8-mont-win.S
index b521d49..4091a5a 100644
--- a/src/gen/bcm/armv8-mont-win.S
+++ b/src/gen/bcm/armv8-mont-win.S
@@ -208,7 +208,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldr	x29,[sp],#64
 	AARCH64_VALIDATE_LINK_REGISTER
@@ -969,7 +969,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
@@ -1414,7 +1414,7 @@
 	ldp	x19,x20,[x29,#16]
 	mov	sp,x29
 	ldp	x21,x22,[x29,#32]
-	mov	x0,#1
+	// No return value
 	ldp	x23,x24,[x29,#48]
 	ldp	x25,x26,[x29,#64]
 	ldp	x27,x28,[x29,#80]
diff --git a/src/gen/bcm/bn-586-apple.S b/src/gen/bcm/bn-586-apple.S
index f483ef1..3e6f791 100644
--- a/src/gen/bcm/bn-586-apple.S
+++ b/src/gen/bcm/bn-586-apple.S
@@ -156,16 +156,6 @@
 	popl	%ebx
 	popl	%ebp
 	ret
-.globl	_bn_div_words
-.private_extern	_bn_div_words
-.align	4
-_bn_div_words:
-L_bn_div_words_begin:
-	movl	4(%esp),%edx
-	movl	8(%esp),%eax
-	movl	12(%esp),%ecx
-	divl	%ecx
-	ret
 .globl	_bn_add_words
 .private_extern	_bn_add_words
 .align	4
diff --git a/src/gen/bcm/bn-586-linux.S b/src/gen/bcm/bn-586-linux.S
index fb83b22..808f63e 100644
--- a/src/gen/bcm/bn-586-linux.S
+++ b/src/gen/bcm/bn-586-linux.S
@@ -162,18 +162,6 @@
 	popl	%ebp
 	ret
 .size	bn_sqr_words,.-.L_bn_sqr_words_begin
-.globl	bn_div_words
-.hidden	bn_div_words
-.type	bn_div_words,@function
-.align	16
-bn_div_words:
-.L_bn_div_words_begin:
-	movl	4(%esp),%edx
-	movl	8(%esp),%eax
-	movl	12(%esp),%ecx
-	divl	%ecx
-	ret
-.size	bn_div_words,.-.L_bn_div_words_begin
 .globl	bn_add_words
 .hidden	bn_add_words
 .type	bn_add_words,@function
diff --git a/src/gen/bcm/bn-586-win.asm b/src/gen/bcm/bn-586-win.asm
index 09aafb8..1250eb6 100644
--- a/src/gen/bcm/bn-586-win.asm
+++ b/src/gen/bcm/bn-586-win.asm
@@ -161,15 +161,6 @@
 	pop	ebx
 	pop	ebp
 	ret
-global	_bn_div_words
-align	16
-_bn_div_words:
-L$_bn_div_words_begin:
-	mov	edx,DWORD [4+esp]
-	mov	eax,DWORD [8+esp]
-	mov	ecx,DWORD [12+esp]
-	div	ecx
-	ret
 global	_bn_add_words
 align	16
 _bn_add_words:
diff --git a/src/gen/bcm/ghash-ssse3-x86_64-apple.S b/src/gen/bcm/ghash-ssse3-x86_64-apple.S
index 651cca3..53af23f 100644
--- a/src/gen/bcm/ghash-ssse3-x86_64-apple.S
+++ b/src/gen/bcm/ghash-ssse3-x86_64-apple.S
@@ -23,7 +23,7 @@
 	movdqa	L$low4_mask(%rip),%xmm2
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 
 	movdqa	%xmm2,%xmm1
@@ -43,7 +43,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -51,8 +51,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -91,7 +91,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -99,8 +99,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -139,7 +139,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -147,8 +147,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -181,7 +181,7 @@
 	pxor	%xmm3,%xmm2
 	pxor	%xmm3,%xmm3
 
-.byte	102,65,15,56,0,210
+	pshufb	%xmm10,%xmm2
 	movdqu	%xmm2,(%rdi)
 
 
@@ -218,14 +218,14 @@
 
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 
 	pxor	%xmm3,%xmm3
 L$oop_ghash:
 
 	movdqu	(%rdx),%xmm1
-.byte	102,65,15,56,0,202
+	pshufb	%xmm10,%xmm1
 	pxor	%xmm1,%xmm0
 
 
@@ -246,7 +246,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -254,8 +254,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -294,7 +294,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -302,8 +302,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -342,7 +342,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -350,8 +350,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -394,7 +394,7 @@
 	jnz	L$oop_ghash
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 	movdqu	%xmm0,(%rdi)
 
 
diff --git a/src/gen/bcm/ghash-ssse3-x86_64-linux.S b/src/gen/bcm/ghash-ssse3-x86_64-linux.S
index 84ac20a..edce38d 100644
--- a/src/gen/bcm/ghash-ssse3-x86_64-linux.S
+++ b/src/gen/bcm/ghash-ssse3-x86_64-linux.S
@@ -23,7 +23,7 @@
 	movdqa	.Llow4_mask(%rip),%xmm2
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 
 	movdqa	%xmm2,%xmm1
@@ -43,7 +43,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -51,8 +51,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -91,7 +91,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -99,8 +99,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -139,7 +139,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -147,8 +147,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -181,7 +181,7 @@
 	pxor	%xmm3,%xmm2
 	pxor	%xmm3,%xmm3
 
-.byte	102,65,15,56,0,210
+	pshufb	%xmm10,%xmm2
 	movdqu	%xmm2,(%rdi)
 
 
@@ -218,14 +218,14 @@
 
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 
 	pxor	%xmm3,%xmm3
 .Loop_ghash:
 
 	movdqu	(%rdx),%xmm1
-.byte	102,65,15,56,0,202
+	pshufb	%xmm10,%xmm1
 	pxor	%xmm1,%xmm0
 
 
@@ -246,7 +246,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -254,8 +254,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -294,7 +294,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -302,8 +302,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -342,7 +342,7 @@
 
 
 	movdqa	%xmm2,%xmm6
-.byte	102,15,58,15,243,1
+	palignr	$1,%xmm3,%xmm6
 	movdqa	%xmm6,%xmm3
 	psrldq	$1,%xmm2
 
@@ -350,8 +350,8 @@
 
 
 	movdqa	%xmm4,%xmm5
-.byte	102,15,56,0,224
-.byte	102,15,56,0,233
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm1,%xmm5
 
 
 	pxor	%xmm5,%xmm2
@@ -394,7 +394,7 @@
 	jnz	.Loop_ghash
 
 
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 	movdqu	%xmm0,(%rdi)
 
 
diff --git a/src/gen/bcm/ghash-ssse3-x86_64-win.asm b/src/gen/bcm/ghash-ssse3-x86_64-win.asm
index c00e039..5bcd094 100644
--- a/src/gen/bcm/ghash-ssse3-x86_64-win.asm
+++ b/src/gen/bcm/ghash-ssse3-x86_64-win.asm
@@ -37,7 +37,7 @@
 	movdqa	xmm2,XMMWORD[$L$low4_mask]
 
 
-DB	102,65,15,56,0,194
+	pshufb	xmm0,xmm10
 
 
 	movdqa	xmm1,xmm2
@@ -57,7 +57,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -65,8 +65,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -105,7 +105,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -113,8 +113,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -153,7 +153,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -161,8 +161,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -195,7 +195,7 @@
 	pxor	xmm2,xmm3
 	pxor	xmm3,xmm3
 
-DB	102,65,15,56,0,210
+	pshufb	xmm2,xmm10
 	movdqu	XMMWORD[rcx],xmm2
 
 
@@ -243,14 +243,14 @@
 
 
 
-DB	102,65,15,56,0,194
+	pshufb	xmm0,xmm10
 
 
 	pxor	xmm3,xmm3
 $L$oop_ghash:
 
 	movdqu	xmm1,XMMWORD[r8]
-DB	102,65,15,56,0,202
+	pshufb	xmm1,xmm10
 	pxor	xmm0,xmm1
 
 
@@ -271,7 +271,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -279,8 +279,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -319,7 +319,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -327,8 +327,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -367,7 +367,7 @@
 
 
 	movdqa	xmm6,xmm2
-DB	102,15,58,15,243,1
+	palignr	xmm6,xmm3,1
 	movdqa	xmm3,xmm6
 	psrldq	xmm2,1
 
@@ -375,8 +375,8 @@
 
 
 	movdqa	xmm5,xmm4
-DB	102,15,56,0,224
-DB	102,15,56,0,233
+	pshufb	xmm4,xmm0
+	pshufb	xmm5,xmm1
 
 
 	pxor	xmm2,xmm5
@@ -419,7 +419,7 @@
 	jnz	NEAR $L$oop_ghash
 
 
-DB	102,65,15,56,0,194
+	pshufb	xmm0,xmm10
 	movdqu	XMMWORD[rcx],xmm0
 
 
diff --git a/src/gen/bcm/ghash-x86_64-apple.S b/src/gen/bcm/ghash-x86_64-apple.S
index 4961298..0cf60d1 100644
--- a/src/gen/bcm/ghash-x86_64-apple.S
+++ b/src/gen/bcm/ghash-x86_64-apple.S
@@ -38,9 +38,9 @@
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -78,14 +78,14 @@
 	movdqu	%xmm2,0(%rdi)
 	pxor	%xmm0,%xmm4
 	movdqu	%xmm0,16(%rdi)
-.byte	102,15,58,15,227,8
+	palignr	$8,%xmm3,%xmm4
 	movdqu	%xmm4,32(%rdi)
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -121,9 +121,9 @@
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -161,7 +161,7 @@
 	movdqu	%xmm5,48(%rdi)
 	pxor	%xmm0,%xmm4
 	movdqu	%xmm0,64(%rdi)
-.byte	102,15,58,15,227,8
+	palignr	$8,%xmm3,%xmm4
 	movdqu	%xmm4,80(%rdi)
 	ret
 
@@ -179,13 +179,13 @@
 	movdqa	L$bswap_mask(%rip),%xmm5
 	movdqu	(%rsi),%xmm2
 	movdqu	32(%rsi),%xmm4
-.byte	102,15,56,0,197
+	pshufb	%xmm5,%xmm0
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,220,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm4,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -217,7 +217,7 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,197
+	pshufb	%xmm5,%xmm0
 	movdqu	%xmm0,(%rdi)
 	ret
 
@@ -236,7 +236,7 @@
 	movdqu	(%rdi),%xmm0
 	movdqu	(%rsi),%xmm2
 	movdqu	32(%rsi),%xmm7
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 	subq	$0x10,%rcx
 	jz	L$odd_tail
@@ -255,21 +255,21 @@
 
 	movdqu	48(%rdx),%xmm3
 	movdqu	32(%rdx),%xmm11
-.byte	102,65,15,56,0,218
-.byte	102,69,15,56,0,218
+	pshufb	%xmm10,%xmm3
+	pshufb	%xmm10,%xmm11
 	movdqa	%xmm3,%xmm5
 	pshufd	$78,%xmm3,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,68,218,0
-.byte	102,15,58,68,234,17
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
+	pclmulqdq	$0x11,%xmm2,%xmm5
+	pclmulqdq	$0x00,%xmm7,%xmm4
 
 	movdqa	%xmm11,%xmm13
 	pshufd	$78,%xmm11,%xmm12
 	pxor	%xmm11,%xmm12
-.byte	102,68,15,58,68,222,0
-.byte	102,68,15,58,68,238,17
-.byte	102,68,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm11
+	pclmulqdq	$0x11,%xmm6,%xmm13
+	pclmulqdq	$0x10,%xmm7,%xmm12
 	xorps	%xmm11,%xmm3
 	xorps	%xmm13,%xmm5
 	movups	80(%rsi),%xmm7
@@ -277,18 +277,18 @@
 
 	movdqu	16(%rdx),%xmm11
 	movdqu	0(%rdx),%xmm8
-.byte	102,69,15,56,0,218
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm11
+	pshufb	%xmm10,%xmm8
 	movdqa	%xmm11,%xmm13
 	pshufd	$78,%xmm11,%xmm12
 	pxor	%xmm8,%xmm0
 	pxor	%xmm11,%xmm12
-.byte	102,69,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm14,%xmm11
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm8
 	pxor	%xmm0,%xmm8
-.byte	102,69,15,58,68,238,17
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x11,%xmm14,%xmm13
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	xorps	%xmm11,%xmm3
 	xorps	%xmm13,%xmm5
 
@@ -299,22 +299,22 @@
 	jmp	L$mod4_loop
 .p2align	5
 L$mod4_loop:
-.byte	102,65,15,58,68,199,0
+	pclmulqdq	$0x00,%xmm15,%xmm0
 	xorps	%xmm12,%xmm4
 	movdqu	48(%rdx),%xmm11
-.byte	102,69,15,56,0,218
-.byte	102,65,15,58,68,207,17
+	pshufb	%xmm10,%xmm11
+	pclmulqdq	$0x11,%xmm15,%xmm1
 	xorps	%xmm3,%xmm0
 	movdqu	32(%rdx),%xmm3
 	movdqa	%xmm11,%xmm13
-.byte	102,68,15,58,68,199,16
+	pclmulqdq	$0x10,%xmm7,%xmm8
 	pshufd	$78,%xmm11,%xmm12
 	xorps	%xmm5,%xmm1
 	pxor	%xmm11,%xmm12
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm3
 	movups	32(%rsi),%xmm7
 	xorps	%xmm4,%xmm8
-.byte	102,68,15,58,68,218,0
+	pclmulqdq	$0x00,%xmm2,%xmm11
 	pshufd	$78,%xmm3,%xmm4
 
 	pxor	%xmm0,%xmm8
@@ -322,22 +322,22 @@
 	pxor	%xmm1,%xmm8
 	pxor	%xmm3,%xmm4
 	movdqa	%xmm8,%xmm9
-.byte	102,68,15,58,68,234,17
+	pclmulqdq	$0x11,%xmm2,%xmm13
 	pslldq	$8,%xmm8
 	psrldq	$8,%xmm9
 	pxor	%xmm8,%xmm0
 	movdqa	L$7_mask(%rip),%xmm8
 	pxor	%xmm9,%xmm1
-.byte	102,76,15,110,200
+	movq	%rax,%xmm9
 
 	pand	%xmm0,%xmm8
-.byte	102,69,15,56,0,200
+	pshufb	%xmm8,%xmm9
 	pxor	%xmm0,%xmm9
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	psllq	$57,%xmm9
 	movdqa	%xmm9,%xmm8
 	pslldq	$8,%xmm9
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	psrldq	$8,%xmm8
 	pxor	%xmm9,%xmm0
 	pxor	%xmm8,%xmm1
@@ -345,14 +345,14 @@
 
 	movdqa	%xmm0,%xmm9
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,238,17
+	pclmulqdq	$0x11,%xmm6,%xmm5
 	xorps	%xmm11,%xmm3
 	movdqu	16(%rdx),%xmm11
-.byte	102,69,15,56,0,218
-.byte	102,15,58,68,231,16
+	pshufb	%xmm10,%xmm11
+	pclmulqdq	$0x10,%xmm7,%xmm4
 	xorps	%xmm13,%xmm5
 	movups	80(%rsi),%xmm7
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm8
 	pxor	%xmm9,%xmm1
 	pxor	%xmm0,%xmm9
 	psrlq	$5,%xmm0
@@ -363,16 +363,16 @@
 	pxor	%xmm9,%xmm0
 	pxor	%xmm8,%xmm1
 	pxor	%xmm11,%xmm12
-.byte	102,69,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm14,%xmm11
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 	movdqa	%xmm0,%xmm1
-.byte	102,69,15,58,68,238,17
+	pclmulqdq	$0x11,%xmm14,%xmm13
 	xorps	%xmm11,%xmm3
 	pshufd	$78,%xmm0,%xmm8
 	pxor	%xmm0,%xmm8
 
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
@@ -380,9 +380,9 @@
 	jnc	L$mod4_loop
 
 L$tail4x:
-.byte	102,65,15,58,68,199,0
-.byte	102,65,15,58,68,207,17
-.byte	102,68,15,58,68,199,16
+	pclmulqdq	$0x00,%xmm15,%xmm0
+	pclmulqdq	$0x11,%xmm15,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm8
 	xorps	%xmm12,%xmm4
 	xorps	%xmm3,%xmm0
 	xorps	%xmm5,%xmm1
@@ -433,16 +433,16 @@
 
 	movdqu	(%rdx),%xmm8
 	movdqu	16(%rdx),%xmm3
-.byte	102,69,15,56,0,194
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm8
+	pshufb	%xmm10,%xmm3
 	pxor	%xmm8,%xmm0
 
 	movdqa	%xmm3,%xmm5
 	pshufd	$78,%xmm3,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,68,218,0
-.byte	102,15,58,68,234,17
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
+	pclmulqdq	$0x11,%xmm2,%xmm5
+	pclmulqdq	$0x00,%xmm7,%xmm4
 
 	leaq	32(%rdx),%rdx
 	nop
@@ -458,21 +458,21 @@
 	pshufd	$78,%xmm0,%xmm4
 	pxor	%xmm0,%xmm4
 
-.byte	102,15,58,68,198,0
-.byte	102,15,58,68,206,17
-.byte	102,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm0
+	pclmulqdq	$0x11,%xmm6,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm4
 
 	pxor	%xmm3,%xmm0
 	pxor	%xmm5,%xmm1
 	movdqu	(%rdx),%xmm9
 	pxor	%xmm0,%xmm8
-.byte	102,69,15,56,0,202
+	pshufb	%xmm10,%xmm9
 	movdqu	16(%rdx),%xmm3
 
 	pxor	%xmm1,%xmm8
 	pxor	%xmm9,%xmm1
 	pxor	%xmm8,%xmm4
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm3
 	movdqa	%xmm4,%xmm8
 	psrldq	$8,%xmm8
 	pslldq	$8,%xmm4
@@ -485,7 +485,7 @@
 	movdqa	%xmm0,%xmm8
 	psllq	$5,%xmm0
 	pxor	%xmm0,%xmm8
-.byte	102,15,58,68,218,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
 	psllq	$1,%xmm0
 	pxor	%xmm8,%xmm0
 	psllq	$57,%xmm0
@@ -499,14 +499,14 @@
 
 	movdqa	%xmm0,%xmm9
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,234,17
+	pclmulqdq	$0x11,%xmm2,%xmm5
 	pxor	%xmm9,%xmm1
 	pxor	%xmm0,%xmm9
 	psrlq	$5,%xmm0
 	pxor	%xmm9,%xmm0
 	leaq	32(%rdx),%rdx
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm4
 	pxor	%xmm1,%xmm0
 
 	subq	$0x20,%rcx
@@ -518,9 +518,9 @@
 	pshufd	$78,%xmm0,%xmm4
 	pxor	%xmm0,%xmm4
 
-.byte	102,15,58,68,198,0
-.byte	102,15,58,68,206,17
-.byte	102,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm0
+	pclmulqdq	$0x11,%xmm6,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm4
 
 	pxor	%xmm3,%xmm0
 	pxor	%xmm5,%xmm1
@@ -560,14 +560,14 @@
 
 L$odd_tail:
 	movdqu	(%rdx),%xmm8
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm8
 	pxor	%xmm8,%xmm0
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,223,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm7,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -600,7 +600,7 @@
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 L$done:
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 	movdqu	%xmm0,(%rdi)
 	ret
 
diff --git a/src/gen/bcm/ghash-x86_64-linux.S b/src/gen/bcm/ghash-x86_64-linux.S
index e00bb9f..f1ffcb8 100644
--- a/src/gen/bcm/ghash-x86_64-linux.S
+++ b/src/gen/bcm/ghash-x86_64-linux.S
@@ -38,9 +38,9 @@
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -78,14 +78,14 @@
 	movdqu	%xmm2,0(%rdi)
 	pxor	%xmm0,%xmm4
 	movdqu	%xmm0,16(%rdi)
-.byte	102,15,58,15,227,8
+	palignr	$8,%xmm3,%xmm4
 	movdqu	%xmm4,32(%rdi)
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -121,9 +121,9 @@
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -161,7 +161,7 @@
 	movdqu	%xmm5,48(%rdi)
 	pxor	%xmm0,%xmm4
 	movdqu	%xmm0,64(%rdi)
-.byte	102,15,58,15,227,8
+	palignr	$8,%xmm3,%xmm4
 	movdqu	%xmm4,80(%rdi)
 	ret
 .cfi_endproc	
@@ -179,13 +179,13 @@
 	movdqa	.Lbswap_mask(%rip),%xmm5
 	movdqu	(%rsi),%xmm2
 	movdqu	32(%rsi),%xmm4
-.byte	102,15,56,0,197
+	pshufb	%xmm5,%xmm0
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,220,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm4,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -217,7 +217,7 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,197
+	pshufb	%xmm5,%xmm0
 	movdqu	%xmm0,(%rdi)
 	ret
 .cfi_endproc	
@@ -236,7 +236,7 @@
 	movdqu	(%rdi),%xmm0
 	movdqu	(%rsi),%xmm2
 	movdqu	32(%rsi),%xmm7
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 
 	subq	$0x10,%rcx
 	jz	.Lodd_tail
@@ -255,21 +255,21 @@
 
 	movdqu	48(%rdx),%xmm3
 	movdqu	32(%rdx),%xmm11
-.byte	102,65,15,56,0,218
-.byte	102,69,15,56,0,218
+	pshufb	%xmm10,%xmm3
+	pshufb	%xmm10,%xmm11
 	movdqa	%xmm3,%xmm5
 	pshufd	$78,%xmm3,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,68,218,0
-.byte	102,15,58,68,234,17
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
+	pclmulqdq	$0x11,%xmm2,%xmm5
+	pclmulqdq	$0x00,%xmm7,%xmm4
 
 	movdqa	%xmm11,%xmm13
 	pshufd	$78,%xmm11,%xmm12
 	pxor	%xmm11,%xmm12
-.byte	102,68,15,58,68,222,0
-.byte	102,68,15,58,68,238,17
-.byte	102,68,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm11
+	pclmulqdq	$0x11,%xmm6,%xmm13
+	pclmulqdq	$0x10,%xmm7,%xmm12
 	xorps	%xmm11,%xmm3
 	xorps	%xmm13,%xmm5
 	movups	80(%rsi),%xmm7
@@ -277,18 +277,18 @@
 
 	movdqu	16(%rdx),%xmm11
 	movdqu	0(%rdx),%xmm8
-.byte	102,69,15,56,0,218
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm11
+	pshufb	%xmm10,%xmm8
 	movdqa	%xmm11,%xmm13
 	pshufd	$78,%xmm11,%xmm12
 	pxor	%xmm8,%xmm0
 	pxor	%xmm11,%xmm12
-.byte	102,69,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm14,%xmm11
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm8
 	pxor	%xmm0,%xmm8
-.byte	102,69,15,58,68,238,17
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x11,%xmm14,%xmm13
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	xorps	%xmm11,%xmm3
 	xorps	%xmm13,%xmm5
 
@@ -299,22 +299,22 @@
 	jmp	.Lmod4_loop
 .align	32
 .Lmod4_loop:
-.byte	102,65,15,58,68,199,0
+	pclmulqdq	$0x00,%xmm15,%xmm0
 	xorps	%xmm12,%xmm4
 	movdqu	48(%rdx),%xmm11
-.byte	102,69,15,56,0,218
-.byte	102,65,15,58,68,207,17
+	pshufb	%xmm10,%xmm11
+	pclmulqdq	$0x11,%xmm15,%xmm1
 	xorps	%xmm3,%xmm0
 	movdqu	32(%rdx),%xmm3
 	movdqa	%xmm11,%xmm13
-.byte	102,68,15,58,68,199,16
+	pclmulqdq	$0x10,%xmm7,%xmm8
 	pshufd	$78,%xmm11,%xmm12
 	xorps	%xmm5,%xmm1
 	pxor	%xmm11,%xmm12
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm3
 	movups	32(%rsi),%xmm7
 	xorps	%xmm4,%xmm8
-.byte	102,68,15,58,68,218,0
+	pclmulqdq	$0x00,%xmm2,%xmm11
 	pshufd	$78,%xmm3,%xmm4
 
 	pxor	%xmm0,%xmm8
@@ -322,22 +322,22 @@
 	pxor	%xmm1,%xmm8
 	pxor	%xmm3,%xmm4
 	movdqa	%xmm8,%xmm9
-.byte	102,68,15,58,68,234,17
+	pclmulqdq	$0x11,%xmm2,%xmm13
 	pslldq	$8,%xmm8
 	psrldq	$8,%xmm9
 	pxor	%xmm8,%xmm0
 	movdqa	.L7_mask(%rip),%xmm8
 	pxor	%xmm9,%xmm1
-.byte	102,76,15,110,200
+	movq	%rax,%xmm9
 
 	pand	%xmm0,%xmm8
-.byte	102,69,15,56,0,200
+	pshufb	%xmm8,%xmm9
 	pxor	%xmm0,%xmm9
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	psllq	$57,%xmm9
 	movdqa	%xmm9,%xmm8
 	pslldq	$8,%xmm9
-.byte	102,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm6,%xmm3
 	psrldq	$8,%xmm8
 	pxor	%xmm9,%xmm0
 	pxor	%xmm8,%xmm1
@@ -345,14 +345,14 @@
 
 	movdqa	%xmm0,%xmm9
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,238,17
+	pclmulqdq	$0x11,%xmm6,%xmm5
 	xorps	%xmm11,%xmm3
 	movdqu	16(%rdx),%xmm11
-.byte	102,69,15,56,0,218
-.byte	102,15,58,68,231,16
+	pshufb	%xmm10,%xmm11
+	pclmulqdq	$0x10,%xmm7,%xmm4
 	xorps	%xmm13,%xmm5
 	movups	80(%rsi),%xmm7
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm8
 	pxor	%xmm9,%xmm1
 	pxor	%xmm0,%xmm9
 	psrlq	$5,%xmm0
@@ -363,16 +363,16 @@
 	pxor	%xmm9,%xmm0
 	pxor	%xmm8,%xmm1
 	pxor	%xmm11,%xmm12
-.byte	102,69,15,58,68,222,0
+	pclmulqdq	$0x00,%xmm14,%xmm11
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 	movdqa	%xmm0,%xmm1
-.byte	102,69,15,58,68,238,17
+	pclmulqdq	$0x11,%xmm14,%xmm13
 	xorps	%xmm11,%xmm3
 	pshufd	$78,%xmm0,%xmm8
 	pxor	%xmm0,%xmm8
 
-.byte	102,68,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm12
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
@@ -380,9 +380,9 @@
 	jnc	.Lmod4_loop
 
 .Ltail4x:
-.byte	102,65,15,58,68,199,0
-.byte	102,65,15,58,68,207,17
-.byte	102,68,15,58,68,199,16
+	pclmulqdq	$0x00,%xmm15,%xmm0
+	pclmulqdq	$0x11,%xmm15,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm8
 	xorps	%xmm12,%xmm4
 	xorps	%xmm3,%xmm0
 	xorps	%xmm5,%xmm1
@@ -433,16 +433,16 @@
 
 	movdqu	(%rdx),%xmm8
 	movdqu	16(%rdx),%xmm3
-.byte	102,69,15,56,0,194
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm8
+	pshufb	%xmm10,%xmm3
 	pxor	%xmm8,%xmm0
 
 	movdqa	%xmm3,%xmm5
 	pshufd	$78,%xmm3,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,68,218,0
-.byte	102,15,58,68,234,17
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
+	pclmulqdq	$0x11,%xmm2,%xmm5
+	pclmulqdq	$0x00,%xmm7,%xmm4
 
 	leaq	32(%rdx),%rdx
 	nop
@@ -458,21 +458,21 @@
 	pshufd	$78,%xmm0,%xmm4
 	pxor	%xmm0,%xmm4
 
-.byte	102,15,58,68,198,0
-.byte	102,15,58,68,206,17
-.byte	102,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm0
+	pclmulqdq	$0x11,%xmm6,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm4
 
 	pxor	%xmm3,%xmm0
 	pxor	%xmm5,%xmm1
 	movdqu	(%rdx),%xmm9
 	pxor	%xmm0,%xmm8
-.byte	102,69,15,56,0,202
+	pshufb	%xmm10,%xmm9
 	movdqu	16(%rdx),%xmm3
 
 	pxor	%xmm1,%xmm8
 	pxor	%xmm9,%xmm1
 	pxor	%xmm8,%xmm4
-.byte	102,65,15,56,0,218
+	pshufb	%xmm10,%xmm3
 	movdqa	%xmm4,%xmm8
 	psrldq	$8,%xmm8
 	pslldq	$8,%xmm4
@@ -485,7 +485,7 @@
 	movdqa	%xmm0,%xmm8
 	psllq	$5,%xmm0
 	pxor	%xmm0,%xmm8
-.byte	102,15,58,68,218,0
+	pclmulqdq	$0x00,%xmm2,%xmm3
 	psllq	$1,%xmm0
 	pxor	%xmm8,%xmm0
 	psllq	$57,%xmm0
@@ -499,14 +499,14 @@
 
 	movdqa	%xmm0,%xmm9
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,234,17
+	pclmulqdq	$0x11,%xmm2,%xmm5
 	pxor	%xmm9,%xmm1
 	pxor	%xmm0,%xmm9
 	psrlq	$5,%xmm0
 	pxor	%xmm9,%xmm0
 	leaq	32(%rdx),%rdx
 	psrlq	$1,%xmm0
-.byte	102,15,58,68,231,0
+	pclmulqdq	$0x00,%xmm7,%xmm4
 	pxor	%xmm1,%xmm0
 
 	subq	$0x20,%rcx
@@ -518,9 +518,9 @@
 	pshufd	$78,%xmm0,%xmm4
 	pxor	%xmm0,%xmm4
 
-.byte	102,15,58,68,198,0
-.byte	102,15,58,68,206,17
-.byte	102,15,58,68,231,16
+	pclmulqdq	$0x00,%xmm6,%xmm0
+	pclmulqdq	$0x11,%xmm6,%xmm1
+	pclmulqdq	$0x10,%xmm7,%xmm4
 
 	pxor	%xmm3,%xmm0
 	pxor	%xmm5,%xmm1
@@ -560,14 +560,14 @@
 
 .Lodd_tail:
 	movdqu	(%rdx),%xmm8
-.byte	102,69,15,56,0,194
+	pshufb	%xmm10,%xmm8
 	pxor	%xmm8,%xmm0
 	movdqa	%xmm0,%xmm1
 	pshufd	$78,%xmm0,%xmm3
 	pxor	%xmm0,%xmm3
-.byte	102,15,58,68,194,0
-.byte	102,15,58,68,202,17
-.byte	102,15,58,68,223,0
+	pclmulqdq	$0x00,%xmm2,%xmm0
+	pclmulqdq	$0x11,%xmm2,%xmm1
+	pclmulqdq	$0x00,%xmm7,%xmm3
 	pxor	%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 
@@ -600,7 +600,7 @@
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 .Ldone:
-.byte	102,65,15,56,0,194
+	pshufb	%xmm10,%xmm0
 	movdqu	%xmm0,(%rdi)
 	ret
 .cfi_endproc	
diff --git a/src/gen/bcm/ghash-x86_64-win.asm b/src/gen/bcm/ghash-x86_64-win.asm
index b5416b3..5cfb844 100644
--- a/src/gen/bcm/ghash-x86_64-win.asm
+++ b/src/gen/bcm/ghash-x86_64-win.asm
@@ -50,9 +50,9 @@
 	movdqa	xmm1,xmm0
 	pshufd	xmm3,xmm0,78
 	pxor	xmm3,xmm0
-DB	102,15,58,68,194,0
-DB	102,15,58,68,202,17
-DB	102,15,58,68,222,0
+	pclmulqdq	xmm0,xmm2,0x00
+	pclmulqdq	xmm1,xmm2,0x11
+	pclmulqdq	xmm3,xmm6,0x00
 	pxor	xmm3,xmm0
 	pxor	xmm3,xmm1
 
@@ -90,14 +90,14 @@
 	movdqu	XMMWORD[rcx],xmm2
 	pxor	xmm4,xmm0
 	movdqu	XMMWORD[16+rcx],xmm0
-DB	102,15,58,15,227,8
+	palignr	xmm4,xmm3,8
 	movdqu	XMMWORD[32+rcx],xmm4
 	movdqa	xmm1,xmm0
 	pshufd	xmm3,xmm0,78
 	pxor	xmm3,xmm0
-DB	102,15,58,68,194,0
-DB	102,15,58,68,202,17
-DB	102,15,58,68,222,0
+	pclmulqdq	xmm0,xmm2,0x00
+	pclmulqdq	xmm1,xmm2,0x11
+	pclmulqdq	xmm3,xmm6,0x00
 	pxor	xmm3,xmm0
 	pxor	xmm3,xmm1
 
@@ -133,9 +133,9 @@
 	movdqa	xmm1,xmm0
 	pshufd	xmm3,xmm0,78
 	pxor	xmm3,xmm0
-DB	102,15,58,68,194,0
-DB	102,15,58,68,202,17
-DB	102,15,58,68,222,0
+	pclmulqdq	xmm0,xmm2,0x00
+	pclmulqdq	xmm1,xmm2,0x11
+	pclmulqdq	xmm3,xmm6,0x00
 	pxor	xmm3,xmm0
 	pxor	xmm3,xmm1
 
@@ -173,7 +173,7 @@
 	movdqu	XMMWORD[48+rcx],xmm5
 	pxor	xmm4,xmm0
 	movdqu	XMMWORD[64+rcx],xmm0
-DB	102,15,58,15,227,8
+	palignr	xmm4,xmm3,8
 	movdqu	XMMWORD[80+rcx],xmm4
 	movaps	xmm6,XMMWORD[rsp]
 	lea	rsp,[24+rsp]
@@ -192,13 +192,13 @@
 	movdqa	xmm5,XMMWORD[$L$bswap_mask]
 	movdqu	xmm2,XMMWORD[rdx]
 	movdqu	xmm4,XMMWORD[32+rdx]
-DB	102,15,56,0,197
+	pshufb	xmm0,xmm5
 	movdqa	xmm1,xmm0
 	pshufd	xmm3,xmm0,78
 	pxor	xmm3,xmm0
-DB	102,15,58,68,194,0
-DB	102,15,58,68,202,17
-DB	102,15,58,68,220,0
+	pclmulqdq	xmm0,xmm2,0x00
+	pclmulqdq	xmm1,xmm2,0x11
+	pclmulqdq	xmm3,xmm4,0x00
 	pxor	xmm3,xmm0
 	pxor	xmm3,xmm1
 
@@ -230,7 +230,7 @@
 	pxor	xmm0,xmm4
 	psrlq	xmm0,1
 	pxor	xmm0,xmm1
-DB	102,15,56,0,197
+	pshufb	xmm0,xmm5
 	movdqu	XMMWORD[rcx],xmm0
 	ret
 
@@ -272,7 +272,7 @@
 	movdqu	xmm0,XMMWORD[rcx]
 	movdqu	xmm2,XMMWORD[rdx]
 	movdqu	xmm7,XMMWORD[32+rdx]
-DB	102,65,15,56,0,194
+	pshufb	xmm0,xmm10
 
 	sub	r9,0x10
 	jz	NEAR $L$odd_tail
@@ -291,21 +291,21 @@
 
 	movdqu	xmm3,XMMWORD[48+r8]
 	movdqu	xmm11,XMMWORD[32+r8]
-DB	102,65,15,56,0,218
-DB	102,69,15,56,0,218
+	pshufb	xmm3,xmm10
+	pshufb	xmm11,xmm10
 	movdqa	xmm5,xmm3
 	pshufd	xmm4,xmm3,78
 	pxor	xmm4,xmm3
-DB	102,15,58,68,218,0
-DB	102,15,58,68,234,17
-DB	102,15,58,68,231,0
+	pclmulqdq	xmm3,xmm2,0x00
+	pclmulqdq	xmm5,xmm2,0x11
+	pclmulqdq	xmm4,xmm7,0x00
 
 	movdqa	xmm13,xmm11
 	pshufd	xmm12,xmm11,78
 	pxor	xmm12,xmm11
-DB	102,68,15,58,68,222,0
-DB	102,68,15,58,68,238,17
-DB	102,68,15,58,68,231,16
+	pclmulqdq	xmm11,xmm6,0x00
+	pclmulqdq	xmm13,xmm6,0x11
+	pclmulqdq	xmm12,xmm7,0x10
 	xorps	xmm3,xmm11
 	xorps	xmm5,xmm13
 	movups	xmm7,XMMWORD[80+rdx]
@@ -313,18 +313,18 @@
 
 	movdqu	xmm11,XMMWORD[16+r8]
 	movdqu	xmm8,XMMWORD[r8]
-DB	102,69,15,56,0,218
-DB	102,69,15,56,0,194
+	pshufb	xmm11,xmm10
+	pshufb	xmm8,xmm10
 	movdqa	xmm13,xmm11
 	pshufd	xmm12,xmm11,78
 	pxor	xmm0,xmm8
 	pxor	xmm12,xmm11
-DB	102,69,15,58,68,222,0
+	pclmulqdq	xmm11,xmm14,0x00
 	movdqa	xmm1,xmm0
 	pshufd	xmm8,xmm0,78
 	pxor	xmm8,xmm0
-DB	102,69,15,58,68,238,17
-DB	102,68,15,58,68,231,0
+	pclmulqdq	xmm13,xmm14,0x11
+	pclmulqdq	xmm12,xmm7,0x00
 	xorps	xmm3,xmm11
 	xorps	xmm5,xmm13
 
@@ -335,22 +335,22 @@
 	jmp	NEAR $L$mod4_loop
 ALIGN	32
 $L$mod4_loop:
-DB	102,65,15,58,68,199,0
+	pclmulqdq	xmm0,xmm15,0x00
 	xorps	xmm4,xmm12
 	movdqu	xmm11,XMMWORD[48+r8]
-DB	102,69,15,56,0,218
-DB	102,65,15,58,68,207,17
+	pshufb	xmm11,xmm10
+	pclmulqdq	xmm1,xmm15,0x11
 	xorps	xmm0,xmm3
 	movdqu	xmm3,XMMWORD[32+r8]
 	movdqa	xmm13,xmm11
-DB	102,68,15,58,68,199,16
+	pclmulqdq	xmm8,xmm7,0x10
 	pshufd	xmm12,xmm11,78
 	xorps	xmm1,xmm5
 	pxor	xmm12,xmm11
-DB	102,65,15,56,0,218
+	pshufb	xmm3,xmm10
 	movups	xmm7,XMMWORD[32+rdx]
 	xorps	xmm8,xmm4
-DB	102,68,15,58,68,218,0
+	pclmulqdq	xmm11,xmm2,0x00
 	pshufd	xmm4,xmm3,78
 
 	pxor	xmm8,xmm0
@@ -358,22 +358,22 @@
 	pxor	xmm8,xmm1
 	pxor	xmm4,xmm3
 	movdqa	xmm9,xmm8
-DB	102,68,15,58,68,234,17
+	pclmulqdq	xmm13,xmm2,0x11
 	pslldq	xmm8,8
 	psrldq	xmm9,8
 	pxor	xmm0,xmm8
 	movdqa	xmm8,XMMWORD[$L$7_mask]
 	pxor	xmm1,xmm9
-DB	102,76,15,110,200
+	movq	xmm9,rax
 
 	pand	xmm8,xmm0
-DB	102,69,15,56,0,200
+	pshufb	xmm9,xmm8
 	pxor	xmm9,xmm0
-DB	102,68,15,58,68,231,0
+	pclmulqdq	xmm12,xmm7,0x00
 	psllq	xmm9,57
 	movdqa	xmm8,xmm9
 	pslldq	xmm9,8
-DB	102,15,58,68,222,0
+	pclmulqdq	xmm3,xmm6,0x00
 	psrldq	xmm8,8
 	pxor	xmm0,xmm9
 	pxor	xmm1,xmm8
@@ -381,14 +381,14 @@
 
 	movdqa	xmm9,xmm0
 	psrlq	xmm0,1
-DB	102,15,58,68,238,17
+	pclmulqdq	xmm5,xmm6,0x11
 	xorps	xmm3,xmm11
 	movdqu	xmm11,XMMWORD[16+r8]
-DB	102,69,15,56,0,218
-DB	102,15,58,68,231,16
+	pshufb	xmm11,xmm10
+	pclmulqdq	xmm4,xmm7,0x10
 	xorps	xmm5,xmm13
 	movups	xmm7,XMMWORD[80+rdx]
-DB	102,69,15,56,0,194
+	pshufb	xmm8,xmm10
 	pxor	xmm1,xmm9
 	pxor	xmm9,xmm0
 	psrlq	xmm0,5
@@ -399,16 +399,16 @@
 	pxor	xmm0,xmm9
 	pxor	xmm1,xmm8
 	pxor	xmm12,xmm11
-DB	102,69,15,58,68,222,0
+	pclmulqdq	xmm11,xmm14,0x00
 	psrlq	xmm0,1
 	pxor	xmm0,xmm1
 	movdqa	xmm1,xmm0
-DB	102,69,15,58,68,238,17
+	pclmulqdq	xmm13,xmm14,0x11
 	xorps	xmm3,xmm11
 	pshufd	xmm8,xmm0,78
 	pxor	xmm8,xmm0
 
-DB	102,68,15,58,68,231,0
+	pclmulqdq	xmm12,xmm7,0x00
 	xorps	xmm5,xmm13
 
 	lea	r8,[64+r8]
@@ -416,9 +416,9 @@
 	jnc	NEAR $L$mod4_loop
 
 $L$tail4x:
-DB	102,65,15,58,68,199,0
-DB	102,65,15,58,68,207,17
-DB	102,68,15,58,68,199,16
+	pclmulqdq	xmm0,xmm15,0x00
+	pclmulqdq	xmm1,xmm15,0x11
+	pclmulqdq	xmm8,xmm7,0x10
 	xorps	xmm4,xmm12
 	xorps	xmm0,xmm3
 	xorps	xmm1,xmm5
@@ -469,16 +469,16 @@
 
 	movdqu	xmm8,XMMWORD[r8]
 	movdqu	xmm3,XMMWORD[16+r8]
-DB	102,69,15,56,0,194
-DB	102,65,15,56,0,218
+	pshufb	xmm8,xmm10
+	pshufb	xmm3,xmm10
 	pxor	xmm0,xmm8
 
 	movdqa	xmm5,xmm3
 	pshufd	xmm4,xmm3,78
 	pxor	xmm4,xmm3
-DB	102,15,58,68,218,0
-DB	102,15,58,68,234,17
-DB	102,15,58,68,231,0
+	pclmulqdq	xmm3,xmm2,0x00
+	pclmulqdq	xmm5,xmm2,0x11
+	pclmulqdq	xmm4,xmm7,0x00
 
 	lea	r8,[32+r8]
 	nop
@@ -494,21 +494,21 @@
 	pshufd	xmm4,xmm0,78
 	pxor	xmm4,xmm0
 
-DB	102,15,58,68,198,0
-DB	102,15,58,68,206,17
-DB	102,15,58,68,231,16
+	pclmulqdq	xmm0,xmm6,0x00
+	pclmulqdq	xmm1,xmm6,0x11
+	pclmulqdq	xmm4,xmm7,0x10
 
 	pxor	xmm0,xmm3
 	pxor	xmm1,xmm5
 	movdqu	xmm9,XMMWORD[r8]
 	pxor	xmm8,xmm0
-DB	102,69,15,56,0,202
+	pshufb	xmm9,xmm10
 	movdqu	xmm3,XMMWORD[16+r8]
 
 	pxor	xmm8,xmm1
 	pxor	xmm1,xmm9
 	pxor	xmm4,xmm8
-DB	102,65,15,56,0,218
+	pshufb	xmm3,xmm10
 	movdqa	xmm8,xmm4
 	psrldq	xmm8,8
 	pslldq	xmm4,8
@@ -521,7 +521,7 @@
 	movdqa	xmm8,xmm0
 	psllq	xmm0,5
 	pxor	xmm8,xmm0
-DB	102,15,58,68,218,0
+	pclmulqdq	xmm3,xmm2,0x00
 	psllq	xmm0,1
 	pxor	xmm0,xmm8
 	psllq	xmm0,57
@@ -535,14 +535,14 @@
 
 	movdqa	xmm9,xmm0
 	psrlq	xmm0,1
-DB	102,15,58,68,234,17
+	pclmulqdq	xmm5,xmm2,0x11
 	pxor	xmm1,xmm9
 	pxor	xmm9,xmm0
 	psrlq	xmm0,5
 	pxor	xmm0,xmm9
 	lea	r8,[32+r8]
 	psrlq	xmm0,1
-DB	102,15,58,68,231,0
+	pclmulqdq	xmm4,xmm7,0x00
 	pxor	xmm0,xmm1
 
 	sub	r9,0x20
@@ -554,9 +554,9 @@
 	pshufd	xmm4,xmm0,78
 	pxor	xmm4,xmm0
 
-DB	102,15,58,68,198,0
-DB	102,15,58,68,206,17
-DB	102,15,58,68,231,16
+	pclmulqdq	xmm0,xmm6,0x00
+	pclmulqdq	xmm1,xmm6,0x11
+	pclmulqdq	xmm4,xmm7,0x10
 
 	pxor	xmm0,xmm3
 	pxor	xmm1,xmm5
@@ -596,14 +596,14 @@
 
 $L$odd_tail:
 	movdqu	xmm8,XMMWORD[r8]
-DB	102,69,15,56,0,194
+	pshufb	xmm8,xmm10
 	pxor	xmm0,xmm8
 	movdqa	xmm1,xmm0
 	pshufd	xmm3,xmm0,78
 	pxor	xmm3,xmm0
-DB	102,15,58,68,194,0
-DB	102,15,58,68,202,17
-DB	102,15,58,68,223,0
+	pclmulqdq	xmm0,xmm2,0x00
+	pclmulqdq	xmm1,xmm2,0x11
+	pclmulqdq	xmm3,xmm7,0x00
 	pxor	xmm3,xmm0
 	pxor	xmm3,xmm1
 
@@ -636,7 +636,7 @@
 	psrlq	xmm0,1
 	pxor	xmm0,xmm1
 $L$done:
-DB	102,65,15,56,0,194
+	pshufb	xmm0,xmm10
 	movdqu	XMMWORD[rcx],xmm0
 	movaps	xmm6,XMMWORD[rsp]
 	movaps	xmm7,XMMWORD[16+rsp]
diff --git a/src/gen/bcm/p256-x86_64-asm-apple.S b/src/gen/bcm/p256-x86_64-asm-apple.S
index d43fcfc..80ffa01 100644
--- a/src/gen/bcm/p256-x86_64-asm-apple.S
+++ b/src/gen/bcm/p256-x86_64-asm-apple.S
@@ -450,21 +450,21 @@
 	movq	%rax,%rbp
 	mulq	%r8
 	movq	%rax,%r9
-.byte	102,72,15,110,205
+	movq	%rbp,%xmm1
 	movq	%r14,%rax
 	movq	%rdx,%r10
 
 	mulq	%r8
 	addq	%rax,%r10
 	movq	%r15,%rax
-.byte	102,73,15,110,214
+	movq	%r14,%xmm2
 	adcq	$0,%rdx
 	movq	%rdx,%r11
 
 	mulq	%r8
 	addq	%rax,%r11
 	movq	%r15,%rax
-.byte	102,73,15,110,223
+	movq	%r15,%xmm3
 	adcq	$0,%rdx
 	movq	%rdx,%r12
 
@@ -503,20 +503,20 @@
 
 	mulq	%rax
 	movq	%rax,%r8
-.byte	102,72,15,126,200
+	movq	%xmm1,%rax
 	movq	%rdx,%rbp
 
 	mulq	%rax
 	addq	%rbp,%r9
 	adcq	%rax,%r10
-.byte	102,72,15,126,208
+	movq	%xmm2,%rax
 	adcq	$0,%rdx
 	movq	%rdx,%rbp
 
 	mulq	%rax
 	addq	%rbp,%r11
 	adcq	%rax,%r12
-.byte	102,72,15,126,216
+	movq	%xmm3,%rax
 	adcq	$0,%rdx
 	movq	%rdx,%rbp
 
@@ -977,11 +977,11 @@
 	mulxq	%r14,%r9,%r10
 	mulxq	%r15,%rcx,%r11
 	movq	%rdx,%rax
-.byte	102,73,15,110,206
+	movq	%r14,%xmm1
 	mulxq	%r8,%rbp,%r12
 	movq	%r14,%rdx
 	addq	%rcx,%r10
-.byte	102,73,15,110,215
+	movq	%r15,%xmm2
 	adcq	%rbp,%r11
 	adcq	$0,%r12
 	xorq	%r13,%r13
@@ -998,7 +998,7 @@
 
 	mulxq	%r8,%rcx,%r14
 	movq	%rax,%rdx
-.byte	102,73,15,110,216
+	movq	%r8,%xmm3
 	xorq	%r15,%r15
 	adcxq	%r9,%r9
 	adoxq	%rcx,%r13
@@ -1007,18 +1007,18 @@
 
 
 	mulxq	%rdx,%r8,%rbp
-.byte	102,72,15,126,202
+	movq	%xmm1,%rdx
 	adcxq	%r11,%r11
 	adoxq	%rbp,%r9
 	adcxq	%r12,%r12
 	mulxq	%rdx,%rcx,%rax
-.byte	102,72,15,126,210
+	movq	%xmm2,%rdx
 	adcxq	%r13,%r13
 	adoxq	%rcx,%r10
 	adcxq	%r14,%r14
 	mulxq	%rdx,%rcx,%rbp
 .byte	0x67
-.byte	102,72,15,126,218
+	movq	%xmm3,%rdx
 	adoxq	%rax,%r11
 	adcxq	%r15,%r15
 	adoxq	%rcx,%r12
@@ -2462,9 +2462,9 @@
 	movdqa	%xmm1,96+16(%rsp)
 	leaq	32(%rdi),%r10
 	leaq	64(%rdi),%r11
-.byte	102,72,15,110,199
-.byte	102,73,15,110,202
-.byte	102,73,15,110,211
+	movq	%rdi,%xmm0
+	movq	%r10,%xmm1
+	movq	%r11,%xmm2
 
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_by_2q
@@ -2492,7 +2492,7 @@
 	movq	64+24(%rbx),%r12
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rbx),%rbx
-.byte	102,72,15,126,215
+	movq	%xmm2,%rdi
 	call	__ecp_nistz256_mul_montq
 	call	__ecp_nistz256_mul_by_2q
 
@@ -2517,7 +2517,7 @@
 	leaq	0+0(%rsp),%rsi
 	movq	16+0(%rsp),%r15
 	movq	24+0(%rsp),%r8
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sqr_montq
 	xorq	%r9,%r9
 	movq	%r12,%rax
@@ -2592,7 +2592,7 @@
 	leaq	0+32(%rsp),%rsi
 	movq	16+32(%rsp),%r15
 	movq	24+32(%rsp),%r8
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	call	__ecp_nistz256_sqr_montq
 
 	leaq	128(%rsp),%rbx
@@ -2625,8 +2625,8 @@
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_montq
 
-.byte	102,72,15,126,203
-.byte	102,72,15,126,207
+	movq	%xmm1,%rbx
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sub_fromq
 
 	leaq	160+56(%rsp),%rsi
@@ -2708,7 +2708,7 @@
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 
 	leaq	64-0(%rsi),%rsi
 	movq	%rax,544+0(%rsp)
@@ -2731,7 +2731,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
-.byte	102,72,15,110,203
+	movq	%rbx,%xmm1
 
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -2786,7 +2786,7 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 	por	%xmm5,%xmm2
-.byte	102,73,15,110,220
+	movq	%r12,%xmm3
 
 	movq	384(%rsp),%rax
 	leaq	384(%rsp),%rbx
@@ -2816,8 +2816,8 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 
-.byte	102,73,15,126,208
-.byte	102,73,15,126,217
+	movq	%xmm2,%r8
+	movq	%xmm3,%r9
 	orq	%r8,%r12
 .byte	0x3e
 	jnz	L$add_proceedq
@@ -2832,7 +2832,7 @@
 
 
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	pxor	%xmm0,%xmm0
 	movdqu	%xmm0,0(%rdi)
 	movdqu	%xmm0,16(%rdi)
@@ -2844,8 +2844,8 @@
 
 .p2align	5
 L$add_doubleq:
-.byte	102,72,15,126,206
-.byte	102,72,15,126,199
+	movq	%xmm1,%rsi
+	movq	%xmm0,%rdi
 	addq	$416,%rsp
 
 	jmp	L$point_double_shortcutq
@@ -2981,7 +2981,7 @@
 	leaq	320(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromq
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -3128,7 +3128,7 @@
 	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 	movdqa	%xmm2,448(%rsp)
 	movdqa	%xmm3,448+16(%rsp)
 	por	%xmm2,%xmm3
@@ -3306,7 +3306,7 @@
 	leaq	256(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromq
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -3572,9 +3572,9 @@
 	movdqa	%xmm1,96+16(%rsp)
 	leaq	32(%rdi),%r10
 	leaq	64(%rdi),%r11
-.byte	102,72,15,110,199
-.byte	102,73,15,110,202
-.byte	102,73,15,110,211
+	movq	%rdi,%xmm0
+	movq	%r10,%xmm1
+	movq	%r11,%xmm2
 
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_by_2x
@@ -3602,7 +3602,7 @@
 	movq	64+24(%rbx),%r12
 	leaq	64-128(%rbx),%rsi
 	leaq	32(%rbx),%rbx
-.byte	102,72,15,126,215
+	movq	%xmm2,%rdi
 	call	__ecp_nistz256_mul_montx
 	call	__ecp_nistz256_mul_by_2x
 
@@ -3627,7 +3627,7 @@
 	leaq	-128+0(%rsp),%rsi
 	movq	16+0(%rsp),%r15
 	movq	24+0(%rsp),%r8
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sqr_montx
 	xorq	%r9,%r9
 	movq	%r12,%rax
@@ -3702,7 +3702,7 @@
 	leaq	-128+32(%rsp),%rsi
 	movq	16+32(%rsp),%r15
 	movq	24+32(%rsp),%r8
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	call	__ecp_nistz256_sqr_montx
 
 	leaq	128(%rsp),%rbx
@@ -3735,8 +3735,8 @@
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_montx
 
-.byte	102,72,15,126,203
-.byte	102,72,15,126,207
+	movq	%xmm1,%rbx
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sub_fromx
 
 	leaq	160+56(%rsp),%rsi
@@ -3818,7 +3818,7 @@
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 
 	leaq	64-128(%rsi),%rsi
 	movq	%rdx,544+0(%rsp)
@@ -3841,7 +3841,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
-.byte	102,72,15,110,203
+	movq	%rbx,%xmm1
 
 	leaq	64-128(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -3896,7 +3896,7 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 	por	%xmm5,%xmm2
-.byte	102,73,15,110,220
+	movq	%r12,%xmm3
 
 	movq	384(%rsp),%rdx
 	leaq	384(%rsp),%rbx
@@ -3926,8 +3926,8 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 
-.byte	102,73,15,126,208
-.byte	102,73,15,126,217
+	movq	%xmm2,%r8
+	movq	%xmm3,%r9
 	orq	%r8,%r12
 .byte	0x3e
 	jnz	L$add_proceedx
@@ -3942,7 +3942,7 @@
 
 
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	pxor	%xmm0,%xmm0
 	movdqu	%xmm0,0(%rdi)
 	movdqu	%xmm0,16(%rdi)
@@ -3954,8 +3954,8 @@
 
 .p2align	5
 L$add_doublex:
-.byte	102,72,15,126,206
-.byte	102,72,15,126,199
+	movq	%xmm1,%rsi
+	movq	%xmm0,%rdi
 	addq	$416,%rsp
 
 	jmp	L$point_double_shortcutx
@@ -4091,7 +4091,7 @@
 	leaq	320(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromx
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -4238,7 +4238,7 @@
 	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 	movdqa	%xmm2,448(%rsp)
 	movdqa	%xmm3,448+16(%rsp)
 	por	%xmm2,%xmm3
@@ -4416,7 +4416,7 @@
 	leaq	256(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromx
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
diff --git a/src/gen/bcm/p256-x86_64-asm-linux.S b/src/gen/bcm/p256-x86_64-asm-linux.S
index b14ef80..c54d577 100644
--- a/src/gen/bcm/p256-x86_64-asm-linux.S
+++ b/src/gen/bcm/p256-x86_64-asm-linux.S
@@ -464,21 +464,21 @@
 	movq	%rax,%rbp
 	mulq	%r8
 	movq	%rax,%r9
-.byte	102,72,15,110,205
+	movq	%rbp,%xmm1
 	movq	%r14,%rax
 	movq	%rdx,%r10
 
 	mulq	%r8
 	addq	%rax,%r10
 	movq	%r15,%rax
-.byte	102,73,15,110,214
+	movq	%r14,%xmm2
 	adcq	$0,%rdx
 	movq	%rdx,%r11
 
 	mulq	%r8
 	addq	%rax,%r11
 	movq	%r15,%rax
-.byte	102,73,15,110,223
+	movq	%r15,%xmm3
 	adcq	$0,%rdx
 	movq	%rdx,%r12
 
@@ -517,20 +517,20 @@
 
 	mulq	%rax
 	movq	%rax,%r8
-.byte	102,72,15,126,200
+	movq	%xmm1,%rax
 	movq	%rdx,%rbp
 
 	mulq	%rax
 	addq	%rbp,%r9
 	adcq	%rax,%r10
-.byte	102,72,15,126,208
+	movq	%xmm2,%rax
 	adcq	$0,%rdx
 	movq	%rdx,%rbp
 
 	mulq	%rax
 	addq	%rbp,%r11
 	adcq	%rax,%r12
-.byte	102,72,15,126,216
+	movq	%xmm3,%rax
 	adcq	$0,%rdx
 	movq	%rdx,%rbp
 
@@ -1003,11 +1003,11 @@
 	mulxq	%r14,%r9,%r10
 	mulxq	%r15,%rcx,%r11
 	movq	%rdx,%rax
-.byte	102,73,15,110,206
+	movq	%r14,%xmm1
 	mulxq	%r8,%rbp,%r12
 	movq	%r14,%rdx
 	addq	%rcx,%r10
-.byte	102,73,15,110,215
+	movq	%r15,%xmm2
 	adcq	%rbp,%r11
 	adcq	$0,%r12
 	xorq	%r13,%r13
@@ -1024,7 +1024,7 @@
 
 	mulxq	%r8,%rcx,%r14
 	movq	%rax,%rdx
-.byte	102,73,15,110,216
+	movq	%r8,%xmm3
 	xorq	%r15,%r15
 	adcxq	%r9,%r9
 	adoxq	%rcx,%r13
@@ -1033,18 +1033,18 @@
 
 
 	mulxq	%rdx,%r8,%rbp
-.byte	102,72,15,126,202
+	movq	%xmm1,%rdx
 	adcxq	%r11,%r11
 	adoxq	%rbp,%r9
 	adcxq	%r12,%r12
 	mulxq	%rdx,%rcx,%rax
-.byte	102,72,15,126,210
+	movq	%xmm2,%rdx
 	adcxq	%r13,%r13
 	adoxq	%rcx,%r10
 	adcxq	%r14,%r14
 	mulxq	%rdx,%rcx,%rbp
 .byte	0x67
-.byte	102,72,15,126,218
+	movq	%xmm3,%rdx
 	adoxq	%rax,%r11
 	adcxq	%r15,%r15
 	adoxq	%rcx,%r12
@@ -2518,9 +2518,9 @@
 	movdqa	%xmm1,96+16(%rsp)
 	leaq	32(%rdi),%r10
 	leaq	64(%rdi),%r11
-.byte	102,72,15,110,199
-.byte	102,73,15,110,202
-.byte	102,73,15,110,211
+	movq	%rdi,%xmm0
+	movq	%r10,%xmm1
+	movq	%r11,%xmm2
 
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_by_2q
@@ -2548,7 +2548,7 @@
 	movq	64+24(%rbx),%r12
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rbx),%rbx
-.byte	102,72,15,126,215
+	movq	%xmm2,%rdi
 	call	__ecp_nistz256_mul_montq
 	call	__ecp_nistz256_mul_by_2q
 
@@ -2573,7 +2573,7 @@
 	leaq	0+0(%rsp),%rsi
 	movq	16+0(%rsp),%r15
 	movq	24+0(%rsp),%r8
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sqr_montq
 	xorq	%r9,%r9
 	movq	%r12,%rax
@@ -2648,7 +2648,7 @@
 	leaq	0+32(%rsp),%rsi
 	movq	16+32(%rsp),%r15
 	movq	24+32(%rsp),%r8
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	call	__ecp_nistz256_sqr_montq
 
 	leaq	128(%rsp),%rbx
@@ -2681,8 +2681,8 @@
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_montq
 
-.byte	102,72,15,126,203
-.byte	102,72,15,126,207
+	movq	%xmm1,%rbx
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sub_fromq
 
 	leaq	160+56(%rsp),%rsi
@@ -2770,7 +2770,7 @@
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 
 	leaq	64-0(%rsi),%rsi
 	movq	%rax,544+0(%rsp)
@@ -2793,7 +2793,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
-.byte	102,72,15,110,203
+	movq	%rbx,%xmm1
 
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -2848,7 +2848,7 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 	por	%xmm5,%xmm2
-.byte	102,73,15,110,220
+	movq	%r12,%xmm3
 
 	movq	384(%rsp),%rax
 	leaq	384(%rsp),%rbx
@@ -2878,8 +2878,8 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 
-.byte	102,73,15,126,208
-.byte	102,73,15,126,217
+	movq	%xmm2,%r8
+	movq	%xmm3,%r9
 	orq	%r8,%r12
 .byte	0x3e
 	jnz	.Ladd_proceedq
@@ -2894,7 +2894,7 @@
 
 
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	pxor	%xmm0,%xmm0
 	movdqu	%xmm0,0(%rdi)
 	movdqu	%xmm0,16(%rdi)
@@ -2906,8 +2906,8 @@
 
 .align	32
 .Ladd_doubleq:
-.byte	102,72,15,126,206
-.byte	102,72,15,126,199
+	movq	%xmm1,%rsi
+	movq	%xmm0,%rdi
 	addq	$416,%rsp
 .cfi_adjust_cfa_offset	-416
 	jmp	.Lpoint_double_shortcutq
@@ -3043,7 +3043,7 @@
 	leaq	320(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromq
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -3196,7 +3196,7 @@
 	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 	movdqa	%xmm2,448(%rsp)
 	movdqa	%xmm3,448+16(%rsp)
 	por	%xmm2,%xmm3
@@ -3374,7 +3374,7 @@
 	leaq	256(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromq
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -3646,9 +3646,9 @@
 	movdqa	%xmm1,96+16(%rsp)
 	leaq	32(%rdi),%r10
 	leaq	64(%rdi),%r11
-.byte	102,72,15,110,199
-.byte	102,73,15,110,202
-.byte	102,73,15,110,211
+	movq	%rdi,%xmm0
+	movq	%r10,%xmm1
+	movq	%r11,%xmm2
 
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_by_2x
@@ -3676,7 +3676,7 @@
 	movq	64+24(%rbx),%r12
 	leaq	64-128(%rbx),%rsi
 	leaq	32(%rbx),%rbx
-.byte	102,72,15,126,215
+	movq	%xmm2,%rdi
 	call	__ecp_nistz256_mul_montx
 	call	__ecp_nistz256_mul_by_2x
 
@@ -3701,7 +3701,7 @@
 	leaq	-128+0(%rsp),%rsi
 	movq	16+0(%rsp),%r15
 	movq	24+0(%rsp),%r8
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sqr_montx
 	xorq	%r9,%r9
 	movq	%r12,%rax
@@ -3776,7 +3776,7 @@
 	leaq	-128+32(%rsp),%rsi
 	movq	16+32(%rsp),%r15
 	movq	24+32(%rsp),%r8
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	call	__ecp_nistz256_sqr_montx
 
 	leaq	128(%rsp),%rbx
@@ -3809,8 +3809,8 @@
 	leaq	0(%rsp),%rdi
 	call	__ecp_nistz256_mul_montx
 
-.byte	102,72,15,126,203
-.byte	102,72,15,126,207
+	movq	%xmm1,%rbx
+	movq	%xmm1,%rdi
 	call	__ecp_nistz256_sub_fromx
 
 	leaq	160+56(%rsp),%rsi
@@ -3898,7 +3898,7 @@
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 
 	leaq	64-128(%rsi),%rsi
 	movq	%rdx,544+0(%rsp)
@@ -3921,7 +3921,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
-.byte	102,72,15,110,203
+	movq	%rbx,%xmm1
 
 	leaq	64-128(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -3976,7 +3976,7 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 	por	%xmm5,%xmm2
-.byte	102,73,15,110,220
+	movq	%r12,%xmm3
 
 	movq	384(%rsp),%rdx
 	leaq	384(%rsp),%rbx
@@ -4006,8 +4006,8 @@
 	orq	%r8,%r12
 	orq	%r9,%r12
 
-.byte	102,73,15,126,208
-.byte	102,73,15,126,217
+	movq	%xmm2,%r8
+	movq	%xmm3,%r9
 	orq	%r8,%r12
 .byte	0x3e
 	jnz	.Ladd_proceedx
@@ -4022,7 +4022,7 @@
 
 
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 	pxor	%xmm0,%xmm0
 	movdqu	%xmm0,0(%rdi)
 	movdqu	%xmm0,16(%rdi)
@@ -4034,8 +4034,8 @@
 
 .align	32
 .Ladd_doublex:
-.byte	102,72,15,126,206
-.byte	102,72,15,126,199
+	movq	%xmm1,%rsi
+	movq	%xmm0,%rdi
 	addq	$416,%rsp
 .cfi_adjust_cfa_offset	-416
 	jmp	.Lpoint_double_shortcutx
@@ -4171,7 +4171,7 @@
 	leaq	320(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromx
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
@@ -4324,7 +4324,7 @@
 	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movq	%rdi,%xmm0
 	movdqa	%xmm2,448(%rsp)
 	movdqa	%xmm3,448+16(%rsp)
 	por	%xmm2,%xmm3
@@ -4502,7 +4502,7 @@
 	leaq	256(%rsp),%rdi
 	call	__ecp_nistz256_sub_fromx
 
-.byte	102,72,15,126,199
+	movq	%xmm0,%rdi
 
 	movdqa	%xmm5,%xmm0
 	movdqa	%xmm5,%xmm1
diff --git a/src/gen/bcm/p256-x86_64-asm-win.asm b/src/gen/bcm/p256-x86_64-asm-win.asm
index 10a1c0d..194df1c 100644
--- a/src/gen/bcm/p256-x86_64-asm-win.asm
+++ b/src/gen/bcm/p256-x86_64-asm-win.asm
@@ -486,21 +486,21 @@
 	mov	rbp,rax
 	mul	r8
 	mov	r9,rax
-DB	102,72,15,110,205
+	movq	xmm1,rbp
 	mov	rax,r14
 	mov	r10,rdx
 
 	mul	r8
 	add	r10,rax
 	mov	rax,r15
-DB	102,73,15,110,214
+	movq	xmm2,r14
 	adc	rdx,0
 	mov	r11,rdx
 
 	mul	r8
 	add	r11,rax
 	mov	rax,r15
-DB	102,73,15,110,223
+	movq	xmm3,r15
 	adc	rdx,0
 	mov	r12,rdx
 
@@ -539,20 +539,20 @@
 
 	mul	rax
 	mov	r8,rax
-DB	102,72,15,126,200
+	movq	rax,xmm1
 	mov	rbp,rdx
 
 	mul	rax
 	add	r9,rbp
 	adc	r10,rax
-DB	102,72,15,126,208
+	movq	rax,xmm2
 	adc	rdx,0
 	mov	rbp,rdx
 
 	mul	rax
 	add	r11,rbp
 	adc	r12,rax
-DB	102,72,15,126,216
+	movq	rax,xmm3
 	adc	rdx,0
 	mov	rbp,rdx
 
@@ -1033,11 +1033,11 @@
 	mulx	r10,r9,r14
 	mulx	r11,rcx,r15
 	mov	rax,rdx
-DB	102,73,15,110,206
+	movq	xmm1,r14
 	mulx	r12,rbp,r8
 	mov	rdx,r14
 	add	r10,rcx
-DB	102,73,15,110,215
+	movq	xmm2,r15
 	adc	r11,rbp
 	adc	r12,0
 	xor	r13,r13
@@ -1054,7 +1054,7 @@
 
 	mulx	r14,rcx,r8
 	mov	rdx,rax
-DB	102,73,15,110,216
+	movq	xmm3,r8
 	xor	r15,r15
 	adcx	r9,r9
 	adox	r13,rcx
@@ -1063,18 +1063,18 @@
 
 
 	mulx	rbp,r8,rdx
-DB	102,72,15,126,202
+	movq	rdx,xmm1
 	adcx	r11,r11
 	adox	r9,rbp
 	adcx	r12,r12
 	mulx	rax,rcx,rdx
-DB	102,72,15,126,210
+	movq	rdx,xmm2
 	adcx	r13,r13
 	adox	r10,rcx
 	adcx	r14,r14
 	mulx	rbp,rcx,rdx
 	DB	0x67
-DB	102,72,15,126,218
+	movq	rdx,xmm3
 	adox	r11,rax
 	adcx	r15,r15
 	adox	r12,rcx
@@ -2659,9 +2659,9 @@
 	movdqa	XMMWORD[(96+16)+rsp],xmm1
 	lea	r10,[32+rdi]
 	lea	r11,[64+rdi]
-DB	102,72,15,110,199
-DB	102,73,15,110,202
-DB	102,73,15,110,211
+	movq	xmm0,rdi
+	movq	xmm1,r10
+	movq	xmm2,r11
 
 	lea	rdi,[rsp]
 	call	__ecp_nistz256_mul_by_2q
@@ -2689,7 +2689,7 @@
 	mov	r12,QWORD[((64+24))+rbx]
 	lea	rsi,[((64-0))+rbx]
 	lea	rbx,[32+rbx]
-DB	102,72,15,126,215
+	movq	rdi,xmm2
 	call	__ecp_nistz256_mul_montq
 	call	__ecp_nistz256_mul_by_2q
 
@@ -2714,7 +2714,7 @@
 	lea	rsi,[((0+0))+rsp]
 	mov	r15,QWORD[((16+0))+rsp]
 	mov	r8,QWORD[((24+0))+rsp]
-DB	102,72,15,126,207
+	movq	rdi,xmm1
 	call	__ecp_nistz256_sqr_montq
 	xor	r9,r9
 	mov	rax,r12
@@ -2789,7 +2789,7 @@
 	lea	rsi,[((0+32))+rsp]
 	mov	r15,QWORD[((16+32))+rsp]
 	mov	r8,QWORD[((24+32))+rsp]
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 	call	__ecp_nistz256_sqr_montq
 
 	lea	rbx,[128+rsp]
@@ -2822,8 +2822,8 @@
 	lea	rdi,[rsp]
 	call	__ecp_nistz256_mul_montq
 
-DB	102,72,15,126,203
-DB	102,72,15,126,207
+	movq	rbx,xmm1
+	movq	rdi,xmm1
 	call	__ecp_nistz256_sub_fromq
 
 	lea	rsi,[((160+56))+rsp]
@@ -2915,7 +2915,7 @@
 	por	xmm5,xmm4
 	pxor	xmm4,xmm4
 	por	xmm1,xmm0
-DB	102,72,15,110,199
+	movq	xmm0,rdi
 
 	lea	rsi,[((64-0))+rsi]
 	mov	QWORD[((544+0))+rsp],rax
@@ -2938,7 +2938,7 @@
 	mov	r14,QWORD[((64+8))+rbx]
 	mov	r15,QWORD[((64+16))+rbx]
 	mov	r8,QWORD[((64+24))+rbx]
-DB	102,72,15,110,203
+	movq	xmm1,rbx
 
 	lea	rsi,[((64-0))+rbx]
 	lea	rdi,[32+rsp]
@@ -2993,7 +2993,7 @@
 	or	r12,r8
 	or	r12,r9
 	por	xmm2,xmm5
-DB	102,73,15,110,220
+	movq	xmm3,r12
 
 	mov	rax,QWORD[384+rsp]
 	lea	rbx,[384+rsp]
@@ -3023,8 +3023,8 @@
 	or	r12,r8
 	or	r12,r9
 
-DB	102,73,15,126,208
-DB	102,73,15,126,217
+	movq	r8,xmm2
+	movq	r9,xmm3
 	or	r12,r8
 	DB	0x3e
 	jnz	NEAR $L$add_proceedq
@@ -3039,7 +3039,7 @@
 
 
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 	pxor	xmm0,xmm0
 	movdqu	XMMWORD[rdi],xmm0
 	movdqu	XMMWORD[16+rdi],xmm0
@@ -3051,8 +3051,8 @@
 
 ALIGN	32
 $L$add_doubleq:
-DB	102,72,15,126,206
-DB	102,72,15,126,199
+	movq	rsi,xmm1
+	movq	rdi,xmm0
 	add	rsp,416
 
 	jmp	NEAR $L$point_double_shortcutq
@@ -3188,7 +3188,7 @@
 	lea	rdi,[320+rsp]
 	call	__ecp_nistz256_sub_fromq
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 
 	movdqa	xmm0,xmm5
 	movdqa	xmm1,xmm5
@@ -3345,7 +3345,7 @@
 	pshufd	xmm4,xmm5,0x1e
 	movdqa	XMMWORD[(416+16)+rsp],xmm1
 	por	xmm1,xmm0
-DB	102,72,15,110,199
+	movq	xmm0,rdi
 	movdqa	XMMWORD[448+rsp],xmm2
 	movdqa	XMMWORD[(448+16)+rsp],xmm3
 	por	xmm3,xmm2
@@ -3523,7 +3523,7 @@
 	lea	rdi,[256+rsp]
 	call	__ecp_nistz256_sub_fromq
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 
 	movdqa	xmm0,xmm5
 	movdqa	xmm1,xmm5
@@ -3798,9 +3798,9 @@
 	movdqa	XMMWORD[(96+16)+rsp],xmm1
 	lea	r10,[32+rdi]
 	lea	r11,[64+rdi]
-DB	102,72,15,110,199
-DB	102,73,15,110,202
-DB	102,73,15,110,211
+	movq	xmm0,rdi
+	movq	xmm1,r10
+	movq	xmm2,r11
 
 	lea	rdi,[rsp]
 	call	__ecp_nistz256_mul_by_2x
@@ -3828,7 +3828,7 @@
 	mov	r12,QWORD[((64+24))+rbx]
 	lea	rsi,[((64-128))+rbx]
 	lea	rbx,[32+rbx]
-DB	102,72,15,126,215
+	movq	rdi,xmm2
 	call	__ecp_nistz256_mul_montx
 	call	__ecp_nistz256_mul_by_2x
 
@@ -3853,7 +3853,7 @@
 	lea	rsi,[((-128+0))+rsp]
 	mov	r15,QWORD[((16+0))+rsp]
 	mov	r8,QWORD[((24+0))+rsp]
-DB	102,72,15,126,207
+	movq	rdi,xmm1
 	call	__ecp_nistz256_sqr_montx
 	xor	r9,r9
 	mov	rax,r12
@@ -3928,7 +3928,7 @@
 	lea	rsi,[((-128+32))+rsp]
 	mov	r15,QWORD[((16+32))+rsp]
 	mov	r8,QWORD[((24+32))+rsp]
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 	call	__ecp_nistz256_sqr_montx
 
 	lea	rbx,[128+rsp]
@@ -3961,8 +3961,8 @@
 	lea	rdi,[rsp]
 	call	__ecp_nistz256_mul_montx
 
-DB	102,72,15,126,203
-DB	102,72,15,126,207
+	movq	rbx,xmm1
+	movq	rdi,xmm1
 	call	__ecp_nistz256_sub_fromx
 
 	lea	rsi,[((160+56))+rsp]
@@ -4054,7 +4054,7 @@
 	por	xmm5,xmm4
 	pxor	xmm4,xmm4
 	por	xmm1,xmm0
-DB	102,72,15,110,199
+	movq	xmm0,rdi
 
 	lea	rsi,[((64-128))+rsi]
 	mov	QWORD[((544+0))+rsp],rdx
@@ -4077,7 +4077,7 @@
 	mov	r14,QWORD[((64+8))+rbx]
 	mov	r15,QWORD[((64+16))+rbx]
 	mov	r8,QWORD[((64+24))+rbx]
-DB	102,72,15,110,203
+	movq	xmm1,rbx
 
 	lea	rsi,[((64-128))+rbx]
 	lea	rdi,[32+rsp]
@@ -4132,7 +4132,7 @@
 	or	r12,r8
 	or	r12,r9
 	por	xmm2,xmm5
-DB	102,73,15,110,220
+	movq	xmm3,r12
 
 	mov	rdx,QWORD[384+rsp]
 	lea	rbx,[384+rsp]
@@ -4162,8 +4162,8 @@
 	or	r12,r8
 	or	r12,r9
 
-DB	102,73,15,126,208
-DB	102,73,15,126,217
+	movq	r8,xmm2
+	movq	r9,xmm3
 	or	r12,r8
 	DB	0x3e
 	jnz	NEAR $L$add_proceedx
@@ -4178,7 +4178,7 @@
 
 
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 	pxor	xmm0,xmm0
 	movdqu	XMMWORD[rdi],xmm0
 	movdqu	XMMWORD[16+rdi],xmm0
@@ -4190,8 +4190,8 @@
 
 ALIGN	32
 $L$add_doublex:
-DB	102,72,15,126,206
-DB	102,72,15,126,199
+	movq	rsi,xmm1
+	movq	rdi,xmm0
 	add	rsp,416
 
 	jmp	NEAR $L$point_double_shortcutx
@@ -4327,7 +4327,7 @@
 	lea	rdi,[320+rsp]
 	call	__ecp_nistz256_sub_fromx
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 
 	movdqa	xmm0,xmm5
 	movdqa	xmm1,xmm5
@@ -4484,7 +4484,7 @@
 	pshufd	xmm4,xmm5,0x1e
 	movdqa	XMMWORD[(416+16)+rsp],xmm1
 	por	xmm1,xmm0
-DB	102,72,15,110,199
+	movq	xmm0,rdi
 	movdqa	XMMWORD[448+rsp],xmm2
 	movdqa	XMMWORD[(448+16)+rsp],xmm3
 	por	xmm3,xmm2
@@ -4662,7 +4662,7 @@
 	lea	rdi,[256+rsp]
 	call	__ecp_nistz256_sub_fromx
 
-DB	102,72,15,126,199
+	movq	rdi,xmm0
 
 	movdqa	xmm0,xmm5
 	movdqa	xmm1,xmm5
diff --git a/src/gen/bcm/rdrand-x86_64-apple.S b/src/gen/bcm/rdrand-x86_64-apple.S
index 5fdf105..4f990d9 100644
--- a/src/gen/bcm/rdrand-x86_64-apple.S
+++ b/src/gen/bcm/rdrand-x86_64-apple.S
@@ -17,7 +17,7 @@
 
 _CET_ENDBR
 	xorq	%rax,%rax
-.byte	72,15,199,242
+	rdrand	%rdx
 
 	adcq	%rax,%rax
 	movq	%rdx,0(%rdi)
@@ -40,7 +40,7 @@
 	jz	L$out
 	movq	$8,%rdx
 L$loop:
-.byte	72,15,199,241
+	rdrand	%rcx
 	jnc	L$err
 	movq	%rcx,0(%rdi)
 	addq	%rdx,%rdi
diff --git a/src/gen/bcm/rdrand-x86_64-linux.S b/src/gen/bcm/rdrand-x86_64-linux.S
index fe81dac..52a1eb2 100644
--- a/src/gen/bcm/rdrand-x86_64-linux.S
+++ b/src/gen/bcm/rdrand-x86_64-linux.S
@@ -17,7 +17,7 @@
 .cfi_startproc	
 _CET_ENDBR
 	xorq	%rax,%rax
-.byte	72,15,199,242
+	rdrand	%rdx
 
 	adcq	%rax,%rax
 	movq	%rdx,0(%rdi)
@@ -40,7 +40,7 @@
 	jz	.Lout
 	movq	$8,%rdx
 .Lloop:
-.byte	72,15,199,241
+	rdrand	%rcx
 	jnc	.Lerr
 	movq	%rcx,0(%rdi)
 	addq	%rdx,%rdi
diff --git a/src/gen/bcm/rdrand-x86_64-win.asm b/src/gen/bcm/rdrand-x86_64-win.asm
index aae3d76..6dba87b 100644
--- a/src/gen/bcm/rdrand-x86_64-win.asm
+++ b/src/gen/bcm/rdrand-x86_64-win.asm
@@ -24,7 +24,7 @@
 
 _CET_ENDBR
 	xor	rax,rax
-DB	73,15,199,240
+	rdrand	r8
 
 	adc	rax,rax
 	mov	QWORD[rcx],r8
@@ -46,7 +46,7 @@
 	jz	NEAR $L$out
 	mov	r8,8
 $L$loop:
-DB	73,15,199,241
+	rdrand	r9
 	jnc	NEAR $L$err
 	mov	QWORD[rcx],r9
 	add	rcx,r8
diff --git a/src/gen/bcm/sha1-x86_64-apple.S b/src/gen/bcm/sha1-x86_64-apple.S
index a1ea1e6..32b3bc7 100644
--- a/src/gen/bcm/sha1-x86_64-apple.S
+++ b/src/gen/bcm/sha1-x86_64-apple.S
@@ -1259,12 +1259,12 @@
 	movdqu	16(%rsi),%xmm5
 	pshufd	$27,%xmm1,%xmm1
 	movdqu	32(%rsi),%xmm6
-.byte	102,15,56,0,227
+	pshufb	%xmm3,%xmm4
 	movdqu	48(%rsi),%xmm7
-.byte	102,15,56,0,235
-.byte	102,15,56,0,243
+	pshufb	%xmm3,%xmm5
+	pshufb	%xmm3,%xmm6
 	movdqa	%xmm1,%xmm9
-.byte	102,15,56,0,251
+	pshufb	%xmm3,%xmm7
 	jmp	L$oop_shaext
 
 .p2align	4
@@ -1275,133 +1275,133 @@
 	cmovneq	%r8,%rsi
 	prefetcht0	512(%rsi)
 	movdqa	%xmm0,%xmm8
-.byte	15,56,201,229
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,213
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,0
-.byte	15,56,200,206
+	sha1rnds4	$0,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,215
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,0
-.byte	15,56,200,204
+	sha1rnds4	$0,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,213
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,206
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,1
-.byte	15,56,200,215
+	sha1rnds4	$1,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,204
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,1
-.byte	15,56,200,213
+	sha1rnds4	$1,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,206
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,215
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,2
-.byte	15,56,200,204
+	sha1rnds4	$2,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,213
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,2
-.byte	15,56,200,206
+	sha1rnds4	$2,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,215
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	15,56,200,204
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
+	sha1msg2	%xmm6,%xmm7
 	movdqu	(%rsi),%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,3
-.byte	15,56,200,213
+	sha1rnds4	$3,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	movdqu	16(%rsi),%xmm5
-.byte	102,15,56,0,227
+	pshufb	%xmm3,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	15,56,200,206
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	movdqu	32(%rsi),%xmm6
-.byte	102,15,56,0,235
+	pshufb	%xmm3,%xmm5
 
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,3
-.byte	15,56,200,215
+	sha1rnds4	$3,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	movdqu	48(%rsi),%xmm7
-.byte	102,15,56,0,243
+	pshufb	%xmm3,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	65,15,56,200,201
-.byte	102,15,56,0,251
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm9,%xmm1
+	pshufb	%xmm3,%xmm7
 
 	paddd	%xmm8,%xmm0
 	movdqa	%xmm1,%xmm9
@@ -1460,12 +1460,12 @@
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
 	movdqu	48(%r9),%xmm3
-.byte	102,15,56,0,198
-.byte	102,15,56,0,206
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm0
+	pshufb	%xmm6,%xmm1
+	pshufb	%xmm6,%xmm2
 	addq	$64,%r9
 	paddd	%xmm9,%xmm0
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm9,%xmm1
 	paddd	%xmm9,%xmm2
 	movdqa	%xmm0,0(%rsp)
@@ -2357,12 +2357,12 @@
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
 	movdqu	48(%r9),%xmm3
-.byte	102,15,56,0,198
+	pshufb	%xmm6,%xmm0
 	addq	$64,%r9
 	addl	16(%rsp),%ebx
 	xorl	%ebp,%esi
 	movl	%ecx,%edi
-.byte	102,15,56,0,206
+	pshufb	%xmm6,%xmm1
 	roll	$5,%ecx
 	addl	%esi,%ebx
 	xorl	%ebp,%edi
@@ -2398,7 +2398,7 @@
 	addl	32(%rsp),%ecx
 	xorl	%eax,%esi
 	movl	%edx,%edi
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm2
 	roll	$5,%edx
 	addl	%esi,%ecx
 	xorl	%eax,%edi
@@ -2434,7 +2434,7 @@
 	addl	48(%rsp),%edx
 	xorl	%ebx,%esi
 	movl	%ebp,%edi
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	roll	$5,%ebp
 	addl	%esi,%edx
 	xorl	%ebx,%edi
diff --git a/src/gen/bcm/sha1-x86_64-linux.S b/src/gen/bcm/sha1-x86_64-linux.S
index 39d9ad3..1f4807a 100644
--- a/src/gen/bcm/sha1-x86_64-linux.S
+++ b/src/gen/bcm/sha1-x86_64-linux.S
@@ -1259,12 +1259,12 @@
 	movdqu	16(%rsi),%xmm5
 	pshufd	$27,%xmm1,%xmm1
 	movdqu	32(%rsi),%xmm6
-.byte	102,15,56,0,227
+	pshufb	%xmm3,%xmm4
 	movdqu	48(%rsi),%xmm7
-.byte	102,15,56,0,235
-.byte	102,15,56,0,243
+	pshufb	%xmm3,%xmm5
+	pshufb	%xmm3,%xmm6
 	movdqa	%xmm1,%xmm9
-.byte	102,15,56,0,251
+	pshufb	%xmm3,%xmm7
 	jmp	.Loop_shaext
 
 .align	16
@@ -1275,133 +1275,133 @@
 	cmovneq	%r8,%rsi
 	prefetcht0	512(%rsi)
 	movdqa	%xmm0,%xmm8
-.byte	15,56,201,229
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,213
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,0
-.byte	15,56,200,206
+	sha1rnds4	$0,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,215
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,0
-.byte	15,56,200,204
+	sha1rnds4	$0,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,0
-.byte	15,56,200,213
+	sha1rnds4	$0,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,206
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,1
-.byte	15,56,200,215
+	sha1rnds4	$1,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,204
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,1
-.byte	15,56,200,213
+	sha1rnds4	$1,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,1
-.byte	15,56,200,206
+	sha1rnds4	$1,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,215
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,2
-.byte	15,56,200,204
+	sha1rnds4	$2,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
-.byte	15,56,201,229
+	sha1msg2	%xmm6,%xmm7
+	sha1msg1	%xmm5,%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,213
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	pxor	%xmm6,%xmm4
-.byte	15,56,201,238
-.byte	15,56,202,231
+	sha1msg1	%xmm6,%xmm5
+	sha1msg2	%xmm7,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,2
-.byte	15,56,200,206
+	sha1rnds4	$2,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	pxor	%xmm7,%xmm5
-.byte	15,56,202,236
-.byte	15,56,201,247
+	sha1msg2	%xmm4,%xmm5
+	sha1msg1	%xmm7,%xmm6
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,2
-.byte	15,56,200,215
+	sha1rnds4	$2,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	pxor	%xmm4,%xmm6
-.byte	15,56,201,252
-.byte	15,56,202,245
+	sha1msg1	%xmm4,%xmm7
+	sha1msg2	%xmm5,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	15,56,200,204
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm4,%xmm1
 	pxor	%xmm5,%xmm7
-.byte	15,56,202,254
+	sha1msg2	%xmm6,%xmm7
 	movdqu	(%rsi),%xmm4
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,3
-.byte	15,56,200,213
+	sha1rnds4	$3,%xmm1,%xmm0
+	sha1nexte	%xmm5,%xmm2
 	movdqu	16(%rsi),%xmm5
-.byte	102,15,56,0,227
+	pshufb	%xmm3,%xmm4
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	15,56,200,206
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm6,%xmm1
 	movdqu	32(%rsi),%xmm6
-.byte	102,15,56,0,235
+	pshufb	%xmm3,%xmm5
 
 	movdqa	%xmm0,%xmm2
-.byte	15,58,204,193,3
-.byte	15,56,200,215
+	sha1rnds4	$3,%xmm1,%xmm0
+	sha1nexte	%xmm7,%xmm2
 	movdqu	48(%rsi),%xmm7
-.byte	102,15,56,0,243
+	pshufb	%xmm3,%xmm6
 
 	movdqa	%xmm0,%xmm1
-.byte	15,58,204,194,3
-.byte	65,15,56,200,201
-.byte	102,15,56,0,251
+	sha1rnds4	$3,%xmm2,%xmm0
+	sha1nexte	%xmm9,%xmm1
+	pshufb	%xmm3,%xmm7
 
 	paddd	%xmm8,%xmm0
 	movdqa	%xmm1,%xmm9
@@ -1460,12 +1460,12 @@
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
 	movdqu	48(%r9),%xmm3
-.byte	102,15,56,0,198
-.byte	102,15,56,0,206
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm0
+	pshufb	%xmm6,%xmm1
+	pshufb	%xmm6,%xmm2
 	addq	$64,%r9
 	paddd	%xmm9,%xmm0
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm9,%xmm1
 	paddd	%xmm9,%xmm2
 	movdqa	%xmm0,0(%rsp)
@@ -2357,12 +2357,12 @@
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
 	movdqu	48(%r9),%xmm3
-.byte	102,15,56,0,198
+	pshufb	%xmm6,%xmm0
 	addq	$64,%r9
 	addl	16(%rsp),%ebx
 	xorl	%ebp,%esi
 	movl	%ecx,%edi
-.byte	102,15,56,0,206
+	pshufb	%xmm6,%xmm1
 	roll	$5,%ecx
 	addl	%esi,%ebx
 	xorl	%ebp,%edi
@@ -2398,7 +2398,7 @@
 	addl	32(%rsp),%ecx
 	xorl	%eax,%esi
 	movl	%edx,%edi
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm2
 	roll	$5,%edx
 	addl	%esi,%ecx
 	xorl	%eax,%edi
@@ -2434,7 +2434,7 @@
 	addl	48(%rsp),%edx
 	xorl	%ebx,%esi
 	movl	%ebp,%edi
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	roll	$5,%ebp
 	addl	%esi,%edx
 	xorl	%ebx,%edi
diff --git a/src/gen/bcm/sha1-x86_64-win.asm b/src/gen/bcm/sha1-x86_64-win.asm
index 92e9b9c..c5da333 100644
--- a/src/gen/bcm/sha1-x86_64-win.asm
+++ b/src/gen/bcm/sha1-x86_64-win.asm
@@ -1291,12 +1291,12 @@
 	movdqu	xmm5,XMMWORD[16+rsi]
 	pshufd	xmm1,xmm1,27
 	movdqu	xmm6,XMMWORD[32+rsi]
-DB	102,15,56,0,227
+	pshufb	xmm4,xmm3
 	movdqu	xmm7,XMMWORD[48+rsi]
-DB	102,15,56,0,235
-DB	102,15,56,0,243
+	pshufb	xmm5,xmm3
+	pshufb	xmm6,xmm3
 	movdqa	xmm9,xmm1
-DB	102,15,56,0,251
+	pshufb	xmm7,xmm3
 	jmp	NEAR $L$oop_shaext
 
 ALIGN	16
@@ -1307,133 +1307,133 @@
 	cmovne	rsi,r8
 	prefetcht0	[512+rsi]
 	movdqa	xmm8,xmm0
-	DB	15,56,201,229
+	sha1msg1	xmm4,xmm5
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,0
-	DB	15,56,200,213
+	sha1rnds4	xmm0,xmm1,0
+	sha1nexte	xmm2,xmm5
 	pxor	xmm4,xmm6
-	DB	15,56,201,238
-	DB	15,56,202,231
+	sha1msg1	xmm5,xmm6
+	sha1msg2	xmm4,xmm7
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,0
-	DB	15,56,200,206
+	sha1rnds4	xmm0,xmm2,0
+	sha1nexte	xmm1,xmm6
 	pxor	xmm5,xmm7
-	DB	15,56,202,236
-	DB	15,56,201,247
+	sha1msg2	xmm5,xmm4
+	sha1msg1	xmm6,xmm7
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,0
-	DB	15,56,200,215
+	sha1rnds4	xmm0,xmm1,0
+	sha1nexte	xmm2,xmm7
 	pxor	xmm6,xmm4
-	DB	15,56,201,252
-	DB	15,56,202,245
+	sha1msg1	xmm7,xmm4
+	sha1msg2	xmm6,xmm5
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,0
-	DB	15,56,200,204
+	sha1rnds4	xmm0,xmm2,0
+	sha1nexte	xmm1,xmm4
 	pxor	xmm7,xmm5
-	DB	15,56,202,254
-	DB	15,56,201,229
+	sha1msg2	xmm7,xmm6
+	sha1msg1	xmm4,xmm5
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,0
-	DB	15,56,200,213
+	sha1rnds4	xmm0,xmm1,0
+	sha1nexte	xmm2,xmm5
 	pxor	xmm4,xmm6
-	DB	15,56,201,238
-	DB	15,56,202,231
+	sha1msg1	xmm5,xmm6
+	sha1msg2	xmm4,xmm7
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,1
-	DB	15,56,200,206
+	sha1rnds4	xmm0,xmm2,1
+	sha1nexte	xmm1,xmm6
 	pxor	xmm5,xmm7
-	DB	15,56,202,236
-	DB	15,56,201,247
+	sha1msg2	xmm5,xmm4
+	sha1msg1	xmm6,xmm7
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,1
-	DB	15,56,200,215
+	sha1rnds4	xmm0,xmm1,1
+	sha1nexte	xmm2,xmm7
 	pxor	xmm6,xmm4
-	DB	15,56,201,252
-	DB	15,56,202,245
+	sha1msg1	xmm7,xmm4
+	sha1msg2	xmm6,xmm5
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,1
-	DB	15,56,200,204
+	sha1rnds4	xmm0,xmm2,1
+	sha1nexte	xmm1,xmm4
 	pxor	xmm7,xmm5
-	DB	15,56,202,254
-	DB	15,56,201,229
+	sha1msg2	xmm7,xmm6
+	sha1msg1	xmm4,xmm5
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,1
-	DB	15,56,200,213
+	sha1rnds4	xmm0,xmm1,1
+	sha1nexte	xmm2,xmm5
 	pxor	xmm4,xmm6
-	DB	15,56,201,238
-	DB	15,56,202,231
+	sha1msg1	xmm5,xmm6
+	sha1msg2	xmm4,xmm7
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,1
-	DB	15,56,200,206
+	sha1rnds4	xmm0,xmm2,1
+	sha1nexte	xmm1,xmm6
 	pxor	xmm5,xmm7
-	DB	15,56,202,236
-	DB	15,56,201,247
+	sha1msg2	xmm5,xmm4
+	sha1msg1	xmm6,xmm7
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,2
-	DB	15,56,200,215
+	sha1rnds4	xmm0,xmm1,2
+	sha1nexte	xmm2,xmm7
 	pxor	xmm6,xmm4
-	DB	15,56,201,252
-	DB	15,56,202,245
+	sha1msg1	xmm7,xmm4
+	sha1msg2	xmm6,xmm5
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,2
-	DB	15,56,200,204
+	sha1rnds4	xmm0,xmm2,2
+	sha1nexte	xmm1,xmm4
 	pxor	xmm7,xmm5
-	DB	15,56,202,254
-	DB	15,56,201,229
+	sha1msg2	xmm7,xmm6
+	sha1msg1	xmm4,xmm5
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,2
-	DB	15,56,200,213
+	sha1rnds4	xmm0,xmm1,2
+	sha1nexte	xmm2,xmm5
 	pxor	xmm4,xmm6
-	DB	15,56,201,238
-	DB	15,56,202,231
+	sha1msg1	xmm5,xmm6
+	sha1msg2	xmm4,xmm7
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,2
-	DB	15,56,200,206
+	sha1rnds4	xmm0,xmm2,2
+	sha1nexte	xmm1,xmm6
 	pxor	xmm5,xmm7
-	DB	15,56,202,236
-	DB	15,56,201,247
+	sha1msg2	xmm5,xmm4
+	sha1msg1	xmm6,xmm7
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,2
-	DB	15,56,200,215
+	sha1rnds4	xmm0,xmm1,2
+	sha1nexte	xmm2,xmm7
 	pxor	xmm6,xmm4
-	DB	15,56,201,252
-	DB	15,56,202,245
+	sha1msg1	xmm7,xmm4
+	sha1msg2	xmm6,xmm5
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,3
-	DB	15,56,200,204
+	sha1rnds4	xmm0,xmm2,3
+	sha1nexte	xmm1,xmm4
 	pxor	xmm7,xmm5
-	DB	15,56,202,254
+	sha1msg2	xmm7,xmm6
 	movdqu	xmm4,XMMWORD[rsi]
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,3
-	DB	15,56,200,213
+	sha1rnds4	xmm0,xmm1,3
+	sha1nexte	xmm2,xmm5
 	movdqu	xmm5,XMMWORD[16+rsi]
-DB	102,15,56,0,227
+	pshufb	xmm4,xmm3
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,3
-	DB	15,56,200,206
+	sha1rnds4	xmm0,xmm2,3
+	sha1nexte	xmm1,xmm6
 	movdqu	xmm6,XMMWORD[32+rsi]
-DB	102,15,56,0,235
+	pshufb	xmm5,xmm3
 
 	movdqa	xmm2,xmm0
-	DB	15,58,204,193,3
-	DB	15,56,200,215
+	sha1rnds4	xmm0,xmm1,3
+	sha1nexte	xmm2,xmm7
 	movdqu	xmm7,XMMWORD[48+rsi]
-DB	102,15,56,0,243
+	pshufb	xmm6,xmm3
 
 	movdqa	xmm1,xmm0
-	DB	15,58,204,194,3
-	DB	65,15,56,200,201
-DB	102,15,56,0,251
+	sha1rnds4	xmm0,xmm2,3
+	sha1nexte	xmm1,xmm9
+	pshufb	xmm7,xmm3
 
 	paddd	xmm0,xmm8
 	movdqa	xmm9,xmm1
@@ -1515,12 +1515,12 @@
 	movdqu	xmm1,XMMWORD[16+r9]
 	movdqu	xmm2,XMMWORD[32+r9]
 	movdqu	xmm3,XMMWORD[48+r9]
-DB	102,15,56,0,198
-DB	102,15,56,0,206
-DB	102,15,56,0,214
+	pshufb	xmm0,xmm6
+	pshufb	xmm1,xmm6
+	pshufb	xmm2,xmm6
 	add	r9,64
 	paddd	xmm0,xmm9
-DB	102,15,56,0,222
+	pshufb	xmm3,xmm6
 	paddd	xmm1,xmm9
 	paddd	xmm2,xmm9
 	movdqa	XMMWORD[rsp],xmm0
@@ -2412,12 +2412,12 @@
 	movdqu	xmm1,XMMWORD[16+r9]
 	movdqu	xmm2,XMMWORD[32+r9]
 	movdqu	xmm3,XMMWORD[48+r9]
-DB	102,15,56,0,198
+	pshufb	xmm0,xmm6
 	add	r9,64
 	add	ebx,DWORD[16+rsp]
 	xor	esi,ebp
 	mov	edi,ecx
-DB	102,15,56,0,206
+	pshufb	xmm1,xmm6
 	rol	ecx,5
 	add	ebx,esi
 	xor	edi,ebp
@@ -2453,7 +2453,7 @@
 	add	ecx,DWORD[32+rsp]
 	xor	esi,eax
 	mov	edi,edx
-DB	102,15,56,0,214
+	pshufb	xmm2,xmm6
 	rol	edx,5
 	add	ecx,esi
 	xor	edi,eax
@@ -2489,7 +2489,7 @@
 	add	edx,DWORD[48+rsp]
 	xor	esi,ebx
 	mov	edi,ebp
-DB	102,15,56,0,222
+	pshufb	xmm3,xmm6
 	rol	ebp,5
 	add	edx,esi
 	xor	edi,ebx
diff --git a/src/gen/bcm/sha256-x86_64-apple.S b/src/gen/bcm/sha256-x86_64-apple.S
index b33f807..367f0d3 100644
--- a/src/gen/bcm/sha256-x86_64-apple.S
+++ b/src/gen/bcm/sha256-x86_64-apple.S
@@ -1780,7 +1780,7 @@
 	pshufd	$0xb1,%xmm1,%xmm1
 	pshufd	$0x1b,%xmm2,%xmm2
 	movdqa	%xmm7,%xmm8
-.byte	102,15,58,15,202,8
+	palignr	$8,%xmm2,%xmm1
 	punpcklqdq	%xmm0,%xmm2
 	jmp	L$oop_shaext
 
@@ -1789,176 +1789,176 @@
 	movdqu	(%rsi),%xmm3
 	movdqu	16(%rsi),%xmm4
 	movdqu	32(%rsi),%xmm5
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	movdqu	48(%rsi),%xmm6
 
 	movdqa	0-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	102,15,56,0,231
+	pshufb	%xmm7,%xmm4
 	movdqa	%xmm2,%xmm10
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	nop
 	movdqa	%xmm1,%xmm9
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	32-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	102,15,56,0,239
-.byte	15,56,203,209
+	pshufb	%xmm7,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	leaq	64(%rsi),%rsi
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	64-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	102,15,56,0,247
-.byte	15,56,203,209
+	pshufb	%xmm7,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	96-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	128-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	160-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
+	palignr	$4,%xmm4,%xmm7
 	nop
 	paddd	%xmm7,%xmm6
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	192-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,205,245
-.byte	15,56,203,209
+	sha256msg2	%xmm5,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	224-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	256-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	288-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
+	palignr	$4,%xmm4,%xmm7
 	nop
 	paddd	%xmm7,%xmm6
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	320-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,205,245
-.byte	15,56,203,209
+	sha256msg2	%xmm5,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	352-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	384-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	416-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
-.byte	15,56,203,202
+	palignr	$4,%xmm4,%xmm7
+	sha256rnds2	%xmm2,%xmm1
 	paddd	%xmm7,%xmm6
 
 	movdqa	448-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
-.byte	15,56,205,245
+	sha256msg2	%xmm5,%xmm6
 	movdqa	%xmm8,%xmm7
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	480-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
 	nop
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	decq	%rdx
 	nop
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	paddd	%xmm10,%xmm2
 	paddd	%xmm9,%xmm1
@@ -1968,7 +1968,7 @@
 	pshufd	$0x1b,%xmm1,%xmm7
 	pshufd	$0xb1,%xmm1,%xmm1
 	punpckhqdq	%xmm2,%xmm1
-.byte	102,15,58,15,215,8
+	palignr	$8,%xmm7,%xmm2
 
 	movdqu	%xmm1,(%rdi)
 	movdqu	%xmm2,16(%rdi)
@@ -2024,16 +2024,16 @@
 	movdqu	0(%rsi),%xmm0
 	movdqu	16(%rsi),%xmm1
 	movdqu	32(%rsi),%xmm2
-.byte	102,15,56,0,199
+	pshufb	%xmm7,%xmm0
 	movdqu	48(%rsi),%xmm3
 	leaq	K256(%rip),%rbp
-.byte	102,15,56,0,207
+	pshufb	%xmm7,%xmm1
 	movdqa	0(%rbp),%xmm4
 	movdqa	32(%rbp),%xmm5
-.byte	102,15,56,0,215
+	pshufb	%xmm7,%xmm2
 	paddd	%xmm0,%xmm4
 	movdqa	64(%rbp),%xmm6
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	movdqa	96(%rbp),%xmm7
 	paddd	%xmm1,%xmm5
 	paddd	%xmm2,%xmm6
@@ -2061,10 +2061,10 @@
 	xorl	%r10d,%r12d
 	rorl	$5,%r13d
 	xorl	%eax,%r14d
-.byte	102,15,58,15,224,4
+	palignr	$4,%xmm0,%xmm4
 	andl	%r8d,%r12d
 	xorl	%r8d,%r13d
-.byte	102,15,58,15,250,4
+	palignr	$4,%xmm2,%xmm7
 	addl	0(%rsp),%r11d
 	movl	%eax,%r15d
 	xorl	%r10d,%r12d
@@ -2205,10 +2205,10 @@
 	xorl	%ecx,%r12d
 	rorl	$5,%r13d
 	xorl	%r8d,%r14d
-.byte	102,15,58,15,225,4
+	palignr	$4,%xmm1,%xmm4
 	andl	%eax,%r12d
 	xorl	%eax,%r13d
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	addl	16(%rsp),%edx
 	movl	%r8d,%r15d
 	xorl	%ecx,%r12d
@@ -2349,10 +2349,10 @@
 	xorl	%r10d,%r12d
 	rorl	$5,%r13d
 	xorl	%eax,%r14d
-.byte	102,15,58,15,226,4
+	palignr	$4,%xmm2,%xmm4
 	andl	%r8d,%r12d
 	xorl	%r8d,%r13d
-.byte	102,15,58,15,248,4
+	palignr	$4,%xmm0,%xmm7
 	addl	32(%rsp),%r11d
 	movl	%eax,%r15d
 	xorl	%r10d,%r12d
@@ -2493,10 +2493,10 @@
 	xorl	%ecx,%r12d
 	rorl	$5,%r13d
 	xorl	%r8d,%r14d
-.byte	102,15,58,15,227,4
+	palignr	$4,%xmm3,%xmm4
 	andl	%eax,%r12d
 	xorl	%eax,%r13d
-.byte	102,15,58,15,249,4
+	palignr	$4,%xmm1,%xmm7
 	addl	48(%rsp),%edx
 	movl	%r8d,%r15d
 	xorl	%ecx,%r12d
diff --git a/src/gen/bcm/sha256-x86_64-linux.S b/src/gen/bcm/sha256-x86_64-linux.S
index 8476b03..938f531 100644
--- a/src/gen/bcm/sha256-x86_64-linux.S
+++ b/src/gen/bcm/sha256-x86_64-linux.S
@@ -1780,7 +1780,7 @@
 	pshufd	$0xb1,%xmm1,%xmm1
 	pshufd	$0x1b,%xmm2,%xmm2
 	movdqa	%xmm7,%xmm8
-.byte	102,15,58,15,202,8
+	palignr	$8,%xmm2,%xmm1
 	punpcklqdq	%xmm0,%xmm2
 	jmp	.Loop_shaext
 
@@ -1789,176 +1789,176 @@
 	movdqu	(%rsi),%xmm3
 	movdqu	16(%rsi),%xmm4
 	movdqu	32(%rsi),%xmm5
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	movdqu	48(%rsi),%xmm6
 
 	movdqa	0-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	102,15,56,0,231
+	pshufb	%xmm7,%xmm4
 	movdqa	%xmm2,%xmm10
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	nop
 	movdqa	%xmm1,%xmm9
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	32-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	102,15,56,0,239
-.byte	15,56,203,209
+	pshufb	%xmm7,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	leaq	64(%rsi),%rsi
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	64-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	102,15,56,0,247
-.byte	15,56,203,209
+	pshufb	%xmm7,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	96-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	128-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	160-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
+	palignr	$4,%xmm4,%xmm7
 	nop
 	paddd	%xmm7,%xmm6
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	192-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,205,245
-.byte	15,56,203,209
+	sha256msg2	%xmm5,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	224-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	256-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	288-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
+	palignr	$4,%xmm4,%xmm7
 	nop
 	paddd	%xmm7,%xmm6
-.byte	15,56,204,220
-.byte	15,56,203,202
+	sha256msg1	%xmm4,%xmm3
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	320-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,205,245
-.byte	15,56,203,209
+	sha256msg2	%xmm5,%xmm6
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm6,%xmm7
-.byte	102,15,58,15,253,4
+	palignr	$4,%xmm5,%xmm7
 	nop
 	paddd	%xmm7,%xmm3
-.byte	15,56,204,229
-.byte	15,56,203,202
+	sha256msg1	%xmm5,%xmm4
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	352-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
-.byte	15,56,205,222
-.byte	15,56,203,209
+	sha256msg2	%xmm6,%xmm3
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm3,%xmm7
-.byte	102,15,58,15,254,4
+	palignr	$4,%xmm6,%xmm7
 	nop
 	paddd	%xmm7,%xmm4
-.byte	15,56,204,238
-.byte	15,56,203,202
+	sha256msg1	%xmm6,%xmm5
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	384-128(%rcx),%xmm0
 	paddd	%xmm3,%xmm0
-.byte	15,56,205,227
-.byte	15,56,203,209
+	sha256msg2	%xmm3,%xmm4
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm4,%xmm7
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	nop
 	paddd	%xmm7,%xmm5
-.byte	15,56,204,243
-.byte	15,56,203,202
+	sha256msg1	%xmm3,%xmm6
+	sha256rnds2	%xmm2,%xmm1
 	movdqa	416-128(%rcx),%xmm0
 	paddd	%xmm4,%xmm0
-.byte	15,56,205,236
-.byte	15,56,203,209
+	sha256msg2	%xmm4,%xmm5
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	movdqa	%xmm5,%xmm7
-.byte	102,15,58,15,252,4
-.byte	15,56,203,202
+	palignr	$4,%xmm4,%xmm7
+	sha256rnds2	%xmm2,%xmm1
 	paddd	%xmm7,%xmm6
 
 	movdqa	448-128(%rcx),%xmm0
 	paddd	%xmm5,%xmm0
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
-.byte	15,56,205,245
+	sha256msg2	%xmm5,%xmm6
 	movdqa	%xmm8,%xmm7
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	movdqa	480-128(%rcx),%xmm0
 	paddd	%xmm6,%xmm0
 	nop
-.byte	15,56,203,209
+	sha256rnds2	%xmm1,%xmm2
 	pshufd	$0x0e,%xmm0,%xmm0
 	decq	%rdx
 	nop
-.byte	15,56,203,202
+	sha256rnds2	%xmm2,%xmm1
 
 	paddd	%xmm10,%xmm2
 	paddd	%xmm9,%xmm1
@@ -1968,7 +1968,7 @@
 	pshufd	$0x1b,%xmm1,%xmm7
 	pshufd	$0xb1,%xmm1,%xmm1
 	punpckhqdq	%xmm2,%xmm1
-.byte	102,15,58,15,215,8
+	palignr	$8,%xmm7,%xmm2
 
 	movdqu	%xmm1,(%rdi)
 	movdqu	%xmm2,16(%rdi)
@@ -2024,16 +2024,16 @@
 	movdqu	0(%rsi),%xmm0
 	movdqu	16(%rsi),%xmm1
 	movdqu	32(%rsi),%xmm2
-.byte	102,15,56,0,199
+	pshufb	%xmm7,%xmm0
 	movdqu	48(%rsi),%xmm3
 	leaq	K256(%rip),%rbp
-.byte	102,15,56,0,207
+	pshufb	%xmm7,%xmm1
 	movdqa	0(%rbp),%xmm4
 	movdqa	32(%rbp),%xmm5
-.byte	102,15,56,0,215
+	pshufb	%xmm7,%xmm2
 	paddd	%xmm0,%xmm4
 	movdqa	64(%rbp),%xmm6
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	movdqa	96(%rbp),%xmm7
 	paddd	%xmm1,%xmm5
 	paddd	%xmm2,%xmm6
@@ -2061,10 +2061,10 @@
 	xorl	%r10d,%r12d
 	rorl	$5,%r13d
 	xorl	%eax,%r14d
-.byte	102,15,58,15,224,4
+	palignr	$4,%xmm0,%xmm4
 	andl	%r8d,%r12d
 	xorl	%r8d,%r13d
-.byte	102,15,58,15,250,4
+	palignr	$4,%xmm2,%xmm7
 	addl	0(%rsp),%r11d
 	movl	%eax,%r15d
 	xorl	%r10d,%r12d
@@ -2205,10 +2205,10 @@
 	xorl	%ecx,%r12d
 	rorl	$5,%r13d
 	xorl	%r8d,%r14d
-.byte	102,15,58,15,225,4
+	palignr	$4,%xmm1,%xmm4
 	andl	%eax,%r12d
 	xorl	%eax,%r13d
-.byte	102,15,58,15,251,4
+	palignr	$4,%xmm3,%xmm7
 	addl	16(%rsp),%edx
 	movl	%r8d,%r15d
 	xorl	%ecx,%r12d
@@ -2349,10 +2349,10 @@
 	xorl	%r10d,%r12d
 	rorl	$5,%r13d
 	xorl	%eax,%r14d
-.byte	102,15,58,15,226,4
+	palignr	$4,%xmm2,%xmm4
 	andl	%r8d,%r12d
 	xorl	%r8d,%r13d
-.byte	102,15,58,15,248,4
+	palignr	$4,%xmm0,%xmm7
 	addl	32(%rsp),%r11d
 	movl	%eax,%r15d
 	xorl	%r10d,%r12d
@@ -2493,10 +2493,10 @@
 	xorl	%ecx,%r12d
 	rorl	$5,%r13d
 	xorl	%r8d,%r14d
-.byte	102,15,58,15,227,4
+	palignr	$4,%xmm3,%xmm4
 	andl	%eax,%r12d
 	xorl	%eax,%r13d
-.byte	102,15,58,15,249,4
+	palignr	$4,%xmm1,%xmm7
 	addl	48(%rsp),%edx
 	movl	%r8d,%r15d
 	xorl	%ecx,%r12d
diff --git a/src/gen/bcm/sha256-x86_64-win.asm b/src/gen/bcm/sha256-x86_64-win.asm
index ada8dba..b720603 100644
--- a/src/gen/bcm/sha256-x86_64-win.asm
+++ b/src/gen/bcm/sha256-x86_64-win.asm
@@ -1818,7 +1818,7 @@
 	pshufd	xmm1,xmm1,0xb1
 	pshufd	xmm2,xmm2,0x1b
 	movdqa	xmm8,xmm7
-DB	102,15,58,15,202,8
+	palignr	xmm1,xmm2,8
 	punpcklqdq	xmm2,xmm0
 	jmp	NEAR $L$oop_shaext
 
@@ -1827,176 +1827,176 @@
 	movdqu	xmm3,XMMWORD[rsi]
 	movdqu	xmm4,XMMWORD[16+rsi]
 	movdqu	xmm5,XMMWORD[32+rsi]
-DB	102,15,56,0,223
+	pshufb	xmm3,xmm7
 	movdqu	xmm6,XMMWORD[48+rsi]
 
 	movdqa	xmm0,XMMWORD[((0-128))+rcx]
 	paddd	xmm0,xmm3
-DB	102,15,56,0,231
+	pshufb	xmm4,xmm7
 	movdqa	xmm10,xmm2
-	DB	15,56,203,209
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	nop
 	movdqa	xmm9,xmm1
-	DB	15,56,203,202
+	sha256rnds2	xmm1,xmm2
 
 	movdqa	xmm0,XMMWORD[((32-128))+rcx]
 	paddd	xmm0,xmm4
-DB	102,15,56,0,239
-	DB	15,56,203,209
+	pshufb	xmm5,xmm7
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	lea	rsi,[64+rsi]
-	DB	15,56,204,220
-	DB	15,56,203,202
+	sha256msg1	xmm3,xmm4
+	sha256rnds2	xmm1,xmm2
 
 	movdqa	xmm0,XMMWORD[((64-128))+rcx]
 	paddd	xmm0,xmm5
-DB	102,15,56,0,247
-	DB	15,56,203,209
+	pshufb	xmm6,xmm7
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm6
-DB	102,15,58,15,253,4
+	palignr	xmm7,xmm5,4
 	nop
 	paddd	xmm3,xmm7
-	DB	15,56,204,229
-	DB	15,56,203,202
+	sha256msg1	xmm4,xmm5
+	sha256rnds2	xmm1,xmm2
 
 	movdqa	xmm0,XMMWORD[((96-128))+rcx]
 	paddd	xmm0,xmm6
-	DB	15,56,205,222
-	DB	15,56,203,209
+	sha256msg2	xmm3,xmm6
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm3
-DB	102,15,58,15,254,4
+	palignr	xmm7,xmm6,4
 	nop
 	paddd	xmm4,xmm7
-	DB	15,56,204,238
-	DB	15,56,203,202
+	sha256msg1	xmm5,xmm6
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((128-128))+rcx]
 	paddd	xmm0,xmm3
-	DB	15,56,205,227
-	DB	15,56,203,209
+	sha256msg2	xmm4,xmm3
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm4
-DB	102,15,58,15,251,4
+	palignr	xmm7,xmm3,4
 	nop
 	paddd	xmm5,xmm7
-	DB	15,56,204,243
-	DB	15,56,203,202
+	sha256msg1	xmm6,xmm3
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((160-128))+rcx]
 	paddd	xmm0,xmm4
-	DB	15,56,205,236
-	DB	15,56,203,209
+	sha256msg2	xmm5,xmm4
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm5
-DB	102,15,58,15,252,4
+	palignr	xmm7,xmm4,4
 	nop
 	paddd	xmm6,xmm7
-	DB	15,56,204,220
-	DB	15,56,203,202
+	sha256msg1	xmm3,xmm4
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((192-128))+rcx]
 	paddd	xmm0,xmm5
-	DB	15,56,205,245
-	DB	15,56,203,209
+	sha256msg2	xmm6,xmm5
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm6
-DB	102,15,58,15,253,4
+	palignr	xmm7,xmm5,4
 	nop
 	paddd	xmm3,xmm7
-	DB	15,56,204,229
-	DB	15,56,203,202
+	sha256msg1	xmm4,xmm5
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((224-128))+rcx]
 	paddd	xmm0,xmm6
-	DB	15,56,205,222
-	DB	15,56,203,209
+	sha256msg2	xmm3,xmm6
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm3
-DB	102,15,58,15,254,4
+	palignr	xmm7,xmm6,4
 	nop
 	paddd	xmm4,xmm7
-	DB	15,56,204,238
-	DB	15,56,203,202
+	sha256msg1	xmm5,xmm6
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((256-128))+rcx]
 	paddd	xmm0,xmm3
-	DB	15,56,205,227
-	DB	15,56,203,209
+	sha256msg2	xmm4,xmm3
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm4
-DB	102,15,58,15,251,4
+	palignr	xmm7,xmm3,4
 	nop
 	paddd	xmm5,xmm7
-	DB	15,56,204,243
-	DB	15,56,203,202
+	sha256msg1	xmm6,xmm3
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((288-128))+rcx]
 	paddd	xmm0,xmm4
-	DB	15,56,205,236
-	DB	15,56,203,209
+	sha256msg2	xmm5,xmm4
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm5
-DB	102,15,58,15,252,4
+	palignr	xmm7,xmm4,4
 	nop
 	paddd	xmm6,xmm7
-	DB	15,56,204,220
-	DB	15,56,203,202
+	sha256msg1	xmm3,xmm4
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((320-128))+rcx]
 	paddd	xmm0,xmm5
-	DB	15,56,205,245
-	DB	15,56,203,209
+	sha256msg2	xmm6,xmm5
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm6
-DB	102,15,58,15,253,4
+	palignr	xmm7,xmm5,4
 	nop
 	paddd	xmm3,xmm7
-	DB	15,56,204,229
-	DB	15,56,203,202
+	sha256msg1	xmm4,xmm5
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((352-128))+rcx]
 	paddd	xmm0,xmm6
-	DB	15,56,205,222
-	DB	15,56,203,209
+	sha256msg2	xmm3,xmm6
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm3
-DB	102,15,58,15,254,4
+	palignr	xmm7,xmm6,4
 	nop
 	paddd	xmm4,xmm7
-	DB	15,56,204,238
-	DB	15,56,203,202
+	sha256msg1	xmm5,xmm6
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((384-128))+rcx]
 	paddd	xmm0,xmm3
-	DB	15,56,205,227
-	DB	15,56,203,209
+	sha256msg2	xmm4,xmm3
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm4
-DB	102,15,58,15,251,4
+	palignr	xmm7,xmm3,4
 	nop
 	paddd	xmm5,xmm7
-	DB	15,56,204,243
-	DB	15,56,203,202
+	sha256msg1	xmm6,xmm3
+	sha256rnds2	xmm1,xmm2
 	movdqa	xmm0,XMMWORD[((416-128))+rcx]
 	paddd	xmm0,xmm4
-	DB	15,56,205,236
-	DB	15,56,203,209
+	sha256msg2	xmm5,xmm4
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	movdqa	xmm7,xmm5
-DB	102,15,58,15,252,4
-	DB	15,56,203,202
+	palignr	xmm7,xmm4,4
+	sha256rnds2	xmm1,xmm2
 	paddd	xmm6,xmm7
 
 	movdqa	xmm0,XMMWORD[((448-128))+rcx]
 	paddd	xmm0,xmm5
-	DB	15,56,203,209
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
-	DB	15,56,205,245
+	sha256msg2	xmm6,xmm5
 	movdqa	xmm7,xmm8
-	DB	15,56,203,202
+	sha256rnds2	xmm1,xmm2
 
 	movdqa	xmm0,XMMWORD[((480-128))+rcx]
 	paddd	xmm0,xmm6
 	nop
-	DB	15,56,203,209
+	sha256rnds2	xmm2,xmm1
 	pshufd	xmm0,xmm0,0x0e
 	dec	rdx
 	nop
-	DB	15,56,203,202
+	sha256rnds2	xmm1,xmm2
 
 	paddd	xmm2,xmm10
 	paddd	xmm1,xmm9
@@ -2006,7 +2006,7 @@
 	pshufd	xmm7,xmm1,0x1b
 	pshufd	xmm1,xmm1,0xb1
 	punpckhqdq	xmm1,xmm2
-DB	102,15,58,15,215,8
+	palignr	xmm2,xmm7,8
 
 	movdqu	XMMWORD[rdi],xmm1
 	movdqu	XMMWORD[16+rdi],xmm2
@@ -2083,16 +2083,16 @@
 	movdqu	xmm0,XMMWORD[rsi]
 	movdqu	xmm1,XMMWORD[16+rsi]
 	movdqu	xmm2,XMMWORD[32+rsi]
-DB	102,15,56,0,199
+	pshufb	xmm0,xmm7
 	movdqu	xmm3,XMMWORD[48+rsi]
 	lea	rbp,[K256]
-DB	102,15,56,0,207
+	pshufb	xmm1,xmm7
 	movdqa	xmm4,XMMWORD[rbp]
 	movdqa	xmm5,XMMWORD[32+rbp]
-DB	102,15,56,0,215
+	pshufb	xmm2,xmm7
 	paddd	xmm4,xmm0
 	movdqa	xmm6,XMMWORD[64+rbp]
-DB	102,15,56,0,223
+	pshufb	xmm3,xmm7
 	movdqa	xmm7,XMMWORD[96+rbp]
 	paddd	xmm5,xmm1
 	paddd	xmm6,xmm2
@@ -2120,10 +2120,10 @@
 	xor	r12d,r10d
 	ror	r13d,5
 	xor	r14d,eax
-DB	102,15,58,15,224,4
+	palignr	xmm4,xmm0,4
 	and	r12d,r8d
 	xor	r13d,r8d
-DB	102,15,58,15,250,4
+	palignr	xmm7,xmm2,4
 	add	r11d,DWORD[rsp]
 	mov	r15d,eax
 	xor	r12d,r10d
@@ -2264,10 +2264,10 @@
 	xor	r12d,ecx
 	ror	r13d,5
 	xor	r14d,r8d
-DB	102,15,58,15,225,4
+	palignr	xmm4,xmm1,4
 	and	r12d,eax
 	xor	r13d,eax
-DB	102,15,58,15,251,4
+	palignr	xmm7,xmm3,4
 	add	edx,DWORD[16+rsp]
 	mov	r15d,r8d
 	xor	r12d,ecx
@@ -2408,10 +2408,10 @@
 	xor	r12d,r10d
 	ror	r13d,5
 	xor	r14d,eax
-DB	102,15,58,15,226,4
+	palignr	xmm4,xmm2,4
 	and	r12d,r8d
 	xor	r13d,r8d
-DB	102,15,58,15,248,4
+	palignr	xmm7,xmm0,4
 	add	r11d,DWORD[32+rsp]
 	mov	r15d,eax
 	xor	r12d,r10d
@@ -2552,10 +2552,10 @@
 	xor	r12d,ecx
 	ror	r13d,5
 	xor	r14d,r8d
-DB	102,15,58,15,227,4
+	palignr	xmm4,xmm3,4
 	and	r12d,eax
 	xor	r13d,eax
-DB	102,15,58,15,249,4
+	palignr	xmm7,xmm1,4
 	add	edx,DWORD[48+rsp]
 	mov	r15d,r8d
 	xor	r12d,ecx
diff --git a/src/gen/bcm/vpaes-x86_64-apple.S b/src/gen/bcm/vpaes-x86_64-apple.S
index 5aea40f..bfcc030 100644
--- a/src/gen/bcm/vpaes-x86_64-apple.S
+++ b/src/gen/bcm/vpaes-x86_64-apple.S
@@ -34,9 +34,9 @@
 	movdqu	(%r9),%xmm5
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	L$k_ipt+16(%rip),%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	pxor	%xmm5,%xmm2
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
@@ -48,25 +48,25 @@
 
 	movdqa	%xmm13,%xmm4
 	movdqa	%xmm12,%xmm0
-.byte	102,15,56,0,226
-.byte	102,15,56,0,195
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm5,%xmm4
 	movdqa	%xmm15,%xmm5
 	pxor	%xmm4,%xmm0
 	movdqa	-64(%r11,%r10,1),%xmm1
-.byte	102,15,56,0,234
+	pshufb	%xmm2,%xmm5
 	movdqa	(%r11,%r10,1),%xmm4
 	movdqa	%xmm14,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm0,%xmm3
 	pxor	%xmm5,%xmm2
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
@@ -78,19 +78,19 @@
 	pandn	%xmm0,%xmm1
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,232
+	pshufb	%xmm0,%xmm5
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqa	%xmm10,%xmm4
 	pxor	%xmm5,%xmm3
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	movdqa	%xmm10,%xmm2
 	pxor	%xmm5,%xmm4
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm0,%xmm2
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	movdqu	(%r9),%xmm5
 	pxor	%xmm1,%xmm3
 	jnz	L$enc_loop
@@ -98,12 +98,12 @@
 
 	movdqa	-96(%r10),%xmm4
 	movdqa	-80(%r10),%xmm0
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	pxor	%xmm5,%xmm4
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	movdqa	64(%r11,%r10,1),%xmm1
 	pxor	%xmm4,%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	ret
 
 
@@ -156,12 +156,12 @@
 	psrld	$4,%xmm7
 	pand	%xmm9,%xmm0
 	pand	%xmm9,%xmm6
-.byte	102,15,56,0,208
-.byte	102,68,15,56,0,198
+	pshufb	%xmm0,%xmm2
+	pshufb	%xmm6,%xmm8
 	movdqa	L$k_ipt+16(%rip),%xmm0
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,247
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm7,%xmm6
 	pxor	%xmm5,%xmm2
 	pxor	%xmm5,%xmm8
 	addq	$16,%r9
@@ -177,10 +177,10 @@
 	movdqa	L$k_sb1+16(%rip),%xmm0
 	movdqa	%xmm4,%xmm12
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,226
-.byte	102,69,15,56,0,224
-.byte	102,15,56,0,195
-.byte	102,65,15,56,0,243
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm8,%xmm12
+	pshufb	%xmm3,%xmm0
+	pshufb	%xmm11,%xmm6
 	pxor	%xmm5,%xmm4
 	pxor	%xmm5,%xmm12
 	movdqa	L$k_sb2(%rip),%xmm5
@@ -189,30 +189,30 @@
 	pxor	%xmm12,%xmm6
 	movdqa	-64(%r11,%r10,1),%xmm1
 
-.byte	102,15,56,0,234
-.byte	102,69,15,56,0,232
+	pshufb	%xmm2,%xmm5
+	pshufb	%xmm8,%xmm13
 	movdqa	(%r11,%r10,1),%xmm4
 
 	movdqa	L$k_sb2+16(%rip),%xmm2
 	movdqa	%xmm2,%xmm8
-.byte	102,15,56,0,211
-.byte	102,69,15,56,0,195
+	pshufb	%xmm3,%xmm2
+	pshufb	%xmm11,%xmm8
 	movdqa	%xmm0,%xmm3
 	movdqa	%xmm6,%xmm11
 	pxor	%xmm5,%xmm2
 	pxor	%xmm13,%xmm8
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
 	pxor	%xmm8,%xmm6
-.byte	102,15,56,0,220
-.byte	102,68,15,56,0,220
+	pshufb	%xmm4,%xmm3
+	pshufb	%xmm4,%xmm11
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
 	pxor	%xmm6,%xmm11
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
@@ -230,32 +230,32 @@
 	psrld	$4,%xmm7
 	pand	%xmm9,%xmm0
 	pand	%xmm9,%xmm6
-.byte	102,15,56,0,232
-.byte	102,68,15,56,0,238
+	pshufb	%xmm0,%xmm5
+	pshufb	%xmm6,%xmm13
 	movdqa	%xmm10,%xmm3
 	movdqa	%xmm10,%xmm11
 	pxor	%xmm1,%xmm0
 	pxor	%xmm7,%xmm6
-.byte	102,15,56,0,217
-.byte	102,68,15,56,0,223
+	pshufb	%xmm1,%xmm3
+	pshufb	%xmm7,%xmm11
 	movdqa	%xmm10,%xmm4
 	movdqa	%xmm10,%xmm12
 	pxor	%xmm5,%xmm3
 	pxor	%xmm13,%xmm11
-.byte	102,15,56,0,224
-.byte	102,68,15,56,0,230
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm6,%xmm12
 	movdqa	%xmm10,%xmm2
 	movdqa	%xmm10,%xmm8
 	pxor	%xmm5,%xmm4
 	pxor	%xmm13,%xmm12
-.byte	102,15,56,0,211
-.byte	102,69,15,56,0,195
+	pshufb	%xmm3,%xmm2
+	pshufb	%xmm11,%xmm8
 	movdqa	%xmm10,%xmm3
 	movdqa	%xmm10,%xmm11
 	pxor	%xmm0,%xmm2
 	pxor	%xmm6,%xmm8
-.byte	102,15,56,0,220
-.byte	102,69,15,56,0,220
+	pshufb	%xmm4,%xmm3
+	pshufb	%xmm12,%xmm11
 	movdqu	(%r9),%xmm5
 
 	pxor	%xmm1,%xmm3
@@ -267,18 +267,18 @@
 	movdqa	-80(%r10),%xmm0
 	movdqa	%xmm4,%xmm12
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,226
-.byte	102,69,15,56,0,224
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm8,%xmm12
 	pxor	%xmm5,%xmm4
 	pxor	%xmm5,%xmm12
-.byte	102,15,56,0,195
-.byte	102,65,15,56,0,243
+	pshufb	%xmm3,%xmm0
+	pshufb	%xmm11,%xmm6
 	movdqa	64(%r11,%r10,1),%xmm1
 
 	pxor	%xmm4,%xmm0
 	pxor	%xmm12,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	ret
 
 
@@ -302,11 +302,11 @@
 	movdqu	(%r9),%xmm5
 	shlq	$4,%r11
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	L$k_dipt+16(%rip),%xmm0
 	xorq	$0x30,%r11
 	leaq	L$k_dsbd(%rip),%r10
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	andq	$0x30,%r11
 	pxor	%xmm5,%xmm2
 	movdqa	L$k_mc_forward+48(%rip),%xmm5
@@ -322,35 +322,35 @@
 
 	movdqa	-32(%r10),%xmm4
 	movdqa	-16(%r10),%xmm1
-.byte	102,15,56,0,226
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	0(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	16(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	32(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	48(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	64(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	80(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	addq	$16,%r9
-.byte	102,15,58,15,237,12
+	palignr	$12,%xmm5,%xmm5
 	pxor	%xmm1,%xmm0
 	subq	$1,%rax
 
@@ -361,32 +361,32 @@
 	movdqa	%xmm11,%xmm2
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqa	%xmm10,%xmm4
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	pxor	%xmm2,%xmm4
 	movdqa	%xmm10,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm0,%xmm2
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	movdqu	(%r9),%xmm0
 	pxor	%xmm1,%xmm3
 	jnz	L$dec_loop
 
 
 	movdqa	96(%r10),%xmm4
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	pxor	%xmm0,%xmm4
 	movdqa	112(%r10),%xmm0
 	movdqa	-352(%r11),%xmm2
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm4,%xmm0
-.byte	102,15,56,0,194
+	pshufb	%xmm2,%xmm0
 	ret
 
 
@@ -426,7 +426,7 @@
 L$schedule_am_decrypting:
 
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqu	%xmm3,(%rdx)
 	xorq	$0x30,%r8
 
@@ -480,7 +480,7 @@
 
 L$oop_schedule_192:
 	call	_vpaes_schedule_round
-.byte	102,15,58,15,198,8
+	palignr	$8,%xmm6,%xmm0
 	call	_vpaes_schedule_mangle
 	call	_vpaes_schedule_192_smear
 	call	_vpaes_schedule_mangle
@@ -546,7 +546,7 @@
 
 
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	leaq	L$k_opt(%rip),%r11
 	addq	$32,%rdx
 
@@ -622,13 +622,13 @@
 
 
 	pxor	%xmm1,%xmm1
-.byte	102,65,15,58,15,200,15
-.byte	102,69,15,58,15,192,15
+	palignr	$15,%xmm8,%xmm1
+	palignr	$15,%xmm8,%xmm8
 	pxor	%xmm1,%xmm7
 
 
 	pshufd	$0xFF,%xmm0,%xmm0
-.byte	102,15,58,15,192,1
+	palignr	$1,%xmm0,%xmm0
 
 
 
@@ -649,24 +649,24 @@
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
 	movdqa	%xmm11,%xmm2
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	pxor	%xmm1,%xmm0
 	movdqa	%xmm10,%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
 	movdqa	%xmm10,%xmm4
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	pxor	%xmm2,%xmm4
 	movdqa	%xmm10,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	pxor	%xmm0,%xmm2
 	movdqa	%xmm10,%xmm3
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	pxor	%xmm1,%xmm3
 	movdqa	%xmm13,%xmm4
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	movdqa	%xmm12,%xmm0
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm4,%xmm0
 
 
@@ -694,9 +694,9 @@
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
 	movdqa	(%r11),%xmm2
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	16(%r11),%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	pxor	%xmm2,%xmm0
 	ret
 
@@ -737,11 +737,11 @@
 
 	addq	$16,%rdx
 	pxor	L$k_s63(%rip),%xmm4
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	movdqa	%xmm4,%xmm3
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	pxor	%xmm4,%xmm3
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	pxor	%xmm4,%xmm3
 
 	jmp	L$schedule_mangle_both
@@ -755,40 +755,40 @@
 	pand	%xmm9,%xmm4
 
 	movdqa	0(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	movdqa	16(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	32(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	48(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	64(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	80(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	96(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	112(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
 
 	addq	$-16,%rdx
 
 L$schedule_mangle_both:
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	addq	$-16,%r8
 	andq	$0x30,%r8
 	movdqu	%xmm3,(%rdx)
@@ -969,8 +969,8 @@
 	movdqa	L$rev_ctr(%rip),%xmm1
 	movdqa	%xmm14,%xmm0
 	movdqa	%xmm15,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	call	_vpaes_encrypt_core_2x
 	movdqu	(%rdi),%xmm1
 	movdqu	16(%rdi),%xmm2
diff --git a/src/gen/bcm/vpaes-x86_64-linux.S b/src/gen/bcm/vpaes-x86_64-linux.S
index 019c638..e788464 100644
--- a/src/gen/bcm/vpaes-x86_64-linux.S
+++ b/src/gen/bcm/vpaes-x86_64-linux.S
@@ -34,9 +34,9 @@
 	movdqu	(%r9),%xmm5
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	.Lk_ipt+16(%rip),%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	pxor	%xmm5,%xmm2
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
@@ -48,25 +48,25 @@
 
 	movdqa	%xmm13,%xmm4
 	movdqa	%xmm12,%xmm0
-.byte	102,15,56,0,226
-.byte	102,15,56,0,195
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm5,%xmm4
 	movdqa	%xmm15,%xmm5
 	pxor	%xmm4,%xmm0
 	movdqa	-64(%r11,%r10,1),%xmm1
-.byte	102,15,56,0,234
+	pshufb	%xmm2,%xmm5
 	movdqa	(%r11,%r10,1),%xmm4
 	movdqa	%xmm14,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm0,%xmm3
 	pxor	%xmm5,%xmm2
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
@@ -78,19 +78,19 @@
 	pandn	%xmm0,%xmm1
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,232
+	pshufb	%xmm0,%xmm5
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqa	%xmm10,%xmm4
 	pxor	%xmm5,%xmm3
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	movdqa	%xmm10,%xmm2
 	pxor	%xmm5,%xmm4
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm0,%xmm2
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	movdqu	(%r9),%xmm5
 	pxor	%xmm1,%xmm3
 	jnz	.Lenc_loop
@@ -98,12 +98,12 @@
 
 	movdqa	-96(%r10),%xmm4
 	movdqa	-80(%r10),%xmm0
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	pxor	%xmm5,%xmm4
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	movdqa	64(%r11,%r10,1),%xmm1
 	pxor	%xmm4,%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	ret
 .cfi_endproc	
 .size	_vpaes_encrypt_core,.-_vpaes_encrypt_core
@@ -156,12 +156,12 @@
 	psrld	$4,%xmm7
 	pand	%xmm9,%xmm0
 	pand	%xmm9,%xmm6
-.byte	102,15,56,0,208
-.byte	102,68,15,56,0,198
+	pshufb	%xmm0,%xmm2
+	pshufb	%xmm6,%xmm8
 	movdqa	.Lk_ipt+16(%rip),%xmm0
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,247
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm7,%xmm6
 	pxor	%xmm5,%xmm2
 	pxor	%xmm5,%xmm8
 	addq	$16,%r9
@@ -177,10 +177,10 @@
 	movdqa	.Lk_sb1+16(%rip),%xmm0
 	movdqa	%xmm4,%xmm12
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,226
-.byte	102,69,15,56,0,224
-.byte	102,15,56,0,195
-.byte	102,65,15,56,0,243
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm8,%xmm12
+	pshufb	%xmm3,%xmm0
+	pshufb	%xmm11,%xmm6
 	pxor	%xmm5,%xmm4
 	pxor	%xmm5,%xmm12
 	movdqa	.Lk_sb2(%rip),%xmm5
@@ -189,30 +189,30 @@
 	pxor	%xmm12,%xmm6
 	movdqa	-64(%r11,%r10,1),%xmm1
 
-.byte	102,15,56,0,234
-.byte	102,69,15,56,0,232
+	pshufb	%xmm2,%xmm5
+	pshufb	%xmm8,%xmm13
 	movdqa	(%r11,%r10,1),%xmm4
 
 	movdqa	.Lk_sb2+16(%rip),%xmm2
 	movdqa	%xmm2,%xmm8
-.byte	102,15,56,0,211
-.byte	102,69,15,56,0,195
+	pshufb	%xmm3,%xmm2
+	pshufb	%xmm11,%xmm8
 	movdqa	%xmm0,%xmm3
 	movdqa	%xmm6,%xmm11
 	pxor	%xmm5,%xmm2
 	pxor	%xmm13,%xmm8
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	addq	$16,%r9
 	pxor	%xmm2,%xmm0
 	pxor	%xmm8,%xmm6
-.byte	102,15,56,0,220
-.byte	102,68,15,56,0,220
+	pshufb	%xmm4,%xmm3
+	pshufb	%xmm4,%xmm11
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
 	pxor	%xmm6,%xmm11
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
@@ -230,32 +230,32 @@
 	psrld	$4,%xmm7
 	pand	%xmm9,%xmm0
 	pand	%xmm9,%xmm6
-.byte	102,15,56,0,232
-.byte	102,68,15,56,0,238
+	pshufb	%xmm0,%xmm5
+	pshufb	%xmm6,%xmm13
 	movdqa	%xmm10,%xmm3
 	movdqa	%xmm10,%xmm11
 	pxor	%xmm1,%xmm0
 	pxor	%xmm7,%xmm6
-.byte	102,15,56,0,217
-.byte	102,68,15,56,0,223
+	pshufb	%xmm1,%xmm3
+	pshufb	%xmm7,%xmm11
 	movdqa	%xmm10,%xmm4
 	movdqa	%xmm10,%xmm12
 	pxor	%xmm5,%xmm3
 	pxor	%xmm13,%xmm11
-.byte	102,15,56,0,224
-.byte	102,68,15,56,0,230
+	pshufb	%xmm0,%xmm4
+	pshufb	%xmm6,%xmm12
 	movdqa	%xmm10,%xmm2
 	movdqa	%xmm10,%xmm8
 	pxor	%xmm5,%xmm4
 	pxor	%xmm13,%xmm12
-.byte	102,15,56,0,211
-.byte	102,69,15,56,0,195
+	pshufb	%xmm3,%xmm2
+	pshufb	%xmm11,%xmm8
 	movdqa	%xmm10,%xmm3
 	movdqa	%xmm10,%xmm11
 	pxor	%xmm0,%xmm2
 	pxor	%xmm6,%xmm8
-.byte	102,15,56,0,220
-.byte	102,69,15,56,0,220
+	pshufb	%xmm4,%xmm3
+	pshufb	%xmm12,%xmm11
 	movdqu	(%r9),%xmm5
 
 	pxor	%xmm1,%xmm3
@@ -267,18 +267,18 @@
 	movdqa	-80(%r10),%xmm0
 	movdqa	%xmm4,%xmm12
 	movdqa	%xmm0,%xmm6
-.byte	102,15,56,0,226
-.byte	102,69,15,56,0,224
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm8,%xmm12
 	pxor	%xmm5,%xmm4
 	pxor	%xmm5,%xmm12
-.byte	102,15,56,0,195
-.byte	102,65,15,56,0,243
+	pshufb	%xmm3,%xmm0
+	pshufb	%xmm11,%xmm6
 	movdqa	64(%r11,%r10,1),%xmm1
 
 	pxor	%xmm4,%xmm0
 	pxor	%xmm12,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	ret
 .cfi_endproc	
 .size	_vpaes_encrypt_core_2x,.-_vpaes_encrypt_core_2x
@@ -302,11 +302,11 @@
 	movdqu	(%r9),%xmm5
 	shlq	$4,%r11
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	.Lk_dipt+16(%rip),%xmm0
 	xorq	$0x30,%r11
 	leaq	.Lk_dsbd(%rip),%r10
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	andq	$0x30,%r11
 	pxor	%xmm5,%xmm2
 	movdqa	.Lk_mc_forward+48(%rip),%xmm5
@@ -322,35 +322,35 @@
 
 	movdqa	-32(%r10),%xmm4
 	movdqa	-16(%r10),%xmm1
-.byte	102,15,56,0,226
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	0(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	16(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	32(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	48(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	movdqa	64(%r10),%xmm4
 	pxor	%xmm1,%xmm0
 	movdqa	80(%r10),%xmm1
 
-.byte	102,15,56,0,226
-.byte	102,15,56,0,197
-.byte	102,15,56,0,203
+	pshufb	%xmm2,%xmm4
+	pshufb	%xmm5,%xmm0
+	pshufb	%xmm3,%xmm1
 	pxor	%xmm4,%xmm0
 	addq	$16,%r9
-.byte	102,15,58,15,237,12
+	palignr	$12,%xmm5,%xmm5
 	pxor	%xmm1,%xmm0
 	subq	$1,%rax
 
@@ -361,32 +361,32 @@
 	movdqa	%xmm11,%xmm2
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm1,%xmm0
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqa	%xmm10,%xmm4
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	pxor	%xmm2,%xmm4
 	movdqa	%xmm10,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	movdqa	%xmm10,%xmm3
 	pxor	%xmm0,%xmm2
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	movdqu	(%r9),%xmm0
 	pxor	%xmm1,%xmm3
 	jnz	.Ldec_loop
 
 
 	movdqa	96(%r10),%xmm4
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	pxor	%xmm0,%xmm4
 	movdqa	112(%r10),%xmm0
 	movdqa	-352(%r11),%xmm2
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm4,%xmm0
-.byte	102,15,56,0,194
+	pshufb	%xmm2,%xmm0
 	ret
 .cfi_endproc	
 .size	_vpaes_decrypt_core,.-_vpaes_decrypt_core
@@ -426,7 +426,7 @@
 .Lschedule_am_decrypting:
 
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	movdqu	%xmm3,(%rdx)
 	xorq	$0x30,%r8
 
@@ -480,7 +480,7 @@
 
 .Loop_schedule_192:
 	call	_vpaes_schedule_round
-.byte	102,15,58,15,198,8
+	palignr	$8,%xmm6,%xmm0
 	call	_vpaes_schedule_mangle
 	call	_vpaes_schedule_192_smear
 	call	_vpaes_schedule_mangle
@@ -546,7 +546,7 @@
 
 
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	leaq	.Lk_opt(%rip),%r11
 	addq	$32,%rdx
 
@@ -622,13 +622,13 @@
 .cfi_startproc	
 
 	pxor	%xmm1,%xmm1
-.byte	102,65,15,58,15,200,15
-.byte	102,69,15,58,15,192,15
+	palignr	$15,%xmm8,%xmm1
+	palignr	$15,%xmm8,%xmm8
 	pxor	%xmm1,%xmm7
 
 
 	pshufd	$0xFF,%xmm0,%xmm0
-.byte	102,15,58,15,192,1
+	palignr	$1,%xmm0,%xmm0
 
 
 
@@ -649,24 +649,24 @@
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
 	movdqa	%xmm11,%xmm2
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	pxor	%xmm1,%xmm0
 	movdqa	%xmm10,%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
 	movdqa	%xmm10,%xmm4
-.byte	102,15,56,0,224
+	pshufb	%xmm0,%xmm4
 	pxor	%xmm2,%xmm4
 	movdqa	%xmm10,%xmm2
-.byte	102,15,56,0,211
+	pshufb	%xmm3,%xmm2
 	pxor	%xmm0,%xmm2
 	movdqa	%xmm10,%xmm3
-.byte	102,15,56,0,220
+	pshufb	%xmm4,%xmm3
 	pxor	%xmm1,%xmm3
 	movdqa	%xmm13,%xmm4
-.byte	102,15,56,0,226
+	pshufb	%xmm2,%xmm4
 	movdqa	%xmm12,%xmm0
-.byte	102,15,56,0,195
+	pshufb	%xmm3,%xmm0
 	pxor	%xmm4,%xmm0
 
 
@@ -694,9 +694,9 @@
 	psrld	$4,%xmm1
 	pand	%xmm9,%xmm0
 	movdqa	(%r11),%xmm2
-.byte	102,15,56,0,208
+	pshufb	%xmm0,%xmm2
 	movdqa	16(%r11),%xmm0
-.byte	102,15,56,0,193
+	pshufb	%xmm1,%xmm0
 	pxor	%xmm2,%xmm0
 	ret
 .cfi_endproc	
@@ -737,11 +737,11 @@
 
 	addq	$16,%rdx
 	pxor	.Lk_s63(%rip),%xmm4
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	movdqa	%xmm4,%xmm3
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	pxor	%xmm4,%xmm3
-.byte	102,15,56,0,229
+	pshufb	%xmm5,%xmm4
 	pxor	%xmm4,%xmm3
 
 	jmp	.Lschedule_mangle_both
@@ -755,40 +755,40 @@
 	pand	%xmm9,%xmm4
 
 	movdqa	0(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	movdqa	16(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	32(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	48(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	64(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	80(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
-.byte	102,15,56,0,221
+	pshufb	%xmm5,%xmm3
 
 	movdqa	96(%r11),%xmm2
-.byte	102,15,56,0,212
+	pshufb	%xmm4,%xmm2
 	pxor	%xmm3,%xmm2
 	movdqa	112(%r11),%xmm3
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	pxor	%xmm2,%xmm3
 
 	addq	$-16,%rdx
 
 .Lschedule_mangle_both:
 	movdqa	(%r8,%r10,1),%xmm1
-.byte	102,15,56,0,217
+	pshufb	%xmm1,%xmm3
 	addq	$-16,%r8
 	andq	$0x30,%r8
 	movdqu	%xmm3,(%rdx)
@@ -971,8 +971,8 @@
 	movdqa	.Lrev_ctr(%rip),%xmm1
 	movdqa	%xmm14,%xmm0
 	movdqa	%xmm15,%xmm6
-.byte	102,15,56,0,193
-.byte	102,15,56,0,241
+	pshufb	%xmm1,%xmm0
+	pshufb	%xmm1,%xmm6
 	call	_vpaes_encrypt_core_2x
 	movdqu	(%rdi),%xmm1
 	movdqu	16(%rdi),%xmm2
diff --git a/src/gen/bcm/vpaes-x86_64-win.asm b/src/gen/bcm/vpaes-x86_64-win.asm
index ddbfb12..e28ae47 100644
--- a/src/gen/bcm/vpaes-x86_64-win.asm
+++ b/src/gen/bcm/vpaes-x86_64-win.asm
@@ -42,9 +42,9 @@
 	movdqu	xmm5,XMMWORD[r9]
 	psrld	xmm1,4
 	pand	xmm0,xmm9
-DB	102,15,56,0,208
+	pshufb	xmm2,xmm0
 	movdqa	xmm0,XMMWORD[(($L$k_ipt+16))]
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	pxor	xmm2,xmm5
 	add	r9,16
 	pxor	xmm0,xmm2
@@ -56,25 +56,25 @@
 
 	movdqa	xmm4,xmm13
 	movdqa	xmm0,xmm12
-DB	102,15,56,0,226
-DB	102,15,56,0,195
+	pshufb	xmm4,xmm2
+	pshufb	xmm0,xmm3
 	pxor	xmm4,xmm5
 	movdqa	xmm5,xmm15
 	pxor	xmm0,xmm4
 	movdqa	xmm1,XMMWORD[((-64))+r10*1+r11]
-DB	102,15,56,0,234
+	pshufb	xmm5,xmm2
 	movdqa	xmm4,XMMWORD[r10*1+r11]
 	movdqa	xmm2,xmm14
-DB	102,15,56,0,211
+	pshufb	xmm2,xmm3
 	movdqa	xmm3,xmm0
 	pxor	xmm2,xmm5
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	add	r9,16
 	pxor	xmm0,xmm2
-DB	102,15,56,0,220
+	pshufb	xmm3,xmm4
 	add	r11,16
 	pxor	xmm3,xmm0
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	and	r11,0x30
 	sub	rax,1
 	pxor	xmm0,xmm3
@@ -86,19 +86,19 @@
 	pandn	xmm1,xmm0
 	psrld	xmm1,4
 	pand	xmm0,xmm9
-DB	102,15,56,0,232
+	pshufb	xmm5,xmm0
 	movdqa	xmm3,xmm10
 	pxor	xmm0,xmm1
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	movdqa	xmm4,xmm10
 	pxor	xmm3,xmm5
-DB	102,15,56,0,224
+	pshufb	xmm4,xmm0
 	movdqa	xmm2,xmm10
 	pxor	xmm4,xmm5
-DB	102,15,56,0,211
+	pshufb	xmm2,xmm3
 	movdqa	xmm3,xmm10
 	pxor	xmm2,xmm0
-DB	102,15,56,0,220
+	pshufb	xmm3,xmm4
 	movdqu	xmm5,XMMWORD[r9]
 	pxor	xmm3,xmm1
 	jnz	NEAR $L$enc_loop
@@ -106,12 +106,12 @@
 
 	movdqa	xmm4,XMMWORD[((-96))+r10]
 	movdqa	xmm0,XMMWORD[((-80))+r10]
-DB	102,15,56,0,226
+	pshufb	xmm4,xmm2
 	pxor	xmm4,xmm5
-DB	102,15,56,0,195
+	pshufb	xmm0,xmm3
 	movdqa	xmm1,XMMWORD[64+r10*1+r11]
 	pxor	xmm0,xmm4
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	ret
 
 
@@ -164,12 +164,12 @@
 	psrld	xmm7,4
 	pand	xmm0,xmm9
 	pand	xmm6,xmm9
-DB	102,15,56,0,208
-DB	102,68,15,56,0,198
+	pshufb	xmm2,xmm0
+	pshufb	xmm8,xmm6
 	movdqa	xmm0,XMMWORD[(($L$k_ipt+16))]
 	movdqa	xmm6,xmm0
-DB	102,15,56,0,193
-DB	102,15,56,0,247
+	pshufb	xmm0,xmm1
+	pshufb	xmm6,xmm7
 	pxor	xmm2,xmm5
 	pxor	xmm8,xmm5
 	add	r9,16
@@ -185,10 +185,10 @@
 	movdqa	xmm0,XMMWORD[(($L$k_sb1+16))]
 	movdqa	xmm12,xmm4
 	movdqa	xmm6,xmm0
-DB	102,15,56,0,226
-DB	102,69,15,56,0,224
-DB	102,15,56,0,195
-DB	102,65,15,56,0,243
+	pshufb	xmm4,xmm2
+	pshufb	xmm12,xmm8
+	pshufb	xmm0,xmm3
+	pshufb	xmm6,xmm11
 	pxor	xmm4,xmm5
 	pxor	xmm12,xmm5
 	movdqa	xmm5,XMMWORD[$L$k_sb2]
@@ -197,30 +197,30 @@
 	pxor	xmm6,xmm12
 	movdqa	xmm1,XMMWORD[((-64))+r10*1+r11]
 
-DB	102,15,56,0,234
-DB	102,69,15,56,0,232
+	pshufb	xmm5,xmm2
+	pshufb	xmm13,xmm8
 	movdqa	xmm4,XMMWORD[r10*1+r11]
 
 	movdqa	xmm2,XMMWORD[(($L$k_sb2+16))]
 	movdqa	xmm8,xmm2
-DB	102,15,56,0,211
-DB	102,69,15,56,0,195
+	pshufb	xmm2,xmm3
+	pshufb	xmm8,xmm11
 	movdqa	xmm3,xmm0
 	movdqa	xmm11,xmm6
 	pxor	xmm2,xmm5
 	pxor	xmm8,xmm13
-DB	102,15,56,0,193
-DB	102,15,56,0,241
+	pshufb	xmm0,xmm1
+	pshufb	xmm6,xmm1
 	add	r9,16
 	pxor	xmm0,xmm2
 	pxor	xmm6,xmm8
-DB	102,15,56,0,220
-DB	102,68,15,56,0,220
+	pshufb	xmm3,xmm4
+	pshufb	xmm11,xmm4
 	add	r11,16
 	pxor	xmm3,xmm0
 	pxor	xmm11,xmm6
-DB	102,15,56,0,193
-DB	102,15,56,0,241
+	pshufb	xmm0,xmm1
+	pshufb	xmm6,xmm1
 	and	r11,0x30
 	sub	rax,1
 	pxor	xmm0,xmm3
@@ -238,32 +238,32 @@
 	psrld	xmm7,4
 	pand	xmm0,xmm9
 	pand	xmm6,xmm9
-DB	102,15,56,0,232
-DB	102,68,15,56,0,238
+	pshufb	xmm5,xmm0
+	pshufb	xmm13,xmm6
 	movdqa	xmm3,xmm10
 	movdqa	xmm11,xmm10
 	pxor	xmm0,xmm1
 	pxor	xmm6,xmm7
-DB	102,15,56,0,217
-DB	102,68,15,56,0,223
+	pshufb	xmm3,xmm1
+	pshufb	xmm11,xmm7
 	movdqa	xmm4,xmm10
 	movdqa	xmm12,xmm10
 	pxor	xmm3,xmm5
 	pxor	xmm11,xmm13
-DB	102,15,56,0,224
-DB	102,68,15,56,0,230
+	pshufb	xmm4,xmm0
+	pshufb	xmm12,xmm6
 	movdqa	xmm2,xmm10
 	movdqa	xmm8,xmm10
 	pxor	xmm4,xmm5
 	pxor	xmm12,xmm13
-DB	102,15,56,0,211
-DB	102,69,15,56,0,195
+	pshufb	xmm2,xmm3
+	pshufb	xmm8,xmm11
 	movdqa	xmm3,xmm10
 	movdqa	xmm11,xmm10
 	pxor	xmm2,xmm0
 	pxor	xmm8,xmm6
-DB	102,15,56,0,220
-DB	102,69,15,56,0,220
+	pshufb	xmm3,xmm4
+	pshufb	xmm11,xmm12
 	movdqu	xmm5,XMMWORD[r9]
 
 	pxor	xmm3,xmm1
@@ -275,18 +275,18 @@
 	movdqa	xmm0,XMMWORD[((-80))+r10]
 	movdqa	xmm12,xmm4
 	movdqa	xmm6,xmm0
-DB	102,15,56,0,226
-DB	102,69,15,56,0,224
+	pshufb	xmm4,xmm2
+	pshufb	xmm12,xmm8
 	pxor	xmm4,xmm5
 	pxor	xmm12,xmm5
-DB	102,15,56,0,195
-DB	102,65,15,56,0,243
+	pshufb	xmm0,xmm3
+	pshufb	xmm6,xmm11
 	movdqa	xmm1,XMMWORD[64+r10*1+r11]
 
 	pxor	xmm0,xmm4
 	pxor	xmm6,xmm12
-DB	102,15,56,0,193
-DB	102,15,56,0,241
+	pshufb	xmm0,xmm1
+	pshufb	xmm6,xmm1
 	ret
 
 
@@ -310,11 +310,11 @@
 	movdqu	xmm5,XMMWORD[r9]
 	shl	r11,4
 	pand	xmm0,xmm9
-DB	102,15,56,0,208
+	pshufb	xmm2,xmm0
 	movdqa	xmm0,XMMWORD[(($L$k_dipt+16))]
 	xor	r11,0x30
 	lea	r10,[$L$k_dsbd]
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	and	r11,0x30
 	pxor	xmm2,xmm5
 	movdqa	xmm5,XMMWORD[(($L$k_mc_forward+48))]
@@ -330,35 +330,35 @@
 
 	movdqa	xmm4,XMMWORD[((-32))+r10]
 	movdqa	xmm1,XMMWORD[((-16))+r10]
-DB	102,15,56,0,226
-DB	102,15,56,0,203
+	pshufb	xmm4,xmm2
+	pshufb	xmm1,xmm3
 	pxor	xmm0,xmm4
 	movdqa	xmm4,XMMWORD[r10]
 	pxor	xmm0,xmm1
 	movdqa	xmm1,XMMWORD[16+r10]
 
-DB	102,15,56,0,226
-DB	102,15,56,0,197
-DB	102,15,56,0,203
+	pshufb	xmm4,xmm2
+	pshufb	xmm0,xmm5
+	pshufb	xmm1,xmm3
 	pxor	xmm0,xmm4
 	movdqa	xmm4,XMMWORD[32+r10]
 	pxor	xmm0,xmm1
 	movdqa	xmm1,XMMWORD[48+r10]
 
-DB	102,15,56,0,226
-DB	102,15,56,0,197
-DB	102,15,56,0,203
+	pshufb	xmm4,xmm2
+	pshufb	xmm0,xmm5
+	pshufb	xmm1,xmm3
 	pxor	xmm0,xmm4
 	movdqa	xmm4,XMMWORD[64+r10]
 	pxor	xmm0,xmm1
 	movdqa	xmm1,XMMWORD[80+r10]
 
-DB	102,15,56,0,226
-DB	102,15,56,0,197
-DB	102,15,56,0,203
+	pshufb	xmm4,xmm2
+	pshufb	xmm0,xmm5
+	pshufb	xmm1,xmm3
 	pxor	xmm0,xmm4
 	add	r9,16
-DB	102,15,58,15,237,12
+	palignr	xmm5,xmm5,12
 	pxor	xmm0,xmm1
 	sub	rax,1
 
@@ -369,32 +369,32 @@
 	movdqa	xmm2,xmm11
 	psrld	xmm1,4
 	pand	xmm0,xmm9
-DB	102,15,56,0,208
+	pshufb	xmm2,xmm0
 	movdqa	xmm3,xmm10
 	pxor	xmm0,xmm1
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	movdqa	xmm4,xmm10
 	pxor	xmm3,xmm2
-DB	102,15,56,0,224
+	pshufb	xmm4,xmm0
 	pxor	xmm4,xmm2
 	movdqa	xmm2,xmm10
-DB	102,15,56,0,211
+	pshufb	xmm2,xmm3
 	movdqa	xmm3,xmm10
 	pxor	xmm2,xmm0
-DB	102,15,56,0,220
+	pshufb	xmm3,xmm4
 	movdqu	xmm0,XMMWORD[r9]
 	pxor	xmm3,xmm1
 	jnz	NEAR $L$dec_loop
 
 
 	movdqa	xmm4,XMMWORD[96+r10]
-DB	102,15,56,0,226
+	pshufb	xmm4,xmm2
 	pxor	xmm4,xmm0
 	movdqa	xmm0,XMMWORD[112+r10]
 	movdqa	xmm2,XMMWORD[((-352))+r11]
-DB	102,15,56,0,195
+	pshufb	xmm0,xmm3
 	pxor	xmm0,xmm4
-DB	102,15,56,0,194
+	pshufb	xmm0,xmm2
 	ret
 
 
@@ -434,7 +434,7 @@
 $L$schedule_am_decrypting:
 
 	movdqa	xmm1,XMMWORD[r10*1+r8]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	movdqu	XMMWORD[rdx],xmm3
 	xor	r8,0x30
 
@@ -488,7 +488,7 @@
 
 $L$oop_schedule_192:
 	call	_vpaes_schedule_round
-DB	102,15,58,15,198,8
+	palignr	xmm0,xmm6,8
 	call	_vpaes_schedule_mangle
 	call	_vpaes_schedule_192_smear
 	call	_vpaes_schedule_mangle
@@ -554,7 +554,7 @@
 
 
 	movdqa	xmm1,XMMWORD[r10*1+r8]
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	lea	r11,[$L$k_opt]
 	add	rdx,32
 
@@ -630,13 +630,13 @@
 
 
 	pxor	xmm1,xmm1
-DB	102,65,15,58,15,200,15
-DB	102,69,15,58,15,192,15
+	palignr	xmm1,xmm8,15
+	palignr	xmm8,xmm8,15
 	pxor	xmm7,xmm1
 
 
 	pshufd	xmm0,xmm0,0xFF
-DB	102,15,58,15,192,1
+	palignr	xmm0,xmm0,1
 
 
 
@@ -657,24 +657,24 @@
 	psrld	xmm1,4
 	pand	xmm0,xmm9
 	movdqa	xmm2,xmm11
-DB	102,15,56,0,208
+	pshufb	xmm2,xmm0
 	pxor	xmm0,xmm1
 	movdqa	xmm3,xmm10
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	pxor	xmm3,xmm2
 	movdqa	xmm4,xmm10
-DB	102,15,56,0,224
+	pshufb	xmm4,xmm0
 	pxor	xmm4,xmm2
 	movdqa	xmm2,xmm10
-DB	102,15,56,0,211
+	pshufb	xmm2,xmm3
 	pxor	xmm2,xmm0
 	movdqa	xmm3,xmm10
-DB	102,15,56,0,220
+	pshufb	xmm3,xmm4
 	pxor	xmm3,xmm1
 	movdqa	xmm4,xmm13
-DB	102,15,56,0,226
+	pshufb	xmm4,xmm2
 	movdqa	xmm0,xmm12
-DB	102,15,56,0,195
+	pshufb	xmm0,xmm3
 	pxor	xmm0,xmm4
 
 
@@ -702,9 +702,9 @@
 	psrld	xmm1,4
 	pand	xmm0,xmm9
 	movdqa	xmm2,XMMWORD[r11]
-DB	102,15,56,0,208
+	pshufb	xmm2,xmm0
 	movdqa	xmm0,XMMWORD[16+r11]
-DB	102,15,56,0,193
+	pshufb	xmm0,xmm1
 	pxor	xmm0,xmm2
 	ret
 
@@ -745,11 +745,11 @@
 
 	add	rdx,16
 	pxor	xmm4,XMMWORD[$L$k_s63]
-DB	102,15,56,0,229
+	pshufb	xmm4,xmm5
 	movdqa	xmm3,xmm4
-DB	102,15,56,0,229
+	pshufb	xmm4,xmm5
 	pxor	xmm3,xmm4
-DB	102,15,56,0,229
+	pshufb	xmm4,xmm5
 	pxor	xmm3,xmm4
 
 	jmp	NEAR $L$schedule_mangle_both
@@ -763,40 +763,40 @@
 	pand	xmm4,xmm9
 
 	movdqa	xmm2,XMMWORD[r11]
-DB	102,15,56,0,212
+	pshufb	xmm2,xmm4
 	movdqa	xmm3,XMMWORD[16+r11]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	pxor	xmm3,xmm2
-DB	102,15,56,0,221
+	pshufb	xmm3,xmm5
 
 	movdqa	xmm2,XMMWORD[32+r11]
-DB	102,15,56,0,212
+	pshufb	xmm2,xmm4
 	pxor	xmm2,xmm3
 	movdqa	xmm3,XMMWORD[48+r11]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	pxor	xmm3,xmm2
-DB	102,15,56,0,221
+	pshufb	xmm3,xmm5
 
 	movdqa	xmm2,XMMWORD[64+r11]
-DB	102,15,56,0,212
+	pshufb	xmm2,xmm4
 	pxor	xmm2,xmm3
 	movdqa	xmm3,XMMWORD[80+r11]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	pxor	xmm3,xmm2
-DB	102,15,56,0,221
+	pshufb	xmm3,xmm5
 
 	movdqa	xmm2,XMMWORD[96+r11]
-DB	102,15,56,0,212
+	pshufb	xmm2,xmm4
 	pxor	xmm2,xmm3
 	movdqa	xmm3,XMMWORD[112+r11]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	pxor	xmm3,xmm2
 
 	add	rdx,-16
 
 $L$schedule_mangle_both:
 	movdqa	xmm1,XMMWORD[r10*1+r8]
-DB	102,15,56,0,217
+	pshufb	xmm3,xmm1
 	add	r8,-16
 	and	r8,0x30
 	movdqu	XMMWORD[rdx],xmm3
@@ -1172,8 +1172,8 @@
 	movdqa	xmm1,XMMWORD[$L$rev_ctr]
 	movdqa	xmm0,xmm14
 	movdqa	xmm6,xmm15
-DB	102,15,56,0,193
-DB	102,15,56,0,241
+	pshufb	xmm0,xmm1
+	pshufb	xmm6,xmm1
 	call	_vpaes_encrypt_core_2x
 	movdqu	xmm1,XMMWORD[rdi]
 	movdqu	xmm2,XMMWORD[16+rdi]
diff --git a/src/gen/bcm/x86-mont-apple.S b/src/gen/bcm/x86-mont-apple.S
index a8fd1f9..6e549c7 100644
--- a/src/gen/bcm/x86-mont-apple.S
+++ b/src/gen/bcm/x86-mont-apple.S
@@ -14,10 +14,7 @@
 	pushl	%ebx
 	pushl	%esi
 	pushl	%edi
-	xorl	%eax,%eax
 	movl	40(%esp),%edi
-	cmpl	$4,%edi
-	jl	L000just_leave
 	leal	20(%esp),%esi
 	leal	24(%esp),%edx
 	addl	$2,%edi
@@ -40,15 +37,15 @@
 	leal	(%ebp,%eax,1),%esp
 	movl	(%esp),%eax
 	cmpl	%ebp,%esp
-	ja	L001page_walk
-	jmp	L002page_walk_done
+	ja	L000page_walk
+	jmp	L001page_walk_done
 .align	4,0x90
-L001page_walk:
+L000page_walk:
 	leal	-4096(%esp),%esp
 	movl	(%esp),%eax
 	cmpl	%ebp,%esp
-	ja	L001page_walk
-L002page_walk_done:
+	ja	L000page_walk
+L001page_walk_done:
 	movl	(%esi),%eax
 	movl	4(%esi),%ebx
 	movl	8(%esi),%ecx
@@ -85,7 +82,7 @@
 	psrlq	$32,%mm3
 	incl	%ecx
 .align	4,0x90
-L0031st:
+L0021st:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -100,7 +97,7 @@
 	psrlq	$32,%mm3
 	leal	1(%ecx),%ecx
 	cmpl	%ebx,%ecx
-	jl	L0031st
+	jl	L0021st
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -114,7 +111,7 @@
 	paddq	%mm2,%mm3
 	movq	%mm3,32(%esp,%ebx,4)
 	incl	%edx
-L004outer:
+L003outer:
 	xorl	%ecx,%ecx
 	movd	(%edi,%edx,4),%mm4
 	movd	(%esi),%mm5
@@ -136,7 +133,7 @@
 	paddq	%mm6,%mm2
 	incl	%ecx
 	decl	%ebx
-L005inner:
+L004inner:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -153,7 +150,7 @@
 	paddq	%mm6,%mm2
 	decl	%ebx
 	leal	1(%ecx),%ecx
-	jnz	L005inner
+	jnz	L004inner
 	movl	%ecx,%ebx
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
@@ -171,11 +168,11 @@
 	movq	%mm3,32(%esp,%ebx,4)
 	leal	1(%edx),%edx
 	cmpl	%ebx,%edx
-	jle	L004outer
+	jle	L003outer
 	emms
-	jmp	L006common_tail
+	jmp	L005common_tail
 .align	4,0x90
-L006common_tail:
+L005common_tail:
 	movl	16(%esp),%ebp
 	movl	4(%esp),%edi
 	leal	32(%esp),%esi
@@ -183,19 +180,19 @@
 	movl	%ebx,%ecx
 	xorl	%edx,%edx
 .align	4,0x90
-L007sub:
+L006sub:
 	sbbl	(%ebp,%edx,4),%eax
 	movl	%eax,(%edi,%edx,4)
 	decl	%ecx
 	movl	4(%esi,%edx,4),%eax
 	leal	1(%edx),%edx
-	jge	L007sub
+	jge	L006sub
 	sbbl	$0,%eax
 	movl	$-1,%edx
 	xorl	%eax,%edx
-	jmp	L008copy
+	jmp	L007copy
 .align	4,0x90
-L008copy:
+L007copy:
 	movl	32(%esp,%ebx,4),%esi
 	movl	(%edi,%ebx,4),%ebp
 	movl	%ecx,32(%esp,%ebx,4)
@@ -204,10 +201,8 @@
 	orl	%esi,%ebp
 	movl	%ebp,(%edi,%ebx,4)
 	decl	%ebx
-	jge	L008copy
+	jge	L007copy
 	movl	24(%esp),%esp
-	movl	$1,%eax
-L000just_leave:
 	popl	%edi
 	popl	%esi
 	popl	%ebx
diff --git a/src/gen/bcm/x86-mont-linux.S b/src/gen/bcm/x86-mont-linux.S
index 3d3ddb5..21fbee2 100644
--- a/src/gen/bcm/x86-mont-linux.S
+++ b/src/gen/bcm/x86-mont-linux.S
@@ -15,10 +15,7 @@
 	pushl	%ebx
 	pushl	%esi
 	pushl	%edi
-	xorl	%eax,%eax
 	movl	40(%esp),%edi
-	cmpl	$4,%edi
-	jl	.L000just_leave
 	leal	20(%esp),%esi
 	leal	24(%esp),%edx
 	addl	$2,%edi
@@ -41,15 +38,15 @@
 	leal	(%ebp,%eax,1),%esp
 	movl	(%esp),%eax
 	cmpl	%ebp,%esp
-	ja	.L001page_walk
-	jmp	.L002page_walk_done
+	ja	.L000page_walk
+	jmp	.L001page_walk_done
 .align	16
-.L001page_walk:
+.L000page_walk:
 	leal	-4096(%esp),%esp
 	movl	(%esp),%eax
 	cmpl	%ebp,%esp
-	ja	.L001page_walk
-.L002page_walk_done:
+	ja	.L000page_walk
+.L001page_walk_done:
 	movl	(%esi),%eax
 	movl	4(%esi),%ebx
 	movl	8(%esi),%ecx
@@ -86,7 +83,7 @@
 	psrlq	$32,%mm3
 	incl	%ecx
 .align	16
-.L0031st:
+.L0021st:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -101,7 +98,7 @@
 	psrlq	$32,%mm3
 	leal	1(%ecx),%ecx
 	cmpl	%ebx,%ecx
-	jl	.L0031st
+	jl	.L0021st
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -115,7 +112,7 @@
 	paddq	%mm2,%mm3
 	movq	%mm3,32(%esp,%ebx,4)
 	incl	%edx
-.L004outer:
+.L003outer:
 	xorl	%ecx,%ecx
 	movd	(%edi,%edx,4),%mm4
 	movd	(%esi),%mm5
@@ -137,7 +134,7 @@
 	paddq	%mm6,%mm2
 	incl	%ecx
 	decl	%ebx
-.L005inner:
+.L004inner:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -154,7 +151,7 @@
 	paddq	%mm6,%mm2
 	decl	%ebx
 	leal	1(%ecx),%ecx
-	jnz	.L005inner
+	jnz	.L004inner
 	movl	%ecx,%ebx
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
@@ -172,11 +169,11 @@
 	movq	%mm3,32(%esp,%ebx,4)
 	leal	1(%edx),%edx
 	cmpl	%ebx,%edx
-	jle	.L004outer
+	jle	.L003outer
 	emms
-	jmp	.L006common_tail
+	jmp	.L005common_tail
 .align	16
-.L006common_tail:
+.L005common_tail:
 	movl	16(%esp),%ebp
 	movl	4(%esp),%edi
 	leal	32(%esp),%esi
@@ -184,19 +181,19 @@
 	movl	%ebx,%ecx
 	xorl	%edx,%edx
 .align	16
-.L007sub:
+.L006sub:
 	sbbl	(%ebp,%edx,4),%eax
 	movl	%eax,(%edi,%edx,4)
 	decl	%ecx
 	movl	4(%esi,%edx,4),%eax
 	leal	1(%edx),%edx
-	jge	.L007sub
+	jge	.L006sub
 	sbbl	$0,%eax
 	movl	$-1,%edx
 	xorl	%eax,%edx
-	jmp	.L008copy
+	jmp	.L007copy
 .align	16
-.L008copy:
+.L007copy:
 	movl	32(%esp,%ebx,4),%esi
 	movl	(%edi,%ebx,4),%ebp
 	movl	%ecx,32(%esp,%ebx,4)
@@ -205,10 +202,8 @@
 	orl	%esi,%ebp
 	movl	%ebp,(%edi,%ebx,4)
 	decl	%ebx
-	jge	.L008copy
+	jge	.L007copy
 	movl	24(%esp),%esp
-	movl	$1,%eax
-.L000just_leave:
 	popl	%edi
 	popl	%esi
 	popl	%ebx
diff --git a/src/gen/bcm/x86-mont-win.asm b/src/gen/bcm/x86-mont-win.asm
index 931275d..d154078 100644
--- a/src/gen/bcm/x86-mont-win.asm
+++ b/src/gen/bcm/x86-mont-win.asm
@@ -21,10 +21,7 @@
 	push	ebx
 	push	esi
 	push	edi
-	xor	eax,eax
 	mov	edi,DWORD [40+esp]
-	cmp	edi,4
-	jl	NEAR L$000just_leave
 	lea	esi,[20+esp]
 	lea	edx,[24+esp]
 	add	edi,2
@@ -47,15 +44,15 @@
 	lea	esp,[eax*1+ebp]
 	mov	eax,DWORD [esp]
 	cmp	esp,ebp
-	ja	NEAR L$001page_walk
-	jmp	NEAR L$002page_walk_done
+	ja	NEAR L$000page_walk
+	jmp	NEAR L$001page_walk_done
 align	16
-L$001page_walk:
+L$000page_walk:
 	lea	esp,[esp-4096]
 	mov	eax,DWORD [esp]
 	cmp	esp,ebp
-	ja	NEAR L$001page_walk
-L$002page_walk_done:
+	ja	NEAR L$000page_walk
+L$001page_walk_done:
 	mov	eax,DWORD [esi]
 	mov	ebx,DWORD [4+esi]
 	mov	ecx,DWORD [8+esi]
@@ -92,7 +89,7 @@
 	psrlq	mm3,32
 	inc	ecx
 align	16
-L$0031st:
+L$0021st:
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -107,7 +104,7 @@
 	psrlq	mm3,32
 	lea	ecx,[1+ecx]
 	cmp	ecx,ebx
-	jl	NEAR L$0031st
+	jl	NEAR L$0021st
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -121,7 +118,7 @@
 	paddq	mm3,mm2
 	movq	[32+ebx*4+esp],mm3
 	inc	edx
-L$004outer:
+L$003outer:
 	xor	ecx,ecx
 	movd	mm4,DWORD [edx*4+edi]
 	movd	mm5,DWORD [esi]
@@ -143,7 +140,7 @@
 	paddq	mm2,mm6
 	inc	ecx
 	dec	ebx
-L$005inner:
+L$004inner:
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -160,7 +157,7 @@
 	paddq	mm2,mm6
 	dec	ebx
 	lea	ecx,[1+ecx]
-	jnz	NEAR L$005inner
+	jnz	NEAR L$004inner
 	mov	ebx,ecx
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
@@ -178,11 +175,11 @@
 	movq	[32+ebx*4+esp],mm3
 	lea	edx,[1+edx]
 	cmp	edx,ebx
-	jle	NEAR L$004outer
+	jle	NEAR L$003outer
 	emms
-	jmp	NEAR L$006common_tail
+	jmp	NEAR L$005common_tail
 align	16
-L$006common_tail:
+L$005common_tail:
 	mov	ebp,DWORD [16+esp]
 	mov	edi,DWORD [4+esp]
 	lea	esi,[32+esp]
@@ -190,19 +187,19 @@
 	mov	ecx,ebx
 	xor	edx,edx
 align	16
-L$007sub:
+L$006sub:
 	sbb	eax,DWORD [edx*4+ebp]
 	mov	DWORD [edx*4+edi],eax
 	dec	ecx
 	mov	eax,DWORD [4+edx*4+esi]
 	lea	edx,[1+edx]
-	jge	NEAR L$007sub
+	jge	NEAR L$006sub
 	sbb	eax,0
 	mov	edx,-1
 	xor	edx,eax
-	jmp	NEAR L$008copy
+	jmp	NEAR L$007copy
 align	16
-L$008copy:
+L$007copy:
 	mov	esi,DWORD [32+ebx*4+esp]
 	mov	ebp,DWORD [ebx*4+edi]
 	mov	DWORD [32+ebx*4+esp],ecx
@@ -211,10 +208,8 @@
 	or	ebp,esi
 	mov	DWORD [ebx*4+edi],ebp
 	dec	ebx
-	jge	NEAR L$008copy
+	jge	NEAR L$007copy
 	mov	esp,DWORD [24+esp]
-	mov	eax,1
-L$000just_leave:
 	pop	edi
 	pop	esi
 	pop	ebx
diff --git a/src/gen/bcm/x86_64-mont-apple.S b/src/gen/bcm/x86_64-mont-apple.S
index 4bf0c6d..27a168d 100644
--- a/src/gen/bcm/x86_64-mont-apple.S
+++ b/src/gen/bcm/x86_64-mont-apple.S
@@ -229,7 +229,7 @@
 
 	movq	8(%rsp,%r9,8),%rsi
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 
 	movq	-40(%rsi),%r14
@@ -632,7 +632,7 @@
 	sbbq	$0,%rax
 	movq	%rbp,24(%rdi,%r14,8)
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,224
+	movq	%rax,%xmm4
 	pcmpeqd	%xmm5,%xmm5
 	pshufd	$0,%xmm4,%xmm4
 	movq	%r9,%r15
@@ -662,7 +662,7 @@
 	jnz	L$copy4x
 	movq	8(%rsp,%r9,8),%rsi
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 
 	movq	-40(%rsi),%r14
@@ -764,10 +764,10 @@
 
 L$sqr8x_body:
 
-.byte	102,72,15,110,209
+	movq	%rcx,%xmm2
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,207
-.byte	102,73,15,110,218
+	movq	%rdi,%xmm1
+	movq	%r10,%xmm3
 	testq	%rdx,%rdx
 	jz	L$sqr8x_nox
 
@@ -779,7 +779,7 @@
 	leaq	(%r8,%rcx,1),%rbx
 	movq	%rcx,%r9
 	movq	%rcx,%rdx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	sarq	$3+2,%rcx
 	jmp	L$sqr8x_sub
 
@@ -793,7 +793,7 @@
 	leaq	(%rdi,%r9,1),%rbx
 	movq	%r9,%rcx
 	movq	%r9,%rdx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	sarq	$3+2,%rcx
 	jmp	L$sqr8x_sub
 
@@ -821,7 +821,7 @@
 	leaq	(%rbx,%r9,1),%rbx
 	leaq	(%rdi,%r9,1),%rdi
 
-.byte	102,72,15,110,200
+	movq	%rax,%xmm1
 	pxor	%xmm0,%xmm0
 	pshufd	$0,%xmm1,%xmm1
 	movq	40(%rsp),%rsi
@@ -853,7 +853,7 @@
 	addq	$32,%r9
 	jnz	L$sqr8x_cond_copy
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 
 	movq	-40(%rsi),%r14
@@ -1179,7 +1179,7 @@
 	leaq	64(%rsp),%rbx
 	subq	%rdx,%rdi
 
-.byte	102,73,15,110,207
+	movq	%r15,%xmm1
 	pxor	%xmm0,%xmm0
 	pshufd	$0,%xmm1,%xmm1
 	movq	40(%rsp),%rsi
@@ -1211,7 +1211,7 @@
 
 	movq	%rdx,(%rbx)
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 
 	movq	-40(%rsi),%r14
diff --git a/src/gen/bcm/x86_64-mont-linux.S b/src/gen/bcm/x86_64-mont-linux.S
index 02b282d..51c4b6c 100644
--- a/src/gen/bcm/x86_64-mont-linux.S
+++ b/src/gen/bcm/x86_64-mont-linux.S
@@ -229,7 +229,7 @@
 
 	movq	8(%rsp,%r9,8),%rsi
 .cfi_def_cfa	%rsi,8
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 .cfi_restore	%r15
 	movq	-40(%rsi),%r14
@@ -632,7 +632,7 @@
 	sbbq	$0,%rax
 	movq	%rbp,24(%rdi,%r14,8)
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,224
+	movq	%rax,%xmm4
 	pcmpeqd	%xmm5,%xmm5
 	pshufd	$0,%xmm4,%xmm4
 	movq	%r9,%r15
@@ -662,7 +662,7 @@
 	jnz	.Lcopy4x
 	movq	8(%rsp,%r9,8),%rsi
 .cfi_def_cfa	%rsi, 8
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 .cfi_restore	%r15
 	movq	-40(%rsi),%r14
@@ -766,10 +766,10 @@
 .cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lsqr8x_body:
 
-.byte	102,72,15,110,209
+	movq	%rcx,%xmm2
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,207
-.byte	102,73,15,110,218
+	movq	%rdi,%xmm1
+	movq	%r10,%xmm3
 	testq	%rdx,%rdx
 	jz	.Lsqr8x_nox
 
@@ -781,7 +781,7 @@
 	leaq	(%r8,%rcx,1),%rbx
 	movq	%rcx,%r9
 	movq	%rcx,%rdx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	sarq	$3+2,%rcx
 	jmp	.Lsqr8x_sub
 
@@ -795,7 +795,7 @@
 	leaq	(%rdi,%r9,1),%rbx
 	movq	%r9,%rcx
 	movq	%r9,%rdx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	sarq	$3+2,%rcx
 	jmp	.Lsqr8x_sub
 
@@ -823,7 +823,7 @@
 	leaq	(%rbx,%r9,1),%rbx
 	leaq	(%rdi,%r9,1),%rdi
 
-.byte	102,72,15,110,200
+	movq	%rax,%xmm1
 	pxor	%xmm0,%xmm0
 	pshufd	$0,%xmm1,%xmm1
 	movq	40(%rsp),%rsi
@@ -855,7 +855,7 @@
 	addq	$32,%r9
 	jnz	.Lsqr8x_cond_copy
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 .cfi_restore	%r15
 	movq	-40(%rsi),%r14
@@ -1181,7 +1181,7 @@
 	leaq	64(%rsp),%rbx
 	subq	%rdx,%rdi
 
-.byte	102,73,15,110,207
+	movq	%r15,%xmm1
 	pxor	%xmm0,%xmm0
 	pshufd	$0,%xmm1,%xmm1
 	movq	40(%rsp),%rsi
@@ -1213,7 +1213,7 @@
 
 	movq	%rdx,(%rbx)
 
-	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
 .cfi_restore	%r15
 	movq	-40(%rsi),%r14
diff --git a/src/gen/bcm/x86_64-mont-win.asm b/src/gen/bcm/x86_64-mont-win.asm
index b0611fc..c768d16 100644
--- a/src/gen/bcm/x86_64-mont-win.asm
+++ b/src/gen/bcm/x86_64-mont-win.asm
@@ -248,7 +248,7 @@
 
 	mov	rsi,QWORD[8+r9*8+rsp]
 
-	mov	rax,1
+
 	mov	r15,QWORD[((-48))+rsi]
 
 	mov	r14,QWORD[((-40))+rsi]
@@ -664,7 +664,7 @@
 	sbb	rax,0
 	mov	QWORD[24+r14*8+rdi],rbp
 	pxor	xmm0,xmm0
-DB	102,72,15,110,224
+	movq	xmm4,rax
 	pcmpeqd	xmm5,xmm5
 	pshufd	xmm4,xmm4,0
 	mov	r15,r9
@@ -694,7 +694,7 @@
 	jnz	NEAR $L$copy4x
 	mov	rsi,QWORD[8+r9*8+rsp]
 
-	mov	rax,1
+
 	mov	r15,QWORD[((-48))+rsi]
 
 	mov	r14,QWORD[((-40))+rsi]
@@ -809,10 +809,10 @@
 
 $L$sqr8x_body:
 
-DB	102,72,15,110,209
+	movq	xmm2,rcx
 	pxor	xmm0,xmm0
-DB	102,72,15,110,207
-DB	102,73,15,110,218
+	movq	xmm1,rdi
+	movq	xmm3,r10
 	test	rdx,rdx
 	jz	NEAR $L$sqr8x_nox
 
@@ -824,7 +824,7 @@
 	lea	rbx,[rcx*1+r8]
 	mov	r9,rcx
 	mov	rdx,rcx
-DB	102,72,15,126,207
+	movq	rdi,xmm1
 	sar	rcx,3+2
 	jmp	NEAR $L$sqr8x_sub
 
@@ -838,7 +838,7 @@
 	lea	rbx,[r9*1+rdi]
 	mov	rcx,r9
 	mov	rdx,r9
-DB	102,72,15,126,207
+	movq	rdi,xmm1
 	sar	rcx,3+2
 	jmp	NEAR $L$sqr8x_sub
 
@@ -866,7 +866,7 @@
 	lea	rbx,[r9*1+rbx]
 	lea	rdi,[r9*1+rdi]
 
-DB	102,72,15,110,200
+	movq	xmm1,rax
 	pxor	xmm0,xmm0
 	pshufd	xmm1,xmm1,0
 	mov	rsi,QWORD[40+rsp]
@@ -898,7 +898,7 @@
 	add	r9,32
 	jnz	NEAR $L$sqr8x_cond_copy
 
-	mov	rax,1
+
 	mov	r15,QWORD[((-48))+rsi]
 
 	mov	r14,QWORD[((-40))+rsi]
@@ -1237,7 +1237,7 @@
 	lea	rbx,[64+rsp]
 	sub	rdi,rdx
 
-DB	102,73,15,110,207
+	movq	xmm1,r15
 	pxor	xmm0,xmm0
 	pshufd	xmm1,xmm1,0
 	mov	rsi,QWORD[40+rsp]
@@ -1269,7 +1269,7 @@
 
 	mov	QWORD[rbx],rdx
 
-	mov	rax,1
+
 	mov	r15,QWORD[((-48))+rsi]
 
 	mov	r14,QWORD[((-40))+rsi]
diff --git a/src/gen/bcm/x86_64-mont5-apple.S b/src/gen/bcm/x86_64-mont5-apple.S
index 5cf770f..cd7d797 100644
--- a/src/gen/bcm/x86_64-mont5-apple.S
+++ b/src/gen/bcm/x86_64-mont5-apple.S
@@ -196,7 +196,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	(%r8),%r8
 	movq	(%rsi),%rax
@@ -322,7 +322,7 @@
 	leaq	256(%r12),%r12
 
 	movq	(%rsi),%rax
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	xorq	%r15,%r15
 	movq	%r8,%rbp
@@ -691,7 +691,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	%r13,16+8(%rsp)
 	movq	%rdi,56+8(%rsp)
@@ -899,7 +899,7 @@
 	pshufd	$0x4e,%xmm4,%xmm0
 	por	%xmm4,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	(%r14,%r9,1),%r10
 	movq	%r8,%rbp
@@ -1171,10 +1171,10 @@
 	movq	%rax,40(%rsp)
 
 L$power5_body:
-.byte	102,72,15,110,207
-.byte	102,72,15,110,209
-.byte	102,73,15,110,218
-.byte	102,72,15,110,226
+	movq	%rdi,%xmm1
+	movq	%rcx,%xmm2
+	movq	%r10,%xmm3
+	movq	%rdx,%xmm4
 
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
@@ -1187,8 +1187,8 @@
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
 
-.byte	102,72,15,126,209
-.byte	102,72,15,126,226
+	movq	%xmm2,%rcx
+	movq	%xmm4,%rdx
 	movq	%rsi,%rdi
 	movq	40(%rsp),%rax
 	leaq	32(%rsp),%r8
@@ -1740,7 +1740,7 @@
 	adcq	%rdx,%r8
 	movq	%rbx,-16(%rdi)
 	movq	%r8,-8(%rdi)
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 __bn_sqr8x_reduction:
 	xorq	%rax,%rax
 	leaq	(%r9,%rbp,1),%rcx
@@ -1984,11 +1984,11 @@
 	movq	-8(%rbp),%rcx
 	xorq	%rsi,%rsi
 
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 
 	movq	%r8,0(%rdi)
 	movq	%r9,8(%rdi)
-.byte	102,73,15,126,217
+	movq	%xmm3,%r9
 	movq	%r10,16(%rdi)
 	movq	%r11,24(%rdi)
 	movq	%r12,32(%rdi)
@@ -2009,9 +2009,9 @@
 	movq	0(%rbp),%r12
 	leaq	(%rdi,%r9,1),%rbx
 	movq	%r9,%rcx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	negq	%rax
-.byte	102,72,15,126,206
+	movq	%xmm1,%rsi
 	sarq	$3+2,%rcx
 	decq	%r12
 	xorq	%r10,%r10
@@ -2321,7 +2321,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%rdi),%rdi
-.byte	102,72,15,126,194
+	movq	%xmm0,%rdx
 	leaq	64+32+8(%rsp),%rbx
 
 	movq	%rdx,%r9
@@ -2472,7 +2472,7 @@
 	pshufd	$0x4e,%xmm4,%xmm0
 	por	%xmm4,%xmm0
 	leaq	256(%rdi),%rdi
-.byte	102,72,15,126,194
+	movq	%xmm0,%rdx
 
 	movq	%rbp,(%rbx)
 	leaq	32(%rbx,%rax,1),%rbx
@@ -2689,10 +2689,10 @@
 
 
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,207
-.byte	102,72,15,110,209
-.byte	102,73,15,110,218
-.byte	102,72,15,110,226
+	movq	%rdi,%xmm1
+	movq	%rcx,%xmm2
+	movq	%r10,%xmm3
+	movq	%rdx,%xmm4
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
 
@@ -2711,8 +2711,8 @@
 
 	movq	%r10,%r9
 	movq	%rsi,%rdi
-.byte	102,72,15,126,209
-.byte	102,72,15,126,226
+	movq	%xmm2,%rcx
+	movq	%xmm4,%rdx
 	movq	40(%rsp),%rax
 
 	call	mulx4x_internal
@@ -3077,7 +3077,7 @@
 .p2align	5
 L$sqrx8x_outer_break:
 	movq	%r9,72(%rdi)
-.byte	102,72,15,126,217
+	movq	%xmm3,%rcx
 	movq	%r10,80(%rdi)
 	movq	%r11,88(%rdi)
 	movq	%r12,96(%rdi)
@@ -3151,7 +3151,7 @@
 	movq	%rax,48(%rdi)
 	movq	%rbx,56(%rdi)
 	leaq	64(%rdi),%rdi
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 __bn_sqrx8x_reduction:
 	xorl	%eax,%eax
 	movq	32+8(%rsp),%rbx
@@ -3331,10 +3331,10 @@
 	subq	16+8(%rsp),%rsi
 L$sqrx8x_no_tail:
 	adcq	0(%rdi),%r8
-.byte	102,72,15,126,217
+	movq	%xmm3,%rcx
 	adcq	8(%rdi),%r9
 	movq	56(%rbp),%rsi
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 	adcq	16(%rdi),%r10
 	adcq	24(%rdi),%r11
 	adcq	32(%rdi),%r12
@@ -3372,8 +3372,8 @@
 	negq	%rax
 	sarq	$3+2,%rcx
 
-.byte	102,72,15,126,202
-.byte	102,72,15,126,206
+	movq	%xmm1,%rdx
+	movq	%xmm1,%rsi
 	decq	%r12
 	movq	8(%rbp),%r13
 	xorq	%r8,%r8
diff --git a/src/gen/bcm/x86_64-mont5-linux.S b/src/gen/bcm/x86_64-mont5-linux.S
index dcc02fc..a147041 100644
--- a/src/gen/bcm/x86_64-mont5-linux.S
+++ b/src/gen/bcm/x86_64-mont5-linux.S
@@ -196,7 +196,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	(%r8),%r8
 	movq	(%rsi),%rax
@@ -322,7 +322,7 @@
 	leaq	256(%r12),%r12
 
 	movq	(%rsi),%rax
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	xorq	%r15,%r15
 	movq	%r8,%rbp
@@ -691,7 +691,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	%r13,16+8(%rsp)
 	movq	%rdi,56+8(%rsp)
@@ -899,7 +899,7 @@
 	pshufd	$0x4e,%xmm4,%xmm0
 	por	%xmm4,%xmm0
 	leaq	256(%r12),%r12
-.byte	102,72,15,126,195
+	movq	%xmm0,%rbx
 
 	movq	(%r14,%r9,1),%r10
 	movq	%r8,%rbp
@@ -1171,10 +1171,10 @@
 	movq	%rax,40(%rsp)
 .cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lpower5_body:
-.byte	102,72,15,110,207
-.byte	102,72,15,110,209
-.byte	102,73,15,110,218
-.byte	102,72,15,110,226
+	movq	%rdi,%xmm1
+	movq	%rcx,%xmm2
+	movq	%r10,%xmm3
+	movq	%rdx,%xmm4
 
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
@@ -1187,8 +1187,8 @@
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
 
-.byte	102,72,15,126,209
-.byte	102,72,15,126,226
+	movq	%xmm2,%rcx
+	movq	%xmm4,%rdx
 	movq	%rsi,%rdi
 	movq	40(%rsp),%rax
 	leaq	32(%rsp),%r8
@@ -1740,7 +1740,7 @@
 	adcq	%rdx,%r8
 	movq	%rbx,-16(%rdi)
 	movq	%r8,-8(%rdi)
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 __bn_sqr8x_reduction:
 	xorq	%rax,%rax
 	leaq	(%r9,%rbp,1),%rcx
@@ -1984,11 +1984,11 @@
 	movq	-8(%rbp),%rcx
 	xorq	%rsi,%rsi
 
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 
 	movq	%r8,0(%rdi)
 	movq	%r9,8(%rdi)
-.byte	102,73,15,126,217
+	movq	%xmm3,%r9
 	movq	%r10,16(%rdi)
 	movq	%r11,24(%rdi)
 	movq	%r12,32(%rdi)
@@ -2009,9 +2009,9 @@
 	movq	0(%rbp),%r12
 	leaq	(%rdi,%r9,1),%rbx
 	movq	%r9,%rcx
-.byte	102,72,15,126,207
+	movq	%xmm1,%rdi
 	negq	%rax
-.byte	102,72,15,126,206
+	movq	%xmm1,%rsi
 	sarq	$3+2,%rcx
 	decq	%r12
 	xorq	%r10,%r10
@@ -2321,7 +2321,7 @@
 	pshufd	$0x4e,%xmm0,%xmm1
 	por	%xmm1,%xmm0
 	leaq	256(%rdi),%rdi
-.byte	102,72,15,126,194
+	movq	%xmm0,%rdx
 	leaq	64+32+8(%rsp),%rbx
 
 	movq	%rdx,%r9
@@ -2472,7 +2472,7 @@
 	pshufd	$0x4e,%xmm4,%xmm0
 	por	%xmm4,%xmm0
 	leaq	256(%rdi),%rdi
-.byte	102,72,15,126,194
+	movq	%xmm0,%rdx
 
 	movq	%rbp,(%rbx)
 	leaq	32(%rbx,%rax,1),%rbx
@@ -2689,10 +2689,10 @@
 
 
 	pxor	%xmm0,%xmm0
-.byte	102,72,15,110,207
-.byte	102,72,15,110,209
-.byte	102,73,15,110,218
-.byte	102,72,15,110,226
+	movq	%rdi,%xmm1
+	movq	%rcx,%xmm2
+	movq	%r10,%xmm3
+	movq	%rdx,%xmm4
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
 .cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
@@ -2711,8 +2711,8 @@
 
 	movq	%r10,%r9
 	movq	%rsi,%rdi
-.byte	102,72,15,126,209
-.byte	102,72,15,126,226
+	movq	%xmm2,%rcx
+	movq	%xmm4,%rdx
 	movq	40(%rsp),%rax
 
 	call	mulx4x_internal
@@ -3077,7 +3077,7 @@
 .align	32
 .Lsqrx8x_outer_break:
 	movq	%r9,72(%rdi)
-.byte	102,72,15,126,217
+	movq	%xmm3,%rcx
 	movq	%r10,80(%rdi)
 	movq	%r11,88(%rdi)
 	movq	%r12,96(%rdi)
@@ -3151,7 +3151,7 @@
 	movq	%rax,48(%rdi)
 	movq	%rbx,56(%rdi)
 	leaq	64(%rdi),%rdi
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 __bn_sqrx8x_reduction:
 	xorl	%eax,%eax
 	movq	32+8(%rsp),%rbx
@@ -3331,10 +3331,10 @@
 	subq	16+8(%rsp),%rsi
 .Lsqrx8x_no_tail:
 	adcq	0(%rdi),%r8
-.byte	102,72,15,126,217
+	movq	%xmm3,%rcx
 	adcq	8(%rdi),%r9
 	movq	56(%rbp),%rsi
-.byte	102,72,15,126,213
+	movq	%xmm2,%rbp
 	adcq	16(%rdi),%r10
 	adcq	24(%rdi),%r11
 	adcq	32(%rdi),%r12
@@ -3372,8 +3372,8 @@
 	negq	%rax
 	sarq	$3+2,%rcx
 
-.byte	102,72,15,126,202
-.byte	102,72,15,126,206
+	movq	%xmm1,%rdx
+	movq	%xmm1,%rsi
 	decq	%r12
 	movq	8(%rbp),%r13
 	xorq	%r8,%r8
diff --git a/src/gen/bcm/x86_64-mont5-win.asm b/src/gen/bcm/x86_64-mont5-win.asm
index 3b12405..5ddeb86 100644
--- a/src/gen/bcm/x86_64-mont5-win.asm
+++ b/src/gen/bcm/x86_64-mont5-win.asm
@@ -215,7 +215,7 @@
 	pshufd	xmm1,xmm0,0x4e
 	por	xmm0,xmm1
 	lea	r12,[256+r12]
-DB	102,72,15,126,195
+	movq	rbx,xmm0
 
 	mov	r8,QWORD[r8]
 	mov	rax,QWORD[rsi]
@@ -341,7 +341,7 @@
 	lea	r12,[256+r12]
 
 	mov	rax,QWORD[rsi]
-DB	102,72,15,126,195
+	movq	rbx,xmm0
 
 	xor	r15,r15
 	mov	rbp,r8
@@ -725,7 +725,7 @@
 	pshufd	xmm1,xmm0,0x4e
 	por	xmm0,xmm1
 	lea	r12,[256+r12]
-DB	102,72,15,126,195
+	movq	rbx,xmm0
 
 	mov	QWORD[((16+8))+rsp],r13
 	mov	QWORD[((56+8))+rsp],rdi
@@ -933,7 +933,7 @@
 	pshufd	xmm0,xmm4,0x4e
 	por	xmm0,xmm4
 	lea	r12,[256+r12]
-DB	102,72,15,126,195
+	movq	rbx,xmm0
 
 	mov	r10,QWORD[r9*1+r14]
 	mov	rbp,r8
@@ -1216,10 +1216,10 @@
 	mov	QWORD[40+rsp],rax
 
 $L$power5_body:
-DB	102,72,15,110,207
-DB	102,72,15,110,209
-DB	102,73,15,110,218
-DB	102,72,15,110,226
+	movq	xmm1,rdi
+	movq	xmm2,rcx
+	movq	xmm3,r10
+	movq	xmm4,rdx
 
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
@@ -1232,8 +1232,8 @@
 	call	__bn_sqr8x_internal
 	call	__bn_post4x_internal
 
-DB	102,72,15,126,209
-DB	102,72,15,126,226
+	movq	rcx,xmm2
+	movq	rdx,xmm4
 	mov	rdi,rsi
 	mov	rax,QWORD[40+rsp]
 	lea	r8,[32+rsp]
@@ -1786,7 +1786,7 @@
 	adc	r8,rdx
 	mov	QWORD[((-16))+rdi],rbx
 	mov	QWORD[((-8))+rdi],r8
-DB	102,72,15,126,213
+	movq	rbp,xmm2
 __bn_sqr8x_reduction:
 	xor	rax,rax
 	lea	rcx,[rbp*1+r9]
@@ -2030,11 +2030,11 @@
 	mov	rcx,QWORD[((-8))+rbp]
 	xor	rsi,rsi
 
-DB	102,72,15,126,213
+	movq	rbp,xmm2
 
 	mov	QWORD[rdi],r8
 	mov	QWORD[8+rdi],r9
-DB	102,73,15,126,217
+	movq	r9,xmm3
 	mov	QWORD[16+rdi],r10
 	mov	QWORD[24+rdi],r11
 	mov	QWORD[32+rdi],r12
@@ -2055,9 +2055,9 @@
 	mov	r12,QWORD[rbp]
 	lea	rbx,[r9*1+rdi]
 	mov	rcx,r9
-DB	102,72,15,126,207
+	movq	rdi,xmm1
 	neg	rax
-DB	102,72,15,126,206
+	movq	rsi,xmm1
 	sar	rcx,3+2
 	dec	r12
 	xor	r10,r10
@@ -2380,7 +2380,7 @@
 	pshufd	xmm1,xmm0,0x4e
 	por	xmm0,xmm1
 	lea	rdi,[256+rdi]
-DB	102,72,15,126,194
+	movq	rdx,xmm0
 	lea	rbx,[((64+32+8))+rsp]
 
 	mov	r9,rdx
@@ -2531,7 +2531,7 @@
 	pshufd	xmm0,xmm4,0x4e
 	por	xmm0,xmm4
 	lea	rdi,[256+rdi]
-DB	102,72,15,126,194
+	movq	rdx,xmm0
 
 	mov	QWORD[rbx],rbp
 	lea	rbx,[32+rax*1+rbx]
@@ -2759,10 +2759,10 @@
 
 
 	pxor	xmm0,xmm0
-DB	102,72,15,110,207
-DB	102,72,15,110,209
-DB	102,73,15,110,218
-DB	102,72,15,110,226
+	movq	xmm1,rdi
+	movq	xmm2,rcx
+	movq	xmm3,r10
+	movq	xmm4,rdx
 	mov	QWORD[32+rsp],r8
 	mov	QWORD[40+rsp],rax
 
@@ -2781,8 +2781,8 @@
 
 	mov	r9,r10
 	mov	rdi,rsi
-DB	102,72,15,126,209
-DB	102,72,15,126,226
+	movq	rcx,xmm2
+	movq	rdx,xmm4
 	mov	rax,QWORD[40+rsp]
 
 	call	mulx4x_internal
@@ -3148,7 +3148,7 @@
 ALIGN	32
 $L$sqrx8x_outer_break:
 	mov	QWORD[72+rdi],r9
-DB	102,72,15,126,217
+	movq	rcx,xmm3
 	mov	QWORD[80+rdi],r10
 	mov	QWORD[88+rdi],r11
 	mov	QWORD[96+rdi],r12
@@ -3222,7 +3222,7 @@
 	mov	QWORD[48+rdi],rax
 	mov	QWORD[56+rdi],rbx
 	lea	rdi,[64+rdi]
-DB	102,72,15,126,213
+	movq	rbp,xmm2
 __bn_sqrx8x_reduction:
 	xor	eax,eax
 	mov	rbx,QWORD[((32+8))+rsp]
@@ -3402,10 +3402,10 @@
 	sub	rsi,QWORD[((16+8))+rsp]
 $L$sqrx8x_no_tail:
 	adc	r8,QWORD[rdi]
-DB	102,72,15,126,217
+	movq	rcx,xmm3
 	adc	r9,QWORD[8+rdi]
 	mov	rsi,QWORD[56+rbp]
-DB	102,72,15,126,213
+	movq	rbp,xmm2
 	adc	r10,QWORD[16+rdi]
 	adc	r11,QWORD[24+rdi]
 	adc	r12,QWORD[32+rdi]
@@ -3443,8 +3443,8 @@
 	neg	rax
 	sar	rcx,3+2
 
-DB	102,72,15,126,202
-DB	102,72,15,126,206
+	movq	rdx,xmm1
+	movq	rsi,xmm1
 	dec	r12
 	mov	r13,QWORD[8+rbp]
 	xor	r8,r8
diff --git a/src/gen/crypto/chacha-x86_64-apple.S b/src/gen/crypto/chacha-x86_64-apple.S
index d330661..09481e3 100644
--- a/src/gen/crypto/chacha-x86_64-apple.S
+++ b/src/gen/crypto/chacha-x86_64-apple.S
@@ -91,7 +91,7 @@
 	movq	%rbp,64+0(%rsp)
 	movl	$10,%ebp
 	movq	%rsi,64+8(%rsp)
-.byte	102,72,15,126,214
+	movq	%xmm2,%rsi
 	movq	%rdi,64+16(%rsp)
 	movq	%rsi,%rdi
 	shrq	$32,%rdi
@@ -354,7 +354,7 @@
 L$oop_ssse3:
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -363,7 +363,7 @@
 	por	%xmm4,%xmm1
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -376,7 +376,7 @@
 	nop
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -385,7 +385,7 @@
 	por	%xmm4,%xmm1
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -540,8 +540,8 @@
 	paddd	%xmm13,%xmm9
 	pxor	%xmm8,%xmm0
 	pxor	%xmm9,%xmm1
-.byte	102,15,56,0,199
-.byte	102,15,56,0,207
+	pshufb	%xmm7,%xmm0
+	pshufb	%xmm7,%xmm1
 	paddd	%xmm0,%xmm4
 	paddd	%xmm1,%xmm5
 	pxor	%xmm4,%xmm12
@@ -559,8 +559,8 @@
 	paddd	%xmm13,%xmm9
 	pxor	%xmm8,%xmm0
 	pxor	%xmm9,%xmm1
-.byte	102,15,56,0,198
-.byte	102,15,56,0,206
+	pshufb	%xmm6,%xmm0
+	pshufb	%xmm6,%xmm1
 	paddd	%xmm0,%xmm4
 	paddd	%xmm1,%xmm5
 	pxor	%xmm4,%xmm12
@@ -582,8 +582,8 @@
 	paddd	%xmm15,%xmm11
 	pxor	%xmm10,%xmm2
 	pxor	%xmm11,%xmm3
-.byte	102,15,56,0,215
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm2
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm2,%xmm4
 	paddd	%xmm3,%xmm5
 	pxor	%xmm4,%xmm14
@@ -601,8 +601,8 @@
 	paddd	%xmm15,%xmm11
 	pxor	%xmm10,%xmm2
 	pxor	%xmm11,%xmm3
-.byte	102,15,56,0,214
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm2
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm2,%xmm4
 	paddd	%xmm3,%xmm5
 	pxor	%xmm4,%xmm14
@@ -620,8 +620,8 @@
 	paddd	%xmm14,%xmm9
 	pxor	%xmm8,%xmm3
 	pxor	%xmm9,%xmm0
-.byte	102,15,56,0,223
-.byte	102,15,56,0,199
+	pshufb	%xmm7,%xmm3
+	pshufb	%xmm7,%xmm0
 	paddd	%xmm3,%xmm4
 	paddd	%xmm0,%xmm5
 	pxor	%xmm4,%xmm13
@@ -639,8 +639,8 @@
 	paddd	%xmm14,%xmm9
 	pxor	%xmm8,%xmm3
 	pxor	%xmm9,%xmm0
-.byte	102,15,56,0,222
-.byte	102,15,56,0,198
+	pshufb	%xmm6,%xmm3
+	pshufb	%xmm6,%xmm0
 	paddd	%xmm3,%xmm4
 	paddd	%xmm0,%xmm5
 	pxor	%xmm4,%xmm13
@@ -662,8 +662,8 @@
 	paddd	%xmm12,%xmm11
 	pxor	%xmm10,%xmm1
 	pxor	%xmm11,%xmm2
-.byte	102,15,56,0,207
-.byte	102,15,56,0,215
+	pshufb	%xmm7,%xmm1
+	pshufb	%xmm7,%xmm2
 	paddd	%xmm1,%xmm4
 	paddd	%xmm2,%xmm5
 	pxor	%xmm4,%xmm15
@@ -681,8 +681,8 @@
 	paddd	%xmm12,%xmm11
 	pxor	%xmm10,%xmm1
 	pxor	%xmm11,%xmm2
-.byte	102,15,56,0,206
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm1
+	pshufb	%xmm6,%xmm2
 	paddd	%xmm1,%xmm4
 	paddd	%xmm2,%xmm5
 	pxor	%xmm4,%xmm15
diff --git a/src/gen/crypto/chacha-x86_64-linux.S b/src/gen/crypto/chacha-x86_64-linux.S
index d76e6d0..8ea190d 100644
--- a/src/gen/crypto/chacha-x86_64-linux.S
+++ b/src/gen/crypto/chacha-x86_64-linux.S
@@ -97,7 +97,7 @@
 	movq	%rbp,64+0(%rsp)
 	movl	$10,%ebp
 	movq	%rsi,64+8(%rsp)
-.byte	102,72,15,126,214
+	movq	%xmm2,%rsi
 	movq	%rdi,64+16(%rsp)
 	movq	%rsi,%rdi
 	shrq	$32,%rdi
@@ -360,7 +360,7 @@
 .Loop_ssse3:
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -369,7 +369,7 @@
 	por	%xmm4,%xmm1
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -382,7 +382,7 @@
 	nop
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -391,7 +391,7 @@
 	por	%xmm4,%xmm1
 	paddd	%xmm1,%xmm0
 	pxor	%xmm0,%xmm3
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm3,%xmm2
 	pxor	%xmm2,%xmm1
 	movdqa	%xmm1,%xmm4
@@ -546,8 +546,8 @@
 	paddd	%xmm13,%xmm9
 	pxor	%xmm8,%xmm0
 	pxor	%xmm9,%xmm1
-.byte	102,15,56,0,199
-.byte	102,15,56,0,207
+	pshufb	%xmm7,%xmm0
+	pshufb	%xmm7,%xmm1
 	paddd	%xmm0,%xmm4
 	paddd	%xmm1,%xmm5
 	pxor	%xmm4,%xmm12
@@ -565,8 +565,8 @@
 	paddd	%xmm13,%xmm9
 	pxor	%xmm8,%xmm0
 	pxor	%xmm9,%xmm1
-.byte	102,15,56,0,198
-.byte	102,15,56,0,206
+	pshufb	%xmm6,%xmm0
+	pshufb	%xmm6,%xmm1
 	paddd	%xmm0,%xmm4
 	paddd	%xmm1,%xmm5
 	pxor	%xmm4,%xmm12
@@ -588,8 +588,8 @@
 	paddd	%xmm15,%xmm11
 	pxor	%xmm10,%xmm2
 	pxor	%xmm11,%xmm3
-.byte	102,15,56,0,215
-.byte	102,15,56,0,223
+	pshufb	%xmm7,%xmm2
+	pshufb	%xmm7,%xmm3
 	paddd	%xmm2,%xmm4
 	paddd	%xmm3,%xmm5
 	pxor	%xmm4,%xmm14
@@ -607,8 +607,8 @@
 	paddd	%xmm15,%xmm11
 	pxor	%xmm10,%xmm2
 	pxor	%xmm11,%xmm3
-.byte	102,15,56,0,214
-.byte	102,15,56,0,222
+	pshufb	%xmm6,%xmm2
+	pshufb	%xmm6,%xmm3
 	paddd	%xmm2,%xmm4
 	paddd	%xmm3,%xmm5
 	pxor	%xmm4,%xmm14
@@ -626,8 +626,8 @@
 	paddd	%xmm14,%xmm9
 	pxor	%xmm8,%xmm3
 	pxor	%xmm9,%xmm0
-.byte	102,15,56,0,223
-.byte	102,15,56,0,199
+	pshufb	%xmm7,%xmm3
+	pshufb	%xmm7,%xmm0
 	paddd	%xmm3,%xmm4
 	paddd	%xmm0,%xmm5
 	pxor	%xmm4,%xmm13
@@ -645,8 +645,8 @@
 	paddd	%xmm14,%xmm9
 	pxor	%xmm8,%xmm3
 	pxor	%xmm9,%xmm0
-.byte	102,15,56,0,222
-.byte	102,15,56,0,198
+	pshufb	%xmm6,%xmm3
+	pshufb	%xmm6,%xmm0
 	paddd	%xmm3,%xmm4
 	paddd	%xmm0,%xmm5
 	pxor	%xmm4,%xmm13
@@ -668,8 +668,8 @@
 	paddd	%xmm12,%xmm11
 	pxor	%xmm10,%xmm1
 	pxor	%xmm11,%xmm2
-.byte	102,15,56,0,207
-.byte	102,15,56,0,215
+	pshufb	%xmm7,%xmm1
+	pshufb	%xmm7,%xmm2
 	paddd	%xmm1,%xmm4
 	paddd	%xmm2,%xmm5
 	pxor	%xmm4,%xmm15
@@ -687,8 +687,8 @@
 	paddd	%xmm12,%xmm11
 	pxor	%xmm10,%xmm1
 	pxor	%xmm11,%xmm2
-.byte	102,15,56,0,206
-.byte	102,15,56,0,214
+	pshufb	%xmm6,%xmm1
+	pshufb	%xmm6,%xmm2
 	paddd	%xmm1,%xmm4
 	paddd	%xmm2,%xmm5
 	pxor	%xmm4,%xmm15
diff --git a/src/gen/crypto/chacha-x86_64-win.asm b/src/gen/crypto/chacha-x86_64-win.asm
index f1f9a0d..f9cae3f 100644
--- a/src/gen/crypto/chacha-x86_64-win.asm
+++ b/src/gen/crypto/chacha-x86_64-win.asm
@@ -114,7 +114,7 @@
 	mov	QWORD[((64+0))+rsp],rbp
 	mov	ebp,10
 	mov	QWORD[((64+8))+rsp],rsi
-DB	102,72,15,126,214
+	movq	rsi,xmm2
 	mov	QWORD[((64+16))+rsp],rdi
 	mov	rdi,rsi
 	shr	rdi,32
@@ -392,7 +392,7 @@
 $L$oop_ssse3:
 	paddd	xmm0,xmm1
 	pxor	xmm3,xmm0
-DB	102,15,56,0,222
+	pshufb	xmm3,xmm6
 	paddd	xmm2,xmm3
 	pxor	xmm1,xmm2
 	movdqa	xmm4,xmm1
@@ -401,7 +401,7 @@
 	por	xmm1,xmm4
 	paddd	xmm0,xmm1
 	pxor	xmm3,xmm0
-DB	102,15,56,0,223
+	pshufb	xmm3,xmm7
 	paddd	xmm2,xmm3
 	pxor	xmm1,xmm2
 	movdqa	xmm4,xmm1
@@ -414,7 +414,7 @@
 	nop
 	paddd	xmm0,xmm1
 	pxor	xmm3,xmm0
-DB	102,15,56,0,222
+	pshufb	xmm3,xmm6
 	paddd	xmm2,xmm3
 	pxor	xmm1,xmm2
 	movdqa	xmm4,xmm1
@@ -423,7 +423,7 @@
 	por	xmm1,xmm4
 	paddd	xmm0,xmm1
 	pxor	xmm3,xmm0
-DB	102,15,56,0,223
+	pshufb	xmm3,xmm7
 	paddd	xmm2,xmm3
 	pxor	xmm1,xmm2
 	movdqa	xmm4,xmm1
@@ -603,8 +603,8 @@
 	paddd	xmm9,xmm13
 	pxor	xmm0,xmm8
 	pxor	xmm1,xmm9
-DB	102,15,56,0,199
-DB	102,15,56,0,207
+	pshufb	xmm0,xmm7
+	pshufb	xmm1,xmm7
 	paddd	xmm4,xmm0
 	paddd	xmm5,xmm1
 	pxor	xmm12,xmm4
@@ -622,8 +622,8 @@
 	paddd	xmm9,xmm13
 	pxor	xmm0,xmm8
 	pxor	xmm1,xmm9
-DB	102,15,56,0,198
-DB	102,15,56,0,206
+	pshufb	xmm0,xmm6
+	pshufb	xmm1,xmm6
 	paddd	xmm4,xmm0
 	paddd	xmm5,xmm1
 	pxor	xmm12,xmm4
@@ -645,8 +645,8 @@
 	paddd	xmm11,xmm15
 	pxor	xmm2,xmm10
 	pxor	xmm3,xmm11
-DB	102,15,56,0,215
-DB	102,15,56,0,223
+	pshufb	xmm2,xmm7
+	pshufb	xmm3,xmm7
 	paddd	xmm4,xmm2
 	paddd	xmm5,xmm3
 	pxor	xmm14,xmm4
@@ -664,8 +664,8 @@
 	paddd	xmm11,xmm15
 	pxor	xmm2,xmm10
 	pxor	xmm3,xmm11
-DB	102,15,56,0,214
-DB	102,15,56,0,222
+	pshufb	xmm2,xmm6
+	pshufb	xmm3,xmm6
 	paddd	xmm4,xmm2
 	paddd	xmm5,xmm3
 	pxor	xmm14,xmm4
@@ -683,8 +683,8 @@
 	paddd	xmm9,xmm14
 	pxor	xmm3,xmm8
 	pxor	xmm0,xmm9
-DB	102,15,56,0,223
-DB	102,15,56,0,199
+	pshufb	xmm3,xmm7
+	pshufb	xmm0,xmm7
 	paddd	xmm4,xmm3
 	paddd	xmm5,xmm0
 	pxor	xmm13,xmm4
@@ -702,8 +702,8 @@
 	paddd	xmm9,xmm14
 	pxor	xmm3,xmm8
 	pxor	xmm0,xmm9
-DB	102,15,56,0,222
-DB	102,15,56,0,198
+	pshufb	xmm3,xmm6
+	pshufb	xmm0,xmm6
 	paddd	xmm4,xmm3
 	paddd	xmm5,xmm0
 	pxor	xmm13,xmm4
@@ -725,8 +725,8 @@
 	paddd	xmm11,xmm12
 	pxor	xmm1,xmm10
 	pxor	xmm2,xmm11
-DB	102,15,56,0,207
-DB	102,15,56,0,215
+	pshufb	xmm1,xmm7
+	pshufb	xmm2,xmm7
 	paddd	xmm4,xmm1
 	paddd	xmm5,xmm2
 	pxor	xmm15,xmm4
@@ -744,8 +744,8 @@
 	paddd	xmm11,xmm12
 	pxor	xmm1,xmm10
 	pxor	xmm2,xmm11
-DB	102,15,56,0,206
-DB	102,15,56,0,214
+	pshufb	xmm1,xmm6
+	pshufb	xmm2,xmm6
 	paddd	xmm4,xmm1
 	paddd	xmm5,xmm2
 	pxor	xmm15,xmm4
diff --git a/src/gen/crypto/chacha20_poly1305_x86_64-apple.S b/src/gen/crypto/chacha20_poly1305_x86_64-apple.S
index a261463..4044212 100644
--- a/src/gen/crypto/chacha20_poly1305_x86_64-apple.S
+++ b/src/gen/crypto/chacha20_poly1305_x86_64-apple.S
@@ -278,9 +278,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -299,9 +299,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%r10
 	jne	L$open_sse_init_rounds
@@ -359,10 +359,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -413,10 +413,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -457,18 +457,18 @@
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	L$rol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -493,10 +493,10 @@
 	adcq	$0,%r12
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -532,10 +532,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -563,18 +563,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%rcx
 	jge	L$open_sse_main_loop_rounds
@@ -776,9 +776,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -797,9 +797,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	cmpq	$16,%rcx
 	jae	L$open_sse_tail_64_rounds_and_x1hash
@@ -891,9 +891,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -912,9 +912,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -933,9 +933,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -954,9 +954,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 
 	cmpq	%rcx,%r8
 	jb	L$open_sse_tail_128_rounds_and_x1hash
@@ -1076,9 +1076,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1097,9 +1097,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -1118,9 +1118,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -1139,9 +1139,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1160,9 +1160,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -1181,9 +1181,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	cmpq	%rcx,%r8
 	jb	L$open_sse_tail_192_rounds_and_x1hash
@@ -1368,9 +1368,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm4
 	pxor	%xmm11,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1389,9 +1389,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm5
 	pxor	%xmm11,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -1410,9 +1410,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm6
 	pxor	%xmm11,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	movdqa	0+80(%rbp),%xmm11
 	movq	0+0+0(%rbp),%rax
 	movq	%rax,%r15
@@ -1443,9 +1443,9 @@
 	pslld	$7,%xmm9
 	psrld	$25,%xmm7
 	pxor	%xmm9,%xmm7
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
 	movdqa	0+80(%rbp),%xmm9
 	movq	8+0+0(%rbp),%rax
 	movq	%rax,%r9
@@ -1476,9 +1476,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm4
 	pxor	%xmm11,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1497,9 +1497,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm5
 	pxor	%xmm11,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
@@ -1521,9 +1521,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm6
 	pxor	%xmm11,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 	movdqa	0+80(%rbp),%xmm11
 	movq	%r13,%r10
 	movq	%r14,%r11
@@ -1558,9 +1558,9 @@
 	pslld	$7,%xmm9
 	psrld	$25,%xmm7
 	pxor	%xmm9,%xmm7
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
 	movdqa	0+80(%rbp),%xmm9
 
 	addq	$16,%r8
@@ -1707,7 +1707,7 @@
 	subq	$1,%r8
 	jnz	L$open_sse_tail_16_compose
 
-.byte	102,73,15,126,221
+	movq	%xmm3,%r13
 	pextrq	$1,%xmm3,%r14
 
 	pxor	%xmm1,%xmm3
@@ -1880,9 +1880,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1901,9 +1901,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -1922,9 +1922,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -1943,9 +1943,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -1964,9 +1964,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -1985,9 +1985,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	decq	%r10
 	jnz	L$open_sse_128_rounds
@@ -2155,10 +2155,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2194,10 +2194,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2225,18 +2225,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	L$rol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -2247,10 +2247,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2286,10 +2286,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2317,18 +2317,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%r10
 	jnz	L$seal_sse_init_rounds
@@ -2451,10 +2451,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2503,10 +2503,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2547,18 +2547,18 @@
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	L$rol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -2583,10 +2583,10 @@
 	adcq	$0,%r12
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2622,10 +2622,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2653,18 +2653,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	leaq	16(%rdi),%rdi
 	decq	%r8
@@ -2877,9 +2877,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -2898,9 +2898,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3030,9 +3030,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -3051,9 +3051,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3112,9 +3112,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -3133,9 +3133,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 
 	leaq	16(%rdi),%rdi
 	decq	%rcx
@@ -3250,9 +3250,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -3271,9 +3271,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -3292,9 +3292,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3353,9 +3353,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -3374,9 +3374,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -3395,9 +3395,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	leaq	16(%rdi),%rdi
 	decq	%rcx
@@ -3649,7 +3649,7 @@
 
 
 
-.byte	102,77,15,126,253
+	movq	%xmm15,%r13
 	pextrq	$1,%xmm15,%r14
 	addq	%r13,%r10
 	adcq	%r14,%r11
@@ -3765,7 +3765,7 @@
 	leaq	L$and_masks(%rip),%r15
 	shlq	$4,%rbx
 	pand	-16(%r15,%rbx,1),%xmm15
-.byte	102,77,15,126,253
+	movq	%xmm15,%r13
 	pextrq	$1,%xmm15,%r14
 	addq	%r13,%r10
 	adcq	%r14,%r11
@@ -3927,9 +3927,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -3948,9 +3948,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -3969,9 +3969,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	L$rol16(%rip),%xmm12
@@ -3990,9 +3990,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	L$rol16(%rip),%xmm13
@@ -4011,9 +4011,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	L$rol16(%rip),%xmm14
@@ -4032,9 +4032,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	decq	%r10
 	jnz	L$seal_sse_128_rounds
diff --git a/src/gen/crypto/chacha20_poly1305_x86_64-linux.S b/src/gen/crypto/chacha20_poly1305_x86_64-linux.S
index 180b41e..6fd94c8 100644
--- a/src/gen/crypto/chacha20_poly1305_x86_64-linux.S
+++ b/src/gen/crypto/chacha20_poly1305_x86_64-linux.S
@@ -285,9 +285,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -306,9 +306,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%r10
 	jne	.Lopen_sse_init_rounds
@@ -366,10 +366,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -420,10 +420,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -464,18 +464,18 @@
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	.Lrol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -500,10 +500,10 @@
 	adcq	$0,%r12
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -539,10 +539,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -570,18 +570,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%rcx
 	jge	.Lopen_sse_main_loop_rounds
@@ -783,9 +783,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -804,9 +804,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	cmpq	$16,%rcx
 	jae	.Lopen_sse_tail_64_rounds_and_x1hash
@@ -898,9 +898,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -919,9 +919,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -940,9 +940,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -961,9 +961,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 
 	cmpq	%rcx,%r8
 	jb	.Lopen_sse_tail_128_rounds_and_x1hash
@@ -1083,9 +1083,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1104,9 +1104,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -1125,9 +1125,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -1146,9 +1146,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1167,9 +1167,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -1188,9 +1188,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	cmpq	%rcx,%r8
 	jb	.Lopen_sse_tail_192_rounds_and_x1hash
@@ -1375,9 +1375,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm4
 	pxor	%xmm11,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1396,9 +1396,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm5
 	pxor	%xmm11,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -1417,9 +1417,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm6
 	pxor	%xmm11,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	movdqa	0+80(%rbp),%xmm11
 	movq	0+0+0(%rbp),%rax
 	movq	%rax,%r15
@@ -1450,9 +1450,9 @@
 	pslld	$7,%xmm9
 	psrld	$25,%xmm7
 	pxor	%xmm9,%xmm7
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
 	movdqa	0+80(%rbp),%xmm9
 	movq	8+0+0(%rbp),%rax
 	movq	%rax,%r9
@@ -1483,9 +1483,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm4
 	pxor	%xmm11,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1504,9 +1504,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm5
 	pxor	%xmm11,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
@@ -1528,9 +1528,9 @@
 	pslld	$7,%xmm11
 	psrld	$25,%xmm6
 	pxor	%xmm11,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 	movdqa	0+80(%rbp),%xmm11
 	movq	%r13,%r10
 	movq	%r14,%r11
@@ -1565,9 +1565,9 @@
 	pslld	$7,%xmm9
 	psrld	$25,%xmm7
 	pxor	%xmm9,%xmm7
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
 	movdqa	0+80(%rbp),%xmm9
 
 	addq	$16,%r8
@@ -1714,7 +1714,7 @@
 	subq	$1,%r8
 	jnz	.Lopen_sse_tail_16_compose
 
-.byte	102,73,15,126,221
+	movq	%xmm3,%r13
 	pextrq	$1,%xmm3,%r14
 
 	pxor	%xmm1,%xmm3
@@ -1894,9 +1894,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1915,9 +1915,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -1936,9 +1936,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -1957,9 +1957,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -1978,9 +1978,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -1999,9 +1999,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	decq	%r10
 	jnz	.Lopen_sse_128_rounds
@@ -2176,10 +2176,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2215,10 +2215,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2246,18 +2246,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	.Lrol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -2268,10 +2268,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2307,10 +2307,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2338,18 +2338,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	decq	%r10
 	jnz	.Lseal_sse_init_rounds
@@ -2472,10 +2472,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2524,10 +2524,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2568,18 +2568,18 @@
 	imulq	%r12,%r9
 	addq	%r10,%r15
 	adcq	%rdx,%r9
-.byte	102,15,58,15,255,4
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,12
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$12,%xmm15,%xmm15
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	movdqa	%xmm8,0+80(%rbp)
 	movdqa	.Lrol16(%rip),%xmm8
 	paddd	%xmm7,%xmm3
@@ -2604,10 +2604,10 @@
 	adcq	$0,%r12
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2643,10 +2643,10 @@
 	pxor	%xmm2,%xmm14
 	pxor	%xmm1,%xmm13
 	pxor	%xmm0,%xmm12
-.byte	102,69,15,56,0,248
-.byte	102,69,15,56,0,240
-.byte	102,69,15,56,0,232
-.byte	102,69,15,56,0,224
+	pshufb	%xmm8,%xmm15
+	pshufb	%xmm8,%xmm14
+	pshufb	%xmm8,%xmm13
+	pshufb	%xmm8,%xmm12
 	movdqa	0+80(%rbp),%xmm8
 	paddd	%xmm15,%xmm11
 	paddd	%xmm14,%xmm10
@@ -2674,18 +2674,18 @@
 	pslld	$32-25,%xmm4
 	pxor	%xmm8,%xmm4
 	movdqa	0+80(%rbp),%xmm8
-.byte	102,15,58,15,255,12
-.byte	102,69,15,58,15,219,8
-.byte	102,69,15,58,15,255,4
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm7,%xmm7
+	palignr	$8,%xmm11,%xmm11
+	palignr	$4,%xmm15,%xmm15
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 
 	leaq	16(%rdi),%rdi
 	decq	%r8
@@ -2898,9 +2898,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -2919,9 +2919,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3051,9 +3051,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -3072,9 +3072,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3133,9 +3133,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -3154,9 +3154,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 
 	leaq	16(%rdi),%rdi
 	decq	%rcx
@@ -3271,9 +3271,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -3292,9 +3292,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -3313,9 +3313,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	addq	0+0(%rdi),%r10
 	adcq	8+0(%rdi),%r11
 	adcq	$1,%r12
@@ -3374,9 +3374,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -3395,9 +3395,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -3416,9 +3416,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	leaq	16(%rdi),%rdi
 	decq	%rcx
@@ -3670,7 +3670,7 @@
 
 
 
-.byte	102,77,15,126,253
+	movq	%xmm15,%r13
 	pextrq	$1,%xmm15,%r14
 	addq	%r13,%r10
 	adcq	%r14,%r11
@@ -3786,7 +3786,7 @@
 	leaq	.Land_masks(%rip),%r15
 	shlq	$4,%rbx
 	pand	-16(%r15,%rbx,1),%xmm15
-.byte	102,77,15,126,253
+	movq	%xmm15,%r13
 	pextrq	$1,%xmm15,%r14
 	addq	%r13,%r10
 	adcq	%r14,%r11
@@ -3955,9 +3955,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,4
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,12
+	palignr	$4,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$12,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -3976,9 +3976,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,4
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,12
+	palignr	$4,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$12,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -3997,9 +3997,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,4
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,12
+	palignr	$4,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$12,%xmm14,%xmm14
 	paddd	%xmm4,%xmm0
 	pxor	%xmm0,%xmm12
 	pshufb	.Lrol16(%rip),%xmm12
@@ -4018,9 +4018,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm4
 	pxor	%xmm3,%xmm4
-.byte	102,15,58,15,228,12
-.byte	102,69,15,58,15,192,8
-.byte	102,69,15,58,15,228,4
+	palignr	$12,%xmm4,%xmm4
+	palignr	$8,%xmm8,%xmm8
+	palignr	$4,%xmm12,%xmm12
 	paddd	%xmm5,%xmm1
 	pxor	%xmm1,%xmm13
 	pshufb	.Lrol16(%rip),%xmm13
@@ -4039,9 +4039,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm5
 	pxor	%xmm3,%xmm5
-.byte	102,15,58,15,237,12
-.byte	102,69,15,58,15,201,8
-.byte	102,69,15,58,15,237,4
+	palignr	$12,%xmm5,%xmm5
+	palignr	$8,%xmm9,%xmm9
+	palignr	$4,%xmm13,%xmm13
 	paddd	%xmm6,%xmm2
 	pxor	%xmm2,%xmm14
 	pshufb	.Lrol16(%rip),%xmm14
@@ -4060,9 +4060,9 @@
 	pslld	$7,%xmm3
 	psrld	$25,%xmm6
 	pxor	%xmm3,%xmm6
-.byte	102,15,58,15,246,12
-.byte	102,69,15,58,15,210,8
-.byte	102,69,15,58,15,246,4
+	palignr	$12,%xmm6,%xmm6
+	palignr	$8,%xmm10,%xmm10
+	palignr	$4,%xmm14,%xmm14
 
 	decq	%r10
 	jnz	.Lseal_sse_128_rounds
diff --git a/src/gen/crypto/chacha20_poly1305_x86_64-win.asm b/src/gen/crypto/chacha20_poly1305_x86_64-win.asm
index 25c69ef..7ff65db 100644
--- a/src/gen/crypto/chacha20_poly1305_x86_64-win.asm
+++ b/src/gen/crypto/chacha20_poly1305_x86_64-win.asm
@@ -308,9 +308,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -329,9 +329,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 
 	dec	r10
 	jne	NEAR $L$open_sse_init_rounds
@@ -389,10 +389,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -443,10 +443,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -487,18 +487,18 @@
 	imul	r9,r12
 	add	r15,r10
 	adc	r9,rdx
-DB	102,15,58,15,255,4
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,12
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm7,xmm7,4
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	movdqa	XMMWORD[(160+80)+rbp],xmm8
 	movdqa	xmm8,XMMWORD[$L$rol16]
 	paddd	xmm3,xmm7
@@ -523,10 +523,10 @@
 	adc	r12,0
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -562,10 +562,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -593,18 +593,18 @@
 	pslld	xmm4,32-25
 	pxor	xmm4,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
-DB	102,15,58,15,255,12
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,4
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm7,xmm7,12
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 
 	dec	rcx
 	jge	NEAR $L$open_sse_main_loop_rounds
@@ -806,9 +806,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -827,9 +827,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 
 	cmp	rcx,16
 	jae	NEAR $L$open_sse_tail_64_rounds_and_x1hash
@@ -921,9 +921,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -942,9 +942,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -963,9 +963,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -984,9 +984,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 
 	cmp	r8,rcx
 	jb	NEAR $L$open_sse_tail_128_rounds_and_x1hash
@@ -1106,9 +1106,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -1127,9 +1127,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -1148,9 +1148,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -1169,9 +1169,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -1190,9 +1190,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -1211,9 +1211,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
 
 	cmp	r8,rcx
 	jb	NEAR $L$open_sse_tail_192_rounds_and_x1hash
@@ -1398,9 +1398,9 @@
 	pslld	xmm11,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm11
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -1419,9 +1419,9 @@
 	pslld	xmm11,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm11
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -1440,9 +1440,9 @@
 	pslld	xmm11,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm11
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
 	movdqa	xmm11,XMMWORD[((160+80))+rbp]
 	mov	rax,QWORD[((0+160+0))+rbp]
 	mov	r15,rax
@@ -1473,9 +1473,9 @@
 	pslld	xmm9,7
 	psrld	xmm7,25
 	pxor	xmm7,xmm9
-DB	102,15,58,15,255,4
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,12
+	palignr	xmm7,xmm7,4
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,12
 	movdqa	xmm9,XMMWORD[((160+80))+rbp]
 	mov	rax,QWORD[((8+160+0))+rbp]
 	mov	r9,rax
@@ -1506,9 +1506,9 @@
 	pslld	xmm11,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm11
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -1527,9 +1527,9 @@
 	pslld	xmm11,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm11
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 	imul	r9,r12
 	add	r15,r10
 	adc	r9,rdx
@@ -1551,9 +1551,9 @@
 	pslld	xmm11,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm11
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
 	movdqa	xmm11,XMMWORD[((160+80))+rbp]
 	mov	r10,r13
 	mov	r11,r14
@@ -1588,9 +1588,9 @@
 	pslld	xmm9,7
 	psrld	xmm7,25
 	pxor	xmm7,xmm9
-DB	102,15,58,15,255,12
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,4
+	palignr	xmm7,xmm7,12
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,4
 	movdqa	xmm9,XMMWORD[((160+80))+rbp]
 
 	add	r8,16
@@ -1737,7 +1737,7 @@
 	sub	r8,1
 	jnz	NEAR $L$open_sse_tail_16_compose
 
-DB	102,73,15,126,221
+	movq	r13,xmm3
 	pextrq	r14,xmm3,1
 
 	pxor	xmm3,xmm1
@@ -1923,9 +1923,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -1944,9 +1944,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -1965,9 +1965,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -1986,9 +1986,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -2007,9 +2007,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -2028,9 +2028,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
 
 	dec	r10
 	jnz	NEAR $L$open_sse_128_rounds
@@ -2220,10 +2220,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2259,10 +2259,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2290,18 +2290,18 @@
 	pslld	xmm4,32-25
 	pxor	xmm4,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
-DB	102,15,58,15,255,4
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,12
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm7,xmm7,4
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	movdqa	XMMWORD[(160+80)+rbp],xmm8
 	movdqa	xmm8,XMMWORD[$L$rol16]
 	paddd	xmm3,xmm7
@@ -2312,10 +2312,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2351,10 +2351,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2382,18 +2382,18 @@
 	pslld	xmm4,32-25
 	pxor	xmm4,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
-DB	102,15,58,15,255,12
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,4
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm7,xmm7,12
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 
 	dec	r10
 	jnz	NEAR $L$seal_sse_init_rounds
@@ -2516,10 +2516,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2568,10 +2568,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2612,18 +2612,18 @@
 	imul	r9,r12
 	add	r15,r10
 	adc	r9,rdx
-DB	102,15,58,15,255,4
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,12
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm7,xmm7,4
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	movdqa	XMMWORD[(160+80)+rbp],xmm8
 	movdqa	xmm8,XMMWORD[$L$rol16]
 	paddd	xmm3,xmm7
@@ -2648,10 +2648,10 @@
 	adc	r12,0
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2687,10 +2687,10 @@
 	pxor	xmm14,xmm2
 	pxor	xmm13,xmm1
 	pxor	xmm12,xmm0
-DB	102,69,15,56,0,248
-DB	102,69,15,56,0,240
-DB	102,69,15,56,0,232
-DB	102,69,15,56,0,224
+	pshufb	xmm15,xmm8
+	pshufb	xmm14,xmm8
+	pshufb	xmm13,xmm8
+	pshufb	xmm12,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
 	paddd	xmm11,xmm15
 	paddd	xmm10,xmm14
@@ -2718,18 +2718,18 @@
 	pslld	xmm4,32-25
 	pxor	xmm4,xmm8
 	movdqa	xmm8,XMMWORD[((160+80))+rbp]
-DB	102,15,58,15,255,12
-DB	102,69,15,58,15,219,8
-DB	102,69,15,58,15,255,4
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm7,xmm7,12
+	palignr	xmm11,xmm11,8
+	palignr	xmm15,xmm15,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 
 	lea	rdi,[16+rdi]
 	dec	r8
@@ -2942,9 +2942,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -2963,9 +2963,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	add	r10,QWORD[((0+0))+rdi]
 	adc	r11,QWORD[((8+0))+rdi]
 	adc	r12,1
@@ -3095,9 +3095,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -3116,9 +3116,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	add	r10,QWORD[((0+0))+rdi]
 	adc	r11,QWORD[((8+0))+rdi]
 	adc	r12,1
@@ -3177,9 +3177,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -3198,9 +3198,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 
 	lea	rdi,[16+rdi]
 	dec	rcx
@@ -3315,9 +3315,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -3336,9 +3336,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -3357,9 +3357,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
 	add	r10,QWORD[((0+0))+rdi]
 	adc	r11,QWORD[((8+0))+rdi]
 	adc	r12,1
@@ -3418,9 +3418,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -3439,9 +3439,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -3460,9 +3460,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
 
 	lea	rdi,[16+rdi]
 	dec	rcx
@@ -3714,7 +3714,7 @@
 
 
 
-DB	102,77,15,126,253
+	movq	r13,xmm15
 	pextrq	r14,xmm15,1
 	add	r10,r13
 	adc	r11,r14
@@ -3830,7 +3830,7 @@
 	lea	r15,[$L$and_masks]
 	shl	rbx,4
 	pand	xmm15,XMMWORD[((-16))+rbx*1+r15]
-DB	102,77,15,126,253
+	movq	r13,xmm15
 	pextrq	r14,xmm15,1
 	add	r10,r13
 	adc	r11,r14
@@ -4005,9 +4005,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,4
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,12
+	palignr	xmm4,xmm4,4
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,12
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -4026,9 +4026,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,4
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,12
+	palignr	xmm5,xmm5,4
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,12
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -4047,9 +4047,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,4
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,12
+	palignr	xmm6,xmm6,4
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,12
 	paddd	xmm0,xmm4
 	pxor	xmm12,xmm0
 	pshufb	xmm12,XMMWORD[$L$rol16]
@@ -4068,9 +4068,9 @@
 	pslld	xmm3,7
 	psrld	xmm4,25
 	pxor	xmm4,xmm3
-DB	102,15,58,15,228,12
-DB	102,69,15,58,15,192,8
-DB	102,69,15,58,15,228,4
+	palignr	xmm4,xmm4,12
+	palignr	xmm8,xmm8,8
+	palignr	xmm12,xmm12,4
 	paddd	xmm1,xmm5
 	pxor	xmm13,xmm1
 	pshufb	xmm13,XMMWORD[$L$rol16]
@@ -4089,9 +4089,9 @@
 	pslld	xmm3,7
 	psrld	xmm5,25
 	pxor	xmm5,xmm3
-DB	102,15,58,15,237,12
-DB	102,69,15,58,15,201,8
-DB	102,69,15,58,15,237,4
+	palignr	xmm5,xmm5,12
+	palignr	xmm9,xmm9,8
+	palignr	xmm13,xmm13,4
 	paddd	xmm2,xmm6
 	pxor	xmm14,xmm2
 	pshufb	xmm14,XMMWORD[$L$rol16]
@@ -4110,9 +4110,9 @@
 	pslld	xmm3,7
 	psrld	xmm6,25
 	pxor	xmm6,xmm3
-DB	102,15,58,15,246,12
-DB	102,69,15,58,15,210,8
-DB	102,69,15,58,15,246,4
+	palignr	xmm6,xmm6,12
+	palignr	xmm10,xmm10,8
+	palignr	xmm14,xmm14,4
 
 	dec	r10
 	jnz	NEAR $L$seal_sse_128_rounds
diff --git a/src/gen/crypto/err_data.cc b/src/gen/crypto/err_data.cc
index fd67be8..f3d8f7c 100644
--- a/src/gen/crypto/err_data.cc
+++ b/src/gen/crypto/err_data.cc
@@ -51,8 +51,9 @@
 static_assert(ERR_LIB_CIPHER == 30, "library value changed");
 static_assert(ERR_LIB_HKDF == 31, "library value changed");
 static_assert(ERR_LIB_TRUST_TOKEN == 32, "library value changed");
-static_assert(ERR_LIB_USER == 33, "library value changed");
-static_assert(ERR_NUM_LIBS == 34, "number of libraries changed");
+static_assert(ERR_LIB_CMS == 33, "library value changed");
+static_assert(ERR_LIB_USER == 34, "library value changed");
+static_assert(ERR_NUM_LIBS == 35, "number of libraries changed");
 
 extern const uint32_t kOpenSSLReasonValues[];
 const uint32_t kOpenSSLReasonValues[] = {
@@ -77,172 +78,172 @@
     0xc3b00f7,
     0xc3b8921,
     0x10320892,
-    0x10329672,
-    0x1033167e,
-    0x10339697,
-    0x103416aa,
-    0x10348f93,
-    0x10350cdf,
-    0x103596bd,
-    0x103616e7,
-    0x103696fa,
-    0x10371719,
-    0x10379732,
-    0x10381747,
-    0x10389765,
-    0x10391774,
-    0x10399790,
-    0x103a17ab,
-    0x103a97ba,
-    0x103b17d6,
-    0x103b97f1,
-    0x103c1817,
+    0x103296b2,
+    0x103316be,
+    0x103396d7,
+    0x103416ea,
+    0x10348fd3,
+    0x10350d1f,
+    0x103596fd,
+    0x10361727,
+    0x1036973a,
+    0x10371759,
+    0x10379772,
+    0x10381787,
+    0x103897a5,
+    0x103917b4,
+    0x103997d0,
+    0x103a17eb,
+    0x103a97fa,
+    0x103b1816,
+    0x103b9831,
+    0x103c1857,
     0x103c80f7,
-    0x103d1828,
-    0x103d983c,
-    0x103e185b,
-    0x103e986a,
-    0x103f1881,
-    0x103f9894,
-    0x10400ca3,
-    0x104098a7,
-    0x104118c5,
-    0x104198d8,
-    0x104218f2,
-    0x10429902,
-    0x10431916,
-    0x1043992c,
-    0x10441944,
-    0x10449959,
-    0x1045196d,
-    0x1045997f,
+    0x103d1868,
+    0x103d987c,
+    0x103e189b,
+    0x103e98aa,
+    0x103f18c1,
+    0x103f98d4,
+    0x10400ce3,
+    0x104098e7,
+    0x10411905,
+    0x10419918,
+    0x10421932,
+    0x10429942,
+    0x10431956,
+    0x1043996c,
+    0x10441984,
+    0x10449999,
+    0x104519ad,
+    0x104599bf,
     0x10460635,
     0x1046899a,
-    0x10471994,
-    0x104799ab,
-    0x104819c0,
-    0x104899ce,
-    0x10490edf,
-    0x10499808,
-    0x104a16d2,
-    0x14320c73,
-    0x14328c94,
-    0x14330ca3,
-    0x14338cb5,
+    0x104719d4,
+    0x104799eb,
+    0x10481a00,
+    0x10489a0e,
+    0x10490f1f,
+    0x10499848,
+    0x104a1712,
+    0x14320cb3,
+    0x14328cd4,
+    0x14330ce3,
+    0x14338cf5,
     0x143400b9,
     0x143480f7,
-    0x14350c81,
+    0x14350cc1,
     0x18320090,
-    0x18328fe9,
+    0x18329029,
     0x183300b9,
-    0x18338fff,
-    0x18341013,
+    0x1833903f,
+    0x18341053,
     0x183480f7,
-    0x18351032,
-    0x1835904a,
-    0x18361072,
-    0x18369086,
-    0x183710be,
-    0x183790d4,
-    0x183810e8,
-    0x183890f8,
+    0x18351072,
+    0x1835908a,
+    0x183610b2,
+    0x183690c6,
+    0x183710fe,
+    0x18379114,
+    0x18381128,
+    0x18389138,
     0x18390ac0,
-    0x18399108,
-    0x183a112e,
-    0x183a9154,
-    0x183b0ceb,
-    0x183b91a3,
-    0x183c11b5,
-    0x183c91c0,
-    0x183d11d0,
-    0x183d91e1,
-    0x183e11f2,
-    0x183e9204,
-    0x183f122d,
-    0x183f9246,
-    0x1840125e,
+    0x18399148,
+    0x183a116e,
+    0x183a9194,
+    0x183b0d2b,
+    0x183b91e3,
+    0x183c11f5,
+    0x183c9200,
+    0x183d1210,
+    0x183d9221,
+    0x183e1232,
+    0x183e9244,
+    0x183f126d,
+    0x183f9286,
+    0x1840129e,
     0x1840870d,
-    0x18411177,
-    0x18419142,
-    0x18421161,
-    0x18428c81,
-    0x1843111d,
-    0x18439189,
-    0x18441028,
-    0x184490aa,
-    0x1845105f,
-    0x20321298,
-    0x20329285,
-    0x243212a4,
+    0x184111b7,
+    0x18419182,
+    0x184211a1,
+    0x18428cc1,
+    0x1843115d,
+    0x184391c9,
+    0x18441068,
+    0x184490ea,
+    0x1845109f,
+    0x203212d8,
+    0x203292c5,
+    0x243212e4,
     0x243289e0,
-    0x243312b6,
-    0x243392c3,
-    0x243412d0,
-    0x243492e2,
-    0x243512f1,
-    0x2435930e,
-    0x2436131b,
-    0x24369329,
-    0x24371337,
-    0x24379345,
-    0x2438134e,
-    0x2438935b,
-    0x2439136e,
-    0x24399385,
-    0x28320cd3,
-    0x28328ceb,
-    0x28330ca3,
-    0x28338cfe,
-    0x28340cdf,
+    0x243312f6,
+    0x24339303,
+    0x24341310,
+    0x24349322,
+    0x24351331,
+    0x2435934e,
+    0x2436135b,
+    0x24369369,
+    0x24371377,
+    0x24379385,
+    0x2438138e,
+    0x2438939b,
+    0x243913ae,
+    0x243993c5,
+    0x28320d13,
+    0x28328d2b,
+    0x28330ce3,
+    0x28338d3e,
+    0x28340d1f,
     0x283480b9,
     0x283500f7,
-    0x28358c81,
+    0x28358cc1,
     0x2836099a,
-    0x2c32337d,
-    0x2c3293a3,
-    0x2c33338b,
-    0x2c33b39d,
-    0x2c3433b1,
-    0x2c34b3c3,
-    0x2c3533de,
-    0x2c35b3f0,
-    0x2c363420,
+    0x2c3233f9,
+    0x2c3293e3,
+    0x2c333407,
+    0x2c33b419,
+    0x2c34342d,
+    0x2c34b43f,
+    0x2c35345a,
+    0x2c35b46c,
+    0x2c36349c,
     0x2c36833a,
-    0x2c37342d,
-    0x2c37b459,
-    0x2c383497,
-    0x2c38b4ae,
-    0x2c3934cc,
-    0x2c39b4dc,
-    0x2c3a34ee,
-    0x2c3ab502,
-    0x2c3b3513,
-    0x2c3bb532,
-    0x2c3c13b5,
-    0x2c3c93cb,
-    0x2c3d3577,
-    0x2c3d93e4,
-    0x2c3e35a1,
-    0x2c3eb5af,
-    0x2c3f35c7,
-    0x2c3fb5df,
-    0x2c403609,
-    0x2c409298,
-    0x2c41361a,
-    0x2c41b62d,
-    0x2c42125e,
-    0x2c42b63e,
+    0x2c3734a9,
+    0x2c37b4d5,
+    0x2c383513,
+    0x2c38b52a,
+    0x2c393548,
+    0x2c39b558,
+    0x2c3a356a,
+    0x2c3ab57e,
+    0x2c3b358f,
+    0x2c3bb5ae,
+    0x2c3c13f5,
+    0x2c3c940b,
+    0x2c3d35f3,
+    0x2c3d9424,
+    0x2c3e361d,
+    0x2c3eb62b,
+    0x2c3f3643,
+    0x2c3fb65b,
+    0x2c403685,
+    0x2c4092d8,
+    0x2c413696,
+    0x2c41b6a9,
+    0x2c42129e,
+    0x2c42b6ba,
     0x2c43076d,
-    0x2c43b524,
-    0x2c44346c,
-    0x2c44b5ec,
-    0x2c453403,
-    0x2c45b43f,
-    0x2c4634bc,
-    0x2c46b546,
-    0x2c47355b,
-    0x2c47b594,
-    0x2c48347e,
+    0x2c43b5a0,
+    0x2c4434e8,
+    0x2c44b668,
+    0x2c45347f,
+    0x2c45b4bb,
+    0x2c463538,
+    0x2c46b5c2,
+    0x2c4735d7,
+    0x2c47b610,
+    0x2c4834fa,
     0x30320000,
     0x30328015,
     0x3033001f,
@@ -340,308 +341,310 @@
     0x30610357,
     0x3061873a,
     0x30620392,
-    0x34320bb0,
-    0x34328bc4,
-    0x34330be1,
-    0x34338bf4,
-    0x34340c03,
-    0x34348c5d,
-    0x34350c41,
-    0x34358c20,
+    0x34320bf0,
+    0x34328c04,
+    0x34330c21,
+    0x34338c34,
+    0x34340c43,
+    0x34348c9d,
+    0x34350c81,
+    0x34358c60,
     0x3c320090,
-    0x3c328d28,
-    0x3c330d41,
-    0x3c338d5c,
-    0x3c340d79,
-    0x3c348da3,
-    0x3c350dbe,
-    0x3c358de4,
-    0x3c360dfd,
-    0x3c368e15,
-    0x3c370e26,
-    0x3c378e34,
-    0x3c380e41,
-    0x3c388e55,
-    0x3c390ceb,
-    0x3c398e78,
-    0x3c3a0e8c,
+    0x3c328d68,
+    0x3c330d81,
+    0x3c338d9c,
+    0x3c340db9,
+    0x3c348de3,
+    0x3c350dfe,
+    0x3c358e24,
+    0x3c360e3d,
+    0x3c368e55,
+    0x3c370e66,
+    0x3c378e74,
+    0x3c380e81,
+    0x3c388e95,
+    0x3c390d2b,
+    0x3c398eb8,
+    0x3c3a0ecc,
     0x3c3a895a,
-    0x3c3b0e9c,
-    0x3c3b8eb7,
-    0x3c3c0ec9,
-    0x3c3c8efc,
-    0x3c3d0f06,
-    0x3c3d8f1a,
-    0x3c3e0f28,
-    0x3c3e8f4d,
-    0x3c3f0d14,
-    0x3c3f8f36,
+    0x3c3b0edc,
+    0x3c3b8ef7,
+    0x3c3c0f09,
+    0x3c3c8f3c,
+    0x3c3d0f46,
+    0x3c3d8f5a,
+    0x3c3e0f68,
+    0x3c3e8f8d,
+    0x3c3f0d54,
+    0x3c3f8f76,
     0x3c4000b9,
     0x3c4080f7,
-    0x3c410d94,
-    0x3c418dd3,
-    0x3c420edf,
-    0x3c428e69,
-    0x40321a3a,
-    0x40329a50,
-    0x40331a7e,
-    0x40339a88,
-    0x40341a9f,
-    0x40349abd,
-    0x40351acd,
-    0x40359adf,
-    0x40361aec,
-    0x40369af8,
-    0x40371b0d,
-    0x40379b1f,
-    0x40381b2a,
-    0x40389b3c,
-    0x40390f93,
-    0x40399b4c,
-    0x403a1b5f,
-    0x403a9b80,
-    0x403b1b91,
-    0x403b9ba1,
+    0x3c410dd4,
+    0x3c418e13,
+    0x3c420f1f,
+    0x3c428ea9,
+    0x40321a7a,
+    0x40329a90,
+    0x40331abe,
+    0x40339ac8,
+    0x40341adf,
+    0x40349afd,
+    0x40351b0d,
+    0x40359b1f,
+    0x40361b2c,
+    0x40369b38,
+    0x40371b4d,
+    0x40379b5f,
+    0x40381b6a,
+    0x40389b7c,
+    0x40390fd3,
+    0x40399b8c,
+    0x403a1b9f,
+    0x403a9bc0,
+    0x403b1bd1,
+    0x403b9be1,
     0x403c0071,
     0x403c8090,
-    0x403d1c02,
-    0x403d9c18,
-    0x403e1c27,
-    0x403e9c5f,
-    0x403f1c79,
-    0x403f9ca1,
-    0x40401cb6,
-    0x40409cca,
-    0x40411d05,
-    0x40419d20,
-    0x40421d39,
-    0x40429d4c,
-    0x40431d60,
-    0x40439d8e,
-    0x40441da5,
+    0x403d1c42,
+    0x403d9c58,
+    0x403e1c67,
+    0x403e9c9f,
+    0x403f1cb9,
+    0x403f9ce1,
+    0x40401cf6,
+    0x40409d0a,
+    0x40411d45,
+    0x40419d60,
+    0x40421d79,
+    0x40429d8c,
+    0x40431da0,
+    0x40439dce,
+    0x40441de5,
     0x404480b9,
-    0x40451dba,
-    0x40459dcc,
-    0x40461df0,
-    0x40469e10,
-    0x40471e1e,
-    0x40479e45,
-    0x40481eb6,
-    0x40489f70,
-    0x40491f87,
-    0x40499fa1,
-    0x404a1fb8,
-    0x404a9fd6,
-    0x404b1fee,
-    0x404ba01b,
-    0x404c2031,
-    0x404ca043,
-    0x404d2064,
-    0x404da09d,
-    0x404e20b1,
-    0x404ea0be,
-    0x404f216f,
-    0x404fa1e5,
-    0x4050226f,
-    0x4050a283,
-    0x405122b6,
-    0x405222c6,
-    0x4052a2ea,
-    0x40532302,
-    0x4053a315,
-    0x4054232a,
-    0x4054a34d,
-    0x40552378,
-    0x4055a3b5,
-    0x405623da,
-    0x4056a3f3,
-    0x4057240b,
-    0x4057a41e,
-    0x40582433,
-    0x4058a45a,
-    0x40592489,
-    0x4059a4c9,
-    0x405aa4dd,
-    0x405b24f5,
-    0x405ba506,
-    0x405c2519,
-    0x405ca558,
-    0x405d2565,
-    0x405da58a,
-    0x405e25c8,
+    0x40451dfa,
+    0x40459e0c,
+    0x40461e30,
+    0x40469e50,
+    0x40471e5e,
+    0x40479e85,
+    0x40481ef6,
+    0x40489fb0,
+    0x40491fc7,
+    0x40499fe1,
+    0x404a1ff8,
+    0x404aa016,
+    0x404b202e,
+    0x404ba05b,
+    0x404c2071,
+    0x404ca083,
+    0x404d20a4,
+    0x404da0dd,
+    0x404e20f1,
+    0x404ea0fe,
+    0x404f21af,
+    0x404fa225,
+    0x405022af,
+    0x4050a2c3,
+    0x405122f6,
+    0x40522306,
+    0x4052a32a,
+    0x40532342,
+    0x4053a355,
+    0x4054236a,
+    0x4054a38d,
+    0x405523b8,
+    0x4055a3f5,
+    0x4056241a,
+    0x4056a433,
+    0x4057244b,
+    0x4057a45e,
+    0x40582473,
+    0x4058a49a,
+    0x405924c9,
+    0x4059a509,
+    0x405aa51d,
+    0x405b2535,
+    0x405ba546,
+    0x405c2559,
+    0x405ca598,
+    0x405d25a5,
+    0x405da5ca,
+    0x405e2608,
     0x405e8afe,
-    0x405f2617,
-    0x405fa624,
-    0x40602632,
-    0x4060a654,
-    0x406126c8,
-    0x4061a700,
-    0x40622717,
-    0x4062a728,
-    0x40632775,
-    0x4063a78a,
-    0x406427a1,
-    0x4064a7cd,
-    0x406527e8,
-    0x4065a7ff,
-    0x40662817,
-    0x4066a841,
-    0x4067286c,
-    0x4067a8b1,
-    0x406828f9,
-    0x4068a91a,
-    0x4069294c,
-    0x4069a97a,
-    0x406a299b,
-    0x406aa9bb,
-    0x406b2b43,
-    0x406bab66,
-    0x406c2b7c,
-    0x406cae86,
-    0x406d2eb5,
-    0x406daedd,
-    0x406e2f0b,
-    0x406eaf58,
-    0x406f2fb1,
-    0x406fafe9,
-    0x40702ffc,
-    0x4070b019,
+    0x405f2657,
+    0x405fa664,
+    0x40602672,
+    0x4060a694,
+    0x40612708,
+    0x4061a740,
+    0x40622757,
+    0x4062a768,
+    0x406327b5,
+    0x4063a7ca,
+    0x406427e1,
+    0x4064a80d,
+    0x40652828,
+    0x4065a83f,
+    0x40662857,
+    0x4066a881,
+    0x406728ac,
+    0x4067a8f1,
+    0x40682939,
+    0x4068a95a,
+    0x4069298c,
+    0x4069a9ba,
+    0x406a29db,
+    0x406aa9fb,
+    0x406b2b83,
+    0x406baba6,
+    0x406c2bbc,
+    0x406caec6,
+    0x406d2ef5,
+    0x406daf1d,
+    0x406e2f4b,
+    0x406eaf98,
+    0x406f2ff1,
+    0x406fb029,
+    0x4070303c,
+    0x4070b059,
     0x4071084d,
-    0x4071b02b,
-    0x4072303e,
-    0x4072b074,
-    0x4073308c,
-    0x407395cd,
-    0x407430a0,
-    0x4074b0ba,
-    0x407530cb,
-    0x4075b0df,
-    0x407630ed,
-    0x4076935b,
-    0x40773112,
-    0x4077b16e,
-    0x40783189,
-    0x4078b1c2,
-    0x407931d9,
-    0x4079b1ef,
-    0x407a321b,
-    0x407ab22e,
-    0x407b3243,
-    0x407bb255,
-    0x407c3286,
-    0x407cb28f,
-    0x407d2935,
-    0x407da20d,
-    0x407e319e,
-    0x407ea46a,
-    0x407f1e32,
-    0x407fa005,
-    0x4080217f,
-    0x40809e5a,
-    0x408122d8,
-    0x4081a10c,
-    0x40822ef6,
-    0x40829bad,
-    0x40832445,
-    0x4083a7b2,
-    0x40841e6e,
-    0x4084a4a2,
-    0x4085252a,
-    0x4085a68f,
-    0x408625aa,
-    0x4086a227,
-    0x40872f3c,
-    0x4087a6dd,
-    0x40881beb,
-    0x4088a8c4,
-    0x40891c3a,
-    0x40899bc7,
-    0x408a2bb4,
-    0x408a99e5,
-    0x408b326a,
-    0x408bafc6,
-    0x408c253a,
-    0x408d1f56,
-    0x408d9ea0,
-    0x408e2086,
-    0x408ea395,
-    0x408f28d8,
-    0x408fa6ab,
-    0x4090288d,
-    0x4090a57c,
-    0x40912b9c,
-    0x40919a1d,
-    0x40921c87,
-    0x4092af77,
-    0x40933057,
-    0x4093a238,
-    0x40941e82,
-    0x4094abcd,
-    0x40952739,
-    0x4095b1fb,
-    0x40962f23,
-    0x4096a198,
-    0x4097229e,
-    0x4097a0d5,
-    0x40981ce7,
-    0x4098a74d,
-    0x40992f93,
-    0x4099a3c2,
-    0x409a235b,
-    0x409a9a01,
-    0x409b1edc,
-    0x409b9f07,
-    0x409c3150,
-    0x409c9f2f,
-    0x409d2154,
-    0x409da122,
-    0x409e1d78,
-    0x409ea1cd,
-    0x409f21b5,
-    0x409f9ecf,
-    0x40a021f5,
-    0x40a0a0ef,
-    0x40a1213d,
-    0x40a1a4b6,
-    0x40a22254,
-    0x40a2a608,
-    0x40a3267c,
-    0x40a3b134,
-    0x41f42a6e,
-    0x41f92b00,
-    0x41fe29f3,
-    0x41feaca9,
-    0x41ff2dd7,
-    0x42032a87,
-    0x42082aa9,
-    0x4208aae5,
-    0x420929d7,
-    0x4209ab1f,
-    0x420a2a2e,
-    0x420aaa0e,
-    0x420b2a4e,
-    0x420baac7,
-    0x420c2df3,
-    0x420cabdd,
-    0x420d2c90,
-    0x420dacc7,
-    0x42122cfa,
-    0x42172dba,
-    0x4217ad3c,
-    0x421c2d5e,
-    0x421f2d19,
-    0x42212e6b,
-    0x42262d9d,
-    0x422b2e49,
-    0x422bac6b,
-    0x422c2e2b,
-    0x422cac1e,
-    0x422d2bf7,
-    0x422dae0a,
-    0x422e2c4a,
-    0x42302d79,
-    0x4230ace1,
-    0x423125e9,
+    0x4071b06b,
+    0x4072307e,
+    0x4072b0b4,
+    0x407330cc,
+    0x4073960d,
+    0x407430e0,
+    0x4074b0fa,
+    0x4075310b,
+    0x4075b11f,
+    0x4076312d,
+    0x4076939b,
+    0x40773152,
+    0x4077b1ea,
+    0x40783205,
+    0x4078b23e,
+    0x40793255,
+    0x4079b26b,
+    0x407a3297,
+    0x407ab2aa,
+    0x407b32bf,
+    0x407bb2d1,
+    0x407c3302,
+    0x407cb30b,
+    0x407d2975,
+    0x407da24d,
+    0x407e321a,
+    0x407ea4aa,
+    0x407f1e72,
+    0x407fa045,
+    0x408021bf,
+    0x40809e9a,
+    0x40812318,
+    0x4081a14c,
+    0x40822f36,
+    0x40829bed,
+    0x40832485,
+    0x4083a7f2,
+    0x40841eae,
+    0x4084a4e2,
+    0x4085256a,
+    0x4085a6cf,
+    0x408625ea,
+    0x4086a267,
+    0x40872f7c,
+    0x4087a71d,
+    0x40881c2b,
+    0x4088a904,
+    0x40891c7a,
+    0x40899c07,
+    0x408a2bf4,
+    0x408a9a25,
+    0x408b32e6,
+    0x408bb006,
+    0x408c257a,
+    0x408d1f96,
+    0x408d9ee0,
+    0x408e20c6,
+    0x408ea3d5,
+    0x408f2918,
+    0x408fa6eb,
+    0x409028cd,
+    0x4090a5bc,
+    0x40912bdc,
+    0x40919a5d,
+    0x40921cc7,
+    0x4092afb7,
+    0x40933097,
+    0x4093a278,
+    0x40941ec2,
+    0x4094ac0d,
+    0x40952779,
+    0x4095b277,
+    0x40962f63,
+    0x4096a1d8,
+    0x409722de,
+    0x4097a115,
+    0x40981d27,
+    0x4098a78d,
+    0x40992fd3,
+    0x4099a402,
+    0x409a239b,
+    0x409a9a41,
+    0x409b1f1c,
+    0x409b9f47,
+    0x409c31cc,
+    0x409c9f6f,
+    0x409d2194,
+    0x409da162,
+    0x409e1db8,
+    0x409ea20d,
+    0x409f21f5,
+    0x409f9f0f,
+    0x40a02235,
+    0x40a0a12f,
+    0x40a1217d,
+    0x40a1a4f6,
+    0x40a22294,
+    0x40a2a648,
+    0x40a326bc,
+    0x40a3b174,
+    0x40a43190,
+    0x40a4b1aa,
+    0x41f42aae,
+    0x41f92b40,
+    0x41fe2a33,
+    0x41feace9,
+    0x41ff2e17,
+    0x42032ac7,
+    0x42082ae9,
+    0x4208ab25,
+    0x42092a17,
+    0x4209ab5f,
+    0x420a2a6e,
+    0x420aaa4e,
+    0x420b2a8e,
+    0x420bab07,
+    0x420c2e33,
+    0x420cac1d,
+    0x420d2cd0,
+    0x420dad07,
+    0x42122d3a,
+    0x42172dfa,
+    0x4217ad7c,
+    0x421c2d9e,
+    0x421f2d59,
+    0x42212eab,
+    0x42262ddd,
+    0x422b2e89,
+    0x422bacab,
+    0x422c2e6b,
+    0x422cac5e,
+    0x422d2c37,
+    0x422dae4a,
+    0x422e2c8a,
+    0x42302db9,
+    0x4230ad21,
+    0x42312629,
     0x44320778,
     0x44328787,
     0x44330793,
@@ -659,124 +662,124 @@
     0x4439084d,
     0x4439885b,
     0x443a086e,
-    0x483213a3,
-    0x483293b5,
-    0x483313cb,
-    0x483393e4,
-    0x4c321421,
-    0x4c329431,
-    0x4c331444,
-    0x4c339464,
+    0x483213e3,
+    0x483293f5,
+    0x4833140b,
+    0x48339424,
+    0x4c321461,
+    0x4c329471,
+    0x4c331484,
+    0x4c3394a4,
     0x4c3400b9,
     0x4c3480f7,
-    0x4c351470,
-    0x4c35947e,
-    0x4c36149a,
-    0x4c3694c0,
-    0x4c3714cf,
-    0x4c3794dd,
-    0x4c3814f2,
-    0x4c3894fe,
-    0x4c39151e,
-    0x4c399548,
-    0x4c3a1561,
-    0x4c3a957a,
+    0x4c3514b0,
+    0x4c3594be,
+    0x4c3614da,
+    0x4c369500,
+    0x4c37150f,
+    0x4c37951d,
+    0x4c381532,
+    0x4c38953e,
+    0x4c39155e,
+    0x4c399588,
+    0x4c3a15a1,
+    0x4c3a95ba,
     0x4c3b0635,
-    0x4c3b9593,
-    0x4c3c15a5,
-    0x4c3c95b4,
-    0x4c3d15cd,
-    0x4c3d8cc6,
-    0x4c3e163a,
-    0x4c3e95dc,
-    0x4c3f165c,
-    0x4c3f935b,
-    0x4c4015f2,
-    0x4c40940d,
-    0x4c41162a,
-    0x4c4194ad,
-    0x4c421616,
-    0x4c4293f5,
-    0x50323650,
-    0x5032b65f,
-    0x5033366a,
-    0x5033b67a,
-    0x50343693,
-    0x5034b6ad,
-    0x503536bb,
-    0x5035b6d1,
-    0x503636e3,
-    0x5036b6f9,
-    0x50373712,
-    0x5037b725,
-    0x5038373d,
-    0x5038b74e,
-    0x50393763,
-    0x5039b777,
-    0x503a3797,
-    0x503ab7ad,
-    0x503b37c5,
-    0x503bb7d7,
-    0x503c37f3,
-    0x503cb80a,
-    0x503d3823,
-    0x503db839,
-    0x503e3846,
-    0x503eb85c,
-    0x503f386e,
+    0x4c3b95d3,
+    0x4c3c15e5,
+    0x4c3c95f4,
+    0x4c3d160d,
+    0x4c3d8d06,
+    0x4c3e167a,
+    0x4c3e961c,
+    0x4c3f169c,
+    0x4c3f939b,
+    0x4c401632,
+    0x4c40944d,
+    0x4c41166a,
+    0x4c4194ed,
+    0x4c421656,
+    0x4c429435,
+    0x503236cc,
+    0x5032b6db,
+    0x503336e6,
+    0x5033b6f6,
+    0x5034370f,
+    0x5034b729,
+    0x50353737,
+    0x5035b74d,
+    0x5036375f,
+    0x5036b775,
+    0x5037378e,
+    0x5037b7a1,
+    0x503837b9,
+    0x5038b7ca,
+    0x503937df,
+    0x5039b7f3,
+    0x503a3813,
+    0x503ab829,
+    0x503b3841,
+    0x503bb853,
+    0x503c386f,
+    0x503cb886,
+    0x503d389f,
+    0x503db8b5,
+    0x503e38c2,
+    0x503eb8d8,
+    0x503f38ea,
     0x503f83b3,
-    0x50403881,
-    0x5040b891,
-    0x504138ab,
-    0x5041b8ba,
-    0x504238d4,
-    0x5042b8f1,
-    0x50433901,
-    0x5043b911,
-    0x5044392e,
+    0x504038fd,
+    0x5040b90d,
+    0x50413927,
+    0x5041b936,
+    0x50423950,
+    0x5042b96d,
+    0x5043397d,
+    0x5043b98d,
+    0x504439aa,
     0x50448469,
-    0x50453942,
-    0x5045b960,
-    0x50463973,
-    0x5046b989,
-    0x5047399b,
-    0x5047b9b0,
-    0x504839d6,
-    0x5048b9e4,
-    0x504939f7,
-    0x5049ba0c,
-    0x504a3a22,
-    0x504aba32,
-    0x504b3a52,
-    0x504bba65,
-    0x504c3a88,
-    0x504cbab6,
-    0x504d3ae3,
-    0x504dbb00,
-    0x504e3b1b,
-    0x504ebb37,
-    0x504f3b49,
-    0x504fbb60,
-    0x50503b6f,
+    0x504539be,
+    0x5045b9dc,
+    0x504639ef,
+    0x5046ba05,
+    0x50473a17,
+    0x5047ba2c,
+    0x50483a52,
+    0x5048ba60,
+    0x50493a73,
+    0x5049ba88,
+    0x504a3a9e,
+    0x504abaae,
+    0x504b3ace,
+    0x504bbae1,
+    0x504c3b04,
+    0x504cbb32,
+    0x504d3b5f,
+    0x504dbb7c,
+    0x504e3b97,
+    0x504ebbb3,
+    0x504f3bc5,
+    0x504fbbdc,
+    0x50503beb,
     0x50508729,
-    0x50513b82,
-    0x5051b920,
-    0x50523ac8,
-    0x58320fd1,
-    0x68320f93,
-    0x68328ceb,
-    0x68330cfe,
-    0x68338fa1,
-    0x68340fb1,
+    0x50513bfe,
+    0x5051b99c,
+    0x50523b44,
+    0x58321011,
+    0x68320fd3,
+    0x68328d2b,
+    0x68330d3e,
+    0x68338fe1,
+    0x68340ff1,
     0x683480f7,
     0x6835099a,
-    0x6c320f59,
-    0x6c328cb5,
-    0x6c330f64,
-    0x6c338f7d,
+    0x6c320f99,
+    0x6c328cf5,
+    0x6c330fa4,
+    0x6c338fbd,
     0x74320a66,
     0x743280b9,
-    0x74330cc6,
+    0x74330d06,
     0x783209cb,
     0x783289e0,
     0x783309ec,
@@ -803,22 +806,24 @@
     0x783d8b97,
     0x783e0aed,
     0x783e8a9f,
-    0x7c321274,
-    0x803214c0,
+    0x7c3212b4,
+    0x80321500,
     0x80328090,
-    0x8033334c,
+    0x803333c8,
     0x803380b9,
-    0x8034335b,
-    0x8034b2c3,
-    0x803532e1,
-    0x8035b36f,
-    0x80363323,
-    0x8036b2d2,
-    0x80373315,
-    0x8037b2b0,
-    0x80383336,
-    0x8038b2f2,
-    0x80393307,
+    0x803433d7,
+    0x8034b33f,
+    0x8035335d,
+    0x8035b3eb,
+    0x8036339f,
+    0x8036b34e,
+    0x80373391,
+    0x8037b32c,
+    0x803833b2,
+    0x8038b36e,
+    0x80393383,
+    0x84320bb0,
+    0x84328bc9,
 };
 
 extern const size_t kOpenSSLReasonValuesLen;
@@ -984,6 +989,8 @@
     "UNSUPPORTED_NONCE_SIZE\0"
     "UNSUPPORTED_TAG_SIZE\0"
     "WRONG_FINAL_BLOCK_LENGTH\0"
+    "CERTIFICATE_HAS_NO_KEYID\0"
+    "PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE\0"
     "LIST_CANNOT_BE_NULL\0"
     "MISSING_CLOSE_SQUARE_BRACKET\0"
     "MISSING_EQUAL_SIGN\0"
@@ -1399,6 +1406,8 @@
     "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0"
     "UNSUPPORTED_COMPRESSION_ALGORITHM\0"
     "UNSUPPORTED_CREDENTIAL_LIST\0"
+    "INVALID_TRUST_ANCHOR_LIST\0"
+    "INVALID_CERTIFICATE_PROPERTY_LIST\0"
     "UNSUPPORTED_ECH_SERVER_CONFIG\0"
     "UNSUPPORTED_ELLIPTIC_CURVE\0"
     "UNSUPPORTED_PROTOCOL\0"
diff --git a/src/gen/sources.bzl b/src/gen/sources.bzl
index 082ac46..758f8e7 100644
--- a/src/gen/sources.bzl
+++ b/src/gen/sources.bzl
@@ -29,7 +29,6 @@
     "crypto/fipsmodule/aes/key_wrap.cc.inc",
     "crypto/fipsmodule/aes/mode_wrappers.cc.inc",
     "crypto/fipsmodule/aes/ofb.cc.inc",
-    "crypto/fipsmodule/aes/polyval.cc.inc",
     "crypto/fipsmodule/bn/add.cc.inc",
     "crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
     "crypto/fipsmodule/bn/bn.cc.inc",
@@ -79,7 +78,9 @@
     "crypto/fipsmodule/hkdf/hkdf.cc.inc",
     "crypto/fipsmodule/hmac/hmac.cc.inc",
     "crypto/fipsmodule/keccak/keccak.cc.inc",
+    "crypto/fipsmodule/mldsa/fips_known_values.inc",
     "crypto/fipsmodule/mldsa/mldsa.cc.inc",
+    "crypto/fipsmodule/mlkem/fips_known_values.inc",
     "crypto/fipsmodule/mlkem/mlkem.cc.inc",
     "crypto/fipsmodule/rand/ctrdrbg.cc.inc",
     "crypto/fipsmodule/rand/rand.cc.inc",
@@ -93,6 +94,7 @@
     "crypto/fipsmodule/sha/sha1.cc.inc",
     "crypto/fipsmodule/sha/sha256.cc.inc",
     "crypto/fipsmodule/sha/sha512.cc.inc",
+    "crypto/fipsmodule/slhdsa/fips_known_values.inc",
     "crypto/fipsmodule/slhdsa/fors.cc.inc",
     "crypto/fipsmodule/slhdsa/merkle.cc.inc",
     "crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
@@ -102,10 +104,10 @@
 ]
 
 bcm_sources_asm = [
-    "gen/bcm/aes-gcm-avx10-x86_64-apple.S",
-    "gen/bcm/aes-gcm-avx10-x86_64-linux.S",
     "gen/bcm/aes-gcm-avx2-x86_64-apple.S",
     "gen/bcm/aes-gcm-avx2-x86_64-linux.S",
+    "gen/bcm/aes-gcm-avx512-x86_64-apple.S",
+    "gen/bcm/aes-gcm-avx512-x86_64-linux.S",
     "gen/bcm/aesni-gcm-x86_64-apple.S",
     "gen/bcm/aesni-gcm-x86_64-linux.S",
     "gen/bcm/aesni-x86-apple.S",
@@ -204,8 +206,8 @@
 ]
 
 bcm_sources_nasm = [
-    "gen/bcm/aes-gcm-avx10-x86_64-win.asm",
     "gen/bcm/aes-gcm-avx2-x86_64-win.asm",
+    "gen/bcm/aes-gcm-avx512-x86_64-win.asm",
     "gen/bcm/aesni-gcm-x86_64-win.asm",
     "gen/bcm/aesni-x86-win.asm",
     "gen/bcm/aesni-x86_64-win.asm",
@@ -258,6 +260,7 @@
 ]
 
 crypto_sources = [
+    "crypto/aes/aes.cc",
     "crypto/asn1/a_bitstr.cc",
     "crypto/asn1/a_bool.cc",
     "crypto/asn1/a_d2i_fp.cc",
@@ -300,6 +303,9 @@
     "crypto/blake2/blake2.cc",
     "crypto/bn/bn_asn1.cc",
     "crypto/bn/convert.cc",
+    "crypto/bn/div.cc",
+    "crypto/bn/exponentiation.cc",
+    "crypto/bn/sqrt.cc",
     "crypto/buf/buf.cc",
     "crypto/bytestring/asn1_compat.cc",
     "crypto/bytestring/ber.cc",
@@ -309,6 +315,7 @@
     "crypto/chacha/chacha.cc",
     "crypto/cipher/derive_key.cc",
     "crypto/cipher/e_aesctrhmac.cc",
+    "crypto/cipher/e_aeseax.cc",
     "crypto/cipher/e_aesgcmsiv.cc",
     "crypto/cipher/e_chacha20poly1305.cc",
     "crypto/cipher/e_des.cc",
@@ -318,6 +325,7 @@
     "crypto/cipher/e_tls.cc",
     "crypto/cipher/get_cipher.cc",
     "crypto/cipher/tls_cbc.cc",
+    "crypto/cms/cms.cc",
     "crypto/conf/conf.cc",
     "crypto/cpu_aarch64_apple.cc",
     "crypto/cpu_aarch64_fuchsia.cc",
@@ -366,6 +374,7 @@
     "crypto/evp/sign.cc",
     "crypto/ex_data.cc",
     "crypto/fipsmodule/fips_shared_support.cc",
+    "crypto/fuzzer_mode.cc",
     "crypto/hpke/hpke.cc",
     "crypto/hrss/hrss.cc",
     "crypto/kyber/kyber.cc",
@@ -519,6 +528,7 @@
     "include/openssl/chacha.h",
     "include/openssl/cipher.h",
     "include/openssl/cmac.h",
+    "include/openssl/cms.h",
     "include/openssl/conf.h",
     "include/openssl/cpu.h",
     "include/openssl/crypto.h",
@@ -642,7 +652,7 @@
     "crypto/poly1305/internal.h",
     "crypto/pool/internal.h",
     "crypto/rand/getrandom_fillin.h",
-    "crypto/rand/sysrand_internal.h",
+    "crypto/rand/internal.h",
     "crypto/rsa/internal.h",
     "crypto/spake2plus/internal.h",
     "crypto/trust_token/internal.h",
@@ -704,6 +714,7 @@
     "crypto/chacha/chacha_test.cc",
     "crypto/cipher/aead_test.cc",
     "crypto/cipher/cipher_test.cc",
+    "crypto/cms/cms_test.cc",
     "crypto/compiler_test.cc",
     "crypto/conf/conf_test.cc",
     "crypto/constant_time_test.cc",
@@ -776,6 +787,7 @@
     "crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt",
     "crypto/cipher/test/aes_128_ccm_matter_tests.txt",
     "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt",
+    "crypto/cipher/test/aes_128_eax_test.txt",
     "crypto/cipher/test/aes_128_gcm_randnonce_tests.txt",
     "crypto/cipher/test/aes_128_gcm_siv_tests.txt",
     "crypto/cipher/test/aes_128_gcm_tests.txt",
@@ -783,6 +795,7 @@
     "crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt",
     "crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt",
     "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt",
+    "crypto/cipher/test/aes_256_eax_test.txt",
     "crypto/cipher/test/aes_256_gcm_randnonce_tests.txt",
     "crypto/cipher/test/aes_256_gcm_siv_tests.txt",
     "crypto/cipher/test/aes_256_gcm_tests.txt",
@@ -844,6 +857,15 @@
     "crypto/mlkem/mlkem768_keygen_tests.txt",
     "crypto/mlkem/mlkem768_nist_decap_tests.txt",
     "crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+    "crypto/pkcs7/test/nss.p7c",
+    "crypto/pkcs7/test/openssl_crl.p7c",
+    "crypto/pkcs7/test/sign_cert.pem",
+    "crypto/pkcs7/test/sign_key.pem",
+    "crypto/pkcs7/test/sign_sha1.p7s",
+    "crypto/pkcs7/test/sign_sha1_key_id.p7s",
+    "crypto/pkcs7/test/sign_sha256.p7s",
+    "crypto/pkcs7/test/sign_sha256_key_id.p7s",
+    "crypto/pkcs7/test/windows.p7c",
     "crypto/pkcs8/test/bad1.p12",
     "crypto/pkcs8/test/bad2.p12",
     "crypto/pkcs8/test/bad3.p12",
@@ -952,6 +974,7 @@
     "crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
     "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
     "third_party/wycheproof_testvectors/aes_cmac_test.txt",
+    "third_party/wycheproof_testvectors/aes_eax_test.txt",
     "third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
     "third_party/wycheproof_testvectors/aes_gcm_test.txt",
     "third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
@@ -1070,6 +1093,7 @@
     "fuzz/bn_mod_exp.cc",
     "fuzz/cert.cc",
     "fuzz/client.cc",
+    "fuzz/client_no_fuzzer_mode.cc",
     "fuzz/conf.cc",
     "fuzz/crl_getcrlstatusforcert_fuzzer.cc",
     "fuzz/crl_parse_crl_certificatelist_fuzzer.cc",
@@ -1091,6 +1115,7 @@
     "fuzz/privkey.cc",
     "fuzz/read_pem.cc",
     "fuzz/server.cc",
+    "fuzz/server_no_fuzzer_mode.cc",
     "fuzz/session.cc",
     "fuzz/spki.cc",
     "fuzz/ssl_ctx_api.cc",
@@ -1099,6 +1124,15 @@
     "fuzz/verify_name_match_verifynameinsubtree_fuzzer.cc",
 ]
 
+modulewrapper_sources = [
+    "util/fipstools/acvp/modulewrapper/main.cc",
+    "util/fipstools/acvp/modulewrapper/modulewrapper.cc",
+]
+
+modulewrapper_internal_headers = [
+    "util/fipstools/acvp/modulewrapper/modulewrapper.h",
+]
+
 pki_sources = [
     "pki/cert_error_id.cc",
     "pki/cert_error_params.cc",
@@ -2197,6 +2231,18 @@
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test",
@@ -2205,6 +2251,14 @@
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test",
     "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test",
@@ -2421,6 +2475,7 @@
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test",
@@ -2435,6 +2490,7 @@
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test",
@@ -2443,6 +2499,7 @@
     "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test",
+    "pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test",
     "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test",
     "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem",
diff --git a/src/gen/sources.cmake b/src/gen/sources.cmake
index 5f4afc8..32aaf2b 100644
--- a/src/gen/sources.cmake
+++ b/src/gen/sources.cmake
@@ -33,7 +33,6 @@
   crypto/fipsmodule/aes/key_wrap.cc.inc
   crypto/fipsmodule/aes/mode_wrappers.cc.inc
   crypto/fipsmodule/aes/ofb.cc.inc
-  crypto/fipsmodule/aes/polyval.cc.inc
   crypto/fipsmodule/bn/add.cc.inc
   crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc
   crypto/fipsmodule/bn/bn.cc.inc
@@ -83,7 +82,9 @@
   crypto/fipsmodule/hkdf/hkdf.cc.inc
   crypto/fipsmodule/hmac/hmac.cc.inc
   crypto/fipsmodule/keccak/keccak.cc.inc
+  crypto/fipsmodule/mldsa/fips_known_values.inc
   crypto/fipsmodule/mldsa/mldsa.cc.inc
+  crypto/fipsmodule/mlkem/fips_known_values.inc
   crypto/fipsmodule/mlkem/mlkem.cc.inc
   crypto/fipsmodule/rand/ctrdrbg.cc.inc
   crypto/fipsmodule/rand/rand.cc.inc
@@ -97,6 +98,7 @@
   crypto/fipsmodule/sha/sha1.cc.inc
   crypto/fipsmodule/sha/sha256.cc.inc
   crypto/fipsmodule/sha/sha512.cc.inc
+  crypto/fipsmodule/slhdsa/fips_known_values.inc
   crypto/fipsmodule/slhdsa/fors.cc.inc
   crypto/fipsmodule/slhdsa/merkle.cc.inc
   crypto/fipsmodule/slhdsa/slhdsa.cc.inc
@@ -108,10 +110,10 @@
 set(
   BCM_SOURCES_ASM
 
-  gen/bcm/aes-gcm-avx10-x86_64-apple.S
-  gen/bcm/aes-gcm-avx10-x86_64-linux.S
   gen/bcm/aes-gcm-avx2-x86_64-apple.S
   gen/bcm/aes-gcm-avx2-x86_64-linux.S
+  gen/bcm/aes-gcm-avx512-x86_64-apple.S
+  gen/bcm/aes-gcm-avx512-x86_64-linux.S
   gen/bcm/aesni-gcm-x86_64-apple.S
   gen/bcm/aesni-gcm-x86_64-linux.S
   gen/bcm/aesni-x86-apple.S
@@ -212,8 +214,8 @@
 set(
   BCM_SOURCES_NASM
 
-  gen/bcm/aes-gcm-avx10-x86_64-win.asm
   gen/bcm/aes-gcm-avx2-x86_64-win.asm
+  gen/bcm/aes-gcm-avx512-x86_64-win.asm
   gen/bcm/aesni-gcm-x86_64-win.asm
   gen/bcm/aesni-x86-win.asm
   gen/bcm/aesni-x86_64-win.asm
@@ -272,6 +274,7 @@
 set(
   CRYPTO_SOURCES
 
+  crypto/aes/aes.cc
   crypto/asn1/a_bitstr.cc
   crypto/asn1/a_bool.cc
   crypto/asn1/a_d2i_fp.cc
@@ -314,6 +317,9 @@
   crypto/blake2/blake2.cc
   crypto/bn/bn_asn1.cc
   crypto/bn/convert.cc
+  crypto/bn/div.cc
+  crypto/bn/exponentiation.cc
+  crypto/bn/sqrt.cc
   crypto/buf/buf.cc
   crypto/bytestring/asn1_compat.cc
   crypto/bytestring/ber.cc
@@ -323,6 +329,7 @@
   crypto/chacha/chacha.cc
   crypto/cipher/derive_key.cc
   crypto/cipher/e_aesctrhmac.cc
+  crypto/cipher/e_aeseax.cc
   crypto/cipher/e_aesgcmsiv.cc
   crypto/cipher/e_chacha20poly1305.cc
   crypto/cipher/e_des.cc
@@ -332,6 +339,7 @@
   crypto/cipher/e_tls.cc
   crypto/cipher/get_cipher.cc
   crypto/cipher/tls_cbc.cc
+  crypto/cms/cms.cc
   crypto/conf/conf.cc
   crypto/cpu_aarch64_apple.cc
   crypto/cpu_aarch64_fuchsia.cc
@@ -380,6 +388,7 @@
   crypto/evp/sign.cc
   crypto/ex_data.cc
   crypto/fipsmodule/fips_shared_support.cc
+  crypto/fuzzer_mode.cc
   crypto/hpke/hpke.cc
   crypto/hrss/hrss.cc
   crypto/kyber/kyber.cc
@@ -535,6 +544,7 @@
   include/openssl/chacha.h
   include/openssl/cipher.h
   include/openssl/cmac.h
+  include/openssl/cms.h
   include/openssl/conf.h
   include/openssl/cpu.h
   include/openssl/crypto.h
@@ -660,7 +670,7 @@
   crypto/poly1305/internal.h
   crypto/pool/internal.h
   crypto/rand/getrandom_fillin.h
-  crypto/rand/sysrand_internal.h
+  crypto/rand/internal.h
   crypto/rsa/internal.h
   crypto/spake2plus/internal.h
   crypto/trust_token/internal.h
@@ -728,6 +738,7 @@
   crypto/chacha/chacha_test.cc
   crypto/cipher/aead_test.cc
   crypto/cipher/cipher_test.cc
+  crypto/cms/cms_test.cc
   crypto/compiler_test.cc
   crypto/conf/conf_test.cc
   crypto/constant_time_test.cc
@@ -802,6 +813,7 @@
   crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt
   crypto/cipher/test/aes_128_ccm_matter_tests.txt
   crypto/cipher/test/aes_128_ctr_hmac_sha256.txt
+  crypto/cipher/test/aes_128_eax_test.txt
   crypto/cipher/test/aes_128_gcm_randnonce_tests.txt
   crypto/cipher/test/aes_128_gcm_siv_tests.txt
   crypto/cipher/test/aes_128_gcm_tests.txt
@@ -809,6 +821,7 @@
   crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
   crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
   crypto/cipher/test/aes_256_ctr_hmac_sha256.txt
+  crypto/cipher/test/aes_256_eax_test.txt
   crypto/cipher/test/aes_256_gcm_randnonce_tests.txt
   crypto/cipher/test/aes_256_gcm_siv_tests.txt
   crypto/cipher/test/aes_256_gcm_tests.txt
@@ -870,6 +883,15 @@
   crypto/mlkem/mlkem768_keygen_tests.txt
   crypto/mlkem/mlkem768_nist_decap_tests.txt
   crypto/mlkem/mlkem768_nist_keygen_tests.txt
+  crypto/pkcs7/test/nss.p7c
+  crypto/pkcs7/test/openssl_crl.p7c
+  crypto/pkcs7/test/sign_cert.pem
+  crypto/pkcs7/test/sign_key.pem
+  crypto/pkcs7/test/sign_sha1.p7s
+  crypto/pkcs7/test/sign_sha1_key_id.p7s
+  crypto/pkcs7/test/sign_sha256.p7s
+  crypto/pkcs7/test/sign_sha256_key_id.p7s
+  crypto/pkcs7/test/windows.p7c
   crypto/pkcs8/test/bad1.p12
   crypto/pkcs8/test/bad2.p12
   crypto/pkcs8/test/bad3.p12
@@ -978,6 +1000,7 @@
   crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem
   third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt
   third_party/wycheproof_testvectors/aes_cmac_test.txt
+  third_party/wycheproof_testvectors/aes_eax_test.txt
   third_party/wycheproof_testvectors/aes_gcm_siv_test.txt
   third_party/wycheproof_testvectors/aes_gcm_test.txt
   third_party/wycheproof_testvectors/chacha20_poly1305_test.txt
@@ -1104,6 +1127,7 @@
   fuzz/bn_mod_exp.cc
   fuzz/cert.cc
   fuzz/client.cc
+  fuzz/client_no_fuzzer_mode.cc
   fuzz/conf.cc
   fuzz/crl_getcrlstatusforcert_fuzzer.cc
   fuzz/crl_parse_crl_certificatelist_fuzzer.cc
@@ -1125,6 +1149,7 @@
   fuzz/privkey.cc
   fuzz/read_pem.cc
   fuzz/server.cc
+  fuzz/server_no_fuzzer_mode.cc
   fuzz/session.cc
   fuzz/spki.cc
   fuzz/ssl_ctx_api.cc
@@ -1134,6 +1159,19 @@
 )
 
 set(
+  MODULEWRAPPER_SOURCES
+
+  util/fipstools/acvp/modulewrapper/main.cc
+  util/fipstools/acvp/modulewrapper/modulewrapper.cc
+)
+
+set(
+  MODULEWRAPPER_INTERNAL_HEADERS
+
+  util/fipstools/acvp/modulewrapper/modulewrapper.h
+)
+
+set(
   PKI_SOURCES
 
   pki/cert_error_id.cc
@@ -2241,6 +2279,18 @@
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test
@@ -2249,6 +2299,14 @@
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test
   pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test
@@ -2465,6 +2523,7 @@
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test
@@ -2479,6 +2538,7 @@
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test
@@ -2487,6 +2547,7 @@
   pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test
   pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test
   pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem
diff --git a/src/gen/sources.gni b/src/gen/sources.gni
index 1cc825f..cd760e2 100644
--- a/src/gen/sources.gni
+++ b/src/gen/sources.gni
@@ -29,7 +29,6 @@
   "crypto/fipsmodule/aes/key_wrap.cc.inc",
   "crypto/fipsmodule/aes/mode_wrappers.cc.inc",
   "crypto/fipsmodule/aes/ofb.cc.inc",
-  "crypto/fipsmodule/aes/polyval.cc.inc",
   "crypto/fipsmodule/bn/add.cc.inc",
   "crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
   "crypto/fipsmodule/bn/bn.cc.inc",
@@ -79,7 +78,9 @@
   "crypto/fipsmodule/hkdf/hkdf.cc.inc",
   "crypto/fipsmodule/hmac/hmac.cc.inc",
   "crypto/fipsmodule/keccak/keccak.cc.inc",
+  "crypto/fipsmodule/mldsa/fips_known_values.inc",
   "crypto/fipsmodule/mldsa/mldsa.cc.inc",
+  "crypto/fipsmodule/mlkem/fips_known_values.inc",
   "crypto/fipsmodule/mlkem/mlkem.cc.inc",
   "crypto/fipsmodule/rand/ctrdrbg.cc.inc",
   "crypto/fipsmodule/rand/rand.cc.inc",
@@ -93,6 +94,7 @@
   "crypto/fipsmodule/sha/sha1.cc.inc",
   "crypto/fipsmodule/sha/sha256.cc.inc",
   "crypto/fipsmodule/sha/sha512.cc.inc",
+  "crypto/fipsmodule/slhdsa/fips_known_values.inc",
   "crypto/fipsmodule/slhdsa/fors.cc.inc",
   "crypto/fipsmodule/slhdsa/merkle.cc.inc",
   "crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
@@ -102,10 +104,10 @@
 ]
 
 bcm_sources_asm = [
-  "gen/bcm/aes-gcm-avx10-x86_64-apple.S",
-  "gen/bcm/aes-gcm-avx10-x86_64-linux.S",
   "gen/bcm/aes-gcm-avx2-x86_64-apple.S",
   "gen/bcm/aes-gcm-avx2-x86_64-linux.S",
+  "gen/bcm/aes-gcm-avx512-x86_64-apple.S",
+  "gen/bcm/aes-gcm-avx512-x86_64-linux.S",
   "gen/bcm/aesni-gcm-x86_64-apple.S",
   "gen/bcm/aesni-gcm-x86_64-linux.S",
   "gen/bcm/aesni-x86-apple.S",
@@ -204,8 +206,8 @@
 ]
 
 bcm_sources_nasm = [
-  "gen/bcm/aes-gcm-avx10-x86_64-win.asm",
   "gen/bcm/aes-gcm-avx2-x86_64-win.asm",
+  "gen/bcm/aes-gcm-avx512-x86_64-win.asm",
   "gen/bcm/aesni-gcm-x86_64-win.asm",
   "gen/bcm/aesni-x86-win.asm",
   "gen/bcm/aesni-x86_64-win.asm",
@@ -258,6 +260,7 @@
 ]
 
 crypto_sources = [
+  "crypto/aes/aes.cc",
   "crypto/asn1/a_bitstr.cc",
   "crypto/asn1/a_bool.cc",
   "crypto/asn1/a_d2i_fp.cc",
@@ -300,6 +303,9 @@
   "crypto/blake2/blake2.cc",
   "crypto/bn/bn_asn1.cc",
   "crypto/bn/convert.cc",
+  "crypto/bn/div.cc",
+  "crypto/bn/exponentiation.cc",
+  "crypto/bn/sqrt.cc",
   "crypto/buf/buf.cc",
   "crypto/bytestring/asn1_compat.cc",
   "crypto/bytestring/ber.cc",
@@ -309,6 +315,7 @@
   "crypto/chacha/chacha.cc",
   "crypto/cipher/derive_key.cc",
   "crypto/cipher/e_aesctrhmac.cc",
+  "crypto/cipher/e_aeseax.cc",
   "crypto/cipher/e_aesgcmsiv.cc",
   "crypto/cipher/e_chacha20poly1305.cc",
   "crypto/cipher/e_des.cc",
@@ -318,6 +325,7 @@
   "crypto/cipher/e_tls.cc",
   "crypto/cipher/get_cipher.cc",
   "crypto/cipher/tls_cbc.cc",
+  "crypto/cms/cms.cc",
   "crypto/conf/conf.cc",
   "crypto/cpu_aarch64_apple.cc",
   "crypto/cpu_aarch64_fuchsia.cc",
@@ -366,6 +374,7 @@
   "crypto/evp/sign.cc",
   "crypto/ex_data.cc",
   "crypto/fipsmodule/fips_shared_support.cc",
+  "crypto/fuzzer_mode.cc",
   "crypto/hpke/hpke.cc",
   "crypto/hrss/hrss.cc",
   "crypto/kyber/kyber.cc",
@@ -519,6 +528,7 @@
   "include/openssl/chacha.h",
   "include/openssl/cipher.h",
   "include/openssl/cmac.h",
+  "include/openssl/cms.h",
   "include/openssl/conf.h",
   "include/openssl/cpu.h",
   "include/openssl/crypto.h",
@@ -642,7 +652,7 @@
   "crypto/poly1305/internal.h",
   "crypto/pool/internal.h",
   "crypto/rand/getrandom_fillin.h",
-  "crypto/rand/sysrand_internal.h",
+  "crypto/rand/internal.h",
   "crypto/rsa/internal.h",
   "crypto/spake2plus/internal.h",
   "crypto/trust_token/internal.h",
@@ -704,6 +714,7 @@
   "crypto/chacha/chacha_test.cc",
   "crypto/cipher/aead_test.cc",
   "crypto/cipher/cipher_test.cc",
+  "crypto/cms/cms_test.cc",
   "crypto/compiler_test.cc",
   "crypto/conf/conf_test.cc",
   "crypto/constant_time_test.cc",
@@ -776,6 +787,7 @@
   "crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt",
   "crypto/cipher/test/aes_128_ccm_matter_tests.txt",
   "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt",
+  "crypto/cipher/test/aes_128_eax_test.txt",
   "crypto/cipher/test/aes_128_gcm_randnonce_tests.txt",
   "crypto/cipher/test/aes_128_gcm_siv_tests.txt",
   "crypto/cipher/test/aes_128_gcm_tests.txt",
@@ -783,6 +795,7 @@
   "crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt",
   "crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt",
   "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt",
+  "crypto/cipher/test/aes_256_eax_test.txt",
   "crypto/cipher/test/aes_256_gcm_randnonce_tests.txt",
   "crypto/cipher/test/aes_256_gcm_siv_tests.txt",
   "crypto/cipher/test/aes_256_gcm_tests.txt",
@@ -844,6 +857,15 @@
   "crypto/mlkem/mlkem768_keygen_tests.txt",
   "crypto/mlkem/mlkem768_nist_decap_tests.txt",
   "crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+  "crypto/pkcs7/test/nss.p7c",
+  "crypto/pkcs7/test/openssl_crl.p7c",
+  "crypto/pkcs7/test/sign_cert.pem",
+  "crypto/pkcs7/test/sign_key.pem",
+  "crypto/pkcs7/test/sign_sha1.p7s",
+  "crypto/pkcs7/test/sign_sha1_key_id.p7s",
+  "crypto/pkcs7/test/sign_sha256.p7s",
+  "crypto/pkcs7/test/sign_sha256_key_id.p7s",
+  "crypto/pkcs7/test/windows.p7c",
   "crypto/pkcs8/test/bad1.p12",
   "crypto/pkcs8/test/bad2.p12",
   "crypto/pkcs8/test/bad3.p12",
@@ -952,6 +974,7 @@
   "crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
   "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
   "third_party/wycheproof_testvectors/aes_cmac_test.txt",
+  "third_party/wycheproof_testvectors/aes_eax_test.txt",
   "third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
   "third_party/wycheproof_testvectors/aes_gcm_test.txt",
   "third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
@@ -1070,6 +1093,7 @@
   "fuzz/bn_mod_exp.cc",
   "fuzz/cert.cc",
   "fuzz/client.cc",
+  "fuzz/client_no_fuzzer_mode.cc",
   "fuzz/conf.cc",
   "fuzz/crl_getcrlstatusforcert_fuzzer.cc",
   "fuzz/crl_parse_crl_certificatelist_fuzzer.cc",
@@ -1091,6 +1115,7 @@
   "fuzz/privkey.cc",
   "fuzz/read_pem.cc",
   "fuzz/server.cc",
+  "fuzz/server_no_fuzzer_mode.cc",
   "fuzz/session.cc",
   "fuzz/spki.cc",
   "fuzz/ssl_ctx_api.cc",
@@ -1099,6 +1124,15 @@
   "fuzz/verify_name_match_verifynameinsubtree_fuzzer.cc",
 ]
 
+modulewrapper_sources = [
+  "util/fipstools/acvp/modulewrapper/main.cc",
+  "util/fipstools/acvp/modulewrapper/modulewrapper.cc",
+]
+
+modulewrapper_internal_headers = [
+  "util/fipstools/acvp/modulewrapper/modulewrapper.h",
+]
+
 pki_sources = [
   "pki/cert_error_id.cc",
   "pki/cert_error_params.cc",
@@ -2197,6 +2231,18 @@
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test",
@@ -2205,6 +2251,14 @@
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test",
   "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test",
@@ -2421,6 +2475,7 @@
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test",
@@ -2435,6 +2490,7 @@
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test",
@@ -2443,6 +2499,7 @@
   "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test",
+  "pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test",
   "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test",
   "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem",
diff --git a/src/gen/sources.json b/src/gen/sources.json
index 239b0a8..fb27719 100644
--- a/src/gen/sources.json
+++ b/src/gen/sources.json
@@ -14,7 +14,6 @@
       "crypto/fipsmodule/aes/key_wrap.cc.inc",
       "crypto/fipsmodule/aes/mode_wrappers.cc.inc",
       "crypto/fipsmodule/aes/ofb.cc.inc",
-      "crypto/fipsmodule/aes/polyval.cc.inc",
       "crypto/fipsmodule/bn/add.cc.inc",
       "crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc",
       "crypto/fipsmodule/bn/bn.cc.inc",
@@ -64,7 +63,9 @@
       "crypto/fipsmodule/hkdf/hkdf.cc.inc",
       "crypto/fipsmodule/hmac/hmac.cc.inc",
       "crypto/fipsmodule/keccak/keccak.cc.inc",
+      "crypto/fipsmodule/mldsa/fips_known_values.inc",
       "crypto/fipsmodule/mldsa/mldsa.cc.inc",
+      "crypto/fipsmodule/mlkem/fips_known_values.inc",
       "crypto/fipsmodule/mlkem/mlkem.cc.inc",
       "crypto/fipsmodule/rand/ctrdrbg.cc.inc",
       "crypto/fipsmodule/rand/rand.cc.inc",
@@ -78,6 +79,7 @@
       "crypto/fipsmodule/sha/sha1.cc.inc",
       "crypto/fipsmodule/sha/sha256.cc.inc",
       "crypto/fipsmodule/sha/sha512.cc.inc",
+      "crypto/fipsmodule/slhdsa/fips_known_values.inc",
       "crypto/fipsmodule/slhdsa/fors.cc.inc",
       "crypto/fipsmodule/slhdsa/merkle.cc.inc",
       "crypto/fipsmodule/slhdsa/slhdsa.cc.inc",
@@ -86,10 +88,10 @@
       "crypto/fipsmodule/tls/kdf.cc.inc"
     ],
     "asm": [
-      "gen/bcm/aes-gcm-avx10-x86_64-apple.S",
-      "gen/bcm/aes-gcm-avx10-x86_64-linux.S",
       "gen/bcm/aes-gcm-avx2-x86_64-apple.S",
       "gen/bcm/aes-gcm-avx2-x86_64-linux.S",
+      "gen/bcm/aes-gcm-avx512-x86_64-apple.S",
+      "gen/bcm/aes-gcm-avx512-x86_64-linux.S",
       "gen/bcm/aesni-gcm-x86_64-apple.S",
       "gen/bcm/aesni-gcm-x86_64-linux.S",
       "gen/bcm/aesni-x86-apple.S",
@@ -187,8 +189,8 @@
       "third_party/fiat/asm/fiat_p256_adx_sqr.S"
     ],
     "nasm": [
-      "gen/bcm/aes-gcm-avx10-x86_64-win.asm",
       "gen/bcm/aes-gcm-avx2-x86_64-win.asm",
+      "gen/bcm/aes-gcm-avx512-x86_64-win.asm",
       "gen/bcm/aesni-gcm-x86_64-win.asm",
       "gen/bcm/aesni-x86-win.asm",
       "gen/bcm/aesni-x86_64-win.asm",
@@ -242,6 +244,7 @@
   },
   "crypto": {
     "srcs": [
+      "crypto/aes/aes.cc",
       "crypto/asn1/a_bitstr.cc",
       "crypto/asn1/a_bool.cc",
       "crypto/asn1/a_d2i_fp.cc",
@@ -284,6 +287,9 @@
       "crypto/blake2/blake2.cc",
       "crypto/bn/bn_asn1.cc",
       "crypto/bn/convert.cc",
+      "crypto/bn/div.cc",
+      "crypto/bn/exponentiation.cc",
+      "crypto/bn/sqrt.cc",
       "crypto/buf/buf.cc",
       "crypto/bytestring/asn1_compat.cc",
       "crypto/bytestring/ber.cc",
@@ -293,6 +299,7 @@
       "crypto/chacha/chacha.cc",
       "crypto/cipher/derive_key.cc",
       "crypto/cipher/e_aesctrhmac.cc",
+      "crypto/cipher/e_aeseax.cc",
       "crypto/cipher/e_aesgcmsiv.cc",
       "crypto/cipher/e_chacha20poly1305.cc",
       "crypto/cipher/e_des.cc",
@@ -302,6 +309,7 @@
       "crypto/cipher/e_tls.cc",
       "crypto/cipher/get_cipher.cc",
       "crypto/cipher/tls_cbc.cc",
+      "crypto/cms/cms.cc",
       "crypto/conf/conf.cc",
       "crypto/cpu_aarch64_apple.cc",
       "crypto/cpu_aarch64_fuchsia.cc",
@@ -350,6 +358,7 @@
       "crypto/evp/sign.cc",
       "crypto/ex_data.cc",
       "crypto/fipsmodule/fips_shared_support.cc",
+      "crypto/fuzzer_mode.cc",
       "crypto/hpke/hpke.cc",
       "crypto/hrss/hrss.cc",
       "crypto/kyber/kyber.cc",
@@ -502,6 +511,7 @@
       "include/openssl/chacha.h",
       "include/openssl/cipher.h",
       "include/openssl/cmac.h",
+      "include/openssl/cms.h",
       "include/openssl/conf.h",
       "include/openssl/cpu.h",
       "include/openssl/crypto.h",
@@ -624,7 +634,7 @@
       "crypto/poly1305/internal.h",
       "crypto/pool/internal.h",
       "crypto/rand/getrandom_fillin.h",
-      "crypto/rand/sysrand_internal.h",
+      "crypto/rand/internal.h",
       "crypto/rsa/internal.h",
       "crypto/spake2plus/internal.h",
       "crypto/trust_token/internal.h",
@@ -685,6 +695,7 @@
       "crypto/chacha/chacha_test.cc",
       "crypto/cipher/aead_test.cc",
       "crypto/cipher/cipher_test.cc",
+      "crypto/cms/cms_test.cc",
       "crypto/compiler_test.cc",
       "crypto/conf/conf_test.cc",
       "crypto/constant_time_test.cc",
@@ -756,6 +767,7 @@
       "crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt",
       "crypto/cipher/test/aes_128_ccm_matter_tests.txt",
       "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt",
+      "crypto/cipher/test/aes_128_eax_test.txt",
       "crypto/cipher/test/aes_128_gcm_randnonce_tests.txt",
       "crypto/cipher/test/aes_128_gcm_siv_tests.txt",
       "crypto/cipher/test/aes_128_gcm_tests.txt",
@@ -763,6 +775,7 @@
       "crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt",
       "crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt",
       "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt",
+      "crypto/cipher/test/aes_256_eax_test.txt",
       "crypto/cipher/test/aes_256_gcm_randnonce_tests.txt",
       "crypto/cipher/test/aes_256_gcm_siv_tests.txt",
       "crypto/cipher/test/aes_256_gcm_tests.txt",
@@ -824,6 +837,15 @@
       "crypto/mlkem/mlkem768_keygen_tests.txt",
       "crypto/mlkem/mlkem768_nist_decap_tests.txt",
       "crypto/mlkem/mlkem768_nist_keygen_tests.txt",
+      "crypto/pkcs7/test/nss.p7c",
+      "crypto/pkcs7/test/openssl_crl.p7c",
+      "crypto/pkcs7/test/sign_cert.pem",
+      "crypto/pkcs7/test/sign_key.pem",
+      "crypto/pkcs7/test/sign_sha1.p7s",
+      "crypto/pkcs7/test/sign_sha1_key_id.p7s",
+      "crypto/pkcs7/test/sign_sha256.p7s",
+      "crypto/pkcs7/test/sign_sha256_key_id.p7s",
+      "crypto/pkcs7/test/windows.p7c",
       "crypto/pkcs8/test/bad1.p12",
       "crypto/pkcs8/test/bad2.p12",
       "crypto/pkcs8/test/bad3.p12",
@@ -932,6 +954,7 @@
       "crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
       "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
       "third_party/wycheproof_testvectors/aes_cmac_test.txt",
+      "third_party/wycheproof_testvectors/aes_eax_test.txt",
       "third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
       "third_party/wycheproof_testvectors/aes_gcm_test.txt",
       "third_party/wycheproof_testvectors/chacha20_poly1305_test.txt",
@@ -1052,6 +1075,7 @@
       "fuzz/bn_mod_exp.cc",
       "fuzz/cert.cc",
       "fuzz/client.cc",
+      "fuzz/client_no_fuzzer_mode.cc",
       "fuzz/conf.cc",
       "fuzz/crl_getcrlstatusforcert_fuzzer.cc",
       "fuzz/crl_parse_crl_certificatelist_fuzzer.cc",
@@ -1073,6 +1097,7 @@
       "fuzz/privkey.cc",
       "fuzz/read_pem.cc",
       "fuzz/server.cc",
+      "fuzz/server_no_fuzzer_mode.cc",
       "fuzz/session.cc",
       "fuzz/spki.cc",
       "fuzz/ssl_ctx_api.cc",
@@ -1081,6 +1106,15 @@
       "fuzz/verify_name_match_verifynameinsubtree_fuzzer.cc"
     ]
   },
+  "modulewrapper": {
+    "srcs": [
+      "util/fipstools/acvp/modulewrapper/main.cc",
+      "util/fipstools/acvp/modulewrapper/modulewrapper.cc"
+    ],
+    "internal_hdrs": [
+      "util/fipstools/acvp/modulewrapper/modulewrapper.h"
+    ]
+  },
   "pki": {
     "srcs": [
       "pki/cert_error_id.cc",
@@ -2178,6 +2212,18 @@
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test",
@@ -2186,6 +2232,14 @@
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test",
       "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test",
@@ -2402,6 +2456,7 @@
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test",
@@ -2416,6 +2471,7 @@
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test",
@@ -2424,6 +2480,7 @@
       "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test",
+      "pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test",
       "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test",
       "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem",
diff --git a/src/gen/sources.mk b/src/gen/sources.mk
new file mode 100644
index 0000000..b6888fa
--- /dev/null
+++ b/src/gen/sources.mk
@@ -0,0 +1,2806 @@
+# Copyright 2024 The BoringSSL Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Generated by go ./util/pregenerate. Do not edit manually.
+
+boringssl_bcm_sources := \
+  crypto/fipsmodule/bcm.cc
+
+boringssl_bcm_internal_headers := \
+  crypto/fipsmodule/aes/aes.cc.inc \
+  crypto/fipsmodule/aes/aes_nohw.cc.inc \
+  crypto/fipsmodule/aes/cbc.cc.inc \
+  crypto/fipsmodule/aes/cfb.cc.inc \
+  crypto/fipsmodule/aes/ctr.cc.inc \
+  crypto/fipsmodule/aes/gcm.cc.inc \
+  crypto/fipsmodule/aes/gcm_nohw.cc.inc \
+  crypto/fipsmodule/aes/key_wrap.cc.inc \
+  crypto/fipsmodule/aes/mode_wrappers.cc.inc \
+  crypto/fipsmodule/aes/ofb.cc.inc \
+  crypto/fipsmodule/bn/add.cc.inc \
+  crypto/fipsmodule/bn/asm/x86_64-gcc.cc.inc \
+  crypto/fipsmodule/bn/bn.cc.inc \
+  crypto/fipsmodule/bn/bytes.cc.inc \
+  crypto/fipsmodule/bn/cmp.cc.inc \
+  crypto/fipsmodule/bn/ctx.cc.inc \
+  crypto/fipsmodule/bn/div.cc.inc \
+  crypto/fipsmodule/bn/div_extra.cc.inc \
+  crypto/fipsmodule/bn/exponentiation.cc.inc \
+  crypto/fipsmodule/bn/gcd.cc.inc \
+  crypto/fipsmodule/bn/gcd_extra.cc.inc \
+  crypto/fipsmodule/bn/generic.cc.inc \
+  crypto/fipsmodule/bn/jacobi.cc.inc \
+  crypto/fipsmodule/bn/montgomery.cc.inc \
+  crypto/fipsmodule/bn/montgomery_inv.cc.inc \
+  crypto/fipsmodule/bn/mul.cc.inc \
+  crypto/fipsmodule/bn/prime.cc.inc \
+  crypto/fipsmodule/bn/random.cc.inc \
+  crypto/fipsmodule/bn/rsaz_exp.cc.inc \
+  crypto/fipsmodule/bn/shift.cc.inc \
+  crypto/fipsmodule/bn/sqrt.cc.inc \
+  crypto/fipsmodule/cipher/aead.cc.inc \
+  crypto/fipsmodule/cipher/cipher.cc.inc \
+  crypto/fipsmodule/cipher/e_aes.cc.inc \
+  crypto/fipsmodule/cipher/e_aesccm.cc.inc \
+  crypto/fipsmodule/cmac/cmac.cc.inc \
+  crypto/fipsmodule/dh/check.cc.inc \
+  crypto/fipsmodule/dh/dh.cc.inc \
+  crypto/fipsmodule/digest/digest.cc.inc \
+  crypto/fipsmodule/digest/digests.cc.inc \
+  crypto/fipsmodule/digestsign/digestsign.cc.inc \
+  crypto/fipsmodule/ec/ec.cc.inc \
+  crypto/fipsmodule/ec/ec_key.cc.inc \
+  crypto/fipsmodule/ec/ec_montgomery.cc.inc \
+  crypto/fipsmodule/ec/felem.cc.inc \
+  crypto/fipsmodule/ec/oct.cc.inc \
+  crypto/fipsmodule/ec/p224-64.cc.inc \
+  crypto/fipsmodule/ec/p256-nistz.cc.inc \
+  crypto/fipsmodule/ec/p256.cc.inc \
+  crypto/fipsmodule/ec/scalar.cc.inc \
+  crypto/fipsmodule/ec/simple.cc.inc \
+  crypto/fipsmodule/ec/simple_mul.cc.inc \
+  crypto/fipsmodule/ec/util.cc.inc \
+  crypto/fipsmodule/ec/wnaf.cc.inc \
+  crypto/fipsmodule/ecdh/ecdh.cc.inc \
+  crypto/fipsmodule/ecdsa/ecdsa.cc.inc \
+  crypto/fipsmodule/hkdf/hkdf.cc.inc \
+  crypto/fipsmodule/hmac/hmac.cc.inc \
+  crypto/fipsmodule/keccak/keccak.cc.inc \
+  crypto/fipsmodule/mldsa/fips_known_values.inc \
+  crypto/fipsmodule/mldsa/mldsa.cc.inc \
+  crypto/fipsmodule/mlkem/fips_known_values.inc \
+  crypto/fipsmodule/mlkem/mlkem.cc.inc \
+  crypto/fipsmodule/rand/ctrdrbg.cc.inc \
+  crypto/fipsmodule/rand/rand.cc.inc \
+  crypto/fipsmodule/rsa/blinding.cc.inc \
+  crypto/fipsmodule/rsa/padding.cc.inc \
+  crypto/fipsmodule/rsa/rsa.cc.inc \
+  crypto/fipsmodule/rsa/rsa_impl.cc.inc \
+  crypto/fipsmodule/self_check/fips.cc.inc \
+  crypto/fipsmodule/self_check/self_check.cc.inc \
+  crypto/fipsmodule/service_indicator/service_indicator.cc.inc \
+  crypto/fipsmodule/sha/sha1.cc.inc \
+  crypto/fipsmodule/sha/sha256.cc.inc \
+  crypto/fipsmodule/sha/sha512.cc.inc \
+  crypto/fipsmodule/slhdsa/fips_known_values.inc \
+  crypto/fipsmodule/slhdsa/fors.cc.inc \
+  crypto/fipsmodule/slhdsa/merkle.cc.inc \
+  crypto/fipsmodule/slhdsa/slhdsa.cc.inc \
+  crypto/fipsmodule/slhdsa/thash.cc.inc \
+  crypto/fipsmodule/slhdsa/wots.cc.inc \
+  crypto/fipsmodule/tls/kdf.cc.inc
+
+boringssl_bcm_sources_asm := \
+  gen/bcm/aes-gcm-avx2-x86_64-apple.S \
+  gen/bcm/aes-gcm-avx2-x86_64-linux.S \
+  gen/bcm/aes-gcm-avx512-x86_64-apple.S \
+  gen/bcm/aes-gcm-avx512-x86_64-linux.S \
+  gen/bcm/aesni-gcm-x86_64-apple.S \
+  gen/bcm/aesni-gcm-x86_64-linux.S \
+  gen/bcm/aesni-x86-apple.S \
+  gen/bcm/aesni-x86-linux.S \
+  gen/bcm/aesni-x86_64-apple.S \
+  gen/bcm/aesni-x86_64-linux.S \
+  gen/bcm/aesv8-armv7-linux.S \
+  gen/bcm/aesv8-armv8-apple.S \
+  gen/bcm/aesv8-armv8-linux.S \
+  gen/bcm/aesv8-armv8-win.S \
+  gen/bcm/aesv8-gcm-armv8-apple.S \
+  gen/bcm/aesv8-gcm-armv8-linux.S \
+  gen/bcm/aesv8-gcm-armv8-win.S \
+  gen/bcm/armv4-mont-linux.S \
+  gen/bcm/armv8-mont-apple.S \
+  gen/bcm/armv8-mont-linux.S \
+  gen/bcm/armv8-mont-win.S \
+  gen/bcm/bn-586-apple.S \
+  gen/bcm/bn-586-linux.S \
+  gen/bcm/bn-armv8-apple.S \
+  gen/bcm/bn-armv8-linux.S \
+  gen/bcm/bn-armv8-win.S \
+  gen/bcm/bsaes-armv7-linux.S \
+  gen/bcm/co-586-apple.S \
+  gen/bcm/co-586-linux.S \
+  gen/bcm/ghash-armv4-linux.S \
+  gen/bcm/ghash-neon-armv8-apple.S \
+  gen/bcm/ghash-neon-armv8-linux.S \
+  gen/bcm/ghash-neon-armv8-win.S \
+  gen/bcm/ghash-ssse3-x86-apple.S \
+  gen/bcm/ghash-ssse3-x86-linux.S \
+  gen/bcm/ghash-ssse3-x86_64-apple.S \
+  gen/bcm/ghash-ssse3-x86_64-linux.S \
+  gen/bcm/ghash-x86-apple.S \
+  gen/bcm/ghash-x86-linux.S \
+  gen/bcm/ghash-x86_64-apple.S \
+  gen/bcm/ghash-x86_64-linux.S \
+  gen/bcm/ghashv8-armv7-linux.S \
+  gen/bcm/ghashv8-armv8-apple.S \
+  gen/bcm/ghashv8-armv8-linux.S \
+  gen/bcm/ghashv8-armv8-win.S \
+  gen/bcm/p256-armv8-asm-apple.S \
+  gen/bcm/p256-armv8-asm-linux.S \
+  gen/bcm/p256-armv8-asm-win.S \
+  gen/bcm/p256-x86_64-asm-apple.S \
+  gen/bcm/p256-x86_64-asm-linux.S \
+  gen/bcm/p256_beeu-armv8-asm-apple.S \
+  gen/bcm/p256_beeu-armv8-asm-linux.S \
+  gen/bcm/p256_beeu-armv8-asm-win.S \
+  gen/bcm/p256_beeu-x86_64-asm-apple.S \
+  gen/bcm/p256_beeu-x86_64-asm-linux.S \
+  gen/bcm/rdrand-x86_64-apple.S \
+  gen/bcm/rdrand-x86_64-linux.S \
+  gen/bcm/rsaz-avx2-apple.S \
+  gen/bcm/rsaz-avx2-linux.S \
+  gen/bcm/sha1-586-apple.S \
+  gen/bcm/sha1-586-linux.S \
+  gen/bcm/sha1-armv4-large-linux.S \
+  gen/bcm/sha1-armv8-apple.S \
+  gen/bcm/sha1-armv8-linux.S \
+  gen/bcm/sha1-armv8-win.S \
+  gen/bcm/sha1-x86_64-apple.S \
+  gen/bcm/sha1-x86_64-linux.S \
+  gen/bcm/sha256-586-apple.S \
+  gen/bcm/sha256-586-linux.S \
+  gen/bcm/sha256-armv4-linux.S \
+  gen/bcm/sha256-armv8-apple.S \
+  gen/bcm/sha256-armv8-linux.S \
+  gen/bcm/sha256-armv8-win.S \
+  gen/bcm/sha256-x86_64-apple.S \
+  gen/bcm/sha256-x86_64-linux.S \
+  gen/bcm/sha512-586-apple.S \
+  gen/bcm/sha512-586-linux.S \
+  gen/bcm/sha512-armv4-linux.S \
+  gen/bcm/sha512-armv8-apple.S \
+  gen/bcm/sha512-armv8-linux.S \
+  gen/bcm/sha512-armv8-win.S \
+  gen/bcm/sha512-x86_64-apple.S \
+  gen/bcm/sha512-x86_64-linux.S \
+  gen/bcm/vpaes-armv7-linux.S \
+  gen/bcm/vpaes-armv8-apple.S \
+  gen/bcm/vpaes-armv8-linux.S \
+  gen/bcm/vpaes-armv8-win.S \
+  gen/bcm/vpaes-x86-apple.S \
+  gen/bcm/vpaes-x86-linux.S \
+  gen/bcm/vpaes-x86_64-apple.S \
+  gen/bcm/vpaes-x86_64-linux.S \
+  gen/bcm/x86-mont-apple.S \
+  gen/bcm/x86-mont-linux.S \
+  gen/bcm/x86_64-mont-apple.S \
+  gen/bcm/x86_64-mont-linux.S \
+  gen/bcm/x86_64-mont5-apple.S \
+  gen/bcm/x86_64-mont5-linux.S \
+  third_party/fiat/asm/fiat_p256_adx_mul.S \
+  third_party/fiat/asm/fiat_p256_adx_sqr.S
+
+boringssl_bcm_sources_nasm := \
+  gen/bcm/aes-gcm-avx2-x86_64-win.asm \
+  gen/bcm/aes-gcm-avx512-x86_64-win.asm \
+  gen/bcm/aesni-gcm-x86_64-win.asm \
+  gen/bcm/aesni-x86-win.asm \
+  gen/bcm/aesni-x86_64-win.asm \
+  gen/bcm/bn-586-win.asm \
+  gen/bcm/co-586-win.asm \
+  gen/bcm/ghash-ssse3-x86-win.asm \
+  gen/bcm/ghash-ssse3-x86_64-win.asm \
+  gen/bcm/ghash-x86-win.asm \
+  gen/bcm/ghash-x86_64-win.asm \
+  gen/bcm/p256-x86_64-asm-win.asm \
+  gen/bcm/p256_beeu-x86_64-asm-win.asm \
+  gen/bcm/rdrand-x86_64-win.asm \
+  gen/bcm/rsaz-avx2-win.asm \
+  gen/bcm/sha1-586-win.asm \
+  gen/bcm/sha1-x86_64-win.asm \
+  gen/bcm/sha256-586-win.asm \
+  gen/bcm/sha256-x86_64-win.asm \
+  gen/bcm/sha512-586-win.asm \
+  gen/bcm/sha512-x86_64-win.asm \
+  gen/bcm/vpaes-x86-win.asm \
+  gen/bcm/vpaes-x86_64-win.asm \
+  gen/bcm/x86-mont-win.asm \
+  gen/bcm/x86_64-mont-win.asm \
+  gen/bcm/x86_64-mont5-win.asm
+
+boringssl_bssl_sources := \
+  tool/args.cc \
+  tool/ciphers.cc \
+  tool/client.cc \
+  tool/const.cc \
+  tool/digest.cc \
+  tool/fd.cc \
+  tool/file.cc \
+  tool/generate_ech.cc \
+  tool/generate_ed25519.cc \
+  tool/genrsa.cc \
+  tool/pkcs12.cc \
+  tool/rand.cc \
+  tool/server.cc \
+  tool/sign.cc \
+  tool/speed.cc \
+  tool/tool.cc \
+  tool/transport_common.cc
+
+boringssl_bssl_internal_headers := \
+  tool/internal.h \
+  tool/transport_common.h
+
+boringssl_crypto_sources := \
+  crypto/aes/aes.cc \
+  crypto/asn1/a_bitstr.cc \
+  crypto/asn1/a_bool.cc \
+  crypto/asn1/a_d2i_fp.cc \
+  crypto/asn1/a_dup.cc \
+  crypto/asn1/a_gentm.cc \
+  crypto/asn1/a_i2d_fp.cc \
+  crypto/asn1/a_int.cc \
+  crypto/asn1/a_mbstr.cc \
+  crypto/asn1/a_object.cc \
+  crypto/asn1/a_octet.cc \
+  crypto/asn1/a_strex.cc \
+  crypto/asn1/a_strnid.cc \
+  crypto/asn1/a_time.cc \
+  crypto/asn1/a_type.cc \
+  crypto/asn1/a_utctm.cc \
+  crypto/asn1/asn1_lib.cc \
+  crypto/asn1/asn1_par.cc \
+  crypto/asn1/asn_pack.cc \
+  crypto/asn1/f_int.cc \
+  crypto/asn1/f_string.cc \
+  crypto/asn1/posix_time.cc \
+  crypto/asn1/tasn_dec.cc \
+  crypto/asn1/tasn_enc.cc \
+  crypto/asn1/tasn_fre.cc \
+  crypto/asn1/tasn_new.cc \
+  crypto/asn1/tasn_typ.cc \
+  crypto/asn1/tasn_utl.cc \
+  crypto/base64/base64.cc \
+  crypto/bio/bio.cc \
+  crypto/bio/bio_mem.cc \
+  crypto/bio/connect.cc \
+  crypto/bio/errno.cc \
+  crypto/bio/fd.cc \
+  crypto/bio/file.cc \
+  crypto/bio/hexdump.cc \
+  crypto/bio/pair.cc \
+  crypto/bio/printf.cc \
+  crypto/bio/socket.cc \
+  crypto/bio/socket_helper.cc \
+  crypto/blake2/blake2.cc \
+  crypto/bn/bn_asn1.cc \
+  crypto/bn/convert.cc \
+  crypto/bn/div.cc \
+  crypto/bn/exponentiation.cc \
+  crypto/bn/sqrt.cc \
+  crypto/buf/buf.cc \
+  crypto/bytestring/asn1_compat.cc \
+  crypto/bytestring/ber.cc \
+  crypto/bytestring/cbb.cc \
+  crypto/bytestring/cbs.cc \
+  crypto/bytestring/unicode.cc \
+  crypto/chacha/chacha.cc \
+  crypto/cipher/derive_key.cc \
+  crypto/cipher/e_aesctrhmac.cc \
+  crypto/cipher/e_aeseax.cc \
+  crypto/cipher/e_aesgcmsiv.cc \
+  crypto/cipher/e_chacha20poly1305.cc \
+  crypto/cipher/e_des.cc \
+  crypto/cipher/e_null.cc \
+  crypto/cipher/e_rc2.cc \
+  crypto/cipher/e_rc4.cc \
+  crypto/cipher/e_tls.cc \
+  crypto/cipher/get_cipher.cc \
+  crypto/cipher/tls_cbc.cc \
+  crypto/cms/cms.cc \
+  crypto/conf/conf.cc \
+  crypto/cpu_aarch64_apple.cc \
+  crypto/cpu_aarch64_fuchsia.cc \
+  crypto/cpu_aarch64_linux.cc \
+  crypto/cpu_aarch64_openbsd.cc \
+  crypto/cpu_aarch64_sysreg.cc \
+  crypto/cpu_aarch64_win.cc \
+  crypto/cpu_arm_freebsd.cc \
+  crypto/cpu_arm_linux.cc \
+  crypto/cpu_intel.cc \
+  crypto/crypto.cc \
+  crypto/curve25519/curve25519.cc \
+  crypto/curve25519/curve25519_64_adx.cc \
+  crypto/curve25519/spake25519.cc \
+  crypto/des/des.cc \
+  crypto/dh/dh_asn1.cc \
+  crypto/dh/params.cc \
+  crypto/digest/digest_extra.cc \
+  crypto/dsa/dsa.cc \
+  crypto/dsa/dsa_asn1.cc \
+  crypto/ec/ec_asn1.cc \
+  crypto/ec/ec_derive.cc \
+  crypto/ec/hash_to_curve.cc \
+  crypto/ecdh/ecdh.cc \
+  crypto/ecdsa/ecdsa_asn1.cc \
+  crypto/engine/engine.cc \
+  crypto/err/err.cc \
+  crypto/evp/evp.cc \
+  crypto/evp/evp_asn1.cc \
+  crypto/evp/evp_ctx.cc \
+  crypto/evp/p_dh.cc \
+  crypto/evp/p_dh_asn1.cc \
+  crypto/evp/p_dsa_asn1.cc \
+  crypto/evp/p_ec.cc \
+  crypto/evp/p_ec_asn1.cc \
+  crypto/evp/p_ed25519.cc \
+  crypto/evp/p_ed25519_asn1.cc \
+  crypto/evp/p_hkdf.cc \
+  crypto/evp/p_rsa.cc \
+  crypto/evp/p_rsa_asn1.cc \
+  crypto/evp/p_x25519.cc \
+  crypto/evp/p_x25519_asn1.cc \
+  crypto/evp/pbkdf.cc \
+  crypto/evp/print.cc \
+  crypto/evp/scrypt.cc \
+  crypto/evp/sign.cc \
+  crypto/ex_data.cc \
+  crypto/fipsmodule/fips_shared_support.cc \
+  crypto/fuzzer_mode.cc \
+  crypto/hpke/hpke.cc \
+  crypto/hrss/hrss.cc \
+  crypto/kyber/kyber.cc \
+  crypto/lhash/lhash.cc \
+  crypto/md4/md4.cc \
+  crypto/md5/md5.cc \
+  crypto/mem.cc \
+  crypto/mldsa/mldsa.cc \
+  crypto/mlkem/mlkem.cc \
+  crypto/obj/obj.cc \
+  crypto/obj/obj_xref.cc \
+  crypto/pem/pem_all.cc \
+  crypto/pem/pem_info.cc \
+  crypto/pem/pem_lib.cc \
+  crypto/pem/pem_oth.cc \
+  crypto/pem/pem_pk8.cc \
+  crypto/pem/pem_pkey.cc \
+  crypto/pem/pem_x509.cc \
+  crypto/pem/pem_xaux.cc \
+  crypto/pkcs7/pkcs7.cc \
+  crypto/pkcs7/pkcs7_x509.cc \
+  crypto/pkcs8/p5_pbev2.cc \
+  crypto/pkcs8/pkcs8.cc \
+  crypto/pkcs8/pkcs8_x509.cc \
+  crypto/poly1305/poly1305.cc \
+  crypto/poly1305/poly1305_arm.cc \
+  crypto/poly1305/poly1305_vec.cc \
+  crypto/pool/pool.cc \
+  crypto/rand/deterministic.cc \
+  crypto/rand/fork_detect.cc \
+  crypto/rand/forkunsafe.cc \
+  crypto/rand/getentropy.cc \
+  crypto/rand/ios.cc \
+  crypto/rand/passive.cc \
+  crypto/rand/rand.cc \
+  crypto/rand/trusty.cc \
+  crypto/rand/urandom.cc \
+  crypto/rand/windows.cc \
+  crypto/rc4/rc4.cc \
+  crypto/refcount.cc \
+  crypto/rsa/rsa_asn1.cc \
+  crypto/rsa/rsa_crypt.cc \
+  crypto/rsa/rsa_extra.cc \
+  crypto/rsa/rsa_print.cc \
+  crypto/sha/sha1.cc \
+  crypto/sha/sha256.cc \
+  crypto/sha/sha512.cc \
+  crypto/siphash/siphash.cc \
+  crypto/slhdsa/slhdsa.cc \
+  crypto/spake2plus/spake2plus.cc \
+  crypto/stack/stack.cc \
+  crypto/thread.cc \
+  crypto/thread_none.cc \
+  crypto/thread_pthread.cc \
+  crypto/thread_win.cc \
+  crypto/trust_token/pmbtoken.cc \
+  crypto/trust_token/trust_token.cc \
+  crypto/trust_token/voprf.cc \
+  crypto/x509/a_digest.cc \
+  crypto/x509/a_sign.cc \
+  crypto/x509/a_verify.cc \
+  crypto/x509/algorithm.cc \
+  crypto/x509/asn1_gen.cc \
+  crypto/x509/by_dir.cc \
+  crypto/x509/by_file.cc \
+  crypto/x509/i2d_pr.cc \
+  crypto/x509/name_print.cc \
+  crypto/x509/policy.cc \
+  crypto/x509/rsa_pss.cc \
+  crypto/x509/t_crl.cc \
+  crypto/x509/t_req.cc \
+  crypto/x509/t_x509.cc \
+  crypto/x509/t_x509a.cc \
+  crypto/x509/v3_akey.cc \
+  crypto/x509/v3_akeya.cc \
+  crypto/x509/v3_alt.cc \
+  crypto/x509/v3_bcons.cc \
+  crypto/x509/v3_bitst.cc \
+  crypto/x509/v3_conf.cc \
+  crypto/x509/v3_cpols.cc \
+  crypto/x509/v3_crld.cc \
+  crypto/x509/v3_enum.cc \
+  crypto/x509/v3_extku.cc \
+  crypto/x509/v3_genn.cc \
+  crypto/x509/v3_ia5.cc \
+  crypto/x509/v3_info.cc \
+  crypto/x509/v3_int.cc \
+  crypto/x509/v3_lib.cc \
+  crypto/x509/v3_ncons.cc \
+  crypto/x509/v3_ocsp.cc \
+  crypto/x509/v3_pcons.cc \
+  crypto/x509/v3_pmaps.cc \
+  crypto/x509/v3_prn.cc \
+  crypto/x509/v3_purp.cc \
+  crypto/x509/v3_skey.cc \
+  crypto/x509/v3_utl.cc \
+  crypto/x509/x509.cc \
+  crypto/x509/x509_att.cc \
+  crypto/x509/x509_cmp.cc \
+  crypto/x509/x509_d2.cc \
+  crypto/x509/x509_def.cc \
+  crypto/x509/x509_ext.cc \
+  crypto/x509/x509_lu.cc \
+  crypto/x509/x509_obj.cc \
+  crypto/x509/x509_req.cc \
+  crypto/x509/x509_set.cc \
+  crypto/x509/x509_trs.cc \
+  crypto/x509/x509_txt.cc \
+  crypto/x509/x509_v3.cc \
+  crypto/x509/x509_vfy.cc \
+  crypto/x509/x509_vpm.cc \
+  crypto/x509/x509cset.cc \
+  crypto/x509/x509name.cc \
+  crypto/x509/x509rset.cc \
+  crypto/x509/x509spki.cc \
+  crypto/x509/x_algor.cc \
+  crypto/x509/x_all.cc \
+  crypto/x509/x_attrib.cc \
+  crypto/x509/x_crl.cc \
+  crypto/x509/x_exten.cc \
+  crypto/x509/x_name.cc \
+  crypto/x509/x_pubkey.cc \
+  crypto/x509/x_req.cc \
+  crypto/x509/x_sig.cc \
+  crypto/x509/x_spki.cc \
+  crypto/x509/x_val.cc \
+  crypto/x509/x_x509.cc \
+  crypto/x509/x_x509a.cc \
+  gen/crypto/err_data.cc
+
+boringssl_crypto_headers := \
+  include/openssl/aead.h \
+  include/openssl/aes.h \
+  include/openssl/arm_arch.h \
+  include/openssl/asm_base.h \
+  include/openssl/asn1.h \
+  include/openssl/asn1_mac.h \
+  include/openssl/asn1t.h \
+  include/openssl/base.h \
+  include/openssl/base64.h \
+  include/openssl/bcm_public.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/cms.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/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/experimental/kyber.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/mldsa.h \
+  include/openssl/mlkem.h \
+  include/openssl/nid.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/posix_time.h \
+  include/openssl/rand.h \
+  include/openssl/rc4.h \
+  include/openssl/ripemd.h \
+  include/openssl/rsa.h \
+  include/openssl/safestack.h \
+  include/openssl/service_indicator.h \
+  include/openssl/sha.h \
+  include/openssl/siphash.h \
+  include/openssl/slhdsa.h \
+  include/openssl/span.h \
+  include/openssl/stack.h \
+  include/openssl/target.h \
+  include/openssl/thread.h \
+  include/openssl/time.h \
+  include/openssl/trust_token.h \
+  include/openssl/type_check.h \
+  include/openssl/x509.h \
+  include/openssl/x509_vfy.h \
+  include/openssl/x509v3.h \
+  include/openssl/x509v3_errors.h
+
+boringssl_crypto_internal_headers := \
+  crypto/asn1/internal.h \
+  crypto/bcm_support.h \
+  crypto/bio/internal.h \
+  crypto/bytestring/internal.h \
+  crypto/chacha/internal.h \
+  crypto/cipher/internal.h \
+  crypto/conf/internal.h \
+  crypto/cpu_arm_linux.h \
+  crypto/curve25519/curve25519_tables.h \
+  crypto/curve25519/internal.h \
+  crypto/des/internal.h \
+  crypto/dsa/internal.h \
+  crypto/ec/internal.h \
+  crypto/err/internal.h \
+  crypto/evp/internal.h \
+  crypto/fipsmodule/aes/internal.h \
+  crypto/fipsmodule/bcm_interface.h \
+  crypto/fipsmodule/bn/internal.h \
+  crypto/fipsmodule/bn/rsaz_exp.h \
+  crypto/fipsmodule/cipher/internal.h \
+  crypto/fipsmodule/delocate.h \
+  crypto/fipsmodule/dh/internal.h \
+  crypto/fipsmodule/digest/internal.h \
+  crypto/fipsmodule/digest/md32_common.h \
+  crypto/fipsmodule/ec/builtin_curves.h \
+  crypto/fipsmodule/ec/internal.h \
+  crypto/fipsmodule/ec/p256-nistz-table.h \
+  crypto/fipsmodule/ec/p256-nistz.h \
+  crypto/fipsmodule/ec/p256_table.h \
+  crypto/fipsmodule/ecdsa/internal.h \
+  crypto/fipsmodule/keccak/internal.h \
+  crypto/fipsmodule/rand/internal.h \
+  crypto/fipsmodule/rsa/internal.h \
+  crypto/fipsmodule/service_indicator/internal.h \
+  crypto/fipsmodule/sha/internal.h \
+  crypto/fipsmodule/slhdsa/address.h \
+  crypto/fipsmodule/slhdsa/fors.h \
+  crypto/fipsmodule/slhdsa/merkle.h \
+  crypto/fipsmodule/slhdsa/params.h \
+  crypto/fipsmodule/slhdsa/thash.h \
+  crypto/fipsmodule/slhdsa/wots.h \
+  crypto/fipsmodule/tls/internal.h \
+  crypto/hrss/internal.h \
+  crypto/internal.h \
+  crypto/kyber/internal.h \
+  crypto/lhash/internal.h \
+  crypto/md5/internal.h \
+  crypto/obj/obj_dat.h \
+  crypto/pem/internal.h \
+  crypto/pkcs7/internal.h \
+  crypto/pkcs8/internal.h \
+  crypto/poly1305/internal.h \
+  crypto/pool/internal.h \
+  crypto/rand/getrandom_fillin.h \
+  crypto/rand/internal.h \
+  crypto/rsa/internal.h \
+  crypto/spake2plus/internal.h \
+  crypto/trust_token/internal.h \
+  crypto/x509/ext_dat.h \
+  crypto/x509/internal.h \
+  third_party/fiat/curve25519_32.h \
+  third_party/fiat/curve25519_64.h \
+  third_party/fiat/curve25519_64_adx.h \
+  third_party/fiat/curve25519_64_msvc.h \
+  third_party/fiat/p256_32.h \
+  third_party/fiat/p256_64.h \
+  third_party/fiat/p256_64_msvc.h
+
+boringssl_crypto_sources_asm := \
+  crypto/curve25519/asm/x25519-asm-arm.S \
+  crypto/hrss/asm/poly_rq_mul.S \
+  crypto/poly1305/poly1305_arm_asm.S \
+  gen/crypto/aes128gcmsiv-x86_64-apple.S \
+  gen/crypto/aes128gcmsiv-x86_64-linux.S \
+  gen/crypto/chacha-armv4-linux.S \
+  gen/crypto/chacha-armv8-apple.S \
+  gen/crypto/chacha-armv8-linux.S \
+  gen/crypto/chacha-armv8-win.S \
+  gen/crypto/chacha-x86-apple.S \
+  gen/crypto/chacha-x86-linux.S \
+  gen/crypto/chacha-x86_64-apple.S \
+  gen/crypto/chacha-x86_64-linux.S \
+  gen/crypto/chacha20_poly1305_armv8-apple.S \
+  gen/crypto/chacha20_poly1305_armv8-linux.S \
+  gen/crypto/chacha20_poly1305_armv8-win.S \
+  gen/crypto/chacha20_poly1305_x86_64-apple.S \
+  gen/crypto/chacha20_poly1305_x86_64-linux.S \
+  gen/crypto/md5-586-apple.S \
+  gen/crypto/md5-586-linux.S \
+  gen/crypto/md5-x86_64-apple.S \
+  gen/crypto/md5-x86_64-linux.S \
+  third_party/fiat/asm/fiat_curve25519_adx_mul.S \
+  third_party/fiat/asm/fiat_curve25519_adx_square.S
+
+boringssl_crypto_sources_nasm := \
+  gen/crypto/aes128gcmsiv-x86_64-win.asm \
+  gen/crypto/chacha-x86-win.asm \
+  gen/crypto/chacha-x86_64-win.asm \
+  gen/crypto/chacha20_poly1305_x86_64-win.asm \
+  gen/crypto/md5-586-win.asm \
+  gen/crypto/md5-x86_64-win.asm
+
+boringssl_crypto_test_sources := \
+  crypto/abi_self_test.cc \
+  crypto/asn1/asn1_test.cc \
+  crypto/base64/base64_test.cc \
+  crypto/bio/bio_test.cc \
+  crypto/blake2/blake2_test.cc \
+  crypto/buf/buf_test.cc \
+  crypto/bytestring/bytestring_test.cc \
+  crypto/chacha/chacha_test.cc \
+  crypto/cipher/aead_test.cc \
+  crypto/cipher/cipher_test.cc \
+  crypto/cms/cms_test.cc \
+  crypto/compiler_test.cc \
+  crypto/conf/conf_test.cc \
+  crypto/constant_time_test.cc \
+  crypto/cpu_arm_linux_test.cc \
+  crypto/crypto_test.cc \
+  crypto/curve25519/ed25519_test.cc \
+  crypto/curve25519/spake25519_test.cc \
+  crypto/curve25519/x25519_test.cc \
+  crypto/dh/dh_test.cc \
+  crypto/digest/digest_test.cc \
+  crypto/dsa/dsa_test.cc \
+  crypto/ecdh/ecdh_test.cc \
+  crypto/err/err_test.cc \
+  crypto/evp/evp_extra_test.cc \
+  crypto/evp/evp_test.cc \
+  crypto/evp/pbkdf_test.cc \
+  crypto/evp/scrypt_test.cc \
+  crypto/fipsmodule/aes/aes_test.cc \
+  crypto/fipsmodule/aes/gcm_test.cc \
+  crypto/fipsmodule/bn/bn_test.cc \
+  crypto/fipsmodule/cmac/cmac_test.cc \
+  crypto/fipsmodule/ec/ec_test.cc \
+  crypto/fipsmodule/ec/p256-nistz_test.cc \
+  crypto/fipsmodule/ec/p256_test.cc \
+  crypto/fipsmodule/ecdsa/ecdsa_test.cc \
+  crypto/fipsmodule/hkdf/hkdf_test.cc \
+  crypto/fipsmodule/keccak/keccak_test.cc \
+  crypto/fipsmodule/rand/ctrdrbg_test.cc \
+  crypto/fipsmodule/service_indicator/service_indicator_test.cc \
+  crypto/fipsmodule/sha/sha_test.cc \
+  crypto/hmac/hmac_test.cc \
+  crypto/hpke/hpke_test.cc \
+  crypto/hrss/hrss_test.cc \
+  crypto/impl_dispatch_test.cc \
+  crypto/kyber/kyber_test.cc \
+  crypto/lhash/lhash_test.cc \
+  crypto/md5/md5_test.cc \
+  crypto/mldsa/mldsa_test.cc \
+  crypto/mlkem/mlkem_test.cc \
+  crypto/obj/obj_test.cc \
+  crypto/pem/pem_test.cc \
+  crypto/pkcs7/pkcs7_test.cc \
+  crypto/pkcs8/pkcs12_test.cc \
+  crypto/pkcs8/pkcs8_test.cc \
+  crypto/poly1305/poly1305_test.cc \
+  crypto/pool/pool_test.cc \
+  crypto/rand/fork_detect_test.cc \
+  crypto/rand/getentropy_test.cc \
+  crypto/rand/rand_test.cc \
+  crypto/refcount_test.cc \
+  crypto/rsa/rsa_test.cc \
+  crypto/self_test.cc \
+  crypto/siphash/siphash_test.cc \
+  crypto/slhdsa/slhdsa_test.cc \
+  crypto/spake2plus/spake2plus_test.cc \
+  crypto/stack/stack_test.cc \
+  crypto/test/gtest_main.cc \
+  crypto/thread_test.cc \
+  crypto/trust_token/trust_token_test.cc \
+  crypto/x509/tab_test.cc \
+  crypto/x509/x509_test.cc \
+  crypto/x509/x509_time_test.cc
+
+boringssl_crypto_test_data := \
+  crypto/blake2/blake2b256_tests.txt \
+  crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt \
+  crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt \
+  crypto/cipher/test/aes_128_ccm_bluetooth_8_tests.txt \
+  crypto/cipher/test/aes_128_ccm_bluetooth_tests.txt \
+  crypto/cipher/test/aes_128_ccm_matter_tests.txt \
+  crypto/cipher/test/aes_128_ctr_hmac_sha256.txt \
+  crypto/cipher/test/aes_128_eax_test.txt \
+  crypto/cipher/test/aes_128_gcm_randnonce_tests.txt \
+  crypto/cipher/test/aes_128_gcm_siv_tests.txt \
+  crypto/cipher/test/aes_128_gcm_tests.txt \
+  crypto/cipher/test/aes_192_gcm_tests.txt \
+  crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt \
+  crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt \
+  crypto/cipher/test/aes_256_ctr_hmac_sha256.txt \
+  crypto/cipher/test/aes_256_eax_test.txt \
+  crypto/cipher/test/aes_256_gcm_randnonce_tests.txt \
+  crypto/cipher/test/aes_256_gcm_siv_tests.txt \
+  crypto/cipher/test/aes_256_gcm_tests.txt \
+  crypto/cipher/test/chacha20_poly1305_tests.txt \
+  crypto/cipher/test/cipher_tests.txt \
+  crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt \
+  crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt \
+  crypto/cipher/test/nist_cavp/aes_128_cbc.txt \
+  crypto/cipher/test/nist_cavp/aes_128_ctr.txt \
+  crypto/cipher/test/nist_cavp/aes_128_gcm.txt \
+  crypto/cipher/test/nist_cavp/aes_192_cbc.txt \
+  crypto/cipher/test/nist_cavp/aes_192_ctr.txt \
+  crypto/cipher/test/nist_cavp/aes_256_cbc.txt \
+  crypto/cipher/test/nist_cavp/aes_256_ctr.txt \
+  crypto/cipher/test/nist_cavp/aes_256_gcm.txt \
+  crypto/cipher/test/nist_cavp/tdes_cbc.txt \
+  crypto/cipher/test/nist_cavp/tdes_ecb.txt \
+  crypto/cipher/test/xchacha20_poly1305_tests.txt \
+  crypto/curve25519/ed25519_tests.txt \
+  crypto/ecdh/ecdh_tests.txt \
+  crypto/evp/evp_tests.txt \
+  crypto/evp/scrypt_tests.txt \
+  crypto/fipsmodule/aes/aes_tests.txt \
+  crypto/fipsmodule/bn/test/exp_tests.txt \
+  crypto/fipsmodule/bn/test/gcd_tests.txt \
+  crypto/fipsmodule/bn/test/miller_rabin_tests.txt \
+  crypto/fipsmodule/bn/test/mod_exp_tests.txt \
+  crypto/fipsmodule/bn/test/mod_inv_tests.txt \
+  crypto/fipsmodule/bn/test/mod_mul_tests.txt \
+  crypto/fipsmodule/bn/test/mod_sqrt_tests.txt \
+  crypto/fipsmodule/bn/test/product_tests.txt \
+  crypto/fipsmodule/bn/test/quotient_tests.txt \
+  crypto/fipsmodule/bn/test/shift_tests.txt \
+  crypto/fipsmodule/bn/test/sum_tests.txt \
+  crypto/fipsmodule/cmac/cavp_3des_cmac_tests.txt \
+  crypto/fipsmodule/cmac/cavp_aes128_cmac_tests.txt \
+  crypto/fipsmodule/cmac/cavp_aes192_cmac_tests.txt \
+  crypto/fipsmodule/cmac/cavp_aes256_cmac_tests.txt \
+  crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt \
+  crypto/fipsmodule/ec/p256-nistz_tests.txt \
+  crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt \
+  crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt \
+  crypto/fipsmodule/keccak/keccak_tests.txt \
+  crypto/fipsmodule/rand/ctrdrbg_vectors.txt \
+  crypto/hmac/hmac_tests.txt \
+  crypto/hpke/hpke_test_vectors.txt \
+  crypto/kyber/kyber_tests.txt \
+  crypto/mldsa/mldsa_nist_keygen_65_tests.txt \
+  crypto/mldsa/mldsa_nist_keygen_87_tests.txt \
+  crypto/mldsa/mldsa_nist_siggen_65_tests.txt \
+  crypto/mldsa/mldsa_nist_siggen_87_tests.txt \
+  crypto/mlkem/mlkem1024_decap_tests.txt \
+  crypto/mlkem/mlkem1024_encap_tests.txt \
+  crypto/mlkem/mlkem1024_keygen_tests.txt \
+  crypto/mlkem/mlkem1024_nist_decap_tests.txt \
+  crypto/mlkem/mlkem1024_nist_keygen_tests.txt \
+  crypto/mlkem/mlkem768_decap_tests.txt \
+  crypto/mlkem/mlkem768_encap_tests.txt \
+  crypto/mlkem/mlkem768_keygen_tests.txt \
+  crypto/mlkem/mlkem768_nist_decap_tests.txt \
+  crypto/mlkem/mlkem768_nist_keygen_tests.txt \
+  crypto/pkcs7/test/nss.p7c \
+  crypto/pkcs7/test/openssl_crl.p7c \
+  crypto/pkcs7/test/sign_cert.pem \
+  crypto/pkcs7/test/sign_key.pem \
+  crypto/pkcs7/test/sign_sha1.p7s \
+  crypto/pkcs7/test/sign_sha1_key_id.p7s \
+  crypto/pkcs7/test/sign_sha256.p7s \
+  crypto/pkcs7/test/sign_sha256_key_id.p7s \
+  crypto/pkcs7/test/windows.p7c \
+  crypto/pkcs8/test/bad1.p12 \
+  crypto/pkcs8/test/bad2.p12 \
+  crypto/pkcs8/test/bad3.p12 \
+  crypto/pkcs8/test/empty_password.p12 \
+  crypto/pkcs8/test/empty_password_ber.p12 \
+  crypto/pkcs8/test/empty_password_ber_nested.p12 \
+  crypto/pkcs8/test/no_encryption.p12 \
+  crypto/pkcs8/test/nss.p12 \
+  crypto/pkcs8/test/null_password.p12 \
+  crypto/pkcs8/test/openssl.p12 \
+  crypto/pkcs8/test/pbes2_sha1.p12 \
+  crypto/pkcs8/test/pbes2_sha256.p12 \
+  crypto/pkcs8/test/unicode_password.p12 \
+  crypto/pkcs8/test/windows.p12 \
+  crypto/poly1305/poly1305_tests.txt \
+  crypto/siphash/siphash_tests.txt \
+  crypto/slhdsa/slhdsa_keygen.txt \
+  crypto/slhdsa/slhdsa_prehash.txt \
+  crypto/slhdsa/slhdsa_siggen.txt \
+  crypto/slhdsa/slhdsa_sigver.txt \
+  crypto/x509/test/basic_constraints_ca.pem \
+  crypto/x509/test/basic_constraints_ca_pathlen_0.pem \
+  crypto/x509/test/basic_constraints_ca_pathlen_1.pem \
+  crypto/x509/test/basic_constraints_ca_pathlen_10.pem \
+  crypto/x509/test/basic_constraints_leaf.pem \
+  crypto/x509/test/basic_constraints_none.pem \
+  crypto/x509/test/invalid_extension_intermediate.pem \
+  crypto/x509/test/invalid_extension_intermediate_authority_key_identifier.pem \
+  crypto/x509/test/invalid_extension_intermediate_basic_constraints.pem \
+  crypto/x509/test/invalid_extension_intermediate_ext_key_usage.pem \
+  crypto/x509/test/invalid_extension_intermediate_key_usage.pem \
+  crypto/x509/test/invalid_extension_intermediate_name_constraints.pem \
+  crypto/x509/test/invalid_extension_intermediate_subject_alt_name.pem \
+  crypto/x509/test/invalid_extension_intermediate_subject_key_identifier.pem \
+  crypto/x509/test/invalid_extension_leaf.pem \
+  crypto/x509/test/invalid_extension_leaf_authority_key_identifier.pem \
+  crypto/x509/test/invalid_extension_leaf_basic_constraints.pem \
+  crypto/x509/test/invalid_extension_leaf_ext_key_usage.pem \
+  crypto/x509/test/invalid_extension_leaf_key_usage.pem \
+  crypto/x509/test/invalid_extension_leaf_name_constraints.pem \
+  crypto/x509/test/invalid_extension_leaf_subject_alt_name.pem \
+  crypto/x509/test/invalid_extension_leaf_subject_key_identifier.pem \
+  crypto/x509/test/invalid_extension_root.pem \
+  crypto/x509/test/invalid_extension_root_authority_key_identifier.pem \
+  crypto/x509/test/invalid_extension_root_basic_constraints.pem \
+  crypto/x509/test/invalid_extension_root_ext_key_usage.pem \
+  crypto/x509/test/invalid_extension_root_key_usage.pem \
+  crypto/x509/test/invalid_extension_root_name_constraints.pem \
+  crypto/x509/test/invalid_extension_root_subject_alt_name.pem \
+  crypto/x509/test/invalid_extension_root_subject_key_identifier.pem \
+  crypto/x509/test/many_constraints.pem \
+  crypto/x509/test/many_names1.pem \
+  crypto/x509/test/many_names2.pem \
+  crypto/x509/test/many_names3.pem \
+  crypto/x509/test/policy_intermediate.pem \
+  crypto/x509/test/policy_intermediate_any.pem \
+  crypto/x509/test/policy_intermediate_duplicate.pem \
+  crypto/x509/test/policy_intermediate_invalid.pem \
+  crypto/x509/test/policy_intermediate_mapped.pem \
+  crypto/x509/test/policy_intermediate_mapped_any.pem \
+  crypto/x509/test/policy_intermediate_mapped_oid3.pem \
+  crypto/x509/test/policy_intermediate_require.pem \
+  crypto/x509/test/policy_intermediate_require1.pem \
+  crypto/x509/test/policy_intermediate_require2.pem \
+  crypto/x509/test/policy_intermediate_require_duplicate.pem \
+  crypto/x509/test/policy_intermediate_require_no_policies.pem \
+  crypto/x509/test/policy_leaf.pem \
+  crypto/x509/test/policy_leaf_any.pem \
+  crypto/x509/test/policy_leaf_duplicate.pem \
+  crypto/x509/test/policy_leaf_invalid.pem \
+  crypto/x509/test/policy_leaf_none.pem \
+  crypto/x509/test/policy_leaf_oid1.pem \
+  crypto/x509/test/policy_leaf_oid2.pem \
+  crypto/x509/test/policy_leaf_oid3.pem \
+  crypto/x509/test/policy_leaf_oid4.pem \
+  crypto/x509/test/policy_leaf_oid5.pem \
+  crypto/x509/test/policy_leaf_require.pem \
+  crypto/x509/test/policy_leaf_require1.pem \
+  crypto/x509/test/policy_root.pem \
+  crypto/x509/test/policy_root2.pem \
+  crypto/x509/test/policy_root_cross_inhibit_mapping.pem \
+  crypto/x509/test/pss_sha1.pem \
+  crypto/x509/test/pss_sha1_explicit.pem \
+  crypto/x509/test/pss_sha1_mgf1_syntax_error.pem \
+  crypto/x509/test/pss_sha224.pem \
+  crypto/x509/test/pss_sha256.pem \
+  crypto/x509/test/pss_sha256_explicit_trailer.pem \
+  crypto/x509/test/pss_sha256_mgf1_sha384.pem \
+  crypto/x509/test/pss_sha256_mgf1_syntax_error.pem \
+  crypto/x509/test/pss_sha256_omit_nulls.pem \
+  crypto/x509/test/pss_sha256_salt31.pem \
+  crypto/x509/test/pss_sha256_salt_overflow.pem \
+  crypto/x509/test/pss_sha256_unknown_mgf.pem \
+  crypto/x509/test/pss_sha256_wrong_trailer.pem \
+  crypto/x509/test/pss_sha384.pem \
+  crypto/x509/test/pss_sha512.pem \
+  crypto/x509/test/some_names1.pem \
+  crypto/x509/test/some_names2.pem \
+  crypto/x509/test/some_names3.pem \
+  crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem \
+  crypto/x509/test/trailing_data_leaf_basic_constraints.pem \
+  crypto/x509/test/trailing_data_leaf_ext_key_usage.pem \
+  crypto/x509/test/trailing_data_leaf_key_usage.pem \
+  crypto/x509/test/trailing_data_leaf_name_constraints.pem \
+  crypto/x509/test/trailing_data_leaf_subject_alt_name.pem \
+  crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem \
+  third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt \
+  third_party/wycheproof_testvectors/aes_cmac_test.txt \
+  third_party/wycheproof_testvectors/aes_eax_test.txt \
+  third_party/wycheproof_testvectors/aes_gcm_siv_test.txt \
+  third_party/wycheproof_testvectors/aes_gcm_test.txt \
+  third_party/wycheproof_testvectors/chacha20_poly1305_test.txt \
+  third_party/wycheproof_testvectors/dsa_test.txt \
+  third_party/wycheproof_testvectors/ecdh_secp224r1_test.txt \
+  third_party/wycheproof_testvectors/ecdh_secp256r1_test.txt \
+  third_party/wycheproof_testvectors/ecdh_secp384r1_test.txt \
+  third_party/wycheproof_testvectors/ecdh_secp521r1_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt \
+  third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt \
+  third_party/wycheproof_testvectors/eddsa_test.txt \
+  third_party/wycheproof_testvectors/hkdf_sha1_test.txt \
+  third_party/wycheproof_testvectors/hkdf_sha256_test.txt \
+  third_party/wycheproof_testvectors/hkdf_sha384_test.txt \
+  third_party/wycheproof_testvectors/hkdf_sha512_test.txt \
+  third_party/wycheproof_testvectors/hmac_sha1_test.txt \
+  third_party/wycheproof_testvectors/hmac_sha224_test.txt \
+  third_party/wycheproof_testvectors/hmac_sha256_test.txt \
+  third_party/wycheproof_testvectors/hmac_sha384_test.txt \
+  third_party/wycheproof_testvectors/hmac_sha512_test.txt \
+  third_party/wycheproof_testvectors/kw_test.txt \
+  third_party/wycheproof_testvectors/kwp_test.txt \
+  third_party/wycheproof_testvectors/mldsa_65_standard_sign_test.txt \
+  third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt \
+  third_party/wycheproof_testvectors/mldsa_87_standard_sign_test.txt \
+  third_party/wycheproof_testvectors/mldsa_87_standard_verify_test.txt \
+  third_party/wycheproof_testvectors/primality_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha1_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha224_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha256_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha384_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha256_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha256_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha1_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt \
+  third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt \
+  third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt \
+  third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_32_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_3072_sha256_mgf1_32_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_4096_sha256_mgf1_32_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_4096_sha512_mgf1_32_test.txt \
+  third_party/wycheproof_testvectors/rsa_pss_misc_test.txt \
+  third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt \
+  third_party/wycheproof_testvectors/rsa_signature_test.txt \
+  third_party/wycheproof_testvectors/x25519_test.txt \
+  third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt
+
+boringssl_decrepit_sources := \
+  decrepit/bio/base64_bio.cc \
+  decrepit/blowfish/blowfish.cc \
+  decrepit/cast/cast.cc \
+  decrepit/cast/cast_tables.cc \
+  decrepit/cfb/cfb.cc \
+  decrepit/des/cfb64ede.cc \
+  decrepit/dh/dh_decrepit.cc \
+  decrepit/dsa/dsa_decrepit.cc \
+  decrepit/evp/dss1.cc \
+  decrepit/evp/evp_do_all.cc \
+  decrepit/obj/obj_decrepit.cc \
+  decrepit/rc4/rc4_decrepit.cc \
+  decrepit/ripemd/ripemd.cc \
+  decrepit/rsa/rsa_decrepit.cc \
+  decrepit/ssl/ssl_decrepit.cc \
+  decrepit/x509/x509_decrepit.cc \
+  decrepit/xts/xts.cc
+
+boringssl_decrepit_internal_headers := \
+  decrepit/cast/internal.h \
+  decrepit/macros.h
+
+boringssl_decrepit_test_sources := \
+  crypto/test/gtest_main.cc \
+  decrepit/blowfish/blowfish_test.cc \
+  decrepit/cast/cast_test.cc \
+  decrepit/cfb/cfb_test.cc \
+  decrepit/des/des_test.cc \
+  decrepit/evp/evp_test.cc \
+  decrepit/ripemd/ripemd_test.cc \
+  decrepit/xts/xts_test.cc
+
+boringssl_fuzz_sources := \
+  fuzz/arm_cpuinfo.cc \
+  fuzz/bn_div.cc \
+  fuzz/bn_mod_exp.cc \
+  fuzz/cert.cc \
+  fuzz/client.cc \
+  fuzz/client_no_fuzzer_mode.cc \
+  fuzz/conf.cc \
+  fuzz/crl_getcrlstatusforcert_fuzzer.cc \
+  fuzz/crl_parse_crl_certificatelist_fuzzer.cc \
+  fuzz/crl_parse_crl_tbscertlist_fuzzer.cc \
+  fuzz/crl_parse_issuing_distribution_point_fuzzer.cc \
+  fuzz/decode_client_hello_inner.cc \
+  fuzz/der_roundtrip.cc \
+  fuzz/dtls_client.cc \
+  fuzz/dtls_server.cc \
+  fuzz/ocsp_parse_ocsp_cert_id_fuzzer.cc \
+  fuzz/ocsp_parse_ocsp_response_data_fuzzer.cc \
+  fuzz/ocsp_parse_ocsp_response_fuzzer.cc \
+  fuzz/ocsp_parse_ocsp_single_response_fuzzer.cc \
+  fuzz/parse_authority_key_identifier_fuzzer.cc \
+  fuzz/parse_certificate_fuzzer.cc \
+  fuzz/parse_crldp_fuzzer.cc \
+  fuzz/pkcs12.cc \
+  fuzz/pkcs8.cc \
+  fuzz/privkey.cc \
+  fuzz/read_pem.cc \
+  fuzz/server.cc \
+  fuzz/server_no_fuzzer_mode.cc \
+  fuzz/session.cc \
+  fuzz/spki.cc \
+  fuzz/ssl_ctx_api.cc \
+  fuzz/verify_name_match_fuzzer.cc \
+  fuzz/verify_name_match_normalizename_fuzzer.cc \
+  fuzz/verify_name_match_verifynameinsubtree_fuzzer.cc
+
+boringssl_modulewrapper_sources := \
+  util/fipstools/acvp/modulewrapper/main.cc \
+  util/fipstools/acvp/modulewrapper/modulewrapper.cc
+
+boringssl_modulewrapper_internal_headers := \
+  util/fipstools/acvp/modulewrapper/modulewrapper.h
+
+boringssl_pki_sources := \
+  pki/cert_error_id.cc \
+  pki/cert_error_params.cc \
+  pki/cert_errors.cc \
+  pki/cert_issuer_source_static.cc \
+  pki/certificate.cc \
+  pki/certificate_policies.cc \
+  pki/common_cert_errors.cc \
+  pki/crl.cc \
+  pki/encode_values.cc \
+  pki/extended_key_usage.cc \
+  pki/general_names.cc \
+  pki/input.cc \
+  pki/ip_util.cc \
+  pki/name_constraints.cc \
+  pki/ocsp.cc \
+  pki/parse_certificate.cc \
+  pki/parse_name.cc \
+  pki/parse_values.cc \
+  pki/parsed_certificate.cc \
+  pki/parser.cc \
+  pki/path_builder.cc \
+  pki/pem.cc \
+  pki/revocation_util.cc \
+  pki/signature_algorithm.cc \
+  pki/simple_path_builder_delegate.cc \
+  pki/string_util.cc \
+  pki/trust_store.cc \
+  pki/trust_store_collection.cc \
+  pki/trust_store_in_memory.cc \
+  pki/verify.cc \
+  pki/verify_certificate_chain.cc \
+  pki/verify_error.cc \
+  pki/verify_name_match.cc \
+  pki/verify_signed_data.cc
+
+boringssl_pki_headers := \
+  include/openssl/pki/certificate.h \
+  include/openssl/pki/ocsp.h \
+  include/openssl/pki/signature_verify_cache.h \
+  include/openssl/pki/verify.h \
+  include/openssl/pki/verify_error.h
+
+boringssl_pki_internal_headers := \
+  pki/cert_error_id.h \
+  pki/cert_error_params.h \
+  pki/cert_errors.h \
+  pki/cert_issuer_source.h \
+  pki/cert_issuer_source_static.h \
+  pki/cert_issuer_source_sync_unittest.h \
+  pki/certificate_policies.h \
+  pki/common_cert_errors.h \
+  pki/crl.h \
+  pki/encode_values.h \
+  pki/extended_key_usage.h \
+  pki/general_names.h \
+  pki/input.h \
+  pki/ip_util.h \
+  pki/mock_signature_verify_cache.h \
+  pki/name_constraints.h \
+  pki/nist_pkits_unittest.h \
+  pki/ocsp.h \
+  pki/parse_certificate.h \
+  pki/parse_name.h \
+  pki/parse_values.h \
+  pki/parsed_certificate.h \
+  pki/parser.h \
+  pki/path_builder.h \
+  pki/pem.h \
+  pki/revocation_util.h \
+  pki/signature_algorithm.h \
+  pki/simple_path_builder_delegate.h \
+  pki/string_util.h \
+  pki/test_helpers.h \
+  pki/testdata/nist-pkits/pkits_testcases-inl.h \
+  pki/trust_store.h \
+  pki/trust_store_collection.h \
+  pki/trust_store_in_memory.h \
+  pki/verify_certificate_chain.h \
+  pki/verify_certificate_chain_typed_unittest.h \
+  pki/verify_name_match.h \
+  pki/verify_signed_data.h
+
+boringssl_pki_test_sources := \
+  crypto/test/gtest_main.cc \
+  pki/cert_issuer_source_static_unittest.cc \
+  pki/certificate_policies_unittest.cc \
+  pki/certificate_unittest.cc \
+  pki/crl_unittest.cc \
+  pki/encode_values_unittest.cc \
+  pki/extended_key_usage_unittest.cc \
+  pki/general_names_unittest.cc \
+  pki/input_unittest.cc \
+  pki/ip_util_unittest.cc \
+  pki/mock_signature_verify_cache.cc \
+  pki/name_constraints_unittest.cc \
+  pki/nist_pkits_unittest.cc \
+  pki/ocsp_unittest.cc \
+  pki/parse_certificate_unittest.cc \
+  pki/parse_name_unittest.cc \
+  pki/parse_values_unittest.cc \
+  pki/parsed_certificate_unittest.cc \
+  pki/parser_unittest.cc \
+  pki/path_builder_pkits_unittest.cc \
+  pki/path_builder_unittest.cc \
+  pki/path_builder_verify_certificate_chain_unittest.cc \
+  pki/pem_unittest.cc \
+  pki/signature_algorithm_unittest.cc \
+  pki/simple_path_builder_delegate_unittest.cc \
+  pki/string_util_unittest.cc \
+  pki/test_helpers.cc \
+  pki/trust_store_collection_unittest.cc \
+  pki/trust_store_in_memory_unittest.cc \
+  pki/verify_certificate_chain_pkits_unittest.cc \
+  pki/verify_certificate_chain_unittest.cc \
+  pki/verify_name_match_unittest.cc \
+  pki/verify_signed_data_unittest.cc \
+  pki/verify_unittest.cc
+
+boringssl_pki_test_data := \
+  pki/testdata/cert_issuer_source_static_unittest/c1.pem \
+  pki/testdata/cert_issuer_source_static_unittest/c2.pem \
+  pki/testdata/cert_issuer_source_static_unittest/d.pem \
+  pki/testdata/cert_issuer_source_static_unittest/e1.pem \
+  pki/testdata/cert_issuer_source_static_unittest/e2.pem \
+  pki/testdata/cert_issuer_source_static_unittest/i1_1.pem \
+  pki/testdata/cert_issuer_source_static_unittest/i1_2.pem \
+  pki/testdata/cert_issuer_source_static_unittest/i2.pem \
+  pki/testdata/cert_issuer_source_static_unittest/i3_1.pem \
+  pki/testdata/cert_issuer_source_static_unittest/i3_2.pem \
+  pki/testdata/cert_issuer_source_static_unittest/root.pem \
+  pki/testdata/certificate_policies_unittest/anypolicy.pem \
+  pki/testdata/certificate_policies_unittest/anypolicy_with_qualifier.pem \
+  pki/testdata/certificate_policies_unittest/invalid-anypolicy_with_custom_qualifier.pem \
+  pki/testdata/certificate_policies_unittest/invalid-empty.pem \
+  pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_dupe.pem \
+  pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyinformation_unconsumed_data.pem \
+  pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem \
+  pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem \
+  pki/testdata/certificate_policies_unittest/invalid-policy_identifier_not_oid.pem \
+  pki/testdata/certificate_policies_unittest/policy_1_2_3.pem \
+  pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4.pem \
+  pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4_with_qualifiers.pem \
+  pki/testdata/certificate_policies_unittest/policy_1_2_3_with_custom_qualifier.pem \
+  pki/testdata/certificate_policies_unittest/policy_1_2_3_with_qualifier.pem \
+  pki/testdata/crl_unittest/bad_crldp_has_crlissuer.pem \
+  pki/testdata/crl_unittest/bad_fake_critical_crlentryextension.pem \
+  pki/testdata/crl_unittest/bad_fake_critical_extension.pem \
+  pki/testdata/crl_unittest/bad_idp_contains_wrong_uri.pem \
+  pki/testdata/crl_unittest/bad_idp_indirectcrl.pem \
+  pki/testdata/crl_unittest/bad_idp_onlycontainscacerts.pem \
+  pki/testdata/crl_unittest/bad_idp_onlycontainscacerts_no_basic_constraints.pem \
+  pki/testdata/crl_unittest/bad_idp_onlycontainsusercerts.pem \
+  pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainscacerts.pem \
+  pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainsusercerts.pem \
+  pki/testdata/crl_unittest/bad_key_rollover_signature.pem \
+  pki/testdata/crl_unittest/bad_nextupdate_too_old.pem \
+  pki/testdata/crl_unittest/bad_signature.pem \
+  pki/testdata/crl_unittest/bad_thisupdate_in_future.pem \
+  pki/testdata/crl_unittest/bad_thisupdate_too_old.pem \
+  pki/testdata/crl_unittest/bad_wrong_issuer.pem \
+  pki/testdata/crl_unittest/good.pem \
+  pki/testdata/crl_unittest/good_fake_extension.pem \
+  pki/testdata/crl_unittest/good_fake_extension_no_nextupdate.pem \
+  pki/testdata/crl_unittest/good_generalizedtime.pem \
+  pki/testdata/crl_unittest/good_idp_contains_uri.pem \
+  pki/testdata/crl_unittest/good_idp_onlycontainscacerts.pem \
+  pki/testdata/crl_unittest/good_idp_onlycontainsusercerts.pem \
+  pki/testdata/crl_unittest/good_idp_onlycontainsusercerts_no_basic_constraints.pem \
+  pki/testdata/crl_unittest/good_idp_uri_and_onlycontainscacerts.pem \
+  pki/testdata/crl_unittest/good_idp_uri_and_onlycontainsusercerts.pem \
+  pki/testdata/crl_unittest/good_issuer_name_normalization.pem \
+  pki/testdata/crl_unittest/good_issuer_no_keyusage.pem \
+  pki/testdata/crl_unittest/good_key_rollover.pem \
+  pki/testdata/crl_unittest/good_no_crldp.pem \
+  pki/testdata/crl_unittest/good_no_nextupdate.pem \
+  pki/testdata/crl_unittest/good_no_version.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_crlentryextensions.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_extensions.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_nextupdate.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_revocationdate.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_revokedcerts.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_signaturevalue.pem \
+  pki/testdata/crl_unittest/invalid_garbage_after_thisupdate.pem \
+  pki/testdata/crl_unittest/invalid_garbage_crlentry.pem \
+  pki/testdata/crl_unittest/invalid_garbage_issuer_name.pem \
+  pki/testdata/crl_unittest/invalid_garbage_revocationdate.pem \
+  pki/testdata/crl_unittest/invalid_garbage_revoked_serial_number.pem \
+  pki/testdata/crl_unittest/invalid_garbage_signaturealgorithm.pem \
+  pki/testdata/crl_unittest/invalid_garbage_signaturevalue.pem \
+  pki/testdata/crl_unittest/invalid_garbage_tbs_signature_algorithm.pem \
+  pki/testdata/crl_unittest/invalid_garbage_tbscertlist.pem \
+  pki/testdata/crl_unittest/invalid_garbage_thisupdate.pem \
+  pki/testdata/crl_unittest/invalid_garbage_version.pem \
+  pki/testdata/crl_unittest/invalid_idp_dpname_choice_extra_data.pem \
+  pki/testdata/crl_unittest/invalid_idp_empty_sequence.pem \
+  pki/testdata/crl_unittest/invalid_idp_onlycontains_user_and_ca_certs.pem \
+  pki/testdata/crl_unittest/invalid_idp_onlycontainsusercerts_v1_leaf.pem \
+  pki/testdata/crl_unittest/invalid_issuer_keyusage_no_crlsign.pem \
+  pki/testdata/crl_unittest/invalid_key_rollover_issuer_keyusage_no_crlsign.pem \
+  pki/testdata/crl_unittest/invalid_mismatched_signature_algorithm.pem \
+  pki/testdata/crl_unittest/invalid_revoked_empty_sequence.pem \
+  pki/testdata/crl_unittest/invalid_v1_explicit.pem \
+  pki/testdata/crl_unittest/invalid_v1_with_crlentryextension.pem \
+  pki/testdata/crl_unittest/invalid_v1_with_extension.pem \
+  pki/testdata/crl_unittest/invalid_v3.pem \
+  pki/testdata/crl_unittest/revoked.pem \
+  pki/testdata/crl_unittest/revoked_fake_crlentryextension.pem \
+  pki/testdata/crl_unittest/revoked_generalized_revocationdate.pem \
+  pki/testdata/crl_unittest/revoked_key_rollover.pem \
+  pki/testdata/crl_unittest/revoked_no_nextupdate.pem \
+  pki/testdata/name_constraints_unittest/directoryname-excludeall.pem \
+  pki/testdata/name_constraints_unittest/directoryname-excluded.pem \
+  pki/testdata/name_constraints_unittest/directoryname.pem \
+  pki/testdata/name_constraints_unittest/directoryname_and_dnsname.pem \
+  pki/testdata/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem \
+  pki/testdata/name_constraints_unittest/dnsname-exclude_dot.pem \
+  pki/testdata/name_constraints_unittest/dnsname-excludeall.pem \
+  pki/testdata/name_constraints_unittest/dnsname-excluded.pem \
+  pki/testdata/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem \
+  pki/testdata/name_constraints_unittest/dnsname-permitted_two_dot.pem \
+  pki/testdata/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem \
+  pki/testdata/name_constraints_unittest/dnsname-with_max.pem \
+  pki/testdata/name_constraints_unittest/dnsname-with_min_0.pem \
+  pki/testdata/name_constraints_unittest/dnsname-with_min_0_and_max.pem \
+  pki/testdata/name_constraints_unittest/dnsname-with_min_1.pem \
+  pki/testdata/name_constraints_unittest/dnsname-with_min_1_and_max.pem \
+  pki/testdata/name_constraints_unittest/dnsname.pem \
+  pki/testdata/name_constraints_unittest/dnsname2.pem \
+  pki/testdata/name_constraints_unittest/edipartyname-excluded.pem \
+  pki/testdata/name_constraints_unittest/edipartyname-permitted.pem \
+  pki/testdata/name_constraints_unittest/invalid-empty_excluded_subtree.pem \
+  pki/testdata/name_constraints_unittest/invalid-empty_permitted_subtree.pem \
+  pki/testdata/name_constraints_unittest/invalid-no_subtrees.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-excludeall.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-excluded.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-invalid_addr.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_1.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_2.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_3.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_4.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-mapped_addrs.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-permit_all.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-permit_prefix1.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-permit_prefix31.pem \
+  pki/testdata/name_constraints_unittest/ipaddress-permit_singlehost.pem \
+  pki/testdata/name_constraints_unittest/ipaddress.pem \
+  pki/testdata/name_constraints_unittest/name-ca.pem \
+  pki/testdata/name_constraints_unittest/name-de.pem \
+  pki/testdata/name_constraints_unittest/name-empty.pem \
+  pki/testdata/name_constraints_unittest/name-jp-tokyo.pem \
+  pki/testdata/name_constraints_unittest/name-jp.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-1.1.1.1.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-192.168.1.1.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-email-invalidstring.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-email-localpartcase.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-email-multiple.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-email.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-foo.com.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-ipv6.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona-permitted.example.com.pem \
+  pki/testdata/name_constraints_unittest/name-us-arizona.pem \
+  pki/testdata/name_constraints_unittest/name-us-california-192.168.1.1.pem \
+  pki/testdata/name_constraints_unittest/name-us-california-mountain_view.pem \
+  pki/testdata/name_constraints_unittest/name-us-california-permitted.example.com.pem \
+  pki/testdata/name_constraints_unittest/name-us-california.pem \
+  pki/testdata/name_constraints_unittest/name-us.pem \
+  pki/testdata/name_constraints_unittest/othername-excluded.pem \
+  pki/testdata/name_constraints_unittest/othername-permitted.pem \
+  pki/testdata/name_constraints_unittest/registeredid-excluded.pem \
+  pki/testdata/name_constraints_unittest/registeredid-permitted.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-empty.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-hostname.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-hostnamewithat.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-ipv4.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-quoted.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded-subdomains.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-excluded.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-empty.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-hostname.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-hostnamewithat.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-ipv4.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-quoted.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted-subdomains.pem \
+  pki/testdata/name_constraints_unittest/rfc822name-permitted.pem \
+  pki/testdata/name_constraints_unittest/san-directoryname.pem \
+  pki/testdata/name_constraints_unittest/san-dnsname.pem \
+  pki/testdata/name_constraints_unittest/san-edipartyname.pem \
+  pki/testdata/name_constraints_unittest/san-excluded-directoryname.pem \
+  pki/testdata/name_constraints_unittest/san-excluded-dnsname.pem \
+  pki/testdata/name_constraints_unittest/san-excluded-ipaddress.pem \
+  pki/testdata/name_constraints_unittest/san-invalid-empty.pem \
+  pki/testdata/name_constraints_unittest/san-invalid-ipaddress.pem \
+  pki/testdata/name_constraints_unittest/san-ipaddress4.pem \
+  pki/testdata/name_constraints_unittest/san-ipaddress6.pem \
+  pki/testdata/name_constraints_unittest/san-othername.pem \
+  pki/testdata/name_constraints_unittest/san-permitted.pem \
+  pki/testdata/name_constraints_unittest/san-registeredid.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-domaincase.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-empty-localpart.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-empty.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-ipv4.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-localpartcase.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-multiple.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-no-at.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-quoted.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-no-at.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-two-ats.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-subdomain.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-subdomaincase.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name-two-ats.pem \
+  pki/testdata/name_constraints_unittest/san-rfc822name.pem \
+  pki/testdata/name_constraints_unittest/san-uri.pem \
+  pki/testdata/name_constraints_unittest/san-x400address.pem \
+  pki/testdata/name_constraints_unittest/uri-excluded.pem \
+  pki/testdata/name_constraints_unittest/uri-permitted.pem \
+  pki/testdata/name_constraints_unittest/x400address-excluded.pem \
+  pki/testdata/name_constraints_unittest/x400address-permitted.pem \
+  pki/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt \
+  pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt \
+  pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt \
+  pki/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt \
+  pki/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt \
+  pki/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt \
+  pki/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt \
+  pki/testdata/nist-pkits/certs/BadSignedCACert.crt \
+  pki/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt \
+  pki/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt \
+  pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt \
+  pki/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt \
+  pki/testdata/nist-pkits/certs/DSACACert.crt \
+  pki/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt \
+  pki/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt \
+  pki/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt \
+  pki/testdata/nist-pkits/certs/GoodCACert.crt \
+  pki/testdata/nist-pkits/certs/GoodsubCACert.crt \
+  pki/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt \
+  pki/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt \
+  pki/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt \
+  pki/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt \
+  pki/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt \
+  pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt \
+  pki/testdata/nist-pkits/certs/LongSerialNumberCACert.crt \
+  pki/testdata/nist-pkits/certs/Mapping1to2CACert.crt \
+  pki/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt \
+  pki/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt \
+  pki/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt \
+  pki/testdata/nist-pkits/certs/NameOrderingCACert.crt \
+  pki/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt \
+  pki/testdata/nist-pkits/certs/NoCRLCACert.crt \
+  pki/testdata/nist-pkits/certs/NoPoliciesCACert.crt \
+  pki/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt \
+  pki/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt \
+  pki/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt \
+  pki/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt \
+  pki/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt \
+  pki/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt \
+  pki/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt \
+  pki/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt \
+  pki/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP1234CACert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP123CACert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP12CACert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP2subCACert.crt \
+  pki/testdata/nist-pkits/certs/PoliciesP3CACert.crt \
+  pki/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt \
+  pki/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt \
+  pki/testdata/nist-pkits/certs/RevokedsubCACert.crt \
+  pki/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt \
+  pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt \
+  pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt \
+  pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt \
+  pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt \
+  pki/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt \
+  pki/testdata/nist-pkits/certs/TwoCRLsCACert.crt \
+  pki/testdata/nist-pkits/certs/UIDCACert.crt \
+  pki/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt \
+  pki/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt \
+  pki/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt \
+  pki/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt \
+  pki/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt \
+  pki/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt \
+  pki/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt \
+  pki/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt \
+  pki/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt \
+  pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt \
+  pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt \
+  pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt \
+  pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt \
+  pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt \
+  pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt \
+  pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt \
+  pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt \
+  pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt \
+  pki/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt \
+  pki/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt \
+  pki/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt \
+  pki/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt \
+  pki/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt \
+  pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt \
+  pki/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt \
+  pki/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt \
+  pki/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt \
+  pki/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt \
+  pki/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt \
+  pki/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt \
+  pki/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt \
+  pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt \
+  pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt \
+  pki/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt \
+  pki/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt \
+  pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt \
+  pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt \
+  pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt \
+  pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt \
+  pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt \
+  pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt \
+  pki/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt \
+  pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt \
+  pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt \
+  pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt \
+  pki/testdata/nist-pkits/certs/WrongCRLCACert.crt \
+  pki/testdata/nist-pkits/certs/anyPolicyCACert.crt \
+  pki/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt \
+  pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt \
+  pki/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt \
+  pki/testdata/nist-pkits/certs/distributionPoint1CACert.crt \
+  pki/testdata/nist-pkits/certs/distributionPoint2CACert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt \
+  pki/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt \
+  pki/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt \
+  pki/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt \
+  pki/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt \
+  pki/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt \
+  pki/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt \
+  pki/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt \
+  pki/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt \
+  pki/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt \
+  pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt \
+  pki/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt \
+  pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt \
+  pki/testdata/nist-pkits/crls/BadCRLIssuerNameCACRL.crl \
+  pki/testdata/nist-pkits/crls/BadCRLSignatureCACRL.crl \
+  pki/testdata/nist-pkits/crls/BadSignedCACRL.crl \
+  pki/testdata/nist-pkits/crls/BadnotAfterDateCACRL.crl \
+  pki/testdata/nist-pkits/crls/BadnotBeforeDateCACRL.crl \
+  pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl \
+  pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl \
+  pki/testdata/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl \
+  pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl \
+  pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl \
+  pki/testdata/nist-pkits/crls/DSACACRL.crl \
+  pki/testdata/nist-pkits/crls/DSAParametersInheritedCACRL.crl \
+  pki/testdata/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl \
+  pki/testdata/nist-pkits/crls/GoodCACRL.crl \
+  pki/testdata/nist-pkits/crls/GoodsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl \
+  pki/testdata/nist-pkits/crls/LongSerialNumberCACRL.crl \
+  pki/testdata/nist-pkits/crls/Mapping1to2CACRL.crl \
+  pki/testdata/nist-pkits/crls/MappingFromanyPolicyCACRL.crl \
+  pki/testdata/nist-pkits/crls/MappingToanyPolicyCACRL.crl \
+  pki/testdata/nist-pkits/crls/MissingbasicConstraintsCACRL.crl \
+  pki/testdata/nist-pkits/crls/NameOrderCACRL.crl \
+  pki/testdata/nist-pkits/crls/NegativeSerialNumberCACRL.crl \
+  pki/testdata/nist-pkits/crls/NoPoliciesCACRL.crl \
+  pki/testdata/nist-pkits/crls/NoissuingDistributionPointCACRL.crl \
+  pki/testdata/nist-pkits/crls/OldCRLnextUpdateCACRL.crl \
+  pki/testdata/nist-pkits/crls/P12Mapping1to3CACRL.crl \
+  pki/testdata/nist-pkits/crls/P12Mapping1to3subCACRL.crl \
+  pki/testdata/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/P1Mapping1to234CACRL.crl \
+  pki/testdata/nist-pkits/crls/P1Mapping1to234subCACRL.crl \
+  pki/testdata/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl \
+  pki/testdata/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP1234CACRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP123CACRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP123subCAP12CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP12CACRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP12subCAP1CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP2subCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP2subCACRL.crl \
+  pki/testdata/nist-pkits/crls/PoliciesP3CACRL.crl \
+  pki/testdata/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl \
+  pki/testdata/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl \
+  pki/testdata/nist-pkits/crls/RevokedsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl \
+  pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl \
+  pki/testdata/nist-pkits/crls/TrustAnchorRootCRL.crl \
+  pki/testdata/nist-pkits/crls/TwoCRLsCABadCRL.crl \
+  pki/testdata/nist-pkits/crls/TwoCRLsCAGoodCRL.crl \
+  pki/testdata/nist-pkits/crls/UIDCACRL.crl \
+  pki/testdata/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl \
+  pki/testdata/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl \
+  pki/testdata/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl \
+  pki/testdata/nist-pkits/crls/UnknownCRLExtensionCACRL.crl \
+  pki/testdata/nist-pkits/crls/WrongCRLCACRL.crl \
+  pki/testdata/nist-pkits/crls/anyPolicyCACRL.crl \
+  pki/testdata/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl \
+  pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA1deltaCRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA2deltaCRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA3CRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLCA3deltaCRL.crl \
+  pki/testdata/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl \
+  pki/testdata/nist-pkits/crls/distributionPoint1CACRL.crl \
+  pki/testdata/nist-pkits/crls/distributionPoint2CACRL.crl \
+  pki/testdata/nist-pkits/crls/indirectCRLCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/indirectCRLCA3CRL.crl \
+  pki/testdata/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl \
+  pki/testdata/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl \
+  pki/testdata/nist-pkits/crls/indirectCRLCA5CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/keyUsageNotCriticalCACRL.crl \
+  pki/testdata/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN1CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN2CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN3CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN4CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDN5CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDNS1CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsDNS2CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsURI1CACRL.crl \
+  pki/testdata/nist-pkits/crls/nameConstraintsURI2CACRL.crl \
+  pki/testdata/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl \
+  pki/testdata/nist-pkits/crls/onlyContainsCACertsCACRL.crl \
+  pki/testdata/nist-pkits/crls/onlyContainsUserCertsCACRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl \
+  pki/testdata/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint0CACRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint0subCACRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint1CACRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint1subCACRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6CACRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl \
+  pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl \
+  pki/testdata/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy0CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy10CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy2CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy4CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy5CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy7CACRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl \
+  pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl \
+  pki/testdata/ocsp_unittest/bad_ocsp_type.pem \
+  pki/testdata/ocsp_unittest/bad_signature.pem \
+  pki/testdata/ocsp_unittest/bad_status.pem \
+  pki/testdata/ocsp_unittest/good_response.pem \
+  pki/testdata/ocsp_unittest/good_response_next_update.pem \
+  pki/testdata/ocsp_unittest/good_response_sha256.pem \
+  pki/testdata/ocsp_unittest/has_critical_ct_extension.pem \
+  pki/testdata/ocsp_unittest/has_critical_response_extension.pem \
+  pki/testdata/ocsp_unittest/has_critical_single_extension.pem \
+  pki/testdata/ocsp_unittest/has_extension.pem \
+  pki/testdata/ocsp_unittest/has_single_extension.pem \
+  pki/testdata/ocsp_unittest/has_version.pem \
+  pki/testdata/ocsp_unittest/malformed_request.pem \
+  pki/testdata/ocsp_unittest/missing_response.pem \
+  pki/testdata/ocsp_unittest/multiple_response.pem \
+  pki/testdata/ocsp_unittest/no_response.pem \
+  pki/testdata/ocsp_unittest/ocsp_extra_certs.pem \
+  pki/testdata/ocsp_unittest/ocsp_sign_bad_indirect.pem \
+  pki/testdata/ocsp_unittest/ocsp_sign_direct.pem \
+  pki/testdata/ocsp_unittest/ocsp_sign_indirect.pem \
+  pki/testdata/ocsp_unittest/ocsp_sign_indirect_missing.pem \
+  pki/testdata/ocsp_unittest/other_response.pem \
+  pki/testdata/ocsp_unittest/responder_id.pem \
+  pki/testdata/ocsp_unittest/responder_name.pem \
+  pki/testdata/ocsp_unittest/revoke_response.pem \
+  pki/testdata/ocsp_unittest/revoke_response_reason.pem \
+  pki/testdata/ocsp_unittest/unknown_response.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/empty_sequence.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_extension_sequence.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_issuer_and_serial.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_contents.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_issuer.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_key_identifier.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_serial.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_and_serial.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_only.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier_and_issuer_and_serial.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/serial_only.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier/url_issuer_and_serial.pem \
+  pki/testdata/parse_certificate_unittest/authority_key_identifier_not_sequence.pem \
+  pki/testdata/parse_certificate_unittest/bad_key_usage.pem \
+  pki/testdata/parse_certificate_unittest/bad_policy_qualifiers.pem \
+  pki/testdata/parse_certificate_unittest/bad_signature_algorithm_oid.pem \
+  pki/testdata/parse_certificate_unittest/bad_validity.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_ca_false.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_ca_no_path.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_ca_path_9.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_negative_path.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_not_ca.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_path_too_large.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_255.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_256.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem \
+  pki/testdata/parse_certificate_unittest/basic_constraints_unconsumed_data.pem \
+  pki/testdata/parse_certificate_unittest/cert_algorithm_not_sequence.pem \
+  pki/testdata/parse_certificate_unittest/cert_data_after_signature.pem \
+  pki/testdata/parse_certificate_unittest/cert_empty_sequence.pem \
+  pki/testdata/parse_certificate_unittest/cert_missing_signature.pem \
+  pki/testdata/parse_certificate_unittest/cert_not_sequence.pem \
+  pki/testdata/parse_certificate_unittest/cert_signature_not_bit_string.pem \
+  pki/testdata/parse_certificate_unittest/cert_skeleton.pem \
+  pki/testdata/parse_certificate_unittest/cert_version3.pem \
+  pki/testdata/parse_certificate_unittest/crldp_1uri_noissuer.pem \
+  pki/testdata/parse_certificate_unittest/crldp_3uri_noissuer.pem \
+  pki/testdata/parse_certificate_unittest/crldp_full_name_as_dirname.pem \
+  pki/testdata/parse_certificate_unittest/crldp_issuer_as_dirname.pem \
+  pki/testdata/parse_certificate_unittest/extended_key_usage.pem \
+  pki/testdata/parse_certificate_unittest/extension_critical.pem \
+  pki/testdata/parse_certificate_unittest/extension_critical_0.pem \
+  pki/testdata/parse_certificate_unittest/extension_critical_3.pem \
+  pki/testdata/parse_certificate_unittest/extension_not_critical.pem \
+  pki/testdata/parse_certificate_unittest/extensions_data_after_sequence.pem \
+  pki/testdata/parse_certificate_unittest/extensions_duplicate_key_usage.pem \
+  pki/testdata/parse_certificate_unittest/extensions_empty_sequence.pem \
+  pki/testdata/parse_certificate_unittest/extensions_not_sequence.pem \
+  pki/testdata/parse_certificate_unittest/extensions_real.pem \
+  pki/testdata/parse_certificate_unittest/failed_signature_algorithm.pem \
+  pki/testdata/parse_certificate_unittest/inhibit_any_policy.pem \
+  pki/testdata/parse_certificate_unittest/issuer_bad_printable_string.pem \
+  pki/testdata/parse_certificate_unittest/key_usage.pem \
+  pki/testdata/parse_certificate_unittest/name_constraints_bad_ip.pem \
+  pki/testdata/parse_certificate_unittest/policies.pem \
+  pki/testdata/parse_certificate_unittest/policy_constraints_empty.pem \
+  pki/testdata/parse_certificate_unittest/policy_constraints_inhibit.pem \
+  pki/testdata/parse_certificate_unittest/policy_constraints_inhibit_require.pem \
+  pki/testdata/parse_certificate_unittest/policy_constraints_require.pem \
+  pki/testdata/parse_certificate_unittest/policy_qualifiers_empty_sequence.pem \
+  pki/testdata/parse_certificate_unittest/serial_37_bytes.pem \
+  pki/testdata/parse_certificate_unittest/serial_negative.pem \
+  pki/testdata/parse_certificate_unittest/serial_not_minimal.pem \
+  pki/testdata/parse_certificate_unittest/serial_not_number.pem \
+  pki/testdata/parse_certificate_unittest/serial_zero.pem \
+  pki/testdata/parse_certificate_unittest/serial_zero_padded.pem \
+  pki/testdata/parse_certificate_unittest/serial_zero_padded_21_bytes.pem \
+  pki/testdata/parse_certificate_unittest/signature_algorithm_null.pem \
+  pki/testdata/parse_certificate_unittest/subject_alt_name.pem \
+  pki/testdata/parse_certificate_unittest/subject_blank_subjectaltname_not_critical.pem \
+  pki/testdata/parse_certificate_unittest/subject_key_identifier_not_octet_string.pem \
+  pki/testdata/parse_certificate_unittest/subject_not_ascii.pem \
+  pki/testdata/parse_certificate_unittest/subject_not_printable_string.pem \
+  pki/testdata/parse_certificate_unittest/subject_printable_string_containing_utf8_client_cert.pem \
+  pki/testdata/parse_certificate_unittest/subject_t61string.pem \
+  pki/testdata/parse_certificate_unittest/subject_t61string_1-32.pem \
+  pki/testdata/parse_certificate_unittest/subject_t61string_126-160.pem \
+  pki/testdata/parse_certificate_unittest/subject_t61string_actual.pem \
+  pki/testdata/parse_certificate_unittest/subjectaltname_bad_ip.pem \
+  pki/testdata/parse_certificate_unittest/subjectaltname_dns_not_ascii.pem \
+  pki/testdata/parse_certificate_unittest/subjectaltname_general_names_empty_sequence.pem \
+  pki/testdata/parse_certificate_unittest/subjectaltname_trailing_data.pem \
+  pki/testdata/parse_certificate_unittest/tbs_explicit_v1.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v1.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v1_extensions.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v2_extensions.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v2_no_optionals.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_all_optionals.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_data_after_extensions.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_extensions.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_no_optionals.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v3_real.pem \
+  pki/testdata/parse_certificate_unittest/tbs_v4.pem \
+  pki/testdata/parse_certificate_unittest/tbs_validity_both_generalized_time.pem \
+  pki/testdata/parse_certificate_unittest/tbs_validity_both_utc_time.pem \
+  pki/testdata/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem \
+  pki/testdata/parse_certificate_unittest/tbs_validity_relaxed.pem \
+  pki/testdata/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem \
+  pki/testdata/parse_certificate_unittest/v1_explicit_version.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_match_name_only.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_matching.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_mismatch.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root2.pem \
+  pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/target.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_a.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_b.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_c.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_a.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_b.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_c.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_a.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_b.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_c.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/root.pem \
+  pki/testdata/path_builder_unittest/key_id_prioritization/target.pem \
+  pki/testdata/path_builder_unittest/multi-root-A-by-B.pem \
+  pki/testdata/path_builder_unittest/multi-root-B-by-C.pem \
+  pki/testdata/path_builder_unittest/multi-root-B-by-F.pem \
+  pki/testdata/path_builder_unittest/multi-root-C-by-D.pem \
+  pki/testdata/path_builder_unittest/multi-root-C-by-E.pem \
+  pki/testdata/path_builder_unittest/multi-root-D-by-D.pem \
+  pki/testdata/path_builder_unittest/multi-root-E-by-E.pem \
+  pki/testdata/path_builder_unittest/multi-root-F-by-E.pem \
+  pki/testdata/path_builder_unittest/precertificate/precertificate.pem \
+  pki/testdata/path_builder_unittest/precertificate/root.pem \
+  pki/testdata/path_builder_unittest/self_issued_prioritization/root1.pem \
+  pki/testdata/path_builder_unittest/self_issued_prioritization/root1_cross.pem \
+  pki/testdata/path_builder_unittest/self_issued_prioritization/root2.pem \
+  pki/testdata/path_builder_unittest/self_issued_prioritization/target.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/int_ac.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/int_ad.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/int_bc.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/int_bd.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/root.pem \
+  pki/testdata/path_builder_unittest/validity_date_prioritization/target.pem \
+  pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/main.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-intermediate/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-after.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-before.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration-and-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-after.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-before-ta-with-expiration.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-root/not-before.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-target/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/expired-target/not-after.test \
+  pki/testdata/verify_certificate_chain_unittest/expired-target/not-before.test \
+  pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-any.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/main.test \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/main.test \
+  pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.pem \
+  pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.pem \
+  pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.test \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.pem \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.test \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.pem \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.test \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.pem \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.pem \
+  pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.test \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.pem \
+  pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.test \
+  pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/main.test \
+  pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.4.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.10.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.13.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.4.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.7.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.10.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.11.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.9.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.10.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.4.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.10.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.12.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.13.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.15.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.16.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.17.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.20.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.21.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.22.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.23.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.24.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.25.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.26.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.27.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.28.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.29.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.31.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.33.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.34.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.35.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.36.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.37.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.38.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.7.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.9.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.16.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.7.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.10.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.11.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.12.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.16.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.9.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.1.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.12.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.14.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.2.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.4.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.6.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.7.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.9.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.3.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.5.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.7.txt \
+  pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.8.txt \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/main.test \
+  pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/main.test \
+  pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration-and-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration.test \
+  pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints-require-basic-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-require-basic-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test \
+  pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-constraints.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-expiration.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-and-trust_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-root.test \
+  pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/unspecified-trust-root.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/any.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/any.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/any.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/any.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf-strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict-leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-and-trust_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-not_after.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-wrong_eku.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf_require_self_signed.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfissued/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf-and-trust_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf_require_self_signed.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-and-trust_anchor.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-not_after.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-wrong_eku.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf_require_self_signed.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.test \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.test \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only-trusted_leaf.test \
+  pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/main.test \
+  pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/main.test \
+  pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/main.test \
+  pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/main.test \
+  pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/main.test \
+  pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/chain.pem \
+  pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/main.test \
+  pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/ta-with-constraints.test \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_1.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_2.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-dupe_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_attr.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_rdn.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_1.pem \
+  pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_2.pem \
+  pki/testdata/verify_name_match_unittest/names/custom-custom-normalized.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-badAttributeType.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-empty.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-extradata.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-onlyOneElement.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-setNotSequence.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-Name-setInsteadOfSequence.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-RDN-empty.pem \
+  pki/testdata/verify_name_match_unittest/names/invalid-RDN-sequenceInsteadOfSet.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode-mixed-normalized.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode-mixed-unnormalized.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode_bmp-BMPSTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode_bmp-UNIVERSALSTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode_bmp-UTF8-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UNIVERSALSTRING-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UTF8-unmangled.pem \
+  pki/testdata/verify_name_match_unittest/names/valid-Name-empty.pem \
+  pki/testdata/verify_name_match_unittest/names/valid-minimal.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem \
+  pki/testdata/verify_signed_data_unittest/ecdsa-using-rsa-key.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-using-pss-key-with-params.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-wrong-salt.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem \
+  pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem \
+  pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem \
+  pki/testdata/verify_unittest/google-intermediate1.der \
+  pki/testdata/verify_unittest/google-intermediate2.der \
+  pki/testdata/verify_unittest/google-leaf.der \
+  pki/testdata/verify_unittest/lencr-intermediate-r3.der \
+  pki/testdata/verify_unittest/lencr-leaf.der \
+  pki/testdata/verify_unittest/lencr-root-dst-x3.der \
+  pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der \
+  pki/testdata/verify_unittest/lencr-root-x1.der \
+  pki/testdata/verify_unittest/mozilla_roots.der \
+  pki/testdata/verify_unittest/self-issued.pem
+
+boringssl_rust_bssl_crypto_sources := \
+  rust/bssl-crypto/src/aead.rs \
+  rust/bssl-crypto/src/aes.rs \
+  rust/bssl-crypto/src/cipher/aes_cbc.rs \
+  rust/bssl-crypto/src/cipher/aes_ctr.rs \
+  rust/bssl-crypto/src/cipher/mod.rs \
+  rust/bssl-crypto/src/digest.rs \
+  rust/bssl-crypto/src/ec.rs \
+  rust/bssl-crypto/src/ecdh.rs \
+  rust/bssl-crypto/src/ecdsa.rs \
+  rust/bssl-crypto/src/ed25519.rs \
+  rust/bssl-crypto/src/hkdf.rs \
+  rust/bssl-crypto/src/hmac.rs \
+  rust/bssl-crypto/src/hpke.rs \
+  rust/bssl-crypto/src/lib.rs \
+  rust/bssl-crypto/src/macros.rs \
+  rust/bssl-crypto/src/mem.rs \
+  rust/bssl-crypto/src/mldsa.rs \
+  rust/bssl-crypto/src/mlkem.rs \
+  rust/bssl-crypto/src/rand.rs \
+  rust/bssl-crypto/src/rsa.rs \
+  rust/bssl-crypto/src/scoped.rs \
+  rust/bssl-crypto/src/slhdsa.rs \
+  rust/bssl-crypto/src/test_helpers.rs \
+  rust/bssl-crypto/src/x25519.rs
+
+boringssl_rust_bssl_sys_sources := \
+  rust/bssl-sys/src/lib.rs
+
+boringssl_ssl_sources := \
+  ssl/bio_ssl.cc \
+  ssl/d1_both.cc \
+  ssl/d1_lib.cc \
+  ssl/d1_pkt.cc \
+  ssl/d1_srtp.cc \
+  ssl/dtls_method.cc \
+  ssl/dtls_record.cc \
+  ssl/encrypted_client_hello.cc \
+  ssl/extensions.cc \
+  ssl/handoff.cc \
+  ssl/handshake.cc \
+  ssl/handshake_client.cc \
+  ssl/handshake_server.cc \
+  ssl/s3_both.cc \
+  ssl/s3_lib.cc \
+  ssl/s3_pkt.cc \
+  ssl/ssl_aead_ctx.cc \
+  ssl/ssl_asn1.cc \
+  ssl/ssl_buffer.cc \
+  ssl/ssl_cert.cc \
+  ssl/ssl_cipher.cc \
+  ssl/ssl_credential.cc \
+  ssl/ssl_file.cc \
+  ssl/ssl_key_share.cc \
+  ssl/ssl_lib.cc \
+  ssl/ssl_privkey.cc \
+  ssl/ssl_session.cc \
+  ssl/ssl_stat.cc \
+  ssl/ssl_transcript.cc \
+  ssl/ssl_versions.cc \
+  ssl/ssl_x509.cc \
+  ssl/t1_enc.cc \
+  ssl/tls13_both.cc \
+  ssl/tls13_client.cc \
+  ssl/tls13_enc.cc \
+  ssl/tls13_server.cc \
+  ssl/tls_method.cc \
+  ssl/tls_record.cc
+
+boringssl_ssl_headers := \
+  include/openssl/dtls1.h \
+  include/openssl/srtp.h \
+  include/openssl/ssl.h \
+  include/openssl/ssl3.h \
+  include/openssl/tls1.h
+
+boringssl_ssl_internal_headers := \
+  ssl/internal.h
+
+boringssl_ssl_test_sources := \
+  crypto/test/gtest_main.cc \
+  ssl/span_test.cc \
+  ssl/ssl_c_test.c \
+  ssl/ssl_internal_test.cc \
+  ssl/ssl_test.cc
+
+boringssl_test_support_sources := \
+  crypto/test/abi_test.cc \
+  crypto/test/file_test.cc \
+  crypto/test/file_test_gtest.cc \
+  crypto/test/file_util.cc \
+  crypto/test/test_data.cc \
+  crypto/test/test_util.cc \
+  crypto/test/wycheproof_util.cc
+
+boringssl_test_support_internal_headers := \
+  crypto/test/abi_test.h \
+  crypto/test/file_test.h \
+  crypto/test/file_util.h \
+  crypto/test/gtest_main.h \
+  crypto/test/test_data.h \
+  crypto/test/test_util.h \
+  crypto/test/wycheproof_util.h \
+  ssl/test/async_bio.h \
+  ssl/test/fuzzer.h \
+  ssl/test/fuzzer_tags.h \
+  ssl/test/handshake_util.h \
+  ssl/test/mock_quic_transport.h \
+  ssl/test/packeted_bio.h \
+  ssl/test/settings_writer.h \
+  ssl/test/test_config.h \
+  ssl/test/test_state.h
+
+boringssl_test_support_sources_asm := \
+  gen/test_support/trampoline-armv4-linux.S \
+  gen/test_support/trampoline-armv8-apple.S \
+  gen/test_support/trampoline-armv8-linux.S \
+  gen/test_support/trampoline-armv8-win.S \
+  gen/test_support/trampoline-x86-apple.S \
+  gen/test_support/trampoline-x86-linux.S \
+  gen/test_support/trampoline-x86_64-apple.S \
+  gen/test_support/trampoline-x86_64-linux.S
+
+boringssl_test_support_sources_nasm := \
+  gen/test_support/trampoline-x86-win.asm \
+  gen/test_support/trampoline-x86_64-win.asm
+
+boringssl_urandom_test_sources := \
+  crypto/rand/urandom_test.cc
diff --git a/src/go.mod b/src/go.mod
index 811bf7d..9c29809 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -3,12 +3,54 @@
 go 1.24
 
 require (
+	cloud.google.com/go/storage v1.51.0
 	filippo.io/edwards25519 v1.1.0
-	golang.org/x/crypto v0.31.0
-	golang.org/x/net v0.27.0
+	golang.org/x/crypto v0.37.0
+	golang.org/x/net v0.39.0
+	google.golang.org/api v0.229.0
 )
 
 require (
-	golang.org/x/sys v0.28.0 // indirect
-	golang.org/x/term v0.27.0 // indirect
+	cel.dev/expr v0.23.1 // indirect
+	cloud.google.com/go v0.120.1 // indirect
+	cloud.google.com/go/auth v0.16.0 // indirect
+	cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
+	cloud.google.com/go/compute/metadata v0.6.0 // indirect
+	cloud.google.com/go/iam v1.5.0 // indirect
+	cloud.google.com/go/monitoring v1.24.1 // indirect
+	github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
+	github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
+	github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
+	github.com/cespare/xxhash/v2 v2.3.0 // indirect
+	github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect
+	github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
+	github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
+	github.com/felixge/httpsnoop v1.0.4 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/google/s2a-go v0.1.9 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
+	github.com/googleapis/gax-go/v2 v2.14.1 // indirect
+	github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
+	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
+	go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
+	go.opentelemetry.io/otel v1.35.0 // indirect
+	go.opentelemetry.io/otel/metric v1.35.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.35.0 // indirect
+	go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
+	go.opentelemetry.io/otel/trace v1.35.0 // indirect
+	golang.org/x/oauth2 v0.29.0 // indirect
+	golang.org/x/sync v0.13.0 // indirect
+	golang.org/x/sys v0.32.0 // indirect
+	golang.org/x/term v0.31.0 // indirect
+	golang.org/x/text v0.24.0 // indirect
+	golang.org/x/time v0.11.0 // indirect
+	google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
+	google.golang.org/grpc v1.71.1 // indirect
+	google.golang.org/protobuf v1.36.6 // indirect
 )
diff --git a/src/go.sum b/src/go.sum
index 3b0bcfc..5ada5b4 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -1,10 +1,123 @@
+cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
+cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
+cloud.google.com/go v0.120.1 h1:Z+5V7yd383+9617XDCyszmK5E4wJRJL+tquMfDj9hLM=
+cloud.google.com/go v0.120.1/go.mod h1:56Vs7sf/i2jYM6ZL9NYlC82r04PThNcPS5YgFmb0rp8=
+cloud.google.com/go/auth v0.16.0 h1:Pd8P1s9WkcrBE2n/PhAwKsdrR35V3Sg2II9B+ndM3CU=
+cloud.google.com/go/auth v0.16.0/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
+cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
+cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
+cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
+cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
+cloud.google.com/go/iam v1.5.0 h1:QlLcVMhbLGOjRcGe6VTGGTyQib8dRLK2B/kYNV0+2xs=
+cloud.google.com/go/iam v1.5.0/go.mod h1:U+DOtKQltF/LxPEtcDLoobcsZMilSRwR7mgNL7knOpo=
+cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
+cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
+cloud.google.com/go/longrunning v0.6.6 h1:XJNDo5MUfMM05xK3ewpbSdmt7R2Zw+aQEMbdQR65Rbw=
+cloud.google.com/go/longrunning v0.6.6/go.mod h1:hyeGJUrPHcx0u2Uu1UFSoYZLn4lkMrccJig0t4FI7yw=
+cloud.google.com/go/monitoring v1.24.1 h1:vKiypZVFD/5a3BbQMvI4gZdl8445ITzXFh257XBgrS0=
+cloud.google.com/go/monitoring v1.24.1/go.mod h1:Z05d1/vn9NaujqY2voG6pVQXoJGbp+r3laV+LySt9K0=
+cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDlCw=
+cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc=
+cloud.google.com/go/trace v1.11.5 h1:CALS1loyxJMnRiCwZSpdf8ac7iCsjreMxFD2WGxzzHU=
+cloud.google.com/go/trace v1.11.5/go.mod h1:TwblCcqNInriu5/qzaeYEIH7wzUcchSdeY2l5wL3Eec=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
-golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
-golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
-golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
-golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
-golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
-golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
-golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0 h1:OqVGm6Ei3x5+yZmSJG1Mh2NwHvpVmZ08CB5qJhT9Nuk=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
+github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k=
+github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
+github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
+github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
+github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
+github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
+github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
+github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
+github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
+github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
+github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
+github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
+github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
+github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
+github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
+github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
+github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA=
+go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
+go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
+go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
+go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
+go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
+go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
+go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
+go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
+go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
+go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
+go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
+go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
+go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
+golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
+golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
+golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
+golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
+golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
+google.golang.org/api v0.229.0 h1:p98ymMtqeJ5i3lIBMj5MpR9kzIIgzpHHh8vQ+vgAzx8=
+google.golang.org/api v0.229.0/go.mod h1:wyDfmq5g1wYJWn29O22FDWN48P7Xcz0xz+LBpptYvB0=
+google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e h1:mYHFv3iX85YMwhGSaZS4xpkM8WQDmJUovz7yqsFrwDk=
+google.golang.org/genproto v0.0.0-20250414145226-207652e42e2e/go.mod h1:TQT1YpH/rlDCS5+EuFaqPIMqDfuNMFR1OI8EcZJGgAk=
+google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
+google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
index 570dec6..e9c8fbe 100644
--- a/src/include/openssl/aead.h
+++ b/src/include/openssl/aead.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_AEAD_H
 #define OPENSSL_HEADER_AEAD_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
@@ -186,6 +186,16 @@
 // constant-time AES-GCM.
 OPENSSL_EXPORT int EVP_has_aes_hardware(void);
 
+// EVP_aead_aes_128_eax is AES-128 in EAX mode. Nonce size is either 12 or 16
+// bytes, tag length is 16 bytes.
+// See https://doi.org/10.1007/978-3-540-25937-4_25.
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_eax(void);
+
+// EVP_aead_aes_256_eax is AES-256 in EAX mode. Nonce size is either 12 or 16
+// bytes, tag length is 16 bytes.
+// See https://doi.org/10.1007/978-3-540-25937-4_25.
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_eax(void);
+
 
 // Utility functions.
 
@@ -210,7 +220,7 @@
 // AEAD operations.
 
 union evp_aead_ctx_st_state {
-  uint8_t opaque[564];
+  uint8_t opaque[560];
   uint64_t alignment;
 };
 
@@ -356,12 +366,10 @@
 // If |in| and |out| alias then |out| must be == |in|. |out_tag| may not alias
 // any other argument.
 OPENSSL_EXPORT int EVP_AEAD_CTX_seal_scatter(
-    const EVP_AEAD_CTX *ctx, uint8_t *out,
-    uint8_t *out_tag, size_t *out_tag_len, size_t max_out_tag_len,
-    const uint8_t *nonce, size_t nonce_len,
-    const uint8_t *in, size_t in_len,
-    const uint8_t *extra_in, size_t extra_in_len,
-    const uint8_t *ad, size_t ad_len);
+    const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
+    size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
+    size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+    size_t extra_in_len, const uint8_t *ad, size_t ad_len);
 
 // EVP_AEAD_CTX_open_gather decrypts and authenticates |in_len| bytes from |in|
 // and authenticates |ad_len| bytes from |ad| using |in_tag_len| bytes of
diff --git a/src/include/openssl/aes.h b/src/include/openssl/aes.h
index ea3e9d9..eee88a5 100644
--- a/src/include/openssl/aes.h
+++ b/src/include/openssl/aes.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_AES_H
 #define OPENSSL_HEADER_AES_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 2b06074..8eb8e8b 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_ASN1_H
 #define OPENSSL_HEADER_ASN1_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <time.h>
 
@@ -77,6 +77,10 @@
 // V_ASN1_ANY is used by the ASN.1 templates to indicate an ANY type.
 #define V_ASN1_ANY (-4)
 
+// V_ASN1_ANY_AS_STRING is used by the ASN.1 templates to indicate an ANY type
+// represented with |ASN1_STRING| instead of |ASN1_TYPE|.
+#define V_ASN1_ANY_AS_STRING (-5)
+
 // The following constants are tag numbers for universal types.
 #define V_ASN1_EOC 0
 #define V_ASN1_BOOLEAN 1
@@ -128,21 +132,13 @@
 #define B_ASN1_OCTET_STRING 0x0200
 #define B_ASN1_BIT_STRING 0x0400
 #define B_ASN1_BMPSTRING 0x0800
-#define B_ASN1_UNKNOWN 0x1000
 #define B_ASN1_UTF8STRING 0x2000
 #define B_ASN1_UTCTIME 0x4000
 #define B_ASN1_GENERALIZEDTIME 0x8000
 #define B_ASN1_SEQUENCE 0x10000
 
 // ASN1_tag2bit converts |tag| from the tag number of a universal type to a
-// corresponding |B_ASN1_*| constant, |B_ASN1_UNKNOWN|, or zero. If the
-// |B_ASN1_*| constant above is defined, it will map the corresponding
-// |V_ASN1_*| constant to it. Otherwise, whether it returns |B_ASN1_UNKNOWN| or
-// zero is ill-defined and callers should not rely on it.
-//
-// TODO(https://crbug.com/boringssl/412): Figure out what |B_ASN1_UNNOWN| vs
-// zero is meant to be. The main impact is what values go in |B_ASN1_PRINTABLE|.
-// To that end, we must return zero on types that can't go in |ASN1_STRING|.
+// corresponding |B_ASN1_*| constant, or zero if |tag| has no bitmask.
 OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag);
 
 // ASN1_tag2str returns a string representation of |tag|, interpret as a tag
@@ -1855,50 +1851,6 @@
 #define M_ASN1_UTF8STRING_new() ASN1_UTF8STRING_new()
 #define M_ASN1_UTF8STRING_free(a) ASN1_UTF8STRING_free(a)
 
-// B_ASN1_PRINTABLE is a bitmask for an ad-hoc subset of string-like types. Note
-// the presence of |B_ASN1_UNKNOWN| means it includes types which |ASN1_tag2bit|
-// maps to |B_ASN1_UNKNOWN|.
-//
-// Do not use this. Despite the name, it has no connection to PrintableString or
-// printable characters. See https://crbug.com/boringssl/412.
-#define B_ASN1_PRINTABLE                                              \
-  (B_ASN1_NUMERICSTRING | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | \
-   B_ASN1_IA5STRING | B_ASN1_BIT_STRING | B_ASN1_UNIVERSALSTRING |    \
-   B_ASN1_BMPSTRING | B_ASN1_UTF8STRING | B_ASN1_SEQUENCE | B_ASN1_UNKNOWN)
-
-// ASN1_PRINTABLE_new returns a newly-allocated |ASN1_STRING| with type -1, or
-// NULL on error. The resulting |ASN1_STRING| is not a valid ASN.1 value until
-// initialized with a value.
-OPENSSL_EXPORT ASN1_STRING *ASN1_PRINTABLE_new(void);
-
-// ASN1_PRINTABLE_free calls |ASN1_STRING_free|.
-OPENSSL_EXPORT void ASN1_PRINTABLE_free(ASN1_STRING *str);
-
-// d2i_ASN1_PRINTABLE parses up to |len| bytes from |*inp| as a DER-encoded
-// CHOICE of an ad-hoc subset of string-like types, as described in
-// |d2i_SAMPLE|.
-//
-// Do not use this. Despite, the name it has no connection to PrintableString or
-// printable characters. See https://crbug.com/boringssl/412.
-//
-// TODO(https://crbug.com/boringssl/354): This function currently also accepts
-// BER, but this will be removed in the future.
-OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_PRINTABLE(ASN1_STRING **out,
-                                               const uint8_t **inp, long len);
-
-// i2d_ASN1_PRINTABLE marshals |in| as DER, as described in |i2d_SAMPLE|.
-//
-// Do not use this. Despite the name, it has no connection to PrintableString or
-// printable characters. See https://crbug.com/boringssl/412.
-OPENSSL_EXPORT int i2d_ASN1_PRINTABLE(const ASN1_STRING *in, uint8_t **outp);
-
-// ASN1_PRINTABLE is an |ASN1_ITEM| whose ASN.1 type is a CHOICE of an ad-hoc
-// subset of string-like types, and whose C type is |ASN1_STRING*|.
-//
-// Do not use this. Despite the name, it has no connection to PrintableString or
-// printable characters. See https://crbug.com/boringssl/412.
-DECLARE_ASN1_ITEM(ASN1_PRINTABLE)
-
 // ASN1_INTEGER_set sets |a| to an INTEGER with value |v|. It returns one on
 // success and zero on error.
 //
diff --git a/src/include/openssl/asn1t.h b/src/include/openssl/asn1t.h
index 9ac58a7..60c1b62 100644
--- a/src/include/openssl/asn1t.h
+++ b/src/include/openssl/asn1t.h
@@ -16,7 +16,7 @@
 #define OPENSSL_HEADER_ASN1T_H
 
 #include <openssl/asn1.h>
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 3be025e..ebbb1cf 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -16,10 +16,12 @@
 #define OPENSSL_HEADER_BASE_H
 
 
-// This file should be the first included by all BoringSSL headers.
+// This file should be the first included by all BoringSSL headers. All
+// BoringSSL headers can be assumed to import this file, and this header can be
+// assumed to include stddef.h (size_t) and stdint.h (uint*_t, etc).
 
-#include <stddef.h>
-#include <stdint.h>
+#include <stddef.h>  // IWYU pragma: export
+#include <stdint.h>  // IWYU pragma: export
 #include <stdlib.h>
 #include <sys/types.h>
 
@@ -71,7 +73,7 @@
 // A consumer may use this symbol in the preprocessor to temporarily build
 // against multiple revisions of BoringSSL at the same time. It is not
 // recommended to do so for longer than is necessary.
-#define BORINGSSL_API_VERSION 34
+#define BORINGSSL_API_VERSION 36
 
 #if defined(BORINGSSL_SHARED_LIBRARY)
 
@@ -260,6 +262,8 @@
 typedef struct asn1_type_st ASN1_TYPE;
 typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
 typedef struct BASIC_CONSTRAINTS_st BASIC_CONSTRAINTS;
+typedef struct CMS_ContentInfo_st CMS_ContentInfo;
+typedef struct CMS_SignerInfo_st CMS_SignerInfo;
 typedef struct DIST_POINT_st DIST_POINT;
 typedef struct DSA_SIG_st DSA_SIG;
 typedef struct GENERAL_NAME_st GENERAL_NAME;
diff --git a/src/include/openssl/base64.h b/src/include/openssl/base64.h
index 96086e0..ca265cd 100644
--- a/src/include/openssl/base64.h
+++ b/src/include/openssl/base64.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BASE64_H
 #define OPENSSL_HEADER_BASE64_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/bcm_public.h b/src/include/openssl/bcm_public.h
index a7e97a6..c5326e2 100644
--- a/src/include/openssl/bcm_public.h
+++ b/src/include/openssl/bcm_public.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BCM_PUBLIC_H_
 #define OPENSSL_HEADER_BCM_PUBLIC_H_
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 099d3d7..28e23d8 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BIO_H
 #define OPENSSL_HEADER_BIO_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <stdio.h>  // For FILE
 
diff --git a/src/include/openssl/blake2.h b/src/include/openssl/blake2.h
index 24389c0..5378fc3 100644
--- a/src/include/openssl/blake2.h
+++ b/src/include/openssl/blake2.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BLAKE2_H
 #define OPENSSL_HEADER_BLAKE2_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/blowfish.h b/src/include/openssl/blowfish.h
index 66a1cc9..926555e 100644
--- a/src/include/openssl/blowfish.h
+++ b/src/include/openssl/blowfish.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BLOWFISH_H
 #define OPENSSL_HEADER_BLOWFISH_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index 466823b..6d95db8 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -16,7 +16,7 @@
 #ifndef OPENSSL_HEADER_BN_H
 #define OPENSSL_HEADER_BN_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/thread.h>
 
 #include <inttypes.h>  // for PRIu64 and friends
diff --git a/src/include/openssl/buf.h b/src/include/openssl/buf.h
index 74ef14f..18ae3a1 100644
--- a/src/include/openssl/buf.h
+++ b/src/include/openssl/buf.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BUFFER_H
 #define OPENSSL_HEADER_BUFFER_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index 813decb..1738c08 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_BYTESTRING_H
 #define OPENSSL_HEADER_BYTESTRING_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/span.h>
 #include <time.h>
@@ -601,6 +601,12 @@
 // child's contents nor the length prefix will be included in the output.
 OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);
 
+// CBB_add_asn1_element adds an ASN.1 element with the specified tag and
+// contents. It returns one on success and zero on error. This is a convenience
+// function over |CBB_add_asn1| when the data is already available.
+OPENSSL_EXPORT int CBB_add_asn1_element(CBB *cbb, CBS_ASN1_TAG tag,
+                                        const uint8_t *data, size_t data_len);
+
 // CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1|
 // and writes |value| in its contents. It returns one on success and zero on
 // error.
diff --git a/src/include/openssl/cast.h b/src/include/openssl/cast.h
index 7cd7fc5..8650094 100644
--- a/src/include/openssl/cast.h
+++ b/src/include/openssl/cast.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CAST_H
 #define OPENSSL_HEADER_CAST_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/src/include/openssl/chacha.h b/src/include/openssl/chacha.h
index 1cc4cb2..ff9f55e 100644
--- a/src/include/openssl/chacha.h
+++ b/src/include/openssl/chacha.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CHACHA_H
 #define OPENSSL_HEADER_CHACHA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/cipher.h b/src/include/openssl/cipher.h
index 6bb1358..13e68ad 100644
--- a/src/include/openssl/cipher.h
+++ b/src/include/openssl/cipher.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CIPHER_H
 #define OPENSSL_HEADER_CIPHER_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/cmac.h b/src/include/openssl/cmac.h
index 05aa312..3e5a2d6 100644
--- a/src/include/openssl/cmac.h
+++ b/src/include/openssl/cmac.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CMAC_H
 #define OPENSSL_HEADER_CMAC_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/cms.h b/src/include/openssl/cms.h
new file mode 100644
index 0000000..6616348a
--- /dev/null
+++ b/src/include/openssl/cms.h
@@ -0,0 +1,146 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef OPENSSL_HEADER_CMS_H
+#define OPENSSL_HEADER_CMS_H
+
+#include <openssl/base.h>   // IWYU pragma: export
+
+#include <openssl/stack.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// CMS.
+//
+// This library contains functions for implementing a small subset of OpenSSL's
+// API for CMS (RFC 5652). A general CMS implementation, notably one suitable
+// for S/MIME, is out of scope for BoringSSL.
+//
+// As this library is intentionally not a general CMS implementation, BoringSSL
+// continues to define |OPENSSL_NO_CMS|, so that most callers turn off their
+// general-purpose CMS code. In callers that are compatible with this subset,
+// the |BORINGSSL_NO_NO_CMS| build option can be used to suppress
+// |OPENSSL_NO_CMS|.
+
+DECLARE_STACK_OF(X509)
+
+// CMS_* are flags that can be passed to functions in this library. Their
+// interpretation is specified in the corresponding functinos.
+#define CMS_NOCERTS 0x2
+#define CMS_DETACHED 0x40
+#define CMS_BINARY 0x80
+#define CMS_NOATTR 0x100
+#define CMS_NOSMIMECAP 0x200
+#define CMS_STREAM 0x1000
+#define CMS_PARTIAL 0x4000
+#define CMS_USE_KEYID 0x10000
+#define CMS_NO_SIGNING_TIME 0x400000
+
+// CMS_sign returns a newly-allocated |CMS_ContentInfo| structure for building a
+// SignedData (RFC 5652), or NULL on error.
+//
+// |certs| must be NULL or zero length. BoringSSL does not support embedding
+// certificates in SignedData.
+//
+// |flags| must contain |CMS_DETACHED|, which indicates an external signature.
+// BoringSSL only supports generating external signatures and does not support
+// embedding encapsulated content directly in a SignedData.
+//
+// If |pkey| is non-NULL, |CMS_add1_signer| is automatically called with
+// |signcert|, |pkey|, a default hash of SHA-256, and |flags|. |flags| will then
+// additionally be interpreted as in |CMS_add1_signer|.
+//
+// If |CMS_PARTIAL| or |CMS_STREAM| is set in |flags|, the object will be left
+// incomplete. |data| will then be ignored and should be NULL. The caller can
+// then continue configuring it and finalizing it with |CMS_final|. Otherwise,
+// the object will be finalized with |data| and |flags| passed to |CMS_final|.
+OPENSSL_EXPORT CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
+                                         STACK_OF(X509) *certs, BIO *data,
+                                         uint32_t flags);
+
+// CMS_ContentInfo_free releases memory associated with |cms|.
+OPENSSL_EXPORT void CMS_ContentInfo_free(CMS_ContentInfo *cms);
+
+// CMS_add1_signer adds a signer to |cms|, which must be a SignedData created by
+// |CMS_sign|, with the |CMS_PARTIAL| flag set. The signer will use |signcert|,
+// |pkey|, and |md| for the signing certificate, private key, and digest
+// algorithm, respectively. It returns a non-NULL pointer to the signer on
+// success, and NULL on error. The signer is owned by |cms| and should not be
+// released by the caller.
+//
+// |flags| is interpreted as follows:
+//
+// - |CMS_PARTIAL| must not be set. BoringSSL does not support configuring a
+//   signer in multiple steps.
+//
+// - |CMS_NOCERTS| must be set. BoringSSL does not support embedding
+//   certificates in SignedData.
+//
+// - |CMS_NOATTR| must be set. BoringSSL does not support attributes in
+//   SignedData.
+//
+// - If |CMS_USE_KEYID| is set, SignerInfos will be identified by subject key
+//   identifier instead of issuer and serial number. |signcert| must then have
+//   the subject key identifier extension.
+//
+// BoringSSL currently only supports one signer per |CMS_ContentInfo|.
+// Subsequent calls will fail. Additionally, only RSA keys are currently
+// supported for |pkey|.
+OPENSSL_EXPORT CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
+                                               X509 *signcert, EVP_PKEY *pkey,
+                                               const EVP_MD *md,
+                                               uint32_t flags);
+
+// CMS_final finalizes constructing |cms|, which must have been initialized with
+// the |CMS_PARTIAL| flag. |data| is read, until EOF, as the data to be
+// processed by CMS. It returns one on success and zero on error.
+//
+// |CMS_BINARY| must be set in |flags|. BoringSSL does not support translating
+// inputs according to S/MIME.
+//
+// |dcont| must be NULL. What a non-NULL |dcont| does is not clearly documented
+// by OpenSSL, and there are no tests to demonstrate its behavior.
+OPENSSL_EXPORT int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
+                             uint32_t flags);
+
+// i2d_CMS_bio encodes |cms| as a DER-encoded ContentInfo structure (RFC 5652).
+// It returns one on success and zero on failure.
+OPENSSL_EXPORT int i2d_CMS_bio(BIO *out, CMS_ContentInfo *cms);
+
+// i2d_CMS_bio_stream calls |i2d_CMS_bio|. |in| must be NULL and |flags| must
+// not contain |CMS_STREAM|. BoringSSL does not support any streaming modes for
+// CMS.
+OPENSSL_EXPORT int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
+                                      int flags);
+
+
+#if defined(__cplusplus)
+}  // extern C
+
+extern "C++" {
+BSSL_NAMESPACE_BEGIN
+
+BORINGSSL_MAKE_DELETER(CMS_ContentInfo, CMS_ContentInfo_free)
+
+BSSL_NAMESPACE_END
+}  // extern C++
+#endif
+
+#define CMS_R_CERTIFICATE_HAS_NO_KEYID 100
+#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 101
+
+#endif  // OPENSSL_HEADER_CMS_H
diff --git a/src/include/openssl/conf.h b/src/include/openssl/conf.h
index f1005bb..ff20b60 100644
--- a/src/include/openssl/conf.h
+++ b/src/include/openssl/conf.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CONF_H
 #define OPENSSL_HEADER_CONF_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/stack.h>
 #include <openssl/lhash.h>
diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h
index ff42a95..ca1ca2f 100644
--- a/src/include/openssl/crypto.h
+++ b/src/include/openssl/crypto.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CRYPTO_H
 #define OPENSSL_HEADER_CRYPTO_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/sha.h>
 
 // Upstream OpenSSL defines |OPENSSL_malloc|, etc., in crypto.h rather than
@@ -46,10 +46,17 @@
 // in which case it returns zero.
 OPENSSL_EXPORT int CRYPTO_has_asm(void);
 
-// BORINGSSL_self_test triggers the FIPS KAT-based self tests. It returns one on
-// success and zero on error.
+// BORINGSSL_self_test triggers most of the FIPS KAT-based self tests. It
+// returns one on success and zero on error. It currently skips the SLH-DSA
+// tests, which take a really long time to run.
 OPENSSL_EXPORT int BORINGSSL_self_test(void);
 
+// BORINGSSL_self_test_all triggers all of the FIPS KAT-based self tests. This
+// is the 'self-test' entry point required by FIPS 140. It returns one on
+// success and zero on error. This test will take a very long time to run. You
+// probably do not want to run this in a resource or time constrained test.
+OPENSSL_EXPORT int BORINGSSL_self_test_all(void);
+
 // BORINGSSL_integrity_test triggers the module's integrity test where the code
 // and data of the module is matched against a hash injected at build time. It
 // returns one on success or zero if there's a mismatch. This function only
@@ -71,6 +78,19 @@
 OPENSSL_EXPORT int CRYPTO_needs_hwcap2_workaround(void);
 #endif  // OPENSSL_ARM && OPENSSL_LINUX && !OPENSSL_STATIC_ARMCAP
 
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+// CRYPTO_set_fuzzer_mode, in non-production fuzzer builds, configures a "fuzzer
+// mode" in the library, which disables various signature checks and disables
+// encryption in parts of TLS.
+//
+// By default, fuzzer builds make the PRNG deterministic (and thus unsafe for
+// production), but continue to run cryptographic operations as usual. This
+// allows a fuzzer build of BoringSSL to be used dependency of fuzzer builds of
+// other libraries, without changing in semantics. This function enables further
+// incompatible changes intended for fuzzing BoringSSL itself.
+OPENSSL_EXPORT void CRYPTO_set_fuzzer_mode(int enabled);
+#endif
+
 
 // FIPS monitoring
 
diff --git a/src/include/openssl/ctrdrbg.h b/src/include/openssl/ctrdrbg.h
index a92c065..6074935 100644
--- a/src/include/openssl/ctrdrbg.h
+++ b/src/include/openssl/ctrdrbg.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CTRDRBG_H
 #define OPENSSL_HEADER_CTRDRBG_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/curve25519.h b/src/include/openssl/curve25519.h
index 0d28966..85a08b8 100644
--- a/src/include/openssl/curve25519.h
+++ b/src/include/openssl/curve25519.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_CURVE25519_H
 #define OPENSSL_HEADER_CURVE25519_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/des.h b/src/include/openssl/des.h
index 8f97848..9dbcb8e 100644
--- a/src/include/openssl/des.h
+++ b/src/include/openssl/des.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_DES_H
 #define OPENSSL_HEADER_DES_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h
index 5f2c9aa..5b6ec18 100644
--- a/src/include/openssl/dh.h
+++ b/src/include/openssl/dh.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_DH_H
 #define OPENSSL_HEADER_DH_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/thread.h>
 
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
index 5ddc2d3..6abab76 100644
--- a/src/include/openssl/digest.h
+++ b/src/include/openssl/digest.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_DIGEST_H
 #define OPENSSL_HEADER_DIGEST_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
@@ -166,11 +166,6 @@
 // EVP_MD_block_size returns the native block-size of |md|, in bytes.
 OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md);
 
-// EVP_MD_FLAG_PKEY_DIGEST indicates that the digest function is used with a
-// specific public key in order to verify signatures. (For example,
-// EVP_dss1.)
-#define EVP_MD_FLAG_PKEY_DIGEST 1
-
 // EVP_MD_FLAG_DIGALGID_ABSENT indicates that the parameter type in an X.509
 // DigestAlgorithmIdentifier representing this digest function should be
 // undefined rather than NULL.
@@ -220,9 +215,26 @@
 
 // EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier
 // structure and appends the result to |cbb|. It returns one on success and zero
-// on error.
+// on error. It sets the parameters field to NULL. Use
+// |EVP_marshal_digest_algorithm_no_params| to omit the parameters instead.
+//
+// In general, the parameters should be omitted for digest algorithms, but the
+// following specifications require a NULL parameter instead.
+//
+// - Hash algorithms and MGF-1 hash algorithms used in RSASSA-PSS and RSAES-OAEP
+//   (see RFC 4055, Section 2.1)
+// - The hash algorithm in the DigestInfo structure of RSASSA-PKCS1-v1_5 (see
+//   RFC 8017, Appendix A.2.4)
+//
+// Some existing software also uses NULL parameters in other contexts. In
+// practice, digest algorithms are encoded wildly inconsistently.
 OPENSSL_EXPORT int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md);
 
+// EVP_marshal_digest_algorithm_no_params behaves like
+// |EVP_marshal_digest_algorithm| but omits the parameters field.
+OPENSSL_EXPORT int EVP_marshal_digest_algorithm_no_params(CBB *cbb,
+                                                          const EVP_MD *md);
+
 
 // Deprecated functions.
 
diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h
index 9e5b6e2..9b3d20c 100644
--- a/src/include/openssl/dsa.h
+++ b/src/include/openssl/dsa.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_DSA_H
 #define OPENSSL_HEADER_DSA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/ex_data.h>
 
diff --git a/src/include/openssl/e_os2.h b/src/include/openssl/e_os2.h
index cebb2fc..06dcc70 100644
--- a/src/include/openssl/e_os2.h
+++ b/src/include/openssl/e_os2.h
@@ -15,4 +15,4 @@
 /* This header is provided in order to make compiling against code that expects
    OpenSSL easier. */
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
diff --git a/src/include/openssl/ec.h b/src/include/openssl/ec.h
index 4349965..6f1d3d5 100644
--- a/src/include/openssl/ec.h
+++ b/src/include/openssl/ec.h
@@ -16,7 +16,7 @@
 #ifndef OPENSSL_HEADER_EC_H
 #define OPENSSL_HEADER_EC_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/ec_key.h b/src/include/openssl/ec_key.h
index ac0ac01..1219cf1 100644
--- a/src/include/openssl/ec_key.h
+++ b/src/include/openssl/ec_key.h
@@ -16,7 +16,7 @@
 #ifndef OPENSSL_HEADER_EC_KEY_H
 #define OPENSSL_HEADER_EC_KEY_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/ec.h>
 #include <openssl/engine.h>
diff --git a/src/include/openssl/ecdh.h b/src/include/openssl/ecdh.h
index 14a26a0..35a99e6 100644
--- a/src/include/openssl/ecdh.h
+++ b/src/include/openssl/ecdh.h
@@ -16,7 +16,7 @@
 #ifndef OPENSSL_HEADER_ECDH_H
 #define OPENSSL_HEADER_ECDH_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/ec_key.h>
 
diff --git a/src/include/openssl/ecdsa.h b/src/include/openssl/ecdsa.h
index 5016c2d..f60f037 100644
--- a/src/include/openssl/ecdsa.h
+++ b/src/include/openssl/ecdsa.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_ECDSA_H
 #define OPENSSL_HEADER_ECDSA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/ec_key.h>
 
diff --git a/src/include/openssl/engine.h b/src/include/openssl/engine.h
index 1addd73..6765c28 100644
--- a/src/include/openssl/engine.h
+++ b/src/include/openssl/engine.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_ENGINE_H
 #define OPENSSL_HEADER_ENGINE_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/err.h b/src/include/openssl/err.h
index 8d5596d..0263505 100644
--- a/src/include/openssl/err.h
+++ b/src/include/openssl/err.h
@@ -17,7 +17,7 @@
 
 #include <stdio.h>
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
@@ -253,6 +253,7 @@
   ERR_LIB_CIPHER,
   ERR_LIB_HKDF,
   ERR_LIB_TRUST_TOKEN,
+  ERR_LIB_CMS,
   ERR_LIB_USER,
   ERR_NUM_LIBS
 };
diff --git a/src/include/openssl/evp.h b/src/include/openssl/evp.h
index d99803f..eaf041d 100644
--- a/src/include/openssl/evp.h
+++ b/src/include/openssl/evp.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_EVP_H
 #define OPENSSL_HEADER_EVP_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/evp_errors.h>  // IWYU pragma: export
 #include <openssl/thread.h>
diff --git a/src/include/openssl/ex_data.h b/src/include/openssl/ex_data.h
index 111cb0e..9ce1a93 100644
--- a/src/include/openssl/ex_data.h
+++ b/src/include/openssl/ex_data.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_EX_DATA_H
 #define OPENSSL_HEADER_EX_DATA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/stack.h>
 
diff --git a/src/include/openssl/experimental/kyber.h b/src/include/openssl/experimental/kyber.h
index 7a8d631..14ff973 100644
--- a/src/include/openssl/experimental/kyber.h
+++ b/src/include/openssl/experimental/kyber.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_KYBER_H
 #define OPENSSL_HEADER_KYBER_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/hkdf.h b/src/include/openssl/hkdf.h
index 246c73e..19663db 100644
--- a/src/include/openssl/hkdf.h
+++ b/src/include/openssl/hkdf.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_HKDF_H
 #define OPENSSL_HEADER_HKDF_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/hmac.h b/src/include/openssl/hmac.h
index eab50a35..7f62643 100644
--- a/src/include/openssl/hmac.h
+++ b/src/include/openssl/hmac.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_HMAC_H
 #define OPENSSL_HEADER_HMAC_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/digest.h>
 
diff --git a/src/include/openssl/hpke.h b/src/include/openssl/hpke.h
index 4502ec8..ca10731 100644
--- a/src/include/openssl/hpke.h
+++ b/src/include/openssl/hpke.h
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H
-#define OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H
+#ifndef OPENSSL_HEADER_HPKE_H
+#define OPENSSL_HEADER_HPKE_H
 
 #include <openssl/aead.h>
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/curve25519.h>
 #include <openssl/digest.h>
 
@@ -406,4 +406,4 @@
 }  // extern C++
 #endif
 
-#endif  // OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H
+#endif  // OPENSSL_HEADER_HPKE_H
diff --git a/src/include/openssl/hrss.h b/src/include/openssl/hrss.h
index 974a130..2a24dff 100644
--- a/src/include/openssl/hrss.h
+++ b/src/include/openssl/hrss.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_HRSS_H
 #define OPENSSL_HEADER_HRSS_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/kdf.h b/src/include/openssl/kdf.h
index 9a25a5f..29daa6a 100644
--- a/src/include/openssl/kdf.h
+++ b/src/include/openssl/kdf.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_KDF_H
 #define OPENSSL_HEADER_KDF_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/lhash.h b/src/include/openssl/lhash.h
index 4f816fa..6b305ac 100644
--- a/src/include/openssl/lhash.h
+++ b/src/include/openssl/lhash.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_LHASH_H
 #define OPENSSL_HEADER_LHASH_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/md4.h b/src/include/openssl/md4.h
index b5ebae1..dc45b67 100644
--- a/src/include/openssl/md4.h
+++ b/src/include/openssl/md4.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_MD4_H
 #define OPENSSL_HEADER_MD4_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/md5.h b/src/include/openssl/md5.h
index 2c7e253..1e7d519 100644
--- a/src/include/openssl/md5.h
+++ b/src/include/openssl/md5.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_MD5_H
 #define OPENSSL_HEADER_MD5_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/mem.h b/src/include/openssl/mem.h
index 456876b..e0ac688 100644
--- a/src/include/openssl/mem.h
+++ b/src/include/openssl/mem.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_MEM_H
 #define OPENSSL_HEADER_MEM_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <stdlib.h>
 #include <stdarg.h>
diff --git a/src/include/openssl/mldsa.h b/src/include/openssl/mldsa.h
index 0c1db20..cc0f850 100644
--- a/src/include/openssl/mldsa.h
+++ b/src/include/openssl/mldsa.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_MLDSA_H_
 #define OPENSSL_HEADER_MLDSA_H_
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/mlkem.h b/src/include/openssl/mlkem.h
index b9b3366..56edc16 100644
--- a/src/include/openssl/mlkem.h
+++ b/src/include/openssl/mlkem.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_MLKEM_H
 #define OPENSSL_HEADER_MLKEM_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/nid.h b/src/include/openssl/nid.h
index bf5536d..88a3e2a 100644
--- a/src/include/openssl/nid.h
+++ b/src/include/openssl/nid.h
@@ -17,7 +17,7 @@
 #ifndef OPENSSL_HEADER_NID_H
 #define OPENSSL_HEADER_NID_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/obj.h b/src/include/openssl/obj.h
index 67e3e9a..b3fabca 100644
--- a/src/include/openssl/obj.h
+++ b/src/include/openssl/obj.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_OBJ_H
 #define OPENSSL_HEADER_OBJ_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/bytestring.h>
 #include <openssl/nid.h>  // IWYU pragma: export
diff --git a/src/include/openssl/obj_mac.h b/src/include/openssl/obj_mac.h
index 2fdac44..d70048c 100644
--- a/src/include/openssl/obj_mac.h
+++ b/src/include/openssl/obj_mac.h
@@ -15,4 +15,4 @@
 /* This header is provided in order to make compiling against code that expects
    OpenSSL easier. */
 
-#include "nid.h"
+#include "nid.h"  // IWYU pragma: export
diff --git a/src/include/openssl/opensslconf.h b/src/include/openssl/opensslconf.h
index d06f7d0..7249fdc 100644
--- a/src/include/openssl/opensslconf.h
+++ b/src/include/openssl/opensslconf.h
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-/* This header is provided in order to make compiling against code that expects
-   OpenSSL easier. */
+// This header is provided in order to make compiling against code that expects
+// OpenSSL easier.
 
 #ifndef OPENSSL_HEADER_OPENSSLCONF_H
 #define OPENSSL_HEADER_OPENSSLCONF_H
 
-/* Keep in sync with the list in rust/bssl-sys/build.rs */
+// Keep in sync with the list in rust/bssl-sys/build.rs.
 
 #define OPENSSL_NO_ASYNC
 #define OPENSSL_NO_BF
@@ -27,7 +27,6 @@
 #define OPENSSL_NO_CAMELLIA
 #define OPENSSL_NO_CAPIENG
 #define OPENSSL_NO_CAST
-#define OPENSSL_NO_CMS
 #define OPENSSL_NO_COMP
 #define OPENSSL_NO_CT
 #define OPENSSL_NO_DANE
@@ -68,5 +67,12 @@
 #define OPENSSL_NO_STORE
 #define OPENSSL_NO_WHIRLPOOL
 
+// We do not implement OpenSSL's CMS API, except for a tiny subset. Projects
+// targeting the tiny subset can define BORINGSSL_NO_NO_CMS to suppress
+// OPENSSL_NO_CMS, to make it easier to compile code that expects OpenSSL. This
+// option does not change what APIs are exposed by BoringSSL, only this macro.
+#if !defined(BORINGSSL_NO_NO_CMS)
+#define OPENSSL_NO_CMS
+#endif
 
 #endif  // OPENSSL_HEADER_OPENSSLCONF_H
diff --git a/src/include/openssl/pkcs7.h b/src/include/openssl/pkcs7.h
index ea18c65..9990580 100644
--- a/src/include/openssl/pkcs7.h
+++ b/src/include/openssl/pkcs7.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_PKCS7_H
 #define OPENSSL_HEADER_PKCS7_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/stack.h>
 
diff --git a/src/include/openssl/pkcs8.h b/src/include/openssl/pkcs8.h
index 173ff96..8693566 100644
--- a/src/include/openssl/pkcs8.h
+++ b/src/include/openssl/pkcs8.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_PKCS8_H
 #define OPENSSL_HEADER_PKCS8_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/x509.h>
 
 
@@ -174,11 +174,24 @@
 // |NID_pbe_WithSHA1And40BitRC2_CBC|, |PKCS12_DEFAULT_ITER|, and one,
 // respectively.
 //
-// |key_nid| or |cert_nid| may also be -1 to disable encryption of the key or
-// certificate, respectively. This option is not recommended and is only
-// implemented for compatibility with external packages. Note the output still
-// requires a password for the MAC. Unencrypted keys in PKCS#12 are also not
-// widely supported and may not open in other implementations.
+// |key_nid| and |cert_nid| are then interpreted as follows:
+//
+// * If the NID is a cipher that is supported with PBES2, e.g.
+//   |NID_aes_256_cbc|, this function will use it with PBES2 and a default KDF
+//   (currently PBKDF2 with HMAC-SHA1). There is no way to specify the KDF in
+//   this function.
+//
+// * If the NID is a PBES1 suite, e.g. |NID_pbe_WithSHA1And3_Key_TripleDES_CBC|,
+//   this function will use the specified suite.
+//
+// * If the NID is -1, this function will disable encryption for the key or
+//   certificate. This option is not recommended and is only implemented for
+//   compatibility with external packages. Note the output still requires a
+//   password for the MAC. Unencrypted keys in PKCS#12 are also not widely
+//   supported and may not open in other implementations.
+//
+// WARNING: This differs from other functions in this module, which use a pair
+// of NID and |EVP_CIPHER| parameters to pick between PBES1 and PBES2 schemes.
 //
 // If |cert| or |chain| have associated aliases (see |X509_alias_set1|), they
 // will be included in the output as friendlyName attributes (RFC 2985). It is
diff --git a/src/include/openssl/pki/certificate.h b/src/include/openssl/pki/certificate.h
index a7ef188..3eeeeef 100644
--- a/src/include/openssl/pki/certificate.h
+++ b/src/include/openssl/pki/certificate.h
@@ -19,7 +19,7 @@
 #include <string>
 #include <string_view>
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/span.h>
 
 BSSL_NAMESPACE_BEGIN
diff --git a/src/include/openssl/pki/ocsp.h b/src/include/openssl/pki/ocsp.h
index 4500804..e3f55f9 100644
--- a/src/include/openssl/pki/ocsp.h
+++ b/src/include/openssl/pki/ocsp.h
@@ -15,7 +15,7 @@
 #if !defined(OPENSSL_HEADER_BSSL_PKI_OCSP_H_)  && defined(__cplusplus)
 #define OPENSSL_HEADER_BSSL_PKI_OCSP_H_
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <string_view>
 #include <optional>
 
diff --git a/src/include/openssl/pki/signature_verify_cache.h b/src/include/openssl/pki/signature_verify_cache.h
index a31450d..1bc49ec 100644
--- a/src/include/openssl/pki/signature_verify_cache.h
+++ b/src/include/openssl/pki/signature_verify_cache.h
@@ -15,7 +15,7 @@
 #if !defined(BSSL_PKI_SIGNATURE_VERIFY_CACHE_H_) && defined(__cplusplus)
 #define BSSL_PKI_SIGNATURE_VERIFY_CACHE_H_
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <string>
 
 BSSL_NAMESPACE_BEGIN
diff --git a/src/include/openssl/pki/verify.h b/src/include/openssl/pki/verify.h
index 06ca1af..d22f693 100644
--- a/src/include/openssl/pki/verify.h
+++ b/src/include/openssl/pki/verify.h
@@ -72,6 +72,9 @@
     CLIENT_AUTH_STRICT,
     SERVER_AUTH_STRICT_LEAF,
     CLIENT_AUTH_STRICT_LEAF,
+    RCS_MLS_CLIENT_AUTH,
+    C2PA_TIMESTAMPING,
+    C2PA_MANIFEST
   };
 
   CertificateVerifyOptions();
diff --git a/src/include/openssl/pki/verify_error.h b/src/include/openssl/pki/verify_error.h
index 34cd2bb..22c219d 100644
--- a/src/include/openssl/pki/verify_error.h
+++ b/src/include/openssl/pki/verify_error.h
@@ -15,7 +15,7 @@
 #if !defined(OPENSSL_HEADER_BSSL_PKI_VERIFY_ERROR_H_) && defined(__cplusplus)
 #define OPENSSL_HEADER_BSSL_PKI_VERIFY_ERROR_H_
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <string>
 
diff --git a/src/include/openssl/poly1305.h b/src/include/openssl/poly1305.h
index 196427d..0688d36 100644
--- a/src/include/openssl/poly1305.h
+++ b/src/include/openssl/poly1305.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_POLY1305_H
 #define OPENSSL_HEADER_POLY1305_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/src/include/openssl/pool.h b/src/include/openssl/pool.h
index e739ffe..25ac469 100644
--- a/src/include/openssl/pool.h
+++ b/src/include/openssl/pool.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_POOL_H
 #define OPENSSL_HEADER_POOL_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/stack.h>
 
diff --git a/src/include/openssl/posix_time.h b/src/include/openssl/posix_time.h
index e185adf..b9e0a77 100644
--- a/src/include/openssl/posix_time.h
+++ b/src/include/openssl/posix_time.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_POSIX_TIME_H
 #define OPENSSL_HEADER_POSIX_TIME_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <time.h>
 
diff --git a/src/include/openssl/rand.h b/src/include/openssl/rand.h
index 50cb9ae..1cea36d 100644
--- a/src/include/openssl/rand.h
+++ b/src/include/openssl/rand.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_RAND_H
 #define OPENSSL_HEADER_RAND_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
@@ -59,7 +59,7 @@
 OPENSSL_EXPORT void RAND_disable_fork_unsafe_buffering(void);
 #endif
 
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 // RAND_reset_for_fuzzing resets the fuzzer-only deterministic RNG. This
 // function is only defined in the fuzzer-only build configuration.
 OPENSSL_EXPORT void RAND_reset_for_fuzzing(void);
diff --git a/src/include/openssl/rc4.h b/src/include/openssl/rc4.h
index 3954625..520c3a6 100644
--- a/src/include/openssl/rc4.h
+++ b/src/include/openssl/rc4.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_RC4_H
 #define OPENSSL_HEADER_RC4_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/ripemd.h b/src/include/openssl/ripemd.h
index 6dd1b14..cb23918 100644
--- a/src/include/openssl/ripemd.h
+++ b/src/include/openssl/ripemd.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_RIPEMD_H
 #define OPENSSL_HEADER_RIPEMD_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index f090927..c3395b0 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_RSA_H
 #define OPENSSL_HEADER_RSA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/engine.h>
 #include <openssl/ex_data.h>
@@ -71,7 +71,7 @@
 
 // OPENSSL_RSA_MAX_MODULUS_BITS is the maximum supported RSA modulus, in bits.
 //
-// TODO(davidben): Reduce this to 8192.
+// TODO(crbug.com/402677800): Reduce this to 8192.
 #define OPENSSL_RSA_MAX_MODULUS_BITS 16384
 
 // RSA_bits returns the size of |rsa|, in bits.
diff --git a/src/include/openssl/service_indicator.h b/src/include/openssl/service_indicator.h
index e942f8b..f866b40 100644
--- a/src/include/openssl/service_indicator.h
+++ b/src/include/openssl/service_indicator.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_SERVICE_INDICATOR_H
 #define OPENSSL_HEADER_SERVICE_INDICATOR_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/sha.h b/src/include/openssl/sha.h
index cc9bcf7..8fe7af8 100644
--- a/src/include/openssl/sha.h
+++ b/src/include/openssl/sha.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_SHA_H
 #define OPENSSL_HEADER_SHA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/bcm_public.h> // IWYU pragma: export
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/siphash.h b/src/include/openssl/siphash.h
index 3a5709b..51b0c81 100644
--- a/src/include/openssl/siphash.h
+++ b/src/include/openssl/siphash.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_SIPHASH_H
 #define OPENSSL_HEADER_SIPHASH_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/slhdsa.h b/src/include/openssl/slhdsa.h
index d6aa5b8..e68d741 100644
--- a/src/include/openssl/slhdsa.h
+++ b/src/include/openssl/slhdsa.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_SLHDSA_H
 #define OPENSSL_HEADER_SLHDSA_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/span.h b/src/include/openssl/span.h
index 4d7e791..440b657 100644
--- a/src/include/openssl/span.h
+++ b/src/include/openssl/span.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_SSL_SPAN_H
 #define OPENSSL_HEADER_SSL_SPAN_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if !defined(BORINGSSL_NO_CXX)
 
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index b9bf7ea..f017a03 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -17,7 +17,7 @@
 #ifndef OPENSSL_HEADER_SSL_H
 #define OPENSSL_HEADER_SSL_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <openssl/bio.h>
 #include <openssl/buf.h>
@@ -774,8 +774,6 @@
 // - Whether the peer supports the signature algorithms in the certificate chain
 // - Whether the a server certificate is compatible with the server_name
 //   extension (SNI)
-// - Whether the peer supports the certificate authority that issued the
-//   certificate
 //
 // Credentials may be configured before the handshake or dynamically in the
 // early callback (see |SSL_CTX_set_select_certificate_cb|) and certificate
@@ -829,6 +827,26 @@
 OPENSSL_EXPORT int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL *cred,
                                                      CRYPTO_BUFFER *ocsp);
 
+// SSL_CREDENTIAL_set1_certificate_properties parses
+// |certificate_property_list| as a CertificatePropertyList (see Section 6 of
+// draft-ietf-tls-trust-anchor-ids-00) and applies recognized properties to
+// |cred|. It returns one on success and zero on error. It is an error if
+// |certificate_property_list| does not parse correctly, or if any recognized
+// properties from |certificate_property_list| cannot be applied to |cred|.
+//
+// CertificatePropertyList is an extensible structure which allows serving
+// properties of a certificate chain to be passed from a CA, through an
+// application's issuance and configuration pipeline, and to the TLS serving
+// logic, without requiring application changes for each property defined.
+//
+// BoringSSL currently supports the following properties:
+// * trust_anchor_identifier (see |SSL_CREDENTIAL_set1_trust_anchor_id|)
+//
+// Note this function does not automatically enable issuer matching. Callers
+// must separately call |SSL_CREDENTIAL_set_must_match_issuer| if desired.
+OPENSSL_EXPORT int SSL_CREDENTIAL_set1_certificate_properties(
+    SSL_CREDENTIAL *cred, CRYPTO_BUFFER *cert_property_list);
+
 // SSL_CREDENTIAL_set1_signed_cert_timestamp_list sets |cred|'s list of signed
 // certificate timestamps |sct_list|. |sct_list| must contain one or more SCT
 // structures serialised as a SignedCertificateTimestampList (see
@@ -839,6 +857,27 @@
 OPENSSL_EXPORT int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(
     SSL_CREDENTIAL *cred, CRYPTO_BUFFER *sct_list);
 
+// SSL_CREDENTIAL_set_must_match_issuer configures whether |cred| should check
+// if the peer supports the certificate chain's issuer.
+//
+// If |match| is non-zero, |cred| will only be applicable when the certificate
+// chain is issued by some CA requested by the peer in the
+// certificate_authorities extension or, if |cred| has a trust anchor ID (see
+// |SSL_CREDENTIAL_set1_trust_anchor_id|), the trust_anchors extension. |cred|'s
+// certificate chain must then be a correctly ordered certification path.
+//
+// If |match| is zero (default), |cred| will not be conditioned on the peer's
+// requested CAs. This can be used for certificate chains that are assumed to be
+// usable by most peers.
+//
+// This setting can be used for certificate chains that may not be usable by all
+// peers, e.g. chains with fewer cross-signs or issued from a newer CA. The
+// credential list is tried in order, so more specific credentials that enable
+// issuer matching should generally be ordered before less specific credentials
+// that do not.
+OPENSSL_EXPORT void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred,
+                                                         int match);
+
 // SSL_CTX_add1_credential appends |cred| to |ctx|'s credential list. It returns
 // one on success and zero on error. The credential list is maintained in order
 // of decreasing preference, so earlier calls are preferred over later calls.
@@ -1400,24 +1439,6 @@
 OPENSSL_EXPORT int SSL_CREDENTIAL_set_private_key_method(
     SSL_CREDENTIAL *cred, const SSL_PRIVATE_KEY_METHOD *key_method);
 
-// SSL_CREDENTIAL_set_must_match_issuer sets the flag that this credential
-// should be considered only when it matches a peer request for a particular
-// issuer via a negotiation mechanism (such as the certificate_authorities
-// extension).
-OPENSSL_EXPORT void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred);
-
-// SSL_CREDENTIAL_clear_must_match_issuer clears the flag requiring issuer
-// matching, indicating this credential should be considered regardless of peer
-// issuer matching requests. (This is the default).
-OPENSSL_EXPORT void SSL_CREDENTIAL_clear_must_match_issuer(
-    SSL_CREDENTIAL *cred);
-
-// SSL_CREDENTIAL_must_match_issuer returns the value of the flag indicating
-// that this credential should be considered only when it matches a peer request
-// for a particular issuer via a negotiation mechanism (such as the
-// certificate_authorities extension).
-OPENSSL_EXPORT int SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL *cred);
-
 // SSL_can_release_private_key returns one if |ssl| will no longer call into the
 // private key and zero otherwise. If the function returns one, the caller can
 // release state associated with the private key.
@@ -1802,13 +1823,21 @@
 // SSL_export_keying_material exports a connection-specific secret from |ssl|,
 // as specified in RFC 5705. It writes |out_len| bytes to |out| given a label
 // and optional context. If |use_context| is zero, the |context| parameter is
-// ignored. Prior to TLS 1.3, using a zero-length context and using no context
-// would give different output.
+// ignored.
+//
+// To derive the same value, both sides of a connection must use the same output
+// length, label, and context. In TLS 1.2 and earlier, using a zero-length
+// context and using no context would give different output. In TLS 1.3 and
+// later, the output length impacts the derivation, so a truncated longer export
+// will not match a shorter export.
 //
 // It returns one on success and zero otherwise.
-OPENSSL_EXPORT int SSL_export_keying_material(
-    SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len,
-    const uint8_t *context, size_t context_len, int use_context);
+OPENSSL_EXPORT int SSL_export_keying_material(const SSL *ssl, uint8_t *out,
+                                              size_t out_len, const char *label,
+                                              size_t label_len,
+                                              const uint8_t *context,
+                                              size_t context_len,
+                                              int use_context);
 
 
 // Sessions.
@@ -2034,6 +2063,12 @@
                                                  const uint8_t **out_ptr,
                                                  size_t *out_len);
 
+// SSL_SESSION_is_resumable_across_names returns one if |session| may be resumed
+// with any identity in the server certificate and zero otherwise. See
+// draft-ietf-tls-cross-sni-resumption.
+OPENSSL_EXPORT int SSL_SESSION_is_resumable_across_names(
+    const SSL_SESSION *session);
+
 
 // Session caching.
 //
@@ -2283,6 +2318,32 @@
 // when the lookup has completed.
 OPENSSL_EXPORT SSL_SESSION *SSL_magic_pending_session_ptr(void);
 
+// SSL_CTX_set_resumption_across_names_enabled configures whether |ctx|, as a
+// TLS 1.3 server, signals its sessions are compatible with any identity in the
+// server certificate, e.g. all DNS names in the subjectAlternateNames list.
+// This does not change BoringSSL's resumption behavior, only whether it signals
+// this to the client. See draft-ietf-tls-cross-sni-resumption.
+//
+// When this is enabled, all identities in the server certificate should by
+// hosted by servers that accept TLS 1.3 tickets issued by |ctx|. The connection
+// will otherwise function, but performance may suffer from clients wasting
+// single-use tickets.
+OPENSSL_EXPORT void SSL_CTX_set_resumption_across_names_enabled(SSL_CTX *ctx,
+                                                                int enabled);
+
+// SSL_set_resumption_across_names_enabled configures whether |ssl|, as a
+// TLS 1.3 server, signals its sessions are compatible with any identity in the
+// server certificate, e.g. all DNS names in the subjectAlternateNames list.
+// This does not change BoringSSL's resumption behavior, only whether it signals
+// this to the client. See draft-ietf-tls-cross-sni-resumption.
+//
+// When this is enabled, all identities in the server certificate should by
+// hosted by servers that accept TLS 1.3 tickets issued by |ssl|. The connection
+// will otherwise function, but performance may suffer from clients wasting
+// single-use tickets.
+OPENSSL_EXPORT void SSL_set_resumption_across_names_enabled(SSL *ssl,
+                                                            int enabled);
+
 
 // Session tickets.
 //
@@ -2580,10 +2641,6 @@
 // with |SSL_VERIFY_PEER|, otherwise it won't work.
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
 
-// SSL_VERIFY_PEER_IF_NO_OBC configures a server to request a client certificate
-// if and only if Channel ID is not negotiated.
-#define SSL_VERIFY_PEER_IF_NO_OBC 0x04
-
 // SSL_CTX_set_verify configures certificate verification behavior. |mode| is
 // one of the |SSL_VERIFY_*| values defined above. |callback| should be NULL.
 //
@@ -2887,11 +2944,16 @@
                                                   size_t num_prefs);
 
 
-// Client certificate CA list.
+// Certificate authorities.
 //
-// When requesting a client certificate, a server may advertise a list of
-// certificate authorities which are accepted. These functions may be used to
-// configure this list.
+// TLS implementations can send a list of supported certificate authorities to
+// guide the peer in selecting a certificate. This was originally defined for
+// servers requesting client certificates, but TLS 1.3 generalized it to server
+// certificates with the certificate_authorities extension.
+//
+// The following functions can be used to configure and query this list. They do
+// not directly impact certificate verification, only the list of certificate
+// authorities sent to the peer.
 
 // SSL_set_client_CA_list sets |ssl|'s client certificate CA list to
 // |name_list|. It takes ownership of |name_list|.
@@ -2976,6 +3038,95 @@
                                                       BIO *bio);
 
 
+// Trust Anchor Identifiers.
+//
+// The trust_anchors extension, like certificate_authorities, allows clients to
+// communicate supported CAs to guide server certificate selection, or vice
+// versa. It better supports larger PKIs by referring to CAs by short "trust
+// anchor IDs" and, in the server certificate direction, allowing a client to
+// advertise only a subset of its full list, with DNS hinting and a retry
+// mechanism to manage the subset.
+//
+// See https://datatracker.ietf.org/doc/draft-ietf-tls-trust-anchor-ids/
+//
+// BoringSSL currently only implements this for server certificates, and not yet
+// client certificates.
+
+// SSL_CREDENTIAL_set1_trust_anchor_id sets |cred|'s trust anchor ID to |id|, or
+// clears it if |id_len| is zero. It returns one on success and zero on
+// error. If not clearing, |id| must be in binary format (Section 3 of
+// draft-ietf-tls-trust-anchor-ids-00) of length |id_len|, and describe the
+// issuer of the final certificate in |cred|'s certificate chain.
+//
+// Additionally, |cred| must enable issuer matching (see
+// SSL_CREDENTIAL_set_must_match_issuer|) for this value to take effect.
+//
+// For better extensibility, callers are recommended to configure this
+// information with a CertificatePropertyList instead. See
+// |SSL_CREDENTIAL_set1_certificate_properties|.
+OPENSSL_EXPORT int SSL_CREDENTIAL_set1_trust_anchor_id(SSL_CREDENTIAL *cred,
+                                                       const uint8_t *id,
+                                                       size_t id_len);
+
+// SSL_CTX_set1_requested_trust_anchors configures |ctx| to request a
+// certificate issued by one of the trust anchors in |ids|. It returns one on
+// success and zero on error. |ids| must be a list of trust anchor IDs in
+// wire-format (a series of non-empty, 8-bit length-prefixed strings).
+//
+// The list may describe application's full list of supported trust anchors, or
+// a, possibly empty, subset. Applications can select this subset using
+// out-of-band information, such as the DNS hint in Section 5 of
+// draft-ietf-tls-trust-anchor-ids-00. Client applications sending a subset
+// should use |SSL_get0_peer_available_trust_anchors| to implement the retry
+// flow from Section 4.3 of draft-ietf-tls-trust-anchor-ids-00.
+//
+// If empty (|ids_len| is zero), the trust_anchors extension will still be sent
+// in ClientHello. This may be used by a client application to signal support
+// for the retry flow without requesting specific trust anchors.
+//
+// This function does not directly impact certificate verification, only the
+// list of trust anchors sent to the peer.
+OPENSSL_EXPORT int SSL_CTX_set1_requested_trust_anchors(SSL_CTX *ctx,
+                                                        const uint8_t *ids,
+                                                        size_t ids_len);
+
+// SSL_set1_requested_trust_anchors behaves like
+// |SSL_CTX_set1_requested_trust_anchors| but configures the value on |ssl|.
+OPENSSL_EXPORT int SSL_set1_requested_trust_anchors(SSL *ssl,
+                                                    const uint8_t *ids,
+                                                    size_t ids_len);
+
+// SSL_peer_matched_trust_anchor returns one if the peer reported that its
+// certificate chain matched one of the trust anchor IDs requested by |ssl|, and
+// zero otherwise.
+//
+// This value is only available during the handshake and is expected to be
+// called during certificate verification, e.g. during |SSL_set_custom_verify|
+// or |SSL_CTX_set_cert_verify_callback| callbacks. If the value is one, callers
+// can safely treat the peer's certificate chain as a pre-built path and skip
+// path-building in certificate verification.
+OPENSSL_EXPORT int SSL_peer_matched_trust_anchor(const SSL *ssl);
+
+// SSL_get0_peer_available_trust_anchors gets the peer's available trust anchor
+// IDs. It sets |*out| and |*out_len| so that |*out| points to |*out_len| bytes
+// containing the list in wire format (i.e. a series of non-empty
+// 8-bit-length-prefixed strings). If the peer did not provide a list, the
+// function will output zero bytes. Only servers can provide available trust
+// anchor IDs, so this API will only output a list when |ssl| is a client.
+//
+// This value is only available during the handshake and is expected to be
+// called in the event of certificate verification failure. Client applications
+// can use it to retry the connection, requesting different trust anchors. See
+// Section 4.3 of draft-ietf-tls-trust-anchor-ids-00 for details.
+// |CBS_get_u8_length_prefixed| may be used to iterate over the format.
+//
+// If needed in other contexts, callers may save the value during certificate
+// verification, or at |SSL_CB_HANDSHAKE_DONE| with |SSL_CTX_set_info_callback|.
+OPENSSL_EXPORT void SSL_get0_peer_available_trust_anchors(const SSL *ssl,
+                                                          const uint8_t **out,
+                                                          size_t *out_len);
+
+
 // Server name indication.
 //
 // The server_name extension (RFC 3546) allows the client to advertise the name
@@ -3611,7 +3762,7 @@
 // WARNING: |rate_limit| differs from the client's |error_limit| parameter.
 // Server PAKE credentials must temporarily deduct incomplete handshakes from
 // the limit, until the peer completes the handshake correctly. Thus
-// applications use that multiple connections in parallel may need a higher
+// applications that use multiple connections in parallel may need a higher
 // limit, and thus higher attacker exposure, to avoid failures. Such
 // applications should instead use one PAKE-based connection to established a
 // high-entropy secret (e.g. with |SSL_export_keying_material|) instead of
@@ -4331,20 +4482,118 @@
                                           size_t out_len);
 
 // SSL_get_read_sequence returns, in TLS, the expected sequence number of the
-// next incoming record in the current epoch. In DTLS, it returns the maximum
-// sequence number received in the current epoch and includes the epoch number
-// in the two most significant bytes.
+// next incoming record in the current epoch.
+//
+// TODO(crbug.com/42290608): In DTLS, it returns the maximum sequence number
+// received in the current epoch (for some notion of "current" specific to
+// BoringSSL) and includes the epoch number in the two most significant bytes,
+// but this is deprecated. Use |SSL_get_dtls_read_sequence| instead.
 OPENSSL_EXPORT uint64_t SSL_get_read_sequence(const SSL *ssl);
 
 // SSL_get_write_sequence returns the sequence number of the next outgoing
-// record in the current epoch. In DTLS, it includes the epoch number in the
-// two most significant bytes.
+// record in the current epoch.
+//
+// TODO(crbug.com/42290608): In DTLS, it includes the epoch number in the two
+// most significant bytes, but this is deprecated. Use
+// |SSL_get_dtls_write_sequence| instead.
 OPENSSL_EXPORT uint64_t SSL_get_write_sequence(const SSL *ssl);
 
 // SSL_CTX_set_record_protocol_version returns whether |version| is zero.
 OPENSSL_EXPORT int SSL_CTX_set_record_protocol_version(SSL_CTX *ctx,
                                                        int version);
 
+// SSL_is_dtls_handshake_idle returns one |ssl|'s handshake is idle and zero if
+// it is busy. The handshake is considered idle if all of the following are
+// true:
+//
+// - |ssl| is not mid handshake or post-handshake transaction.
+// - In DTLS 1.3, all sent handshake messages have been acknowledged. That is,
+//   |ssl| does not have data to retransmit.
+// - All received handshake data has been processed. That is, |ssl| has no
+//   buffered partial or out-of-order messages.
+//
+// If any condition is false, the handshake is considered busy. If this function
+// reports the handshake is busy, it is expected that the handshake will become
+// idle after short timers and a few roundtrips of successful communication.
+// However, this is not guaranteed if, e.g., the peer misbehaves or sends many
+// KeyUpdates.
+//
+// WARNING: In DTLS 1.3, this function may return one while multiple active read
+// epochs exist in |ssl|.
+//
+// WARNING: In DTLS 1.2 (or earlier), if |ssl| is the role that speaks last, it
+// retains its final flight for retransmission in case of loss. There is no
+// explicit protocol signal for when this completes, though after receiving
+// application data and/or a timeout it is likely that this is no longer needed.
+// BoringSSL does not currently evaluate either condition and leaves it it to
+// the caller to determine whether this is now unnecessary. This applies when
+// |ssl| is a server for full handshakes and when |ssl| is a client for full
+// handshakes.
+OPENSSL_EXPORT int SSL_is_dtls_handshake_idle(const SSL *ssl);
+
+// SSL_get_dtls_handshake_read_seq returns the 16-bit sequence number of the
+// next DTLS handshake message to be read, or 0x10000 if handshake message
+// 0xffff (the maximum) has already been read.
+OPENSSL_EXPORT uint32_t SSL_get_dtls_handshake_read_seq(const SSL *ssl);
+
+// SSL_get_dtls_handshake_write_seq returns the 16-bit sequence number of the
+// next DTLS handshake message to be written or 0x10000 if handshake message
+// 0xffff (the maximum) has already been written.
+OPENSSL_EXPORT uint32_t SSL_get_dtls_handshake_write_seq(const SSL *ssl);
+
+// SSL_get_dtls_read_epoch returns the highest available DTLS read epoch in
+// |ssl|. In DTLS 1.3, |ssl| may have earlier epochs also active, sometimes to
+// optionally improve handling of reordered packets and sometimes as an
+// important part of the protocol correctness in the face of packet loss.
+//
+// The failure conditions of |SSL_get_dtls_read_traffic_secret| and
+// |SSL_get_dtls_read_sequence| can be used to determine if past epochs are
+// active.
+OPENSSL_EXPORT uint16_t SSL_get_dtls_read_epoch(const SSL *ssl);
+
+// SSL_get_dtls_write_epoch returns the current DTLS write epoch. If the
+// handshake is idle (see |SSL_is_dtls_handshake_idle|), no other write epochs
+// will be active.
+OPENSSL_EXPORT uint16_t SSL_get_dtls_write_epoch(const SSL *ssl);
+
+// SSL_get_dtls_read_sequence returns one more than the sequence number of the
+// highest record received in |epoch|. If no records have been received in
+// |epoch|. If the epoch does not exist, it returns |UINT64_MAX|.
+//
+// It is safe to discard all sequence numbers less than the return value of this
+// function. The sequence numbers returned by this function do not include the
+// epoch number in the upper 16 bits.
+OPENSSL_EXPORT uint64_t SSL_get_dtls_read_sequence(const SSL *ssl,
+                                                   uint16_t epoch);
+
+// SSL_get_dtls_write_sequence returns the sequence number of the next record to
+// be sent in |epoch|. If the epoch does not exist, it returns |UINT64_MAX|.
+//
+// The sequence numbers returned by this function do not include the epoch
+// number in the upper 16 bits.
+OPENSSL_EXPORT uint64_t SSL_get_dtls_write_sequence(const SSL *ssl,
+                                                    uint16_t epoch);
+
+// SSL_get_dtls_read_traffic_secret looks up the traffic secret for read epoch
+// |epoch|. If the epoch exists and is an encrypted (not epoch zero) DTLS 1.3
+// epoch, it sets |*out_data| and |*out_len| to a buffer containing the secrets
+// and returns one. Otherwise, it returns zero. The buffer is valid until the
+// next operation on |ssl|.
+OPENSSL_EXPORT int SSL_get_dtls_read_traffic_secret(const SSL *ssl,
+                                                    const uint8_t **out_data,
+                                                    size_t *out_len,
+                                                    uint16_t epoch);
+
+// SSL_get_dtls_write_traffic_secret looks up the traffic secret for write epoch
+// |epoch|. If the epoch exists and is an encrypted (not epoch zero) DTLS 1.3
+// epoch, it sets |*out_data| and |*out_len| to a buffer containing the secrets
+// and returns one. Otherwise, it returns zero. The buffer is valid until the
+// next operation on |ssl|.
+OPENSSL_EXPORT int SSL_get_dtls_write_traffic_secret(const SSL *ssl,
+                                                     const uint8_t **out_data,
+                                                     size_t *out_len,
+                                                     uint16_t epoch);
+
 
 // Handshake hints.
 //
@@ -6210,6 +6459,8 @@
 #define SSL_R_PAKE_EXHAUSTED 325
 #define SSL_R_PEER_PAKE_MISMATCH 326
 #define SSL_R_UNSUPPORTED_CREDENTIAL_LIST 327
+#define SSL_R_INVALID_TRUST_ANCHOR_LIST 328
+#define SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST 329
 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h
index bdbf642..2332a5a 100644
--- a/src/include/openssl/stack.h
+++ b/src/include/openssl/stack.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_STACK_H
 #define OPENSSL_HEADER_STACK_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/target.h b/src/include/openssl/target.h
index 147ab31..8d4763d 100644
--- a/src/include/openssl/target.h
+++ b/src/include/openssl/target.h
@@ -192,11 +192,6 @@
 #define OPENSSL_THREADS
 #endif
 
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) && \
-    !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-#define BORINGSSL_UNSAFE_DETERMINISTIC_MODE
-#endif
-
 #if defined(__has_feature)
 #if __has_feature(address_sanitizer)
 #define OPENSSL_ASAN
diff --git a/src/include/openssl/thread.h b/src/include/openssl/thread.h
index 5aac953..26a29ca 100644
--- a/src/include/openssl/thread.h
+++ b/src/include/openssl/thread.h
@@ -17,7 +17,7 @@
 
 #include <sys/types.h>
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index 7705e9c..dde04dd 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -17,7 +17,7 @@
 #ifndef OPENSSL_HEADER_TLS1_H
 #define OPENSSL_HEADER_TLS1_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #ifdef __cplusplus
 extern "C" {
@@ -132,6 +132,14 @@
 // This is not an IANA defined extension number
 #define TLSEXT_TYPE_channel_id 30032
 
+// This is not an IANA defined extension number
+// TODO(crbug.com/398275713): Replace with the final codepoint once
+// standardization completes.
+#define TLSEXT_TYPE_trust_anchors 0xca34
+
+// ExtensionType value from draft-ietf-tls-tlsflags.
+#define TLSEXT_TYPE_tls_flags 62
+
 // status request value from RFC 3546
 #define TLSEXT_STATUSTYPE_nothing (-1)
 #define TLSEXT_STATUSTYPE_ocsp 1
diff --git a/src/include/openssl/trust_token.h b/src/include/openssl/trust_token.h
index 1026bcd..0353fd4 100644
--- a/src/include/openssl/trust_token.h
+++ b/src/include/openssl/trust_token.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_TRUST_TOKEN_H
 #define OPENSSL_HEADER_TRUST_TOKEN_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 #include <openssl/stack.h>
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/type_check.h b/src/include/openssl/type_check.h
index 8225f91..185b765 100644
--- a/src/include/openssl/type_check.h
+++ b/src/include/openssl/type_check.h
@@ -15,7 +15,7 @@
 #ifndef OPENSSL_HEADER_TYPE_CHECK_H
 #define OPENSSL_HEADER_TYPE_CHECK_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 3e81b5f..58508a5 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -16,7 +16,7 @@
 #ifndef OPENSSL_HEADER_X509_H
 #define OPENSSL_HEADER_X509_H
 
-#include <openssl/base.h>
+#include <openssl/base.h>   // IWYU pragma: export
 
 #include <time.h>
 
@@ -1504,9 +1504,12 @@
 // pointer for OpenSSL compatibility, but callers should not mutate the result.
 // Doing so will break internal invariants in the library.
 //
-// TODO(https://crbug.com/boringssl/412): Although the spec says any ASN.1 type
-// is allowed, we currently only allow an ad-hoc set of types. Additionally, it
-// is unclear if some types can even be represented by this function.
+// See |ASN1_STRING| for how values are represented in this library. Where a
+// specific |ASN1_STRING| representation exists, that representation is used.
+// Otherwise, the |V_ASN1_OTHER| representation is used. Note that NULL, OBJECT
+// IDENTIFIER, and BOOLEAN attribute values are represented as |V_ASN1_OTHER|,
+// because their usual representation in this library is not
+// |ASN1_STRING|-compatible.
 OPENSSL_EXPORT ASN1_STRING *X509_NAME_ENTRY_get_data(
     const X509_NAME_ENTRY *entry);
 
diff --git a/src/pki/certificate_policies_unittest.cc b/src/pki/certificate_policies_unittest.cc
index cc634a7..ba14490 100644
--- a/src/pki/certificate_policies_unittest.cc
+++ b/src/pki/certificate_policies_unittest.cc
@@ -15,6 +15,9 @@
 #include "certificate_policies.h"
 
 #include <gtest/gtest.h>
+
+#include <openssl/span.h>
+
 #include "input.h"
 #include "parser.h"
 #include "test_helpers.h"
@@ -53,7 +56,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -63,7 +66,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -73,7 +76,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(1U, policies.size());
   EXPECT_EQ(der::Input(kAnyPolicyOid), policies[0]);
@@ -85,7 +88,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(1U, policies.size());
   EXPECT_EQ(der::Input(kAnyPolicyOid), policies[0]);
@@ -99,7 +102,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -109,7 +112,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(1U, policies.size());
   EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]);
@@ -121,7 +124,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(1U, policies.size());
   EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]);
@@ -134,7 +137,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   bool result = ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors);
 
   if (fail_parsing_unknown_qualifier_oids()) {
@@ -153,7 +156,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -165,7 +168,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -177,7 +180,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -189,7 +192,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_FALSE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
 }
 
@@ -199,7 +202,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(2U, policies.size());
   EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]);
@@ -212,7 +215,7 @@
   std::vector<der::Input> policies;
   CertErrors errors;
   EXPECT_TRUE(ParseCertificatePoliciesExtensionOids(
-      der::Input(der), fail_parsing_unknown_qualifier_oids(), &policies,
+      StringAsBytes(der), fail_parsing_unknown_qualifier_oids(), &policies,
       &errors));
   ASSERT_EQ(2U, policies.size());
   EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]);
@@ -224,8 +227,8 @@
   ASSERT_TRUE(LoadTestData("invalid-empty.pem", &der));
   std::vector<PolicyInformation> policies;
   CertErrors errors;
-  EXPECT_FALSE(
-      ParseCertificatePoliciesExtension(der::Input(der), &policies, &errors));
+  EXPECT_FALSE(ParseCertificatePoliciesExtension(StringAsBytes(der), &policies,
+                                                 &errors));
 }
 
 TEST(ParseCertificatePoliciesExtensionTest,
@@ -234,8 +237,8 @@
   ASSERT_TRUE(LoadTestData("invalid-policy_1_2_3_dupe.pem", &der));
   std::vector<PolicyInformation> policies;
   CertErrors errors;
-  EXPECT_FALSE(
-      ParseCertificatePoliciesExtension(der::Input(der), &policies, &errors));
+  EXPECT_FALSE(ParseCertificatePoliciesExtension(StringAsBytes(der), &policies,
+                                                 &errors));
 }
 
 TEST(ParseCertificatePoliciesExtensionTest, OnePolicyWithCustomQualifier) {
@@ -243,8 +246,8 @@
   ASSERT_TRUE(LoadTestData("policy_1_2_3_with_custom_qualifier.pem", &der));
   std::vector<PolicyInformation> policies;
   CertErrors errors;
-  EXPECT_TRUE(
-      ParseCertificatePoliciesExtension(der::Input(der), &policies, &errors));
+  EXPECT_TRUE(ParseCertificatePoliciesExtension(StringAsBytes(der), &policies,
+                                                &errors));
   ASSERT_EQ(1U, policies.size());
   PolicyInformation &policy = policies[0];
   EXPECT_EQ(der::Input(policy_1_2_3_der), policy.policy_oid);
@@ -264,8 +267,8 @@
   ASSERT_TRUE(LoadTestData("policy_1_2_3_and_1_2_4.pem", &der));
   std::vector<PolicyInformation> policies;
   CertErrors errors;
-  EXPECT_TRUE(
-      ParseCertificatePoliciesExtension(der::Input(der), &policies, &errors));
+  EXPECT_TRUE(ParseCertificatePoliciesExtension(StringAsBytes(der), &policies,
+                                                &errors));
   ASSERT_EQ(2U, policies.size());
   {
     PolicyInformation &policy = policies[0];
@@ -284,8 +287,8 @@
   ASSERT_TRUE(LoadTestData("policy_1_2_3_and_1_2_4_with_qualifiers.pem", &der));
   std::vector<PolicyInformation> policies;
   CertErrors errors;
-  EXPECT_TRUE(
-      ParseCertificatePoliciesExtension(der::Input(der), &policies, &errors));
+  EXPECT_TRUE(ParseCertificatePoliciesExtension(StringAsBytes(der), &policies,
+                                                &errors));
   ASSERT_EQ(2U, policies.size());
   {
     PolicyInformation &policy = policies[0];
diff --git a/src/pki/common_cert_errors.cc b/src/pki/common_cert_errors.cc
index 636bfc6..4bb0707 100644
--- a/src/pki/common_cert_errors.cc
+++ b/src/pki/common_cert_errors.cc
@@ -30,6 +30,9 @@
 DEFINE_CERT_ERROR_ID(kUnconsumedCriticalExtension,
                      "Unconsumed critical extension");
 DEFINE_CERT_ERROR_ID(kKeyCertSignBitNotSet, "keyCertSign bit is not set");
+DEFINE_CERT_ERROR_ID(kKeyUsageIncorrectForRcsMlsClient,
+                     "KeyUsage must have only the digitalSignature bit set for "
+                     "rcsMlsClient auth");
 DEFINE_CERT_ERROR_ID(kMaxPathLengthViolated, "max_path_length reached");
 DEFINE_CERT_ERROR_ID(kBasicConstraintsIndicatesNotCa,
                      "Basic Constraints indicates not a CA");
@@ -70,6 +73,17 @@
 DEFINE_CERT_ERROR_ID(kEkuHasProhibitedCodeSigning,
                      "The extended key usage includes code signing which "
                      "is not permitted for this use");
+DEFINE_CERT_ERROR_ID(kEkuIncorrectForRcsMlsClient,
+                     "The extended key usage does not contain only the "
+                     "rcsMlsClient key purpose.");
+DEFINE_CERT_ERROR_ID(kEkuIncorrectForC2PATimeStamping,
+                     "The extended key usage does not contain the time "
+                     "stamping key purpose, or contains prohibited key usages");
+DEFINE_CERT_ERROR_ID(
+    kEkuIncorrectForC2PAManifest,
+    "The extended key usage must contain at least one of: email protection or "
+    "document signing, and must not contain prohibited key usages");
+
 DEFINE_CERT_ERROR_ID(kEkuNotPresent,
                      "Certificate does not have extended key usage");
 DEFINE_CERT_ERROR_ID(kCertIsNotTrustAnchor,
diff --git a/src/pki/common_cert_errors.h b/src/pki/common_cert_errors.h
index 40b02de..5bbf412 100644
--- a/src/pki/common_cert_errors.h
+++ b/src/pki/common_cert_errors.h
@@ -58,6 +58,10 @@
 // keyCertSign KeyUsage was not set.
 OPENSSL_EXPORT extern const CertErrorId kKeyCertSignBitNotSet;
 
+// The certificate is being used for RCS MLS but the required digitalSignature
+// bit was either not set, or was not the only bit set.
+OPENSSL_EXPORT extern const CertErrorId kKeyUsageIncorrectForRcsMlsClient;
+
 // The chain violates the max_path_length from BasicConstraints.
 OPENSSL_EXPORT extern const CertErrorId kMaxPathLengthViolated;
 
@@ -139,6 +143,15 @@
 // The certificate's EKU has Code Signing when it should not.
 OPENSSL_EXPORT extern const CertErrorId kEkuHasProhibitedCodeSigning;
 
+// The certificate's EKU is incorrect for an RcsMlsClient.
+OPENSSL_EXPORT extern const CertErrorId kEkuIncorrectForRcsMlsClient;
+
+// The certificate's EKU is incorrect for C2PA Time Stamping
+OPENSSL_EXPORT extern const CertErrorId kEkuIncorrectForC2PATimeStamping;
+
+// The certificate's EKU is incorrect for C2PA Manifest Signing
+OPENSSL_EXPORT extern const CertErrorId kEkuIncorrectForC2PAManifest;
+
 // The certificate does not have EKU.
 OPENSSL_EXPORT extern const CertErrorId kEkuNotPresent;
 
diff --git a/src/pki/crl.cc b/src/pki/crl.cc
index 5af3e27..abe9d26 100644
--- a/src/pki/crl.cc
+++ b/src/pki/crl.cc
@@ -17,6 +17,7 @@
 
 #include <openssl/base.h>
 #include <openssl/bytestring.h>
+#include <openssl/span.h>
 
 #include "cert_errors.h"
 #include "crl.h"
@@ -444,7 +445,7 @@
   der::Input tbs_cert_list_tlv;
   der::Input signature_algorithm_tlv;
   der::BitString signature_value;
-  if (!ParseCrlCertificateList(der::Input(raw_crl), &tbs_cert_list_tlv,
+  if (!ParseCrlCertificateList(StringAsBytes(raw_crl), &tbs_cert_list_tlv,
                                &signature_algorithm_tlv, &signature_value)) {
     return CRLRevocationStatus::UNKNOWN;
   }
@@ -519,7 +520,8 @@
   if (!NormalizeNameTLV(tbs_cert_list.issuer_tlv, &normalized_crl_issuer)) {
     return CRLRevocationStatus::UNKNOWN;
   }
-  if (der::Input(normalized_crl_issuer) != target_cert->normalized_issuer()) {
+  if (der::Input(StringAsBytes(normalized_crl_issuer)) !=
+      target_cert->normalized_issuer()) {
     return CRLRevocationStatus::UNKNOWN;
   }
 
@@ -639,7 +641,7 @@
     //
     // As the |issuer_cert| is from the already validated chain, it is already
     // known to chain to the same trust anchor as the target certificate.
-    if (der::Input(normalized_crl_issuer) !=
+    if (der::Input(StringAsBytes(normalized_crl_issuer)) !=
         issuer_cert->normalized_subject()) {
       continue;
     }
diff --git a/src/pki/extended_key_usage.h b/src/pki/extended_key_usage.h
index 2556c24..fb10c77 100644
--- a/src/pki/extended_key_usage.h
+++ b/src/pki/extended_key_usage.h
@@ -78,6 +78,24 @@
 inline constexpr uint8_t kOCSPSigning[] = {0x2b, 0x06, 0x01, 0x05,
                                            0x05, 0x07, 0x03, 0x09};
 
+// From RFC 9336 section 3.1:
+// id-kp-documentSigning  OBJECT IDENTIFIER  ::=  { id-kp 36 }
+// In dotted notation: 1.3.6.1.5.5.7.3.36
+inline constexpr uint8_t kDocumentSigning[] = {0x2b, 0x06, 0x01, 0x05,
+                                               0x05, 0x07, 0x03, 0x24};
+
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification.
+// id-gsmaRCSE2EE OBJECT IDENTIFIER ::=  { joint-iso-itu-t(2)
+// international-organizations(23) gsma(146) rcs(2) rcsE2EE (1)}
+// (Note this spec incorrectly says id-appleDraftRCSE2EE in place of
+// id-gmsaRCSE2EE in several places)
+//
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification section A.2.8.8,
+// and A.3.8.7.
+// id-kp-rcsMlsClient OBJECT IDENTIFIER ::= { id-gmsaRCS2EE 3 }
+// In dotted notation: 2.23.146.2.1.3
+inline constexpr uint8_t kRcsMlsClient[] = {0x67, 0x81, 0x12, 0x02, 0x01, 0x03};
+
 // Parses |extension_value|, which contains the extnValue field of an X.509v3
 // Extended Key Usage extension, and populates |eku_oids| with the list of
 // DER-encoded OID values (that is, without tag and length). Returns false if
diff --git a/src/pki/general_names_unittest.cc b/src/pki/general_names_unittest.cc
index 63034f5..b451246 100644
--- a/src/pki/general_names_unittest.cc
+++ b/src/pki/general_names_unittest.cc
@@ -15,6 +15,9 @@
 #include "general_names.h"
 
 #include <gtest/gtest.h>
+
+#include <openssl/span.h>
+
 #include "test_helpers.h"
 
 BSSL_NAMESPACE_BEGIN
@@ -52,7 +55,7 @@
   ASSERT_TRUE(
       LoadTestSubjectAltNameData("san-invalid-empty.pem", &invalid_san_der));
   CertErrors errors;
-  EXPECT_FALSE(GeneralNames::Create(der::Input(invalid_san_der), &errors));
+  EXPECT_FALSE(GeneralNames::Create(StringAsBytes(invalid_san_der), &errors));
 }
 
 TEST(GeneralNames, OtherName) {
@@ -61,7 +64,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_OTHER_NAME, general_names->present_name_types);
   const uint8_t expected_der[] = {0x06, 0x04, 0x2a, 0x03, 0x04, 0x05,
@@ -76,7 +79,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->rfc822_names.size());
@@ -88,7 +91,7 @@
   ASSERT_TRUE(LoadTestSubjectAltNameData("san-rfc822name.pem", &san_der));
   ReplaceFirstSubstring(&san_der, "foo@example.com", "f\xF6\xF6@example.com");
   CertErrors errors;
-  EXPECT_FALSE(GeneralNames::Create(der::Input(san_der), &errors));
+  EXPECT_FALSE(GeneralNames::Create(StringAsBytes(san_der), &errors));
 }
 
 TEST(GeneralNames, DnsName) {
@@ -97,7 +100,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_DNS_NAME, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->dns_names.size());
@@ -109,7 +112,7 @@
   ASSERT_TRUE(LoadTestSubjectAltNameData("san-dnsname.pem", &san_der));
   ReplaceFirstSubstring(&san_der, "foo.example.com", "f\xF6\xF6.example.com");
   CertErrors errors;
-  EXPECT_FALSE(GeneralNames::Create(der::Input(san_der), &errors));
+  EXPECT_FALSE(GeneralNames::Create(StringAsBytes(san_der), &errors));
 }
 
 TEST(GeneralNames, X400Address) {
@@ -118,7 +121,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_X400_ADDRESS, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->x400_addresses.size());
@@ -133,7 +136,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_DIRECTORY_NAME, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->directory_names.size());
@@ -148,7 +151,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_EDI_PARTY_NAME, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->edi_party_names.size());
@@ -162,7 +165,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER,
             general_names->present_name_types);
@@ -177,7 +180,7 @@
   ReplaceFirstSubstring(&san_der, "http://example.com",
                         "http://ex\xE4mple.com");
   CertErrors errors;
-  EXPECT_FALSE(GeneralNames::Create(der::Input(san_der), &errors));
+  EXPECT_FALSE(GeneralNames::Create(StringAsBytes(san_der), &errors));
 }
 
 TEST(GeneralNames, IPAddress_v4) {
@@ -186,7 +189,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->ip_addresses.size());
@@ -201,7 +204,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->ip_addresses.size());
@@ -216,7 +219,7 @@
   ASSERT_TRUE(LoadTestSubjectAltNameData("san-invalid-ipaddress.pem",
                                          &invalid_san_der));
   CertErrors errors;
-  EXPECT_FALSE(GeneralNames::Create(der::Input(invalid_san_der), &errors));
+  EXPECT_FALSE(GeneralNames::Create(StringAsBytes(invalid_san_der), &errors));
 }
 
 TEST(GeneralNames, RegisteredIDs) {
@@ -225,7 +228,7 @@
 
   CertErrors errors;
   std::unique_ptr<GeneralNames> general_names =
-      GeneralNames::Create(der::Input(san_der), &errors);
+      GeneralNames::Create(StringAsBytes(san_der), &errors);
   ASSERT_TRUE(general_names);
   EXPECT_EQ(GENERAL_NAME_REGISTERED_ID, general_names->present_name_types);
   ASSERT_EQ(1U, general_names->registered_ids.size());
diff --git a/src/pki/name_constraints_unittest.cc b/src/pki/name_constraints_unittest.cc
index 9037deb..fa7cbec 100644
--- a/src/pki/name_constraints_unittest.cc
+++ b/src/pki/name_constraints_unittest.cc
@@ -18,6 +18,9 @@
 #include <memory>
 
 #include <gtest/gtest.h>
+
+#include <openssl/span.h>
+
 #include "common_cert_errors.h"
 #include "test_helpers.h"
 
@@ -60,7 +63,7 @@
     return load_result;
   }
   CertErrors errors;
-  *result = GeneralNames::Create(der::Input(*result_der), &errors);
+  *result = GeneralNames::Create(StringAsBytes(*result_der), &errors);
   if (!*result) {
     return ::testing::AssertionFailure() << "Create failed";
   }
@@ -114,7 +117,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example.com"));
@@ -203,7 +206,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("dnsname2.pem", &a));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // Matches permitted exactly.
@@ -234,7 +237,7 @@
       LoadTestNameConstraint("dnsname-permitted_with_leading_dot.pem", &a));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // A permitted dNSName constraint of ".bar.com" should only match subdomains
@@ -252,7 +255,7 @@
       LoadTestNameConstraint("dnsname-excluded_with_leading_dot.pem", &a));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // An excluded dNSName constraint of ".bar.com" should only match subdomains
@@ -269,7 +272,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("dnsname-permitted_two_dot.pem", &a));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // A dNSName constraint of ".." isn't meaningful. Shouldn't match anything.
@@ -285,7 +288,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // Only "excluded.permitted.example.com" is excluded, and since permitted is
@@ -305,7 +308,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // "permitted.example.com" is in the permitted section, but since "" is
@@ -323,7 +326,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // "." is excluded, which should match nothing.
@@ -342,7 +345,8 @@
   a.replace(replace_location, 1, 1, -1);
 
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 }
 
 TEST_P(ParseNameConstraints, DirectoryNames) {
@@ -369,7 +373,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // Not in any permitted subtree.
@@ -439,7 +443,7 @@
       LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name_empty;
@@ -470,7 +474,7 @@
       LoadTestNameConstraint("directoryname-excludeall.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name_empty;
@@ -503,7 +507,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // IPv4 tests:
@@ -634,7 +638,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // Only 192.168.5.0/255.255.255.0 is excluded, and since permitted is empty,
@@ -653,7 +657,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // 192.168.0.0/255.255.0.0 and
@@ -675,7 +679,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_FALSE(
@@ -698,7 +702,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_FALSE(
@@ -723,7 +727,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_FALSE(
@@ -742,7 +746,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_TRUE(
@@ -758,7 +762,8 @@
   ASSERT_TRUE(LoadTestNameConstraint("ipaddress-invalid_addr.pem", &a));
 
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 }
 
 TEST_P(ParseNameConstraints, IPAddressesFailOnInvalidMaskNotContiguous) {
@@ -766,19 +771,23 @@
   ASSERT_TRUE(LoadTestNameConstraint(
       "ipaddress-invalid_mask_not_contiguous_1.pem", &a));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 
   ASSERT_TRUE(LoadTestNameConstraint(
       "ipaddress-invalid_mask_not_contiguous_2.pem", &a));
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 
   ASSERT_TRUE(LoadTestNameConstraint(
       "ipaddress-invalid_mask_not_contiguous_3.pem", &a));
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 
   ASSERT_TRUE(LoadTestNameConstraint(
       "ipaddress-invalid_mask_not_contiguous_4.pem", &a));
-  EXPECT_FALSE(NameConstraints::Create(der::Input(a), is_critical(), &errors));
+  EXPECT_FALSE(
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
 }
 
 // Test that v4/v6 mapping is not applied when evaluating name constraints.
@@ -788,7 +797,7 @@
 
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(
-      NameConstraints::Create(der::Input(a), is_critical(), &errors));
+      NameConstraints::Create(StringAsBytes(a), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   // 192.168.1.0/24 is a permitted subtree.
@@ -824,7 +833,7 @@
       LoadTestNameConstraint("othername-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -847,7 +856,7 @@
       LoadTestNameConstraint("othername-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -870,7 +879,7 @@
       LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -932,7 +941,7 @@
       LoadTestNameConstraint("rfc822name-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -982,7 +991,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1041,7 +1050,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1090,7 +1099,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1140,7 +1149,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1190,7 +1199,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1228,7 +1237,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1267,7 +1276,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1292,7 +1301,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1317,7 +1326,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1347,7 +1356,7 @@
       LoadTestNameConstraint("rfc822name-excluded-ipv4.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
@@ -1378,7 +1387,7 @@
       LoadTestNameConstraint("othername-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string san_der;
@@ -1396,7 +1405,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string san_der;
@@ -1415,7 +1424,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string san_der;
@@ -1435,7 +1444,7 @@
       LoadTestNameConstraint("x400address-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1458,7 +1467,7 @@
       LoadTestNameConstraint("x400address-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1481,7 +1490,7 @@
       LoadTestNameConstraint("edipartyname-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1504,7 +1513,7 @@
       LoadTestNameConstraint("edipartyname-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1526,7 +1535,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("uri-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1548,7 +1557,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("uri-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1571,7 +1580,7 @@
       LoadTestNameConstraint("registeredid-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1594,7 +1603,7 @@
       LoadTestNameConstraint("registeredid-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   if (is_critical()) {
@@ -1620,7 +1629,7 @@
   // could be changed to allowed if there are buggy encoders out there that
   // include it anyway.
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1629,7 +1638,7 @@
   ASSERT_TRUE(
       LoadTestNameConstraint("dnsname-with_min_1.pem", &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1639,7 +1648,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_0_and_max.pem",
                                      &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1648,7 +1657,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_1_and_max.pem",
                                      &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1656,14 +1665,14 @@
   std::string constraints_der;
   ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_max.pem", &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
 TEST_P(ParseNameConstraints, FailsOnEmptyExtensionValue) {
   std::string constraints_der = "";
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1672,7 +1681,7 @@
   ASSERT_TRUE(
       LoadTestNameConstraint("invalid-no_subtrees.pem", &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1681,7 +1690,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("invalid-empty_permitted_subtree.pem",
                                      &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1690,7 +1699,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("invalid-empty_excluded_subtree.pem",
                                      &constraints_der));
   CertErrors errors;
-  EXPECT_FALSE(NameConstraints::Create(der::Input(constraints_der),
+  EXPECT_FALSE(NameConstraints::Create(StringAsBytes(constraints_der),
                                        is_critical(), &errors));
 }
 
@@ -1700,7 +1709,7 @@
   ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name;
@@ -1725,7 +1734,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name;
@@ -1758,7 +1767,7 @@
       LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name;
@@ -1791,7 +1800,7 @@
       LoadTestNameConstraint("rfc822name-excluded.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name;
@@ -1827,7 +1836,7 @@
                                      &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name_us_az_foocom;
@@ -1869,7 +1878,7 @@
       "directoryname_and_dnsname_and_ipaddress.pem", &constraints_der));
   CertErrors errors;
   std::unique_ptr<NameConstraints> name_constraints(NameConstraints::Create(
-      der::Input(constraints_der), is_critical(), &errors));
+      StringAsBytes(constraints_der), is_critical(), &errors));
   ASSERT_TRUE(name_constraints);
 
   std::string name_us_az_1_1_1_1;
diff --git a/src/pki/ocsp.cc b/src/pki/ocsp.cc
index 7984050..9f42403 100644
--- a/src/pki/ocsp.cc
+++ b/src/pki/ocsp.cc
@@ -19,6 +19,8 @@
 #include <openssl/mem.h>
 #include <openssl/pool.h>
 #include <openssl/sha.h>
+#include <openssl/span.h>
+
 #include "cert_errors.h"
 #include "extended_key_usage.h"
 #include "parsed_certificate.h"
@@ -887,9 +889,8 @@
     return OCSPRevocationStatus::UNKNOWN;
   }
 
-  der::Input response_der(raw_response);
   OCSPResponse response;
-  if (!ParseOCSPResponse(response_der, &response)) {
+  if (!ParseOCSPResponse(StringAsBytes(raw_response), &response)) {
     *response_details = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
     return OCSPRevocationStatus::UNKNOWN;
   }
@@ -1056,6 +1057,11 @@
   //       issuerNameHash      OCTET STRING, -- Hash of issuer's DN
   //       issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
   //       serialNumber        CertificateSerialNumber }
+  //
+  // It is unclear whether the parameters for hashAlgorithm should be omitted or
+  // NULL. Section 2.1 of RFC 4055 would suggest omitting it is the right
+  // default behavior. However, both OpenSSL and Go include it, so we match them
+  // for now.
 
   // TODO(eroman): Don't use SHA1.
   const EVP_MD *md = EVP_sha1();
diff --git a/src/pki/ocsp_unittest.cc b/src/pki/ocsp_unittest.cc
index 25658cc..23a7d9f 100644
--- a/src/pki/ocsp_unittest.cc
+++ b/src/pki/ocsp_unittest.cc
@@ -15,8 +15,11 @@
 #include "ocsp.h"
 
 #include <gtest/gtest.h>
+
 #include <openssl/base64.h>
 #include <openssl/pool.h>
+#include <openssl/span.h>
+
 #include "encode_values.h"
 #include "string_util.h"
 #include "test_helpers.h"
@@ -182,7 +185,8 @@
   std::vector<uint8_t> encoded_request;
   ASSERT_TRUE(CreateOCSPRequest(cert.get(), issuer.get(), &encoded_request));
 
-  EXPECT_EQ(der::Input(encoded_request), der::Input(request_data));
+  EXPECT_EQ(der::Input(encoded_request),
+            der::Input(StringAsBytes(request_data)));
 }
 
 std::string_view kGetURLTestParams[] = {
diff --git a/src/pki/parse_certificate.h b/src/pki/parse_certificate.h
index 99b822e..d2bf9db 100644
--- a/src/pki/parse_certificate.h
+++ b/src/pki/parse_certificate.h
@@ -440,6 +440,32 @@
 inline constexpr uint8_t kMSApplicationPoliciesOid[] = {
     0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x0a};
 
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification.
+// id-gsmaRCSE2EE OBJECT IDENTIFIER ::=  { joint-iso-itu-t(2)
+// international-organizations(23) gsma(146) rcs(2) rcsE2EE (1)}
+// (Note this spec incorrectly says id-appleDraftRCSE2EE in place of
+// id-gmsaRCSE2EE in several places)
+//
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification section A.2.8.8,
+// and A.3.8.9.
+// id-participantInformation OBJECT IDENTIFIER ::= { id-gmsaRCS2EE 4 }
+// In dotted notation: 2.23.146.2.1.4
+inline constexpr uint8_t kRcsMlsParticipantInformation[] = {0x67, 0x81, 0x12,
+                                                            0x02, 0x01, 0x04};
+
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification.
+// id-gsmaRCSE2EE OBJECT IDENTIFIER ::=  { joint-iso-itu-t(2)
+// international-organizations(23) gsma(146) rcs(2) rcsE2EE (1)}
+// (Note this spec incorrectly says id-appleDraftRCSE2EE in place of
+// id-gmsaRCSE2EE in several places)
+//
+// From GSMA RCC.16 v1.0 End-to-End Encryption Specification section A.2.8.8,
+// and A.3.8.10.
+// id-acsParticipantInformation OBJECT IDENTIFIER ::= { id-gmsaRCS2EE 5 }
+// In dotted notation: 2.23.146.2.1.5
+inline constexpr uint8_t kRcsMlsAcsParticipantInformation[] = {
+    0x67, 0x81, 0x12, 0x02, 0x01, 0x05};
+
 // Parses the Extensions sequence as defined by RFC 5280. Extensions are added
 // to the map |extensions| keyed by the OID. Parsing guarantees that each OID
 // is unique. Note that certificate verification must consume each extension
diff --git a/src/pki/parse_certificate_unittest.cc b/src/pki/parse_certificate_unittest.cc
index 8f867b9..19382a2 100644
--- a/src/pki/parse_certificate_unittest.cc
+++ b/src/pki/parse_certificate_unittest.cc
@@ -15,7 +15,10 @@
 #include "parse_certificate.h"
 
 #include <gtest/gtest.h>
+
 #include <openssl/pool.h>
+#include <openssl/span.h>
+
 #include "cert_errors.h"
 #include "general_names.h"
 #include "input.h"
@@ -73,7 +76,7 @@
   der::BitString signature_value;
   CertErrors errors;
   bool actual_result =
-      ParseCertificate(der::Input(data), &tbs_certificate_tlv,
+      ParseCertificate(StringAsBytes(data), &tbs_certificate_tlv,
                        &signature_algorithm_tlv, &signature_value, &errors);
 
   EXPECT_EQ(expected_result, actual_result);
@@ -82,10 +85,12 @@
   // Ensure that the parsed certificate matches expectations.
   if (expected_result && actual_result) {
     EXPECT_EQ(0, signature_value.unused_bits());
-    EXPECT_EQ(der::Input(expected_signature), signature_value.bytes());
-    EXPECT_EQ(der::Input(expected_signature_algorithm),
+    EXPECT_EQ(der::Input(StringAsBytes(expected_signature)),
+              signature_value.bytes());
+    EXPECT_EQ(der::Input(StringAsBytes(expected_signature_algorithm)),
               signature_algorithm_tlv);
-    EXPECT_EQ(der::Input(expected_tbs_certificate), tbs_certificate_tlv);
+    EXPECT_EQ(der::Input(StringAsBytes(expected_tbs_certificate)),
+              tbs_certificate_tlv);
   }
 }
 
@@ -177,7 +182,7 @@
   ParsedTbsCertificate parsed;
   CertErrors errors;
   bool actual_result =
-      ParseTbsCertificate(der::Input(data), {}, &parsed, &errors);
+      ParseTbsCertificate(StringAsBytes(data), {}, &parsed, &errors);
 
   EXPECT_EQ(expected_result, actual_result);
   VerifyCertErrors(expected_errors, errors, test_file_path);
@@ -189,36 +194,38 @@
   // Ensure that the ParsedTbsCertificate matches expectations.
   EXPECT_EQ(expected_version, parsed.version);
 
-  EXPECT_EQ(der::Input(expected_serial_number), parsed.serial_number);
-  EXPECT_EQ(der::Input(expected_signature_algorithm),
+  EXPECT_EQ(der::Input(StringAsBytes(expected_serial_number)),
+            parsed.serial_number);
+  EXPECT_EQ(der::Input(StringAsBytes(expected_signature_algorithm)),
             parsed.signature_algorithm_tlv);
 
-  EXPECT_EQ(der::Input(expected_issuer), parsed.issuer_tlv);
+  EXPECT_EQ(der::Input(StringAsBytes(expected_issuer)), parsed.issuer_tlv);
 
   // In the test expectations PEM file, validity is described as a
   // textual string of the parsed value (rather than as DER).
   EXPECT_EQ(expected_validity_not_before, ToString(parsed.validity_not_before));
   EXPECT_EQ(expected_validity_not_after, ToString(parsed.validity_not_after));
 
-  EXPECT_EQ(der::Input(expected_subject), parsed.subject_tlv);
-  EXPECT_EQ(der::Input(expected_spki), parsed.spki_tlv);
+  EXPECT_EQ(der::Input(StringAsBytes(expected_subject)), parsed.subject_tlv);
+  EXPECT_EQ(der::Input(StringAsBytes(expected_spki)), parsed.spki_tlv);
 
   EXPECT_EQ(!expected_issuer_unique_id.empty(),
             parsed.issuer_unique_id.has_value());
   if (parsed.issuer_unique_id.has_value()) {
-    EXPECT_EQ(der::Input(expected_issuer_unique_id),
+    EXPECT_EQ(der::Input(StringAsBytes(expected_issuer_unique_id)),
               parsed.issuer_unique_id->bytes());
   }
   EXPECT_EQ(!expected_subject_unique_id.empty(),
             parsed.subject_unique_id.has_value());
   if (parsed.subject_unique_id.has_value()) {
-    EXPECT_EQ(der::Input(expected_subject_unique_id),
+    EXPECT_EQ(der::Input(StringAsBytes(expected_subject_unique_id)),
               parsed.subject_unique_id->bytes());
   }
 
   EXPECT_EQ(!expected_extensions.empty(), parsed.extensions_tlv.has_value());
   if (parsed.extensions_tlv) {
-    EXPECT_EQ(der::Input(expected_extensions), parsed.extensions_tlv.value());
+    EXPECT_EQ(der::Input(StringAsBytes(expected_extensions)),
+              parsed.extensions_tlv.value());
   }
 }
 
@@ -1018,7 +1025,7 @@
       file_name;
   EXPECT_TRUE(ReadTestDataFromPemFile(test_file_path, mappings));
 
-  return ParseAuthorityKeyIdentifier(der::Input(*backing_bytes),
+  return ParseAuthorityKeyIdentifier(StringAsBytes(*backing_bytes),
                                      authority_key_identifier);
 }
 
diff --git a/src/pki/parsed_certificate.h b/src/pki/parsed_certificate.h
index 57a7f1d..88df692 100644
--- a/src/pki/parsed_certificate.h
+++ b/src/pki/parsed_certificate.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include <openssl/base.h>
+#include <openssl/span.h>
 
 #include "certificate_policies.h"
 #include "input.h"
@@ -117,7 +118,7 @@
   // Sequence tag). This is guaranteed to be valid DER, though the contents of
   // unhandled string types are treated as raw bytes.
   der::Input normalized_subject() const {
-    return der::Input(normalized_subject_);
+    return StringAsBytes(normalized_subject_);
   }
   // Returns the DER-encoded raw issuer value (including the outer sequence
   // tag). This is guaranteed to be valid DER, though the contents of unhandled
@@ -127,7 +128,7 @@
   // Sequence tag). This is guaranteed to be valid DER, though the contents of
   // unhandled string types are treated as raw bytes.
   der::Input normalized_issuer() const {
-    return der::Input(normalized_issuer_);
+    return StringAsBytes(normalized_issuer_);
   }
 
   // Returns true if the certificate has a BasicConstraints extension.
diff --git a/src/pki/simple_path_builder_delegate_unittest.cc b/src/pki/simple_path_builder_delegate_unittest.cc
index b345bc1..568cce6 100644
--- a/src/pki/simple_path_builder_delegate_unittest.cc
+++ b/src/pki/simple_path_builder_delegate_unittest.cc
@@ -11,13 +11,17 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+
 #include "simple_path_builder_delegate.h"
 
 #include <memory>
 #include <set>
 
 #include <gtest/gtest.h>
+
 #include <openssl/nid.h>
+#include <openssl/span.h>
+
 #include "cert_errors.h"
 #include "input.h"
 #include "parse_values.h"
@@ -48,11 +52,11 @@
   ASSERT_TRUE(ReadTestDataFromPemFile(path, mappings));
 
   std::optional<SignatureAlgorithm> sigalg_opt =
-      ParseSignatureAlgorithm(der::Input(algorithm_str));
+      ParseSignatureAlgorithm(StringAsBytes(algorithm_str));
   ASSERT_TRUE(sigalg_opt);
   *signature_algorithm = *sigalg_opt;
 
-  ASSERT_TRUE(ParsePublicKey(der::Input(public_key_str), public_key));
+  ASSERT_TRUE(ParsePublicKey(StringAsBytes(public_key_str), public_key));
 }
 
 class SimplePathBuilderDelegate1024SuccessTest
diff --git a/src/pki/test_helpers.cc b/src/pki/test_helpers.cc
index 20f082f..123aacb 100644
--- a/src/pki/test_helpers.cc
+++ b/src/pki/test_helpers.cc
@@ -26,6 +26,7 @@
 #include <openssl/bytestring.h>
 #include <openssl/mem.h>
 #include <openssl/pool.h>
+#include <openssl/span.h>
 
 #include "../crypto/test/test_data.h"
 #include "cert_error_params.h"
@@ -123,7 +124,7 @@
 }  // namespace der
 
 der::Input SequenceValueFromString(std::string_view s) {
-  der::Parser parser((der::Input(s)));
+  der::Parser parser(StringAsBytes(s));
   der::Input data;
   if (!parser.ReadTag(CBS_ASN1_SEQUENCE, &data)) {
     ADD_FAILURE();
@@ -299,7 +300,7 @@
       if (value == "DEFAULT") {
         value = "211005120000Z";
       }
-      if (!der::ParseUTCTime(der::Input(value), &test->time)) {
+      if (!der::ParseUTCTime(StringAsBytes(value), &test->time)) {
         ADD_FAILURE() << "Failed parsing UTC time";
         return false;
       }
@@ -319,6 +320,12 @@
         test->key_purpose = KeyPurpose::SERVER_AUTH_STRICT_LEAF;
       } else if (value == "CLIENT_AUTH_STRICT_LEAF") {
         test->key_purpose = KeyPurpose::CLIENT_AUTH_STRICT_LEAF;
+      } else if (value == "MLS_CLIENT_AUTH") {
+        test->key_purpose = KeyPurpose::RCS_MLS_CLIENT_AUTH;
+      } else if (value == "C2PA_TIMESTAMPING") {
+        test->key_purpose = KeyPurpose::C2PA_TIMESTAMPING;
+      } else if (value == "C2PA_MANIFEST") {
+        test->key_purpose = KeyPurpose::C2PA_MANIFEST;
       } else {
         ADD_FAILURE() << "Unrecognized key_purpose: " << value;
         return false;
diff --git a/src/pki/testdata/nist-pkits/README.chromium b/src/pki/testdata/nist-pkits/README.chromium
deleted file mode 100644
index 3f09e09..0000000
--- a/src/pki/testdata/nist-pkits/README.chromium
+++ /dev/null
@@ -1,20 +0,0 @@
-Name: NIST Public Key Interoperability Test Suite
-Short Name: NIST PKITS
-URL: http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html
-Version: 1.0.1
-Date: 2011-04-14
-License: Public Domain: United States Government Work under 17 U.S.C. 105
-Shipped: no
-Security Critical: no
-
-Description:
-The Public Key Interoperability Test Suite (PKITS) is a comprehensive X.509
-path validation test suite that was developed by NIST in conjunction with BAE
-Systems and NSA.  The PKITS path validation test suite is designed to cover
-most of the features specified in X.509 and RFC 3280.
-
-Local Modifications:
-Only the certs/ and crls/ directories were extracted from PKITS_data.zip.
-
-pkits_testcases-inl.h is generated from the test descriptions in PKITS.pdf
-using generate_tests.py.
diff --git a/src/pki/testdata/nist-pkits/README.md b/src/pki/testdata/nist-pkits/README.md
new file mode 100644
index 0000000..c1e001e
--- /dev/null
+++ b/src/pki/testdata/nist-pkits/README.md
@@ -0,0 +1,7 @@
+# NIST Public Key Interoperability Test Suite
+
+This directory contains test data from the NIST [Public Key Interoperability Test Suite](http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html) (NIST PKITS), version 1.0.1, fetched 2011-04-14. NIST PKITS test data is under public domain (United States Government Work under 17 U.S.C. 105). This directory is not included in BoringSSL when compiled and is only used for testing.
+
+Only the `certs/` and `crls/` directories were extracted from `PKITS_data.zip`.
+
+`pkits_testcases-inl.h` is generated from the test descriptions in `PKITS.pdf` using `generate_tests.py`.
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/generate-all.sh b/src/pki/testdata/verify_certificate_chain_unittest/generate-all.sh
index 15dc4ff..4941ca3 100755
--- a/src/pki/testdata/verify_certificate_chain_unittest/generate-all.sh
+++ b/src/pki/testdata/verify_certificate_chain_unittest/generate-all.sh
@@ -16,6 +16,11 @@
 
 set -e
 
+# As generate-chains.py calls out to the openssl command under the hood
+# this is suboptimal if you don't have openssl installed. We should
+# replace generate-chains.py
+# TODO(bbe): crbug.com/402461221
+
 for dir in */ ; do
   cd "$dir"
 
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test
new file mode 100644
index 0000000..4d092a9
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/any.test
@@ -0,0 +1,5 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: ANY_EKU
+expected_errors:
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test
new file mode 100644
index 0000000..ffae69c
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2pamanifest.test
@@ -0,0 +1,5 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: C2PA_MANIFEST
+expected_errors:
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test
new file mode 100644
index 0000000..c587a36
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/c2patimestamp.test
@@ -0,0 +1,8 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: C2PA_TIMESTAMPING
+expected_errors:
+----- Certificate i=0 (CN=C2PA Cert Leaf) -----
+ERROR: The extended key usage does not contain the time stamping key purpose, or contains prohibited key usages
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem
new file mode 100644
index 0000000..321652c
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/chain.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIBlDCCATqgAwIBAgIBAzAKBggqhkjOPQQDAjAhMR8wHQYDVQQDExZDMlBBIENl
+cnQgSW50ZXJtZWRpYXRlMCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5
+NTlaMBkxFzAVBgNVBAMTDkMyUEEgQ2VydCBMZWFmMFkwEwYHKoZIzj0CAQYIKoZI
+zj0DAQcDQgAEkSrYvFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1S
+ERGnEaiNLpoc0dleTS8wQT/cjw/wPgoeV6NnMGUwDgYDVR0PAQH/BAQDAgeAMB0G
+A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDBDAMBgNVHRMBAf8EAjAAMA0GA1Ud
+DgQGBARsZWFmMBcGA1UdIwQQMA6ADGludGVybWVkaWF0ZTAKBggqhkjOPQQDAgNI
+ADBFAiAqKEacSfBZeF/TXI04niDtv5S+UJ7/TVFAwnC8xH75uwIhAJSQsLXs+a3O
+NkoRHJKGsnuJ8Py2hMfY7r6h95b4p5A3
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBijCCATGgAwIBAgIBAjAKBggqhkjOPQQDAjAZMRcwFQYDVQQDEw5DMlBBIENl
+cnQgUm9vdDAiGA8wMDAwMDEwMTAwMDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAhMR8w
+HQYDVQQDExZDMlBBIENlcnQgSW50ZXJtZWRpYXRlMFkwEwYHKoZIzj0CAQYIKoZI
+zj0DAQcDQgAE4jp8qIzeMUuQvICfzxy+XDhLDG7KBGOik/cUUEofJRC+HdVW9+pK
+lIJKannRCJqNDoODsJOlVlVUf5uC5PslMKNeMFwwDgYDVR0PAQH/BAQDAgIEMBEG
+A1UdJQQKMAgGBmeBEgIBAzAPBgNVHRMBAf8EBTADAQH/MBUGA1UdDgQOBAxpbnRl
+cm1lZGlhdGUwDwYDVR0jBAgwBoAEcm9vdDAKBggqhkjOPQQDAgNHADBEAiBIGr9B
+G10qB/vTMMruFZWBwzUFM7AnP9tlpqKyRorXJwIgEQDzXE5xS+q9PiRjtnD5NA2k
+2tBHjho1duXcd1EsKdc=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBVTCB/aADAgECAgEBMAoGCCqGSM49BAMCMBkxFzAVBgNVBAMTDkMyUEEgQ2Vy
+dCBSb290MCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMBkxFzAV
+BgNVBAMTDkMyUEEgQ2VydCBSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+Jnal2JdRr2O8t43E0yujFVyEK+OE6goUWCOiHlfbSAeoyLDmPkKJdW5PMf+wORRj
+p1FhVSxADxD0icD53Y6JbaMyMDAwDgYDVR0PAQH/BAQDAgIEMA8GA1UdEwEB/wQF
+MAMBAf8wDQYDVR0OBAYEBHJvb3QwCgYIKoZIzj0EAwIDRwAwRAIgcB1lb5KE/GOi
+RTy4bcRudwGKQ65BMBPn2AVGPnmrJ9wCIGwrE1m36y5EkgDHujNcnQD+x6o6gqj3
+WOZICZjXCDKx
+-----END CERTIFICATE-----
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test
new file mode 100644
index 0000000..b46cc5a
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/clientauth.test
@@ -0,0 +1,11 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=C2PA Cert Leaf) -----
+ERROR: The extended key usage does not include client auth
+
+----- Certificate i=1 (CN=C2PA Cert Intermediate) -----
+ERROR: The extended key usage does not include client auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/make-chain.go b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/make-chain.go
new file mode 100644
index 0000000..49ed58b
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/make-chain.go
@@ -0,0 +1,171 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build ignore
+
+// make-chain generates a test certificate chain.
+package main
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/pem"
+	"math/big"
+	"os"
+	"time"
+)
+
+var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
+
+func init() {
+	leafKey = mustParseECDSAKey(leafKeyPEM)
+	intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
+	rootKey = mustParseECDSAKey(rootKeyPEM)
+}
+
+type templateAndKey struct {
+	template x509.Certificate
+	key      *ecdsa.PrivateKey
+}
+
+func mustStartChain(path string, subject, issuer *templateAndKey) []byte {
+	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.OpenFile(path, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
+	if err != nil {
+		panic(err)
+	}
+	defer file.Close()
+	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
+	if err != nil {
+		panic(err)
+	}
+	file.Close()
+	return cert
+}
+
+func mustAppendToChain(path string, subject, issuer *templateAndKey) []byte {
+	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		panic(err)
+	}
+	defer file.Close()
+	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
+	if err != nil {
+		panic(err)
+	}
+	file.Close()
+	return cert
+}
+
+func main() {
+	notBefore, err := time.Parse(time.RFC3339, "0000-01-01T00:00:00Z")
+	if err != nil {
+		panic(err)
+	}
+	notAfter, err := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
+	if err != nil {
+		panic(err)
+	}
+
+	root := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(1),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Root"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("root"),
+		},
+		key: rootKey,
+	}
+	intermediate := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(2),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Intermediate"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("intermediate"),
+			UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}},
+		},
+		key: intermediateKey,
+	}
+
+	leaf := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(3),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Leaf"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  false,
+			KeyUsage:              x509.KeyUsageDigitalSignature,
+			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageEmailProtection},
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("leaf"),
+		},
+		key: leafKey,
+	}
+
+	// Generate a valid certificate chain from the templates.
+	mustStartChain("chain.pem", &leaf, &intermediate)
+	mustAppendToChain("chain.pem", &intermediate, &root)
+	mustAppendToChain("chain.pem", &root, &root)
+}
+
+const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
+024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
+w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
+-----END PRIVATE KEY-----`
+
+const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
+vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
+Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
+-----END PRIVATE KEY-----`
+
+const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
+Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
+ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
+-----END PRIVATE KEY-----`
+
+func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
+	keyBlock, _ := pem.Decode([]byte(in))
+	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
+		panic("could not decode private key")
+	}
+	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
+	if err != nil {
+		panic(err)
+	}
+	return key.(*ecdsa.PrivateKey)
+}
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test
new file mode 100644
index 0000000..ee67119
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2pamanifest/serverauth.test
@@ -0,0 +1,8 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: SERVER_AUTH
+expected_errors:
+----- Certificate i=1 (CN=C2PA Cert Intermediate) -----
+ERROR: The extended key usage does not include server auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test
new file mode 100644
index 0000000..4d092a9
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/any.test
@@ -0,0 +1,5 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: ANY_EKU
+expected_errors:
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test
new file mode 100644
index 0000000..e48463c
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2pamanifest.test
@@ -0,0 +1,8 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: C2PA_MANIFEST
+expected_errors:
+----- Certificate i=0 (CN=C2PA Cert Leaf) -----
+ERROR: The extended key usage must contain at least one of: email protection or document signing, and must not contain prohibited key usages
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test
new file mode 100644
index 0000000..b6c6911
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/c2patimestamp.test
@@ -0,0 +1,5 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: C2PA_TIMESTAMPING
+expected_errors:
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem
new file mode 100644
index 0000000..8df49ce
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/chain.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIBgzCCASqgAwIBAgIBAzAKBggqhkjOPQQDAjAhMR8wHQYDVQQDExZDMlBBIENl
+cnQgSW50ZXJtZWRpYXRlMCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5
+NTlaMBkxFzAVBgNVBAMTDkMyUEEgQ2VydCBMZWFmMFkwEwYHKoZIzj0CAQYIKoZI
+zj0DAQcDQgAEkSrYvFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1S
+ERGnEaiNLpoc0dleTS8wQT/cjw/wPgoeV6NXMFUwHQYDVR0lBBYwFAYIKwYBBQUH
+AwEGCCsGAQUFBwMIMAwGA1UdEwEB/wQCMAAwDQYDVR0OBAYEBGxlYWYwFwYDVR0j
+BBAwDoAMaW50ZXJtZWRpYXRlMAoGCCqGSM49BAMCA0cAMEQCIDfZSkZ9qfE9DtRb
+lU5IOLhh8xpEcwoaQWRUS2UIIAD5AiAFbPG4214Y2skTsSVm58ynjbjam/lO36V0
+C5YREd86tw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBizCCATGgAwIBAgIBAjAKBggqhkjOPQQDAjAZMRcwFQYDVQQDEw5DMlBBIENl
+cnQgUm9vdDAiGA8wMDAwMDEwMTAwMDAwMFoYDzk5OTkxMjMxMjM1OTU5WjAhMR8w
+HQYDVQQDExZDMlBBIENlcnQgSW50ZXJtZWRpYXRlMFkwEwYHKoZIzj0CAQYIKoZI
+zj0DAQcDQgAE4jp8qIzeMUuQvICfzxy+XDhLDG7KBGOik/cUUEofJRC+HdVW9+pK
+lIJKannRCJqNDoODsJOlVlVUf5uC5PslMKNeMFwwDgYDVR0PAQH/BAQDAgIEMBEG
+A1UdJQQKMAgGBmeBEgIBAzAPBgNVHRMBAf8EBTADAQH/MBUGA1UdDgQOBAxpbnRl
+cm1lZGlhdGUwDwYDVR0jBAgwBoAEcm9vdDAKBggqhkjOPQQDAgNIADBFAiEA+M4D
+YTyTHKD6Ism47OXmG52xO0kNCiFSmZ69/6zNW+QCIEPo5nZgHp8QvYN8wMVMKtbt
+dAKAnjgW98HoANRg8zI5
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBVjCB/aADAgECAgEBMAoGCCqGSM49BAMCMBkxFzAVBgNVBAMTDkMyUEEgQ2Vy
+dCBSb290MCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMBkxFzAV
+BgNVBAMTDkMyUEEgQ2VydCBSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+Jnal2JdRr2O8t43E0yujFVyEK+OE6goUWCOiHlfbSAeoyLDmPkKJdW5PMf+wORRj
+p1FhVSxADxD0icD53Y6JbaMyMDAwDgYDVR0PAQH/BAQDAgIEMA8GA1UdEwEB/wQF
+MAMBAf8wDQYDVR0OBAYEBHJvb3QwCgYIKoZIzj0EAwIDSAAwRQIhAIfA7n5sX+4L
+S7/98FuSque5GpwHoELRrQdDxvqzb97oAiBugKrTQN76A+/hvoHQmylV07xnq0v2
+Jn77ADgWGozs8Q==
+-----END CERTIFICATE-----
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test
new file mode 100644
index 0000000..b5b9e03
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/clientauth.test
@@ -0,0 +1,12 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=C2PA Cert Leaf) -----
+WARNING: The extended key usage includes time stamping which is not permitted for this use
+ERROR: The extended key usage does not include client auth
+
+----- Certificate i=1 (CN=C2PA Cert Intermediate) -----
+ERROR: The extended key usage does not include client auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/make-chain.go b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/make-chain.go
new file mode 100644
index 0000000..3a3de84
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/make-chain.go
@@ -0,0 +1,170 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build ignore
+
+// make-chain generates a test certificate chain.
+package main
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/pem"
+	"math/big"
+	"os"
+	"time"
+)
+
+var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
+
+func init() {
+	leafKey = mustParseECDSAKey(leafKeyPEM)
+	intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
+	rootKey = mustParseECDSAKey(rootKeyPEM)
+}
+
+type templateAndKey struct {
+	template x509.Certificate
+	key      *ecdsa.PrivateKey
+}
+
+func mustStartChain(path string, subject, issuer *templateAndKey) []byte {
+	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.OpenFile(path, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
+	if err != nil {
+		panic(err)
+	}
+	defer file.Close()
+	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
+	if err != nil {
+		panic(err)
+	}
+	file.Close()
+	return cert
+}
+
+func mustAppendToChain(path string, subject, issuer *templateAndKey) []byte {
+	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		panic(err)
+	}
+	defer file.Close()
+	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
+	if err != nil {
+		panic(err)
+	}
+	file.Close()
+	return cert
+}
+
+func main() {
+	notBefore, err := time.Parse(time.RFC3339, "0000-01-01T00:00:00Z")
+	if err != nil {
+		panic(err)
+	}
+	notAfter, err := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
+	if err != nil {
+		panic(err)
+	}
+
+	root := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(1),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Root"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("root"),
+		},
+		key: rootKey,
+	}
+	intermediate := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(2),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Intermediate"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("intermediate"),
+			UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}},
+		},
+		key: intermediateKey,
+	}
+
+	leaf := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(3),
+			Subject:               pkix.Name{CommonName: "C2PA Cert Leaf"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  false,
+			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageTimeStamping},
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("leaf"),
+		},
+		key: leafKey,
+	}
+
+	// Generate a valid certificate chain from the templates.
+	mustStartChain("chain.pem", &leaf, &intermediate)
+	mustAppendToChain("chain.pem", &intermediate, &root)
+	mustAppendToChain("chain.pem", &root, &root)
+}
+
+const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
+024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
+w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
+-----END PRIVATE KEY-----`
+
+const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
+vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
+Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
+-----END PRIVATE KEY-----`
+
+const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
+Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
+ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
+-----END PRIVATE KEY-----`
+
+func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
+	keyBlock, _ := pem.Decode([]byte(in))
+	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
+		panic("could not decode private key")
+	}
+	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
+	if err != nil {
+		panic(err)
+	}
+	return key.(*ecdsa.PrivateKey)
+}
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test
new file mode 100644
index 0000000..50b77fd
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-c2patimestamping/serverauth.test
@@ -0,0 +1,11 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: SERVER_AUTH
+expected_errors:
+----- Certificate i=0 (CN=C2PA Cert Leaf) -----
+WARNING: The extended key usage includes time stamping which is not permitted for this use
+
+----- Certificate i=1 (CN=C2PA Cert Intermediate) -----
+ERROR: The extended key usage does not include server auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test
new file mode 100644
index 0000000..67f8d83
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/any.test
@@ -0,0 +1,13 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: ANY_EKU
+expected_errors:
+----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: Unconsumed critical extension
+  oid: 678112020104
+  value: 30080606678112020104
+ERROR: Unconsumed critical extension
+  oid: 678112020105
+  value: 30080606678112020105
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
new file mode 100644
index 0000000..d068d24
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/chain.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIBwTCCAWegAwIBAgIBAzAKBggqhkjOPQQDAjAgMR4wHAYDVQQDExVNTFMgQ2Vy
+dCBJbnRlcm1lZGlhdGUwIhgPMDAwMDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1
+OVowGDEWMBQGA1UEAxMNTUxTIENlcnQgTGVhZjBZMBMGByqGSM49AgEGCCqGSM49
+AwEHA0IABJEq2LxVbZGSZr4q32NCQw2K2UKzSXnDy7dJLCbsdlES+ZwEIkGNUhER
+pxGojS6aHNHZXk0vMEE/3I8P8D4KHlejgZUwgZIwDgYDVR0PAQH/BAQDAgWgMBgG
+A1UdJQQRMA8GBmeBEgIBAwYFZ4EFCAEwDAYDVR0TAQH/BAIwADANBgNVHQ4EBgQE
+bGVhZjAXBgNVHSMEEDAOgAxpbnRlcm1lZGlhdGUwFwYGZ4ESAgEEAQH/BAowCAYG
+Z4ESAgEEMBcGBmeBEgIBBQEB/wQKMAgGBmeBEgIBBTAKBggqhkjOPQQDAgNIADBF
+AiEAoHx0HkcLugc+lfbjUe/V6lEQk26diFlw76bqeLLmrt0CIBOXOwd+gC66weUM
+5np3wcTVet2fxPvyLfu1NwmFQkc/
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBkzCCATmgAwIBAgIBAjAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1NTFMgQ2Vy
+dCBSb290MCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMCAxHjAc
+BgNVBAMTFU1MUyBDZXJ0IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49
+AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSC
+Smp50QiajQ6Dg7CTpVZVVH+bguT7JTCjaDBmMA4GA1UdDwEB/wQEAwICBDAPBgNV
+HRMBAf8EBTADAQH/MBUGA1UdDgQOBAxpbnRlcm1lZGlhdGUwDwYDVR0jBAgwBoAE
+cm9vdDAbBgNVHSUEFDASBgZngRICAQMGCCsGAQUFBwMCMAoGCCqGSM49BAMCA0gA
+MEUCIQCab7y2vrjyMny/WJbdTlJilqPfnuDlEirN0T2AVLJfegIgF+/AcAxZq6Q/
+MIbkA98Th1fRCsTBNVpkVB/fTrp4vXk=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBVTCB+6ADAgECAgEBMAoGCCqGSM49BAMCMBgxFjAUBgNVBAMTDU1MUyBDZXJ0
+IFJvb3QwIhgPMDAwMDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowGDEWMBQG
+A1UEAxMNTUxTIENlcnQgUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCZ2
+pdiXUa9jvLeNxNMroxVchCvjhOoKFFgjoh5X20gHqMiw5j5CiXVuTzH/sDkUY6dR
+YVUsQA8Q9InA+d2OiW2jMjAwMA4GA1UdDwEB/wQEAwICBDAPBgNVHRMBAf8EBTAD
+AQH/MA0GA1UdDgQGBARyb290MAoGCCqGSM49BAMCA0kAMEYCIQCBTvSTnUwq0rQr
+0xFmkVYH1NwAP6OFlfQNfSP9XgeMrQIhAO6ILVuc7gQITkDQQ/9CJLjHD6+aHl9w
+ZSABihMw3UoF
+-----END CERTIFICATE-----
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
new file mode 100644
index 0000000..db097f6
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth-extra/mlsclientauth.test
@@ -0,0 +1,12 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: MLS_CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
+ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
+
+----- Certificate i=1 (CN=MLS Cert Intermediate) -----
+ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test
new file mode 100644
index 0000000..67f8d83
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/any.test
@@ -0,0 +1,13 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: ANY_EKU
+expected_errors:
+----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: Unconsumed critical extension
+  oid: 678112020104
+  value: 30080606678112020104
+ERROR: Unconsumed critical extension
+  oid: 678112020105
+  value: 30080606678112020105
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem
new file mode 100644
index 0000000..c310b97
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/chain.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIBujCCAWCgAwIBAgIBAzAKBggqhkjOPQQDAjAgMR4wHAYDVQQDExVNTFMgQ2Vy
+dCBJbnRlcm1lZGlhdGUwIhgPMDAwMDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1
+OVowGDEWMBQGA1UEAxMNTUxTIENlcnQgTGVhZjBZMBMGByqGSM49AgEGCCqGSM49
+AwEHA0IABJEq2LxVbZGSZr4q32NCQw2K2UKzSXnDy7dJLCbsdlES+ZwEIkGNUhER
+pxGojS6aHNHZXk0vMEE/3I8P8D4KHlejgY4wgYswDgYDVR0PAQH/BAQDAgeAMBEG
+A1UdJQQKMAgGBmeBEgIBAzAMBgNVHRMBAf8EAjAAMA0GA1UdDgQGBARsZWFmMBcG
+A1UdIwQQMA6ADGludGVybWVkaWF0ZTAXBgZngRICAQQBAf8ECjAIBgZngRICAQQw
+FwYGZ4ESAgEFAQH/BAowCAYGZ4ESAgEFMAoGCCqGSM49BAMCA0gAMEUCIEFVao6y
+OepuSGWgIK9Hdvc4DIRLZV+kYbHc9ub5LEO3AiEAiLXBSJffzY24NTMMqxsN+MCn
+w5ADuHTqNXjz6LFTkV0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBiTCCAS+gAwIBAgIBAjAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1NTFMgQ2Vy
+dCBSb290MCIYDzAwMDAwMTAxMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMCAxHjAc
+BgNVBAMTFU1MUyBDZXJ0IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49
+AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSC
+Smp50QiajQ6Dg7CTpVZVVH+bguT7JTCjXjBcMA4GA1UdDwEB/wQEAwICBDAPBgNV
+HRMBAf8EBTADAQH/MBUGA1UdDgQOBAxpbnRlcm1lZGlhdGUwDwYDVR0jBAgwBoAE
+cm9vdDARBgNVHSUECjAIBgZngRICAQMwCgYIKoZIzj0EAwIDSAAwRQIgOETRj6he
+MGkPl27+ZVNsvmd1rWuiNpb2Zc79M9FlrHUCIQDpkCWKOepaN7Zsaw/XSh4Q2pJ7
+E9JUo6Ea1qNumaEx1g==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBVDCB+6ADAgECAgEBMAoGCCqGSM49BAMCMBgxFjAUBgNVBAMTDU1MUyBDZXJ0
+IFJvb3QwIhgPMDAwMDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowGDEWMBQG
+A1UEAxMNTUxTIENlcnQgUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCZ2
+pdiXUa9jvLeNxNMroxVchCvjhOoKFFgjoh5X20gHqMiw5j5CiXVuTzH/sDkUY6dR
+YVUsQA8Q9InA+d2OiW2jMjAwMA4GA1UdDwEB/wQEAwICBDAPBgNVHRMBAf8EBTAD
+AQH/MA0GA1UdDgQGBARyb290MAoGCCqGSM49BAMCA0gAMEUCIF3vtvNCgqJwgw+0
+ugR3xzy/hDMDO9k8/YZl2jfVReQAAiEA1yezH2MtSHGs1HIZyLjBW+32N5abvlll
+zWPFmkMkxJU=
+-----END CERTIFICATE-----
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test
new file mode 100644
index 0000000..f8985ae
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/clientauth.test
@@ -0,0 +1,17 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: The extended key usage does not include client auth
+ERROR: Unconsumed critical extension
+  oid: 678112020104
+  value: 30080606678112020104
+ERROR: Unconsumed critical extension
+  oid: 678112020105
+  value: 30080606678112020105
+
+----- Certificate i=1 (CN=MLS Cert Intermediate) -----
+ERROR: The extended key usage does not include client auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go
new file mode 100644
index 0000000..b1d64cc
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/make-mls-extensions.go
@@ -0,0 +1,192 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build ignore
+
+// make-mls-extensions.go generates test certs to test mls extension handling.
+package main
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/pem"
+	"math/big"
+	"os"
+	"time"
+)
+
+var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
+
+func init() {
+	leafKey = mustParseECDSAKey(leafKeyPEM)
+	intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
+	rootKey = mustParseECDSAKey(rootKeyPEM)
+}
+
+type templateAndKey struct {
+	template x509.Certificate
+	key      *ecdsa.PrivateKey
+}
+
+func rcsMlsParticipantExtension() (ext pkix.Extension, err error) {
+	var oidParticipantInfo = asn1.ObjectIdentifier{2, 23, 146, 2, 1, 4}
+	ext = pkix.Extension{}
+	ext.Id = oidParticipantInfo
+	ext.Critical = true
+	// Not really a valid value, but doesn't matter to us.
+	ext.Value, err = asn1.Marshal([]asn1.ObjectIdentifier{oidParticipantInfo})
+	return ext, err
+}
+
+func rcsAcsMlsParticipantExtension() (ext pkix.Extension, err error) {
+	var oidParticipantInfo = asn1.ObjectIdentifier{2, 23, 146, 2, 1, 5}
+	ext = pkix.Extension{}
+	ext.Id = oidParticipantInfo
+	ext.Critical = true
+	// Not really a valid value, but doesn't matter to us.
+	ext.Value, err = asn1.Marshal([]asn1.ObjectIdentifier{oidParticipantInfo})
+	return ext, err
+}
+
+func mustGenerateCertificate(path string, subject, issuer *templateAndKey) []byte {
+	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.Create(path)
+	if err != nil {
+		panic(err)
+	}
+	defer file.Close()
+	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
+	if err != nil {
+		panic(err)
+	}
+	return cert
+}
+
+func main() {
+	notBefore, err := time.Parse(time.RFC3339, "0000-01-01T00:00:00Z")
+	if err != nil {
+		panic(err)
+	}
+	notAfter, err := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
+	if err != nil {
+		panic(err)
+	}
+
+	root := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(1),
+			Subject:               pkix.Name{CommonName: "MLS Cert Root"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("root"),
+		},
+		key: rootKey,
+	}
+	intermediate := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(2),
+			Subject:               pkix.Name{CommonName: "MLS Cert Intermediate"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  true,
+			KeyUsage:              x509.KeyUsageCertSign,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("intermediate"),
+			UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}},
+		},
+		key: intermediateKey,
+	}
+
+	ParticipantExt, err := rcsMlsParticipantExtension()
+	if err != nil {
+		panic(err)
+	}
+
+	AcsParticipantExt, err := rcsAcsMlsParticipantExtension()
+	if err != nil {
+		panic(err)
+	}
+
+	leaf := templateAndKey{
+		template: x509.Certificate{
+			SerialNumber:          new(big.Int).SetInt64(3),
+			Subject:               pkix.Name{CommonName: "MLS Cert Leaf"},
+			NotBefore:             notBefore,
+			NotAfter:              notAfter,
+			BasicConstraintsValid: true,
+			IsCA:                  false,
+			KeyUsage:              x509.KeyUsageDigitalSignature,
+			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("leaf"),
+			UnknownExtKeyUsage:    []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3}},
+			ExtraExtensions:       append([]pkix.Extension{}, ParticipantExt, AcsParticipantExt),
+		},
+		key: leafKey,
+	}
+
+	// Generate a valid certificate chain from the templates.
+	mustGenerateCertificate("mls_client_root.pem", &root, &root)
+	mustGenerateCertificate("mls_client_intermediate.pem", &intermediate, &root)
+	mustGenerateCertificate("mls_client_leaf.pem", &leaf, &intermediate)
+	intermediateInvalid := intermediate
+	intermediateInvalid.template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3},
+		[]int{2, 23, 133, 8, 1}}
+	mustGenerateCertificate("mls_client_intermediate_extra_eku.pem", &intermediateInvalid, &root)
+	leafInvalid := leaf
+	leafInvalid.template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{[]int{2, 23, 146, 2, 1, 3},
+		[]int{2, 23, 133, 8, 1}}
+	leafInvalid.template.KeyUsage |= x509.KeyUsageKeyEncipherment
+	mustGenerateCertificate("mls_client_leaf_extra_eku.pem", &leafInvalid, &intermediateInvalid)
+}
+
+const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
+024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
+w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
+-----END PRIVATE KEY-----`
+
+const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
+vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
+Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
+-----END PRIVATE KEY-----`
+
+const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
+Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
+ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
+-----END PRIVATE KEY-----`
+
+func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
+	keyBlock, _ := pem.Decode([]byte(in))
+	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
+		panic("could not decode private key")
+	}
+	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
+	if err != nil {
+		panic(err)
+	}
+	return key.(*ecdsa.PrivateKey)
+}
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test
new file mode 100644
index 0000000..f6b4558
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/mlsclientauth.test
@@ -0,0 +1,5 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: MLS_CLIENT_AUTH
+expected_errors:
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test
new file mode 100644
index 0000000..6830ba0
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/intermediate-eku-mlsclientauth/serverauth.test
@@ -0,0 +1,17 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: SERVER_AUTH
+expected_errors:
+----- Certificate i=0 (CN=MLS Cert Leaf) -----
+ERROR: The extended key usage does not include server auth
+ERROR: Unconsumed critical extension
+  oid: 678112020104
+  value: 30080606678112020104
+ERROR: Unconsumed critical extension
+  oid: 678112020105
+  value: 30080606678112020105
+
+----- Certificate i=1 (CN=MLS Cert Intermediate) -----
+ERROR: The extended key usage does not include server auth
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
new file mode 100644
index 0000000..8ce80de
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-any/mlsclientauth.test
@@ -0,0 +1,12 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: MLS_CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
+ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
+
+----- Certificate i=1 (CN=Intermediate) -----
+ERROR: Certificate does not have extended key usage
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
new file mode 100644
index 0000000..8ce80de
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-many/mlsclientauth.test
@@ -0,0 +1,12 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: MLS_CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
+ERROR: The extended key usage does not contain only the rcsMlsClient key purpose.
+
+----- Certificate i=1 (CN=Intermediate) -----
+ERROR: Certificate does not have extended key usage
+
diff --git a/src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
new file mode 100644
index 0000000..c34bd13
--- /dev/null
+++ b/src/pki/testdata/verify_certificate_chain_unittest/target-eku-none/mlsclientauth.test
@@ -0,0 +1,12 @@
+chain: chain.pem
+last_cert_trust: TRUSTED_ANCHOR
+utc_time: DEFAULT
+key_purpose: MLS_CLIENT_AUTH
+expected_errors:
+----- Certificate i=0 (CN=Target) -----
+ERROR: KeyUsage must have only the digitalSignature bit set for rcsMlsClient auth
+ERROR: Certificate does not have extended key usage
+
+----- Certificate i=1 (CN=Intermediate) -----
+ERROR: Certificate does not have extended key usage
+
diff --git a/src/pki/verify.cc b/src/pki/verify.cc
index 09373c0..c0ed8ad 100644
--- a/src/pki/verify.cc
+++ b/src/pki/verify.cc
@@ -261,6 +261,15 @@
     case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH_STRICT_LEAF:
       key_purpose = KeyPurpose::CLIENT_AUTH_STRICT_LEAF;
       break;
+    case CertificateVerifyOptions::KeyPurpose::RCS_MLS_CLIENT_AUTH:
+      key_purpose = KeyPurpose::RCS_MLS_CLIENT_AUTH;
+      break;
+    case CertificateVerifyOptions::KeyPurpose::C2PA_TIMESTAMPING:
+      key_purpose = KeyPurpose::C2PA_TIMESTAMPING;
+      break;
+    case CertificateVerifyOptions::KeyPurpose::C2PA_MANIFEST:
+      key_purpose = KeyPurpose::C2PA_MANIFEST;
+      break;
   }
   CertPathBuilder path_builder(leaf_cert, trust_store, &path_builder_delegate,
                                verification_time, key_purpose,
diff --git a/src/pki/verify_certificate_chain.cc b/src/pki/verify_certificate_chain.cc
index d7c5f29..9bbad95 100644
--- a/src/pki/verify_certificate_chain.cc
+++ b/src/pki/verify_certificate_chain.cc
@@ -33,8 +33,7 @@
 
 namespace {
 
-bool IsHandledCriticalExtension(const ParsedExtension &extension,
-                                const ParsedCertificate &cert) {
+bool IsHandledCriticalExtension(const ParsedExtension &extension) {
   if (extension.oid == der::Input(kBasicConstraintsOid)) {
     return true;
   }
@@ -80,13 +79,6 @@
   if (extension.oid == der::Input(kInhibitAnyPolicyOid)) {
     return true;
   }
-  if (extension.oid == der::Input(kMSApplicationPoliciesOid)) {
-    // Per https://crbug.com/1439638 and
-    // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions#msapplicationpolicies
-    // The MSApplicationPolicies extension may be ignored if the
-    // extendedKeyUsage extension is also present.
-    return cert.has_extended_key_usage();
-  }
 
   return false;
 }
@@ -95,16 +87,33 @@
 // extensions.
 void VerifyNoUnconsumedCriticalExtensions(const ParsedCertificate &cert,
                                           CertErrors *errors,
-                                          bool allow_precertificate) {
+                                          bool allow_precertificate,
+                                          KeyPurpose key_purpose) {
   for (const auto &it : cert.extensions()) {
     const ParsedExtension &extension = it.second;
-    if (allow_precertificate && extension.oid == der::Input(kCtPoisonOid)) {
-      continue;
-    }
-    if (extension.critical && !IsHandledCriticalExtension(extension, cert)) {
-      errors->AddError(cert_errors::kUnconsumedCriticalExtension,
-                       CreateCertErrorParams2Der("oid", extension.oid, "value",
-                                                 extension.value));
+    if (extension.critical) {
+      if (key_purpose == KeyPurpose::RCS_MLS_CLIENT_AUTH) {
+        if (extension.oid == der::Input(kRcsMlsParticipantInformation) ||
+            extension.oid == der::Input(kRcsMlsAcsParticipantInformation)) {
+          continue;
+        }
+      }
+      if (allow_precertificate && extension.oid == der::Input(kCtPoisonOid)) {
+        continue;
+      }
+      if (extension.oid == der::Input(kMSApplicationPoliciesOid) &&
+          cert.has_extended_key_usage()) {
+        // Per https://crbug.com/1439638 and
+        // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions#msapplicationpolicies
+        // The MSApplicationPolicies extension may be ignored if the
+        // extendedKeyUsage extension is also present.
+        continue;
+      }
+      if (!IsHandledCriticalExtension(extension)) {
+        errors->AddError(cert_errors::kUnconsumedCriticalExtension,
+                         CreateCertErrorParams2Der("oid", extension.oid,
+                                                   "value", extension.value));
+      }
     }
   }
 }
@@ -216,8 +225,13 @@
   bool has_code_signing_eku = false;
   bool has_time_stamping_eku = false;
   bool has_ocsp_signing_eku = false;
+  bool has_rcs_mls_client_eku = false;
+  bool has_document_signing_eku = false;
+  bool has_email_protection_eku = false;
+  size_t eku_oid_count = 0;
   if (cert.has_extended_key_usage()) {
     for (const auto &key_purpose_oid : cert.extended_key_usage()) {
+      eku_oid_count++;
       if (key_purpose_oid == der::Input(kAnyEKU)) {
         has_any_eku = true;
       }
@@ -236,9 +250,82 @@
       if (key_purpose_oid == der::Input(kOCSPSigning)) {
         has_ocsp_signing_eku = true;
       }
+      if (key_purpose_oid == der::Input(kRcsMlsClient)) {
+        has_rcs_mls_client_eku = true;
+      }
+      if (key_purpose_oid == der::Input(kEmailProtection)) {
+        has_email_protection_eku = true;
+      }
+      if (key_purpose_oid == der::Input(kDocumentSigning)) {
+        has_document_signing_eku = true;
+      }
     }
   }
 
+  if (required_key_purpose == KeyPurpose::RCS_MLS_CLIENT_AUTH) {
+    // Enforce the key usage restriction for a leaf from section A.3.8.3 here
+    // as well.
+    if (is_target_cert &&
+        (!cert.has_key_usage() ||
+         // This works to enforce that digital signature is the only bit because
+         // digital signature is bit 0.
+         !cert.key_usage().AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE) ||
+         cert.key_usage().bytes().size() != 1 ||
+         cert.key_usage().unused_bits() != 7)) {
+      errors->AddError(cert_errors::kKeyUsageIncorrectForRcsMlsClient);
+    }
+    // Rules for MLS client auth. For the leaf and all intermediates, EKU must
+    // be present and have exactly one EKU which is rcsMlsClient.
+    if (!cert.has_extended_key_usage()) {
+      errors->AddError(cert_errors::kEkuNotPresent);
+    } else if (eku_oid_count != 1 || !has_rcs_mls_client_eku) {
+      errors->AddError(cert_errors::kEkuIncorrectForRcsMlsClient);
+    }
+    return;
+  }
+
+  if (required_key_purpose == KeyPurpose::C2PA_TIMESTAMPING) {
+    // https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_certificate_profiles
+    // For time stamp signing, C2PA requires that the leaf:
+    // 1) must have EKU
+    // 2) must not have EKU ANY, OCSP signing, document signing, or email protection
+    // 3) must have time stamping
+    // 4) should tolerate other EKU's being present.
+    if (is_target_cert) {
+      if (!cert.has_extended_key_usage()) {
+        errors->AddError(cert_errors::kEkuNotPresent);
+      }
+      if (has_any_eku || has_ocsp_signing_eku || has_document_signing_eku ||
+          has_email_protection_eku || !has_time_stamping_eku) {
+        errors->AddError(cert_errors::kEkuIncorrectForC2PATimeStamping);
+      }
+    }
+    return;
+  }
+
+  if (required_key_purpose == KeyPurpose::C2PA_MANIFEST) {
+    // https://c2pa.org/specifications/specifications/2.1/specs/C2PA_Specification.html#_certificate_profiles
+    // For manifest signing, C2PA requires that the leaf:
+    // 1) must have EKU
+    // 2) must not have EKU ANY, time stamping, or OCSP signing
+    // 3) should have document signing and/or email protection
+    // 4) should tolerate other EKU's being present.
+    if (is_target_cert) {
+      if (!cert.has_extended_key_usage()) {
+        errors->AddError(cert_errors::kEkuNotPresent);
+      }
+      if (!cert.has_key_usage() ||
+          !cert.key_usage().AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE) ||
+          has_any_eku || has_ocsp_signing_eku || has_time_stamping_eku ||
+          (!has_email_protection_eku && !has_document_signing_eku)) {
+        errors->AddError(cert_errors::kEkuIncorrectForC2PAManifest);
+      }
+    }
+    return;
+  }
+
+  // Rules TLS client and server authentication variants.
+
   // Apply strict only to leaf certificates in these cases.
   if (required_key_purpose == KeyPurpose::CLIENT_AUTH_STRICT_LEAF) {
     if (!is_target_cert) {
@@ -329,6 +416,9 @@
     case KeyPurpose::ANY_EKU:
     case KeyPurpose::CLIENT_AUTH_STRICT_LEAF:
     case KeyPurpose::SERVER_AUTH_STRICT_LEAF:
+    case KeyPurpose::RCS_MLS_CLIENT_AUTH:
+    case KeyPurpose::C2PA_TIMESTAMPING:
+    case KeyPurpose::C2PA_MANIFEST:
       assert(0);  // NOTREACHED
       return;
     case KeyPurpose::SERVER_AUTH:
@@ -686,7 +776,7 @@
   // This function corresponds to RFC 5280 section 6.1.4's "Preparation for
   // Certificate i+1" procedure. |cert| is expected to be an intermediate.
   void PrepareForNextCertificate(const ParsedCertificate &cert,
-                                 CertErrors *errors);
+                                 KeyPurpose key_purpose, CertErrors *errors);
 
   // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up
   // Procedure". It does processing for the final certificate (the target cert).
@@ -1104,6 +1194,7 @@
 }
 
 void PathVerifier::PrepareForNextCertificate(const ParsedCertificate &cert,
+                                             KeyPurpose key_purpose,
                                              CertErrors *errors) {
   // RFC 5280 section 6.1.4 step a-b
   VerifyPolicyMappings(cert, errors);
@@ -1207,8 +1298,8 @@
   //    the certificate.  Process any other recognized non-critical
   //    extension present in the certificate that is relevant to path
   //    processing.
-  VerifyNoUnconsumedCriticalExtensions(cert, errors,
-                                       delegate_->AcceptPreCertificates());
+  VerifyNoUnconsumedCriticalExtensions(
+      cert, errors, delegate_->AcceptPreCertificates(), key_purpose);
 }
 
 // Checks if the target certificate has the CA bit set. If it does, add
@@ -1232,6 +1323,9 @@
       case KeyPurpose::CLIENT_AUTH_STRICT:
       case KeyPurpose::CLIENT_AUTH_STRICT_LEAF:
       case KeyPurpose::SERVER_AUTH_STRICT_LEAF:
+      case KeyPurpose::RCS_MLS_CLIENT_AUTH:
+      case KeyPurpose::C2PA_TIMESTAMPING:
+      case KeyPurpose::C2PA_MANIFEST:
         errors->AddError(cert_errors::kTargetCertShouldNotBeCa);
         break;
     }
@@ -1270,7 +1364,8 @@
   //
   // Note that this is duplicated by PrepareForNextCertificate() so as to
   // directly match the procedures in RFC 5280's section 6.1.
-  VerifyNoUnconsumedCriticalExtensions(cert, errors, allow_precertificate);
+  VerifyNoUnconsumedCriticalExtensions(cert, errors, allow_precertificate,
+                                       required_key_purpose);
 
   // This calculates the intersection from RFC 5280 section 6.1.5 step g, as
   // well as applying the deferred recursive node that were skipped earlier in
@@ -1372,7 +1467,8 @@
   //    constraints are enforced, clients MUST reject certification paths
   //    containing a trust anchor with unrecognized critical extensions.
   VerifyNoUnconsumedCriticalExtensions(cert, errors,
-                                       /*allow_precertificate=*/false);
+                                       /*allow_precertificate=*/false,
+                                       required_key_purpose);
 }
 
 void PathVerifier::ProcessRootCertificate(const ParsedCertificate &cert,
@@ -1475,7 +1571,8 @@
   // Checking for unknown critical extensions matches Windows, but is stricter
   // than the Mac verifier.
   VerifyNoUnconsumedCriticalExtensions(cert, errors,
-                                       /*allow_precertificate=*/false);
+                                       /*allow_precertificate=*/false,
+                                       required_key_purpose);
 }
 
 bssl::UniquePtr<EVP_PKEY> PathVerifier::ParseAndCheckPublicKey(
@@ -1618,7 +1715,7 @@
       return;
     }
     if (!is_target_cert) {
-      PrepareForNextCertificate(cert, cert_errors);
+      PrepareForNextCertificate(cert, required_key_purpose, cert_errors);
     } else {
       WrapUp(cert, required_key_purpose, user_initial_policy_set,
              delegate->AcceptPreCertificates(), cert_errors);
diff --git a/src/pki/verify_certificate_chain.h b/src/pki/verify_certificate_chain.h
index f2cf603..16b2aba 100644
--- a/src/pki/verify_certificate_chain.h
+++ b/src/pki/verify_certificate_chain.h
@@ -40,10 +40,13 @@
   CLIENT_AUTH,
   SERVER_AUTH_STRICT,  // Skip ANY_EKU when checking, require EKU present in
                        // certificate.
-  SERVER_AUTH_STRICT_LEAF, // Same as above, but only for leaf cert.
+  SERVER_AUTH_STRICT_LEAF,  // Same as above, but only for leaf cert.
   CLIENT_AUTH_STRICT,  // Skip ANY_EKU when checking, require EKU present in
                        // certificate.
-  CLIENT_AUTH_STRICT_LEAF, // Same as above, but only for leaf ce
+  CLIENT_AUTH_STRICT_LEAF,  // Same as above, but only for leaf cert.
+  RCS_MLS_CLIENT_AUTH,      // Client auth for RCS-MLS.
+  C2PA_TIMESTAMPING,    // Leaf can sign timestamps for C2PA.
+  C2PA_MANIFEST,        // Leaf can sign manifests for C2PA.
 };
 
 enum class InitialExplicitPolicy {
diff --git a/src/pki/verify_certificate_chain_typed_unittest.h b/src/pki/verify_certificate_chain_typed_unittest.h
index c7f9f11..aaf96e6 100644
--- a/src/pki/verify_certificate_chain_typed_unittest.h
+++ b/src/pki/verify_certificate_chain_typed_unittest.h
@@ -184,6 +184,24 @@
   this->RunTest("intermediate-eku-clientauth/serverauth-strict-leaf.test");
   this->RunTest("intermediate-eku-clientauth/clientauth-strict.test");
   this->RunTest("intermediate-eku-clientauth/clientauth-strict-leaf.test");
+  this->RunTest("intermediate-eku-mlsclientauth/any.test");
+  this->RunTest("intermediate-eku-mlsclientauth/serverauth.test");
+  this->RunTest("intermediate-eku-mlsclientauth/clientauth.test");
+  this->RunTest("intermediate-eku-mlsclientauth/mlsclientauth.test");
+  this->RunTest("intermediate-eku-mlsclientauth-extra/any.test");
+  this->RunTest("intermediate-eku-mlsclientauth-extra/mlsclientauth.test");
+  this->RunTest("intermediate-eku-mlsclientauth-extra/any.test");
+  this->RunTest("intermediate-eku-mlsclientauth-extra/mlsclientauth.test");
+  this->RunTest("intermediate-eku-c2patimestamping/any.test");
+  this->RunTest("intermediate-eku-c2patimestamping/serverauth.test");
+  this->RunTest("intermediate-eku-c2patimestamping/clientauth.test");
+  this->RunTest("intermediate-eku-c2patimestamping/c2patimestamp.test");
+  this->RunTest("intermediate-eku-c2patimestamping/c2pamanifest.test");
+  this->RunTest("intermediate-eku-c2pamanifest/any.test");
+  this->RunTest("intermediate-eku-c2pamanifest/serverauth.test");
+  this->RunTest("intermediate-eku-c2pamanifest/clientauth.test");
+  this->RunTest("intermediate-eku-c2pamanifest/c2patimestamp.test");
+  this->RunTest("intermediate-eku-c2pamanifest/c2pamanifest.test");
   this->RunTest("intermediate-eku-any-and-clientauth/any.test");
   this->RunTest("intermediate-eku-any-and-clientauth/serverauth.test");
   this->RunTest("intermediate-eku-any-and-clientauth/serverauth-strict.test");
@@ -203,6 +221,7 @@
   this->RunTest("target-eku-any/serverauth-strict.test");
   this->RunTest("target-eku-any/clientauth-strict.test");
   this->RunTest("target-eku-any/clientauth-strict-leaf.test");
+  this->RunTest("target-eku-any/mlsclientauth.test");
   this->RunTest("target-eku-many/any.test");
   this->RunTest("target-eku-many/serverauth.test");
   this->RunTest("target-eku-many/clientauth.test");
@@ -210,12 +229,14 @@
   this->RunTest("target-eku-many/serverauth-strict-leaf.test");
   this->RunTest("target-eku-many/clientauth-strict.test");
   this->RunTest("target-eku-many/clientauth-strict-leaf.test");
+  this->RunTest("target-eku-many/mlsclientauth.test");
   this->RunTest("target-eku-none/any.test");
   this->RunTest("target-eku-none/serverauth.test");
   this->RunTest("target-eku-none/clientauth.test");
   this->RunTest("target-eku-none/serverauth-strict.test");
   this->RunTest("target-eku-none/clientauth-strict.test");
   this->RunTest("target-eku-none/clientauth-strict-leaf.test");
+  this->RunTest("target-eku-none/mlsclientauth.test");
   this->RunTest("root-eku-clientauth/serverauth.test");
   this->RunTest("root-eku-clientauth/serverauth-strict.test");
   this->RunTest("root-eku-clientauth/serverauth-ta-with-constraints.test");
diff --git a/src/pki/verify_name_match_unittest.cc b/src/pki/verify_name_match_unittest.cc
index f4506d3..b461154 100644
--- a/src/pki/verify_name_match_unittest.cc
+++ b/src/pki/verify_name_match_unittest.cc
@@ -15,6 +15,9 @@
 #include "verify_name_match.h"
 
 #include <gtest/gtest.h>
+
+#include <openssl/span.h>
+
 #include "string_util.h"
 #include "test_helpers.h"
 
@@ -508,7 +511,8 @@
   CertErrors errors;
   EXPECT_TRUE(NormalizeName(SequenceValueFromString(empty),
                             &normalized_empty_der, &errors));
-  EXPECT_EQ(SequenceValueFromString(empty), der::Input(normalized_empty_der));
+  EXPECT_EQ(SequenceValueFromString(empty),
+            der::Input(StringAsBytes(normalized_empty_der)));
 
   // An empty name is not equal to non-empty name.
   std::string non_empty;
@@ -595,11 +599,11 @@
   ASSERT_TRUE(NormalizeName(SequenceValueFromString(raw_der), &normalized_der,
                             &errors));
   EXPECT_EQ(SequenceValueFromString(expected_normalized_der),
-            der::Input(normalized_der));
+            der::Input(StringAsBytes(normalized_der)));
   // Re-normalizing an already normalized Name should not change it.
   std::string renormalized_der;
   ASSERT_TRUE(
-      NormalizeName(der::Input(normalized_der), &renormalized_der, &errors));
+      NormalizeName(StringAsBytes(normalized_der), &renormalized_der, &errors));
   EXPECT_EQ(normalized_der, renormalized_der);
 }
 
@@ -612,7 +616,8 @@
   CertErrors errors;
   ASSERT_TRUE(NormalizeName(SequenceValueFromString(raw_der), &normalized_der,
                             &errors));
-  EXPECT_EQ(SequenceValueFromString(raw_der), der::Input(normalized_der));
+  EXPECT_EQ(SequenceValueFromString(raw_der),
+            der::Input(StringAsBytes(normalized_der)));
 }
 
 BSSL_NAMESPACE_END
diff --git a/src/pki/verify_signed_data_unittest.cc b/src/pki/verify_signed_data_unittest.cc
index 294c28e..dea22bb 100644
--- a/src/pki/verify_signed_data_unittest.cc
+++ b/src/pki/verify_signed_data_unittest.cc
@@ -15,10 +15,13 @@
 #include "verify_signed_data.h"
 
 #include <memory>
+#include <optional>
 #include <set>
 
 #include <gtest/gtest.h>
-#include <optional>
+
+#include <openssl/span.h>
+
 #include "cert_errors.h"
 #include "input.h"
 #include "mock_signature_verify_cache.h"
@@ -64,10 +67,10 @@
   ASSERT_TRUE(ReadTestDataFromPemFile(path, mappings));
 
   std::optional<SignatureAlgorithm> signature_algorithm =
-      ParseSignatureAlgorithm(der::Input(algorithm));
+      ParseSignatureAlgorithm(StringAsBytes(algorithm));
   ASSERT_TRUE(signature_algorithm);
 
-  der::Parser signature_value_parser((der::Input(signature_value)));
+  der::Parser signature_value_parser(StringAsBytes(signature_value));
   std::optional<der::BitString> signature_value_bit_string =
       signature_value_parser.ReadBitString();
   ASSERT_TRUE(signature_value_bit_string.has_value())
@@ -75,9 +78,9 @@
 
   bool expected_result_bool = expected_result == SUCCESS;
 
-  bool result = VerifySignedData(*signature_algorithm, der::Input(signed_data),
-                                 signature_value_bit_string.value(),
-                                 der::Input(public_key), cache);
+  bool result = VerifySignedData(
+      *signature_algorithm, StringAsBytes(signed_data),
+      signature_value_bit_string.value(), StringAsBytes(public_key), cache);
 
   EXPECT_EQ(expected_result_bool, result);
 }
diff --git a/src/rust/bssl-crypto/src/ed25519.rs b/src/rust/bssl-crypto/src/ed25519.rs
index 6644aa2..73c90fb 100644
--- a/src/rust/bssl-crypto/src/ed25519.rs
+++ b/src/rust/bssl-crypto/src/ed25519.rs
@@ -34,7 +34,10 @@
 //! assert!(public_key.verify(signed_message, &sig).is_ok());
 //! ```
 
-use crate::{FfiMutSlice, FfiSlice, InvalidSignatureError};
+use crate::{
+    cbb_to_buffer, parse_with_cbs, scoped, with_output_array, Buffer, FfiMutSlice, FfiSlice,
+    InvalidSignatureError,
+};
 
 /// The length in bytes of an Ed25519 public key.
 pub const PUBLIC_KEY_LEN: usize = bssl_sys::ED25519_PUBLIC_KEY_LEN as usize;
@@ -149,6 +152,66 @@
         &self.0
     }
 
+    /// Parse a public key in SubjectPublicKeyInfo format.
+    pub fn from_der_subject_public_key_info(spki: &[u8]) -> Option<Self> {
+        let mut pkey = scoped::EvpPkey::from_ptr(parse_with_cbs(
+            spki,
+            // Safety: `pkey` is a non-null result from `EVP_parse_public_key` here.
+            |pkey| unsafe { bssl_sys::EVP_PKEY_free(pkey) },
+            // Safety: cbs is valid per `parse_with_cbs`.
+            |cbs| unsafe { bssl_sys::EVP_parse_public_key(cbs) },
+        )?);
+
+        let mut out_len = 0;
+        // When the out buffer is null, `out_len` is set to the size of the raw public key.
+        // Safety: the arguments are valid.
+        let result = unsafe {
+            bssl_sys::EVP_PKEY_get_raw_public_key(
+                pkey.as_ffi_ptr(),
+                core::ptr::null_mut(),
+                &mut out_len,
+            )
+        };
+        if result != 1 {
+            return None;
+        }
+        if out_len != PUBLIC_KEY_LEN {
+            return None;
+        }
+
+        // When the out buffer is not null, the raw public key is written into it.
+        // Safety: the arguments are valid.
+        let raw_pkey: [u8; PUBLIC_KEY_LEN] = unsafe {
+            with_output_array(|out, _| {
+                assert_eq!(
+                    1,
+                    bssl_sys::EVP_PKEY_get_raw_public_key(pkey.as_ffi_ptr(), out, &mut out_len)
+                );
+            })
+        };
+        Some(PublicKey(raw_pkey))
+    }
+
+    /// Serialize this key in SubjectPublicKeyInfo format.
+    pub fn to_der_subject_public_key_info(&self) -> Buffer {
+        // Safety: this only copies from the `self.0` buffer.
+        let mut pkey = scoped::EvpPkey::from_ptr(unsafe {
+            bssl_sys::EVP_PKEY_new_raw_public_key(
+                bssl_sys::EVP_PKEY_ED25519,
+                /*unused=*/ core::ptr::null_mut(),
+                self.0.as_ffi_ptr(),
+                PUBLIC_KEY_LEN,
+            )
+        });
+        assert!(!pkey.as_ffi_ptr().is_null());
+
+        cbb_to_buffer(PUBLIC_KEY_LEN + 32, |cbb| unsafe {
+            // The arguments are valid so this will only fail if out of memory,
+            // which this crate doesn't handle.
+            assert_eq!(1, bssl_sys::EVP_marshal_public_key(cbb, pkey.as_ffi_ptr()));
+        })
+    }
+
     /// Verifies that `signature` is a valid signature, by this key, of `msg`.
     pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), InvalidSignatureError> {
         let ret = unsafe {
@@ -183,6 +246,29 @@
     }
 
     #[test]
+    fn der_subject_public_key_info() {
+        let priv_key = PrivateKey::generate();
+        let msg = [0u8; 0];
+        let sig = priv_key.sign(&msg);
+
+        let pub_key = priv_key.to_public();
+        assert!(pub_key.verify(&msg, &sig).is_ok());
+
+        let pub_key_der = pub_key.to_der_subject_public_key_info();
+        let pub_key_from_der =
+            PublicKey::from_der_subject_public_key_info(pub_key_der.as_ref()).unwrap();
+        assert_eq!(pub_key.as_bytes(), pub_key_from_der.as_bytes());
+        assert!(pub_key_from_der.verify(&msg, &sig).is_ok());
+
+        assert!(PublicKey::from_der_subject_public_key_info(
+            &pub_key_from_der.as_bytes()[0..PUBLIC_KEY_LEN / 2]
+        )
+        .is_none());
+
+        assert!(PublicKey::from_der_subject_public_key_info(b"").is_none());
+    }
+
+    #[test]
     fn empty_msg() {
         // Test Case 1 from RFC test vectors: https://www.rfc-editor.org/rfc/rfc8032#section-7.1
         let pk = test_helpers::decode_hex(
diff --git a/src/rust/bssl-crypto/src/hkdf.rs b/src/rust/bssl-crypto/src/hkdf.rs
index 24343ae..968e644 100644
--- a/src/rust/bssl-crypto/src/hkdf.rs
+++ b/src/rust/bssl-crypto/src/hkdf.rs
@@ -184,9 +184,7 @@
     evp_md: *const bssl_sys::EVP_MD,
 }
 
-#[allow(clippy::let_unit_value,
-        clippy::unwrap_used,
-)]
+#[allow(clippy::let_unit_value, clippy::unwrap_used)]
 impl Prk {
     /// Creates a Prk from bytes.
     pub fn new<MD: digest::Algorithm>(prk_bytes: &[u8]) -> Option<Self> {
@@ -210,10 +208,11 @@
 
     /// Returns the bytes of the pseudorandom key.
     pub fn as_bytes(&self) -> &[u8] {
-        self.prk.get(..self.len)
-        // unwrap:`self.len` must be less than the length of `self.prk` thus
-        // this is always in bounds.
-        .unwrap()
+        self.prk
+            .get(..self.len)
+            // unwrap:`self.len` must be less than the length of `self.prk` thus
+            // this is always in bounds.
+            .unwrap()
     }
 
     /// Derive key material for the given info parameter. Attempting
diff --git a/src/rust/bssl-crypto/src/hpke.rs b/src/rust/bssl-crypto/src/hpke.rs
index 2259140..82bb1c1 100644
--- a/src/rust/bssl-crypto/src/hpke.rs
+++ b/src/rust/bssl-crypto/src/hpke.rs
@@ -95,7 +95,6 @@
         }
     }
 
-
     fn from_rfc_id(n: u16) -> Option<Kem> {
         match n {
             n if n == Kem::P256HkdfSha256 as u16 => Some(Self::P256HkdfSha256),
@@ -115,44 +114,70 @@
         // handled by this crate.
         assert_eq!(ret, 1);
 
-        fn get_value_from_key(
-            key: &scoped::EvpHpkeKey,
-            accessor: unsafe extern "C" fn(
-                *const bssl_sys::EVP_HPKE_KEY,
-                // Output buffer.
-                *mut u8,
-                // Number of bytes written.
-                *mut usize,
-                // Maximum output size.
-                usize,
-            ) -> core::ffi::c_int,
-            max_len: usize,
-        ) -> Vec<u8> {
-            unsafe {
-                with_output_vec(max_len, |out| {
-                    let mut out_len = 0usize;
-                    let ret = accessor(key.as_ffi_ptr(), out, &mut out_len, max_len);
-                    // If `max_len` is correct then these functions never fail.
-                    assert_eq!(ret, 1);
-                    assert!(out_len <= max_len);
-                    // Safety: `out_len` bytes have been written, as required.
-                    out_len
-                })
-            }
-        }
-
-        let pub_key = get_value_from_key(
+        let pub_key = Self::get_value_from_key(
             &key,
             bssl_sys::EVP_HPKE_KEY_public_key,
             bssl_sys::EVP_HPKE_MAX_PUBLIC_KEY_LENGTH as usize,
         );
-        let priv_key = get_value_from_key(
+        let priv_key = Self::get_value_from_key(
             &key,
             bssl_sys::EVP_HPKE_KEY_private_key,
             bssl_sys::EVP_HPKE_MAX_PRIVATE_KEY_LENGTH as usize,
         );
         (pub_key, priv_key)
     }
+
+    /// Get a private key's corresponding public key, or `None` if the private
+    /// key is invalid.
+    pub fn public_from_private(&self, priv_key: &[u8]) -> Option<Vec<u8>> {
+        let mut key = scoped::EvpHpkeKey::new();
+        // Safety: `key`, `self`, and `priv_key` must be valid and this function
+        // doesn't take ownership of any of them.
+        let ret = unsafe {
+            bssl_sys::EVP_HPKE_KEY_init(
+                key.as_mut_ffi_ptr(),
+                self.as_ffi_ptr(),
+                priv_key.as_ptr(),
+                priv_key.len(),
+            )
+        };
+        if ret != 1 {
+            return None;
+        }
+
+        let pub_key = Self::get_value_from_key(
+            &key,
+            bssl_sys::EVP_HPKE_KEY_public_key,
+            bssl_sys::EVP_HPKE_MAX_PUBLIC_KEY_LENGTH as usize,
+        );
+        Some(pub_key)
+    }
+
+    fn get_value_from_key(
+        key: &scoped::EvpHpkeKey,
+        accessor: unsafe extern "C" fn(
+            *const bssl_sys::EVP_HPKE_KEY,
+            // Output buffer.
+            *mut u8,
+            // Number of bytes written.
+            *mut usize,
+            // Maximum output size.
+            usize,
+        ) -> core::ffi::c_int,
+        max_len: usize,
+    ) -> Vec<u8> {
+        unsafe {
+            with_output_vec(max_len, |out| {
+                let mut out_len = 0usize;
+                let ret = accessor(key.as_ffi_ptr(), out, &mut out_len, max_len);
+                // If `max_len` is correct then these functions never fail.
+                assert_eq!(ret, 1);
+                assert!(out_len <= max_len);
+                // Safety: `out_len` bytes have been written, as required.
+                out_len
+            })
+        }
+    }
 }
 
 /// Supported KDF algorithms with values detailed in RFC 9180.
@@ -518,10 +543,10 @@
             recipient_priv_key: decode_hex("f3ce7fdae57e1a310d87f1ebbde6f328be0a99cdbcadf4d6589cf29de4b8ffd2"),
             encapsulated_key: decode_hex_into_vec("04a92719c6195d5085104f469a8b9814d5838ff72b60501e2c4466e5e67b325ac98536d7b61a1af4b78e5b7f951c0900be863c403ce65c9bfcb9382657222d18c4"),
             plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"),
-            associated_data: decode_hex("436f756e742d30"), 
-            ciphertext: decode_hex("5ad590bb8baa577f8619db35a36311226a896e7342a6d836d8b7bcd2f20b6c7f9076ac232e3ab2523f39513434"), 
-            exporter_context: decode_hex("54657374436f6e74657874"), 
-            exported_value: decode_hex("d8f1ea7942adbba7412c6d431c62d01371ea476b823eb697e1f6e6cae1dab85a"), 
+            associated_data: decode_hex("436f756e742d30"),
+            ciphertext: decode_hex("5ad590bb8baa577f8619db35a36311226a896e7342a6d836d8b7bcd2f20b6c7f9076ac232e3ab2523f39513434"),
+            exporter_context: decode_hex("54657374436f6e74657874"),
+            exported_value: decode_hex("d8f1ea7942adbba7412c6d431c62d01371ea476b823eb697e1f6e6cae1dab85a"),
         }
     }
 
@@ -563,6 +588,17 @@
         }
     }
 
+    #[test]
+    fn kem_public_from_private() {
+        let kems = vec![Kem::X25519HkdfSha256, Kem::P256HkdfSha256];
+        for kem in &kems {
+            let (pub_key, priv_key) = kem.generate_keypair();
+            assert_eq!(kem.public_from_private(&priv_key), Some(pub_key));
+
+            assert_eq!(kem.public_from_private(b"invalid"), None);
+        }
+    }
+
     fn new_sender_context_for_testing(
         params: &Params,
         recipient_pub_key: &[u8],
diff --git a/src/rust/bssl-sys/CMakeLists.txt b/src/rust/bssl-sys/CMakeLists.txt
index 0ed1c95..a5ca2c3 100644
--- a/src/rust/bssl-sys/CMakeLists.txt
+++ b/src/rust/bssl-sys/CMakeLists.txt
@@ -50,6 +50,6 @@
   target_compile_options(rust_wrapper PRIVATE "-Wno-missing-prototypes")
 endif()
 target_include_directories(rust_wrapper PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(rust_wrapper crypto ssl)
+target_link_libraries(rust_wrapper ssl crypto)
 
 add_custom_target(bssl_sys ALL DEPENDS ${wrapper_rs} rust_wrapper)
diff --git a/src/rust/bssl-sys/README.md b/src/rust/bssl-sys/README.md
index 13b7290..c0fb610 100644
--- a/src/rust/bssl-sys/README.md
+++ b/src/rust/bssl-sys/README.md
@@ -7,8 +7,12 @@
 `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
-1. Build `boringssl` with `-DRUST_BINDINGS=<rust-triple>`, which should match the [Rust target triple](https://doc.rust-lang.org/nightly/rustc/platform-support.html) when building `bssl-sys`,
-2. install `bindgen`, and
-3. install [`cargo-deny`](https://github.com/EmbarkStudios/cargo-deny).
+1. Build `boringssl` with `-DRUST_BINDINGS=<rust-triple>`, which should match the [Rust target triple](https://doc.rust-lang.org/nightly/rustc/platform-support.html) when building `bssl-sys`. For example, to build on 64-bit Linux:
 
-After that, 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.
+       cmake -GNinja -B build -DRUST_BINDINGS=x86_64-unknown-linux-gnu
+       ninja -C build
+
+2. Install `bindgen`.
+3. Install [`cargo-deny`](https://github.com/EmbarkStudios/cargo-deny).
+
+After that, the `bssl-sys` crate can be built via `cargo`. 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 58027b5..aa211e8 100644
--- a/src/rust/bssl-sys/build.rs
+++ b/src/rust/bssl-sys/build.rs
@@ -114,14 +114,9 @@
     // Statically link libraries.
     println!(
         "cargo:rustc-link-search=native={}",
-        bssl_build_dir.join("crypto").display()
+        bssl_build_dir.display()
     );
     println!("cargo:rustc-link-lib=static=crypto");
-
-    println!(
-        "cargo:rustc-link-search=native={}",
-        bssl_build_dir.join("ssl").display()
-    );
     println!("cargo:rustc-link-lib=static=ssl");
 
     println!(
diff --git a/src/rust/bssl-sys/wrapper.h b/src/rust/bssl-sys/wrapper.h
index 8413a3e..6428234 100644
--- a/src/rust/bssl-sys/wrapper.h
+++ b/src/rust/bssl-sys/wrapper.h
@@ -1,6 +1,5 @@
 #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>
diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc
index 7be3159..3ed8a84 100644
--- a/src/ssl/dtls_method.cc
+++ b/src/ssl/dtls_method.cc
@@ -80,6 +80,7 @@
 
   DTLSReadEpoch new_epoch;
   new_epoch.aead = std::move(aead_ctx);
+  new_epoch.traffic_secret.CopyFrom(traffic_secret);
   if (!next_epoch(ssl, &new_epoch.epoch, level, ssl->d1->read_epoch.epoch)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
     return false;
@@ -118,6 +119,7 @@
   DTLSWriteEpoch new_epoch;
   new_epoch.aead = std::move(aead_ctx);
   new_epoch.next_record = DTLSRecordNumber(epoch, 0);
+  new_epoch.traffic_secret.CopyFrom(traffic_secret);
   if (ssl_protocol_version(ssl) > TLS1_2_VERSION) {
     new_epoch.rn_encrypter =
         RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret);
diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc
index 0077338..da5c318 100644
--- a/src/ssl/dtls_record.cc
+++ b/src/ssl/dtls_record.cc
@@ -119,6 +119,33 @@
   return seqnum;
 }
 
+DTLSReadEpoch *dtls_get_read_epoch(const SSL *ssl, uint16_t epoch) {
+  if (epoch == ssl->d1->read_epoch.epoch) {
+    return &ssl->d1->read_epoch;
+  }
+  if (ssl->d1->next_read_epoch != nullptr &&
+      epoch == ssl->d1->next_read_epoch->epoch) {
+    return ssl->d1->next_read_epoch.get();
+  }
+  if (ssl->d1->prev_read_epoch != nullptr &&
+      epoch == ssl->d1->prev_read_epoch->epoch.epoch) {
+    return &ssl->d1->prev_read_epoch->epoch;
+  }
+  return nullptr;
+}
+
+DTLSWriteEpoch *dtls_get_write_epoch(const SSL *ssl, uint16_t epoch) {
+  if (ssl->d1->write_epoch.epoch() == epoch) {
+    return &ssl->d1->write_epoch;
+  }
+  for (const auto &e : ssl->d1->extra_write_epochs) {
+    if (e->epoch() == epoch) {
+      return e.get();
+    }
+  }
+  return nullptr;
+}
+
 static Span<uint8_t> cbs_to_writable_bytes(CBS cbs) {
   return Span(const_cast<uint8_t *>(CBS_data(&cbs)), CBS_len(&cbs));
 }
@@ -177,16 +204,7 @@
 
   // Look up the corresponding epoch. This header form only matches encrypted
   // DTLS 1.3 epochs.
-  DTLSReadEpoch *read_epoch = nullptr;
-  if (epoch == ssl->d1->read_epoch.epoch) {
-    read_epoch = &ssl->d1->read_epoch;
-  } else if (ssl->d1->next_read_epoch != nullptr &&
-             epoch == ssl->d1->next_read_epoch->epoch) {
-    read_epoch = ssl->d1->next_read_epoch.get();
-  } else if (ssl->d1->prev_read_epoch != nullptr &&
-             epoch == ssl->d1->prev_read_epoch->epoch.epoch) {
-    read_epoch = &ssl->d1->prev_read_epoch->epoch;
-  }
+  DTLSReadEpoch *read_epoch = dtls_get_read_epoch(ssl, epoch);
   if (read_epoch != nullptr && use_dtls13_record_header(ssl, epoch)) {
     out->read_epoch = read_epoch;
 
@@ -406,18 +424,6 @@
   return ssl_open_record_success;
 }
 
-static DTLSWriteEpoch *get_write_epoch(const SSL *ssl, uint16_t epoch) {
-  if (ssl->d1->write_epoch.epoch() == epoch) {
-    return &ssl->d1->write_epoch;
-  }
-  for (const auto &e : ssl->d1->extra_write_epochs) {
-    if (e->epoch() == epoch) {
-      return e.get();
-    }
-  }
-  return nullptr;
-}
-
 size_t dtls_record_header_write_len(const SSL *ssl, uint16_t epoch) {
   if (!use_dtls13_record_header(ssl, epoch)) {
     return DTLS_PLAINTEXT_RECORD_HEADER_LENGTH;
@@ -431,7 +437,7 @@
 }
 
 size_t dtls_max_seal_overhead(const SSL *ssl, uint16_t epoch) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -445,7 +451,7 @@
 }
 
 size_t dtls_seal_prefix_len(const SSL *ssl, uint16_t epoch) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -454,7 +460,7 @@
 }
 
 size_t dtls_seal_max_input_len(const SSL *ssl, uint16_t epoch, size_t max_out) {
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     return 0;
   }
@@ -482,7 +488,7 @@
   }
 
   // Determine the parameters for the current epoch.
-  DTLSWriteEpoch *write_epoch = get_write_epoch(ssl, epoch);
+  DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
   if (write_epoch == nullptr) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return false;
diff --git a/src/ssl/encrypted_client_hello.cc b/src/ssl/encrypted_client_hello.cc
index 34f954f..5110508 100644
--- a/src/ssl/encrypted_client_hello.cc
+++ b/src/ssl/encrypted_client_hello.cc
@@ -28,6 +28,7 @@
 #include <openssl/hpke.h>
 #include <openssl/rand.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -295,37 +296,37 @@
 
   // Decrypt the EncodedClientHelloInner.
   Array<uint8_t> encoded;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  // In fuzzer mode, disable encryption to improve coverage. We reserve a short
-  // input to signal decryption failure, so the fuzzer can explore fallback to
-  // ClientHelloOuter.
-  const uint8_t kBadPayload[] = {0xff};
-  if (payload == kBadPayload) {
-    *out_alert = SSL_AD_DECRYPT_ERROR;
-    *out_is_decrypt_error = true;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
-    return false;
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    // In fuzzer mode, disable encryption to improve coverage. We reserve a
+    // short input to signal decryption failure, so the fuzzer can explore
+    // fallback to ClientHelloOuter.
+    const uint8_t kBadPayload[] = {0xff};
+    if (payload == kBadPayload) {
+      *out_alert = SSL_AD_DECRYPT_ERROR;
+      *out_is_decrypt_error = true;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+      return false;
+    }
+    if (!encoded.CopyFrom(payload)) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return false;
+    }
+  } else {
+    if (!encoded.InitForOverwrite(payload.size())) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return false;
+    }
+    size_t len;
+    if (!EVP_HPKE_CTX_open(hs->ech_hpke_ctx.get(), encoded.data(), &len,
+                           encoded.size(), payload.data(), payload.size(),
+                           aad.data(), aad.size())) {
+      *out_alert = SSL_AD_DECRYPT_ERROR;
+      *out_is_decrypt_error = true;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+      return false;
+    }
+    encoded.Shrink(len);
   }
-  if (!encoded.CopyFrom(payload)) {
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return false;
-  }
-#else
-  if (!encoded.InitForOverwrite(payload.size())) {
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return false;
-  }
-  size_t len;
-  if (!EVP_HPKE_CTX_open(hs->ech_hpke_ctx.get(), encoded.data(), &len,
-                         encoded.size(), payload.data(), payload.size(),
-                         aad.data(), aad.size())) {
-    *out_alert = SSL_AD_DECRYPT_ERROR;
-    *out_is_decrypt_error = true;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
-    return false;
-  }
-  encoded.Shrink(len);
-#endif
 
   if (!ssl_decode_client_hello_inner(hs->ssl, out_alert, out, encoded,
                                      client_hello_outer)) {
@@ -701,14 +702,13 @@
 }
 
 static size_t aead_overhead(const EVP_HPKE_AEAD *aead) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  // TODO(https://crbug.com/boringssl/275): Having to adjust the overhead
-  // everywhere is tedious. Change fuzzer mode to append a fake tag but still
-  // otherwise be cleartext, refresh corpora, and then inline this function.
-  return 0;
-#else
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    // TODO(https://crbug.com/boringssl/275): Having to adjust the overhead
+    // everywhere is tedious. Change fuzzer mode to append a fake tag but still
+    // otherwise be cleartext, refresh corpora, and then inline this function.
+    return 0;
+  }
   return EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(aead));
-#endif
 }
 
 // random_size returns a random value between |min| and |max|, inclusive.
@@ -885,19 +885,19 @@
 
   // Replace the payload in |hs->ech_client_outer| with the encrypted value.
   auto payload_span = Span(hs->ech_client_outer).last(payload_len);
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  // In fuzzer mode, the server expects a cleartext payload.
-  assert(payload_span.size() == encoded.size());
-  OPENSSL_memcpy(payload_span.data(), encoded.data(), encoded.size());
-#else
-  if (!EVP_HPKE_CTX_seal(hs->ech_hpke_ctx.get(), payload_span.data(),
-                         &payload_len, payload_span.size(), encoded.data(),
-                         encoded.size(), CBB_data(aad.get()),
-                         CBB_len(aad.get())) ||
-      payload_len != payload_span.size()) {
-    return false;
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    // In fuzzer mode, the server expects a cleartext payload.
+    assert(payload_span.size() == encoded.size());
+    OPENSSL_memcpy(payload_span.data(), encoded.data(), encoded.size());
+  } else {
+    if (!EVP_HPKE_CTX_seal(hs->ech_hpke_ctx.get(), payload_span.data(),
+                           &payload_len, payload_span.size(), encoded.data(),
+                           encoded.size(), CBB_data(aad.get()),
+                           CBB_len(aad.get())) ||
+        payload_len != payload_span.size()) {
+      return false;
+    }
   }
-#endif  // BORINGSSL_UNSAFE_FUZZER_MODE
 
   return true;
 }
diff --git a/src/ssl/extensions.cc b/src/ssl/extensions.cc
index 4bd5c5d..38205c5 100644
--- a/src/ssl/extensions.cc
+++ b/src/ssl/extensions.cc
@@ -45,18 +45,6 @@
 static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
 static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs);
 
-static int compare_uint16_t(const void *p1, const void *p2) {
-  uint16_t u1 = *((const uint16_t *)p1);
-  uint16_t u2 = *((const uint16_t *)p2);
-  if (u1 < u2) {
-    return -1;
-  } else if (u1 > u2) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
 // Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
 // more than one extension of the same type in a ClientHello or ServerHello.
 // This function does an initial scan over the extensions block to filter those
@@ -100,8 +88,7 @@
   assert(CBS_len(&extensions) == 0);
 
   // Sort the extensions and make sure there are no duplicates.
-  qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
-        compare_uint16_t);
+  std::sort(extension_types.begin(), extension_types.end());
   for (size_t i = 1; i < num_extensions; i++) {
     if (extension_types[i - 1] == extension_types[i]) {
       return false;
@@ -159,7 +146,7 @@
       CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 ||
       !CBS_get_u8_length_prefixed(cbs, &compression_methods) ||
       CBS_len(&compression_methods) < 1) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
     return false;
   }
 
@@ -361,6 +348,96 @@
   return true;
 }
 
+// Flags.
+//
+// https://www.ietf.org/archive/id/draft-ietf-tls-tlsflags-14.html
+
+bool ssl_add_flags_extension(CBB *cbb, SSLFlags flags) {
+  if (flags == 0) {
+    return true;
+  }
+
+  CBB body, child;
+  if (!CBB_add_u16(cbb, TLSEXT_TYPE_tls_flags) ||
+      !CBB_add_u16_length_prefixed(cbb, &body) ||
+      !CBB_add_u8_length_prefixed(&body, &child)) {
+    return false;
+  }
+
+  while (flags != 0) {
+    if (!CBB_add_u8(&child, static_cast<uint8_t>(flags))) {
+      return false;
+    }
+    flags >>= 8;
+  }
+
+  return CBB_flush(cbb);
+}
+
+static bool ssl_parse_flags_extension(const CBS *cbs, SSLFlags *out,
+                                      uint8_t *out_alert, bool allow_unknown) {
+  CBS copy = *cbs, flags;
+  if (!CBS_get_u8_length_prefixed(&copy, &flags) ||  //
+      CBS_len(&copy) != 0 ||                         //
+      CBS_len(&flags) == 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return false;
+  }
+
+  // There may not be any trailing zeros.
+  if (CBS_data(&flags)[CBS_len(&flags) - 1] == 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return false;
+  }
+
+  // We can only represent flags that fit in SSLFlags, so any bits beyond that
+  // are necessarily unsolicited. Unsolicited flags are allowed in CH, CR, and
+  // NST, but forbidden in SH, EE, CT, and HRR. See Section 3 of
+  // draft-ietf-tls-tlsflags-14.
+  if (!allow_unknown && CBS_len(&flags) > sizeof(SSLFlags)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return false;
+  }
+
+  // We currently use the same in-memory and wire representation for flags.
+  uint8_t padded[sizeof(SSLFlags)] = {0};
+  OPENSSL_memcpy(padded, CBS_data(&flags),
+                 std::min(CBS_len(&flags), size_t{4}));
+  static_assert(sizeof(SSLFlags) == sizeof(uint32_t),
+                "We currently assume SSLFlags is 32-bit");
+  *out = CRYPTO_load_u32_le(padded);
+  return true;
+}
+
+bool ssl_parse_flags_extension_request(const CBS *cbs, SSLFlags *out,
+                                       uint8_t *out_alert) {
+  // In a request message, unsolicited flags are allowed and ignored.
+  return ssl_parse_flags_extension(cbs, out, out_alert,
+                                   /*allow_unknown=*/true);
+}
+
+bool ssl_parse_flags_extension_response(const CBS *cbs, SSLFlags *out,
+                                        uint8_t *out_alert,
+                                        SSLFlags allowed_flags) {
+  // In a response message, unsolicited flags are not allowed.
+  if (!ssl_parse_flags_extension(cbs, out, out_alert,
+                                 /*allow_unknown=*/false)) {
+    return false;
+  }
+
+  // Check for unsolicited flags that fit in |SSLFlags|.
+  if ((*out & allowed_flags) != *out) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return false;
+  }
+
+  return true;
+}
+
 // tls_extension represents a TLS extension that is handled internally.
 //
 // The parse callbacks receive a |CBS| that contains the contents of the
@@ -685,9 +762,9 @@
                     ssl->s3->previous_client_finished.size()) &&
       CBS_mem_equal(&server_verify, ssl->s3->previous_server_finished.data(),
                     ssl->s3->previous_server_finished.size());
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  ok = true;
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    ok = true;
+  }
   if (!ok) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
     *out_alert = SSL_AD_HANDSHAKE_FAILURE;
@@ -2510,12 +2587,14 @@
 static bool ext_certificate_authorities_add_clienthello(
     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
     ssl_client_hello_type_t type) {
+  // TODO(crbug.com/398275713): What should this send in ClientHelloOuter?
   if (ssl_has_CA_names(hs->config)) {
     CBB ca_contents;
-    if (!CBB_add_u16(out, TLSEXT_TYPE_certificate_authorities) ||  //
-        !CBB_add_u16_length_prefixed(out, &ca_contents) ||         //
-        !ssl_add_CA_names(hs, &ca_contents) ||                     //
-        !CBB_flush(out)) {
+    if (!CBB_add_u16(out_compressible,
+                     TLSEXT_TYPE_certificate_authorities) ||  //
+        !CBB_add_u16_length_prefixed(out_compressible, &ca_contents) ||    //
+        !ssl_add_CA_names(hs, &ca_contents) ||                //
+        !CBB_flush(out_compressible)) {
       return false;
     }
   }
@@ -2542,6 +2621,124 @@
 }
 
 
+// Trust Anchor Identifiers
+//
+// https://datatracker.ietf.org/doc/draft-ietf-tls-trust-anchor-ids/
+
+bool ssl_is_valid_trust_anchor_list(Span<const uint8_t> in) {
+  CBS ids = in;
+  while (CBS_len(&ids) > 0) {
+    CBS id;
+    if (!CBS_get_u8_length_prefixed(&ids, &id) ||  //
+        CBS_len(&id) == 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static bool ext_trust_anchors_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out,
+                                              CBB *out_compressible,
+                                              ssl_client_hello_type_t type) {
+  if (!hs->config->requested_trust_anchors.has_value()) {
+    return true;
+  }
+  // TODO(crbug.com/398275713): What should this send in ClientHelloOuter?
+  CBB contents, list;
+  if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_trust_anchors) ||  //
+      !CBB_add_u16_length_prefixed(out_compressible, &contents) ||  //
+      !CBB_add_u16_length_prefixed(&contents, &list) ||             //
+      !CBB_add_bytes(&list, hs->config->requested_trust_anchors->data(),
+                     hs->config->requested_trust_anchors->size()) ||
+      !CBB_flush(out_compressible)) {
+    return false;
+  }
+  return true;
+}
+
+static bool ext_trust_anchors_parse_clienthello(SSL_HANDSHAKE *hs,
+                                                uint8_t *out_alert,
+                                                CBS *contents) {
+  if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
+    return true;
+  }
+
+  CBS child;
+  if (!CBS_get_u16_length_prefixed(contents, &child) ||
+      !ssl_is_valid_trust_anchor_list(child)) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return false;
+  }
+
+  hs->peer_requested_trust_anchors.emplace();
+  if (!hs->peer_requested_trust_anchors->CopyFrom(child)) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    return false;
+  }
+  return true;
+}
+
+static bool ext_trust_anchors_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  const auto &creds = hs->config->cert->credentials;
+  if (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
+      // Check if any credentials have trust anchor IDs.
+      std::none_of(creds.begin(), creds.end(), [](const auto &cred) {
+        return !cred->trust_anchor_id.empty();
+      })) {
+    return true;
+  }
+  CBB contents, list;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_trust_anchors) ||  //
+      !CBB_add_u16_length_prefixed(out, &contents) ||  //
+      !CBB_add_u16_length_prefixed(&contents, &list)) {
+    return false;
+  }
+  for (const auto &cred : creds) {
+    if (!cred->trust_anchor_id.empty()) {
+      CBB child;
+      if (!CBB_add_u8_length_prefixed(&list, &child) ||  //
+          !CBB_add_bytes(&child, cred->trust_anchor_id.data(),
+                         cred->trust_anchor_id.size()) ||
+          !CBB_flush(&list)) {
+        return false;
+      }
+    }
+  }
+  return CBB_flush(out);
+}
+
+static bool ext_trust_anchors_parse_serverhello(SSL_HANDSHAKE *hs,
+                                                uint8_t *out_alert,
+                                                CBS *contents) {
+  if (contents == nullptr) {
+    return true;
+  }
+
+  if (ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+    return false;
+  }
+
+  CBS child;
+  if (!CBS_get_u16_length_prefixed(contents, &child) ||
+      // The list of available trust anchors may not be empty.
+      CBS_len(&child) == 0 ||  //
+      !ssl_is_valid_trust_anchor_list(child)) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return false;
+  }
+
+  if (!hs->peer_available_trust_anchors.CopyFrom(child)) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    return false;
+  }
+  return true;
+}
+
 // QUIC Transport Parameters
 
 static bool ext_quic_transport_params_add_clienthello_impl(
@@ -2847,8 +3044,7 @@
     }
   }
 
-  qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t),
-        compare_uint16_t);
+  std::sort(given_alg_ids.begin(), given_alg_ids.end());
   for (size_t i = 1; i < num_given_alg_ids; i++) {
     if (given_alg_ids[i - 1] == given_alg_ids[i]) {
       return false;
@@ -3490,6 +3686,13 @@
         ext_pake_parse_clienthello,
         dont_add_serverhello,
     },
+    {
+        TLSEXT_TYPE_trust_anchors,
+        ext_trust_anchors_add_clienthello,
+        ext_trust_anchors_parse_serverhello,
+        ext_trust_anchors_parse_clienthello,
+        ext_trust_anchors_add_serverhello,
+    },
 };
 
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
@@ -4059,9 +4262,9 @@
   HMAC_Final(hmac_ctx, mac, NULL);
   assert(mac_len == ticket_mac.size());
   bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  mac_ok = true;
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    mac_ok = true;
+  }
   if (!mac_ok) {
     return ssl_ticket_aead_ignore_ticket;
   }
@@ -4069,26 +4272,26 @@
   // Decrypt the session data.
   auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len);
   Array<uint8_t> plaintext;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  if (!plaintext.CopyFrom(ciphertext)) {
-    return ssl_ticket_aead_error;
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    if (!plaintext.CopyFrom(ciphertext)) {
+      return ssl_ticket_aead_error;
+    }
+  } else {
+    if (ciphertext.size() >= INT_MAX) {
+      return ssl_ticket_aead_ignore_ticket;
+    }
+    if (!plaintext.InitForOverwrite(ciphertext.size())) {
+      return ssl_ticket_aead_error;
+    }
+    int len1, len2;
+    if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1,
+                           ciphertext.data(), (int)ciphertext.size()) ||
+        !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
+      ERR_clear_error();
+      return ssl_ticket_aead_ignore_ticket;
+    }
+    plaintext.Shrink(static_cast<size_t>(len1) + len2);
   }
-#else
-  if (ciphertext.size() >= INT_MAX) {
-    return ssl_ticket_aead_ignore_ticket;
-  }
-  if (!plaintext.InitForOverwrite(ciphertext.size())) {
-    return ssl_ticket_aead_error;
-  }
-  int len1, len2;
-  if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(),
-                         (int)ciphertext.size()) ||
-      !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) {
-    ERR_clear_error();
-    return ssl_ticket_aead_ignore_ticket;
-  }
-  plaintext.Shrink(static_cast<size_t>(len1) + len2);
-#endif
 
   *out = std::move(plaintext);
   return ssl_ticket_aead_success;
@@ -4408,10 +4611,10 @@
   }
 
   bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get());
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  sig_ok = true;
-  ERR_clear_error();
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    sig_ok = true;
+    ERR_clear_error();
+  }
   if (!sig_ok) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index 4cee993..a24d741 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -910,9 +910,9 @@
   }
 
   if (!hints->server_random_tls13.empty()) {
-    if (!CBB_add_asn1(&seq, &child, kServerRandomTLS13Tag) ||
-        !CBB_add_bytes(&child, hints->server_random_tls13.data(),
-                       hints->server_random_tls13.size())) {
+    if (!CBB_add_asn1_element(&seq, kServerRandomTLS13Tag,
+                              hints->server_random_tls13.data(),
+                              hints->server_random_tls13.size())) {
       return 0;
     }
   }
@@ -944,9 +944,9 @@
   }
 
   if (!hints->decrypted_psk.empty()) {
-    if (!CBB_add_asn1(&seq, &child, kDecryptedPSKTag) ||
-        !CBB_add_bytes(&child, hints->decrypted_psk.data(),
-                       hints->decrypted_psk.size())) {
+    if (!CBB_add_asn1_element(&seq, kDecryptedPSKTag,
+                              hints->decrypted_psk.data(),
+                              hints->decrypted_psk.size())) {
       return 0;
     }
   }
@@ -971,9 +971,9 @@
   }
 
   if (!hints->server_random_tls12.empty()) {
-    if (!CBB_add_asn1(&seq, &child, kServerRandomTLS12Tag) ||
-        !CBB_add_bytes(&child, hints->server_random_tls12.data(),
-                       hints->server_random_tls12.size())) {
+    if (!CBB_add_asn1_element(&seq, kServerRandomTLS12Tag,
+                              hints->server_random_tls12.data(),
+                              hints->server_random_tls12.size())) {
       return 0;
     }
   }
@@ -992,9 +992,9 @@
 
 
   if (!hints->decrypted_ticket.empty()) {
-    if (!CBB_add_asn1(&seq, &child, kDecryptedTicketTag) ||
-        !CBB_add_bytes(&child, hints->decrypted_ticket.data(),
-                       hints->decrypted_ticket.size())) {
+    if (!CBB_add_asn1_element(&seq, kDecryptedTicketTag,
+                              hints->decrypted_ticket.data(),
+                              hints->decrypted_ticket.size())) {
       return 0;
     }
   }
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 58a2406..a3a3863 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -56,7 +56,9 @@
       apply_jdk11_workaround(false),
       can_release_private_key(false),
       channel_id_negotiated(false),
-      received_hello_verify_request(false) {
+      received_hello_verify_request(false),
+      matched_peer_trust_anchor(false),
+      peer_matched_trust_anchor(false) {
   assert(ssl);
 
   // Draw entropy for all GREASE values at once. This avoids calling
@@ -384,10 +386,10 @@
     return ssl_hs_error;
   }
 
-  int finished_ok = CBS_mem_equal(&msg.body, finished, finished_len);
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  finished_ok = 1;
-#endif
+  bool finished_ok = CBS_mem_equal(&msg.body, finished, finished_len);
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    finished_ok = true;
+  }
   if (!finished_ok) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
     OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 7319df7..4ce8d18 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -1270,7 +1270,8 @@
   // check the ECDSA curve. Prior to TLS 1.3, there is no way to determine which
   // ECDSA curves are supported by the peer, so we must assume all curves are
   // supported.
-  return tls1_choose_signature_algorithm(hs, cred, out_sigalg);
+  return tls1_choose_signature_algorithm(hs, cred, out_sigalg) &&
+         ssl_credential_matches_requested_issuers(hs, cred);
 }
 
 static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 12f5662..6986141 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -163,9 +163,10 @@
   // comment about |in_group_flags| in the |SSLCipherPreferenceList|
   // struct.
   const bool *in_group_flags;
-  // group_min contains the minimal index so far found in a group, or -1 if no
-  // such value exists yet.
-  int group_min = -1;
+  // best_index contains the index of the best matching cipher suite found so
+  // far, indexed into |allow|. If |best_index| is |SIZE_MAX|, no matching
+  // cipher suite has been found yet.
+  size_t best_index = SIZE_MAX;
 
   const SSLCipherPreferenceList *server_pref =
       hs->config->cipher_list ? hs->config->cipher_list.get()
@@ -176,12 +177,13 @@
     allow = client_pref;
   } else {
     prio = client_pref;
-    in_group_flags = NULL;
+    in_group_flags = nullptr;
     allow = server_pref->ciphers.get();
   }
 
   for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
     const SSL_CIPHER *c = sk_SSL_CIPHER_value(prio, i);
+    const bool in_group = in_group_flags != nullptr && in_group_flags[i];
 
     size_t cipher_index;
     if (  // Check if the cipher is supported for the current version.
@@ -192,27 +194,22 @@
         (c->algorithm_auth & mask_a) &&  //
         // Check the cipher is in the |allow| list.
         sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
-      if (in_group_flags != NULL && in_group_flags[i]) {
-        // This element of |prio| is in a group. Update the minimum index found
-        // so far and continue looking.
-        if (group_min == -1 || (size_t)group_min > cipher_index) {
-          group_min = cipher_index;
-        }
-      } else {
-        if (group_min != -1 && (size_t)group_min < cipher_index) {
-          cipher_index = group_min;
-        }
-        return sk_SSL_CIPHER_value(allow, cipher_index);
+      // Within a group, |allow|'s preference order applies.
+      if (best_index == SIZE_MAX || best_index > cipher_index) {
+        best_index = cipher_index;
       }
     }
 
-    if (in_group_flags != NULL && !in_group_flags[i] && group_min != -1) {
-      // We are about to leave a group, but we found a match in it, so that's
-      // our answer.
-      return sk_SSL_CIPHER_value(allow, group_min);
+    // We are about to leave a (possibly singleton) group, but we found a match
+    // in it, so that's our answer.
+    if (!in_group && best_index != SIZE_MAX) {
+      return sk_SSL_CIPHER_value(allow, best_index);
     }
   }
 
+  // The final cipher suite must end a group, so, if we found a match, we must
+  // have returned early above.
+  assert(best_index == SIZE_MAX);
   OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
   return nullptr;
 }
@@ -273,9 +270,12 @@
 
   TLS12ServerParams params;
   params.cipher = choose_cipher(hs, client_pref, mask_k, mask_a);
-  if (params.cipher == nullptr) {
+  if (params.cipher == nullptr ||
+      (cred != nullptr &&
+       !ssl_credential_matches_requested_issuers(hs, cred))) {
     return TLS12ServerParams();
   }
+  // Only report the selected signature algorithm if it will be used.
   if (ssl_cipher_requires_server_key_exchange(params.cipher) &&
       ssl_cipher_uses_certificate_auth(params.cipher)) {
     params.signature_algorithm = sigalg;
@@ -833,18 +833,10 @@
       hs->new_session->group_id = group_id;
     }
 
-    // Determine whether to request a client certificate.
-    hs->cert_request = !!(hs->config->verify_mode & SSL_VERIFY_PEER);
-    // Only request a certificate if Channel ID isn't negotiated.
-    if ((hs->config->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
-        hs->channel_id_negotiated) {
-      hs->cert_request = false;
-    }
-    // CertificateRequest may only be sent in certificate-based ciphers.
-    if (!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
-      hs->cert_request = false;
-    }
-
+    // Determine whether to request a client certificate. CertificateRequest may
+    // only be sent in certificate-based ciphers.
+    hs->cert_request = (hs->config->verify_mode & SSL_VERIFY_PEER) &&
+                       ssl_cipher_uses_certificate_auth(hs->new_cipher);
     if (!hs->cert_request) {
       // OpenSSL returns X509_V_OK when no certificates are requested. This is
       // classed by them as a bug, but it's assumed by at least NGINX.
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 05af44f..ba6b444 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -27,6 +27,7 @@
 #include <initializer_list>
 #include <limits>
 #include <new>
+#include <optional>
 #include <string_view>
 #include <type_traits>
 #include <utility>
@@ -49,9 +50,7 @@
 
 #if defined(OPENSSL_WINDOWS)
 // Windows defines struct timeval in winsock2.h.
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <sys/time.h>
 #endif
@@ -1094,7 +1093,7 @@
   // to |max_seq_num_ - i|.
   std::bitset<256> map_;
   // max_seq_num_ is the largest sequence number seen so far as a 64-bit
-  // integer.
+  // integer, or zero if none have been seen.
   uint64_t max_seq_num_ = 0;
 };
 
@@ -1178,6 +1177,7 @@
   UniquePtr<SSLAEADContext> aead;
   UniquePtr<RecordNumberEncrypter> rn_encrypter;
   DTLSReplayBitmap bitmap;
+  InplaceVector<uint8_t, SSL_MAX_MD_SIZE> traffic_secret;
 };
 
 struct DTLSWriteEpoch {
@@ -1188,6 +1188,7 @@
   DTLSRecordNumber next_record;
   UniquePtr<SSLAEADContext> aead;
   UniquePtr<RecordNumberEncrypter> rn_encrypter;
+  InplaceVector<uint8_t, SSL_MAX_MD_SIZE> traffic_secret;
 };
 
 // ssl_record_prefix_len returns the length of the prefix before the ciphertext
@@ -1276,6 +1277,11 @@
 // fit in a record of up to |max_out| bytes, or zero if none may fit.
 size_t dtls_seal_max_input_len(const SSL *ssl, uint16_t epoch, size_t max_out);
 
+// dtls_get_read_epoch and dtls_get_write_epoch return the epoch corresponding
+// to |epoch| or nullptr if there is none.
+DTLSReadEpoch *dtls_get_read_epoch(const SSL *ssl, uint16_t epoch);
+DTLSWriteEpoch *dtls_get_write_epoch(const SSL *ssl, uint16_t epoch);
+
 // dtls_seal_record implements |tls_seal_record| for DTLS. |epoch| selects which
 // epoch's cipher state to use. Unlike |tls_seal_record|, |in| and |out| may
 // alias but, if they do, |in| must be exactly |dtls_seal_prefix_len| bytes
@@ -1659,7 +1665,7 @@
 
 // tls13_export_keying_material provides an exporter interface to use the
 // |exporter_secret|.
-bool tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
+bool tls13_export_keying_material(const SSL *ssl, Span<uint8_t> out,
                                   Span<const uint8_t> secret,
                                   std::string_view label,
                                   Span<const uint8_t> context);
@@ -1942,11 +1948,17 @@
   // |ClaimPAKEAttempt| call.
   void RestorePAKEAttempt() const;
 
+  // trust_anchor_id, if non-empty, is the trust anchor ID for the root of the
+  // chain in |chain|.
+  bssl::Array<uint8_t> trust_anchor_id;
+
   CRYPTO_EX_DATA ex_data;
 
   // must_match_issuer is a flag indicating that this credential should be
   // considered only when it matches a peer request for a particular issuer via
   // a negotiation mechanism (such as the certificate_authorities extension).
+  // This also implies that chain is a certificate path ending in a certificate
+  // issued by the certificate with that trust anchor identifier.
   bool must_match_issuer = false;
 
  private:
@@ -2266,6 +2278,16 @@
   // extension in our peer's CertificateRequest or ClientHello message
   UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names;
 
+  // peer_requested_trust_anchors, if not nullopt, contains the trust anchor IDs
+  // (possibly none) the peer requested in ClientHello or CertificateRequest. If
+  // nullopt, the peer did not send the extension.
+  std::optional<Array<uint8_t>> peer_requested_trust_anchors;
+
+  // peer_available_trust_anchors, if not empty, is the list of trust anchor IDs
+  // the peer reported as available in EncryptedExtensions. This is only sent by
+  // servers to clients.
+  Array<uint8_t> peer_available_trust_anchors;
+
   // cached_x509_ca_names contains a cache of parsed versions of the elements of
   // |ca_names|. This pointer is left non-owning so only
   // |ssl_crypto_x509_method| needs to link against crypto/x509.
@@ -2414,6 +2436,14 @@
   // message from the server.
   bool received_hello_verify_request : 1;
 
+  // matched_peer_trust_anchor indicates that we have matched a trust anchor
+  // the peer requested in the trust anchors extension.
+  bool matched_peer_trust_anchor : 1;
+
+  // peer_matched_trust_anchor is true if the peer indicated a match with one of
+  // our requested trust anchors.
+  bool peer_matched_trust_anchor : 1;
+
   // client_version is the value sent or received in the ClientHello version.
   uint16_t client_version = 0;
 
@@ -2626,6 +2656,10 @@
 bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                         const SSL_CLIENT_HELLO *client_hello);
 
+// ssl_is_valid_trust_anchor_list returns whether |in| is a valid trust anchor
+// identifiers list.
+bool ssl_is_valid_trust_anchor_list(Span<const uint8_t> in);
+
 struct SSLExtension {
   SSLExtension(uint16_t type_arg, bool allowed_arg = true)
       : type(type_arg), allowed(allowed_arg), present(false) {
@@ -2673,6 +2707,43 @@
 void ssl_done_writing_client_hello(SSL_HANDSHAKE *hs);
 
 
+// Flags.
+
+// SSLFlags is a bitmask of flags that can be encoded with the TLS flags
+// extension, draft-ietf-tls-tlsflags-14. For now, our in-memory representation
+// matches the wire representation, and we only support flags up to 32. If
+// higher values are needed, we can increase the size of the bitmask, or only
+// store the flags we implement in the bitmask.
+using SSLFlags = uint32_t;
+inline constexpr SSLFlags kSSLFlagResumptionAcrossNames = 1 << 8;
+
+// ssl_add_flags_extension encodes a tls_flags extension (including the header)
+// containing the flags in |flags|. It returns true on success and false on
+// error. If |flags| is zero (no flags set), it returns true without adding
+// anything to |cbb|.
+bool ssl_add_flags_extension(CBB *cbb, SSLFlags flags);
+
+// ssl_parse_flags_extension_request parses tls_flags extension value (excluding
+// the header) from |cbs|, for a request message (ClientHello,
+// CertificateRequest, or NewSessionTicket). Unrecognized flags will be ignored.
+//
+// On success, it sets |*out| to the parsed flags and returns true. On error, it
+// sets |*out_alert| to a TLS alert and returns false.
+bool ssl_parse_flags_extension_request(const CBS *cbs, SSLFlags *out,
+                                       uint8_t *out_alert);
+
+// ssl_parse_flags_extension_response parses tls_flags extension value
+// (excluding the header) from |cbs|, for a response message (HelloRetryRequest,
+// ServerHello, EncryptedExtensions, or Certificate). Only the flags in
+// |allowed_flags| may be present.
+//
+// On success, it sets |*out| to the parsed flags and returns true. On error, it
+// sets |*out_alert| to a TLS alert and returns false.
+bool ssl_parse_flags_extension_response(const CBS *cbs, SSLFlags *out,
+                                        uint8_t *out_alert,
+                                        SSLFlags allowed_flags);
+
+
 // SSLKEYLOGFILE functions.
 
 // ssl_log_secret logs |secret| with label |label|, if logging is enabled for
@@ -3615,6 +3686,9 @@
   // moment we are not crossing those streams.
   UniquePtr<STACK_OF(CRYPTO_BUFFER)> CA_names;
 
+  // Trust anchor IDs to be requested in the trust_anchors extension.
+  std::optional<Array<uint8_t>> requested_trust_anchors;
+
   Array<uint16_t> supported_group_list;  // our list
 
   // channel_id_private is the client's Channel ID private key, or null if
@@ -4148,6 +4222,9 @@
   // What we put in client hello in the CA extension.
   bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> CA_names;
 
+  // What we request in the trust_anchors extension.
+  std::optional<bssl::Array<uint8_t>> requested_trust_anchors;
+
   // Default values to use in SSL structures follow (these are copied by
   // SSL_new)
 
@@ -4352,6 +4429,10 @@
   // |aes_hw_override| is true.
   bool aes_hw_override_value : 1;
 
+  // resumption_across_names_enabled indicates whether a TLS 1.3 server should
+  // signal its sessions may be resumed across names in the server certificate.
+  bool resumption_across_names_enabled : 1;
+
  private:
   friend RefCounted;
   ~ssl_ctx_st();
@@ -4439,6 +4520,10 @@
 
   // If enable_early_data is true, early data can be sent and accepted.
   bool enable_early_data : 1;
+
+  // resumption_across_names_enabled indicates whether a TLS 1.3 server should
+  // signal its sessions may be resumed across names in the server certificate.
+  bool resumption_across_names_enabled : 1;
 };
 
 struct ssl_session_st : public bssl::RefCounted<ssl_session_st> {
@@ -4579,6 +4664,10 @@
   // session.
   bool has_application_settings : 1;
 
+  // is_resumable_across_names indicates whether the session may be resumed for
+  // any of the identities presented in the certificate.
+  bool is_resumable_across_names : 1;
+
   // quic_early_data_context is used to determine whether early data must be
   // rejected when performing a QUIC handshake.
   bssl::Array<uint8_t> quic_early_data_context;
diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc
index 584fa84..a30825b 100644
--- a/src/ssl/ssl_aead_ctx.cc
+++ b/src/ssl/ssl_aead_ctx.cc
@@ -25,12 +25,6 @@
 #include "internal.h"
 
 
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-#define FUZZER_MODE true
-#else
-#define FUZZER_MODE false
-#endif
-
 BSSL_NAMESPACE_BEGIN
 
 SSLAEADContext::SSLAEADContext(const SSL_CIPHER *cipher_arg)
@@ -134,7 +128,7 @@
 }
 
 size_t SSLAEADContext::ExplicitNonceLen() const {
-  if (!FUZZER_MODE && variable_nonce_included_in_record_) {
+  if (!CRYPTO_fuzzer_mode_enabled() && variable_nonce_included_in_record_) {
     return variable_nonce_len_;
   }
   return 0;
@@ -142,7 +136,7 @@
 
 bool SSLAEADContext::SuffixLen(size_t *out_suffix_len, const size_t in_len,
                                const size_t extra_in_len) const {
-  if (is_null_cipher() || FUZZER_MODE) {
+  if (is_null_cipher() || CRYPTO_fuzzer_mode_enabled()) {
     *out_suffix_len = extra_in_len;
     return true;
   }
@@ -168,7 +162,7 @@
 
 size_t SSLAEADContext::MaxOverhead() const {
   return ExplicitNonceLen() +
-         (is_null_cipher() || FUZZER_MODE
+         (is_null_cipher() || CRYPTO_fuzzer_mode_enabled()
               ? 0
               : EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(ctx_.get())));
 }
@@ -179,7 +173,7 @@
     return 0;
   }
   max_out -= explicit_nonce_len;
-  if (is_null_cipher() || FUZZER_MODE) {
+  if (is_null_cipher() || CRYPTO_fuzzer_mode_enabled()) {
     return max_out;
   }
   // TODO(crbug.com/42290602): This should be part of |EVP_AEAD_CTX|.
@@ -232,7 +226,7 @@
 bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type,
                           uint16_t record_version, uint64_t seqnum,
                           Span<const uint8_t> header, Span<uint8_t> in) {
-  if (is_null_cipher() || FUZZER_MODE) {
+  if (is_null_cipher() || CRYPTO_fuzzer_mode_enabled()) {
     // Handle the initial NULL cipher.
     *out = in;
     return true;
@@ -321,7 +315,7 @@
     return false;
   }
 
-  if (is_null_cipher() || FUZZER_MODE) {
+  if (is_null_cipher() || CRYPTO_fuzzer_mode_enabled()) {
     // Handle the initial NULL cipher.
     OPENSSL_memmove(out, in, in_len);
     OPENSSL_memmove(out_suffix, extra_in, extra_in_len);
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index f140f5b..484dc9c 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -68,6 +68,7 @@
 //     peerALPS                [30] OCTET STRING OPTIONAL,
 //     -- Either both or none of localALPS and peerALPS must be present. If both
 //     -- are present, earlyALPN must be present and non-empty.
+//     resumableAcrossNames    [31] BOOLEAN OPTIONAL,
 // }
 //
 // Note: historically this serialization has included other optional
@@ -135,6 +136,9 @@
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 29;
 static const CBS_ASN1_TAG kPeerALPSTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 30;
+static const CBS_ASN1_TAG kResumableAcrossNamesTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 31;
+
 
 static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, CBB *cbb,
                                      int for_ticket) {
@@ -164,9 +168,8 @@
   // serialized instead.
   if (sk_CRYPTO_BUFFER_num(in->certs.get()) > 0 && !in->peer_sha256_valid) {
     const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), 0);
-    if (!CBB_add_asn1(&session, &child, kPeerTag) ||
-        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
-                       CRYPTO_BUFFER_len(buffer))) {
+    if (!CBB_add_asn1_element(&session, kPeerTag, CRYPTO_BUFFER_data(buffer),
+                              CRYPTO_BUFFER_len(buffer))) {
       return 0;
     }
   }
@@ -342,6 +345,13 @@
     }
   }
 
+  if (in->is_resumable_across_names) {
+    if (!CBB_add_asn1(&session, &child, kResumableAcrossNamesTag) ||
+        !CBB_add_asn1_bool(&child, true)) {
+      return 0;
+    }
+  }
+
   return CBB_flush(cbb);
 }
 
@@ -664,18 +674,22 @@
   }
 
   CBS settings;
-  int has_local_alps, has_peer_alps;
+  int has_local_alps, has_peer_alps, is_resumable_across_names;
   if (!CBS_get_optional_asn1_octet_string(&session, &settings, &has_local_alps,
                                           kLocalALPSTag) ||
       !ret->local_application_settings.CopyFrom(settings) ||
       !CBS_get_optional_asn1_octet_string(&session, &settings, &has_peer_alps,
                                           kPeerALPSTag) ||
       !ret->peer_application_settings.CopyFrom(settings) ||
+      !CBS_get_optional_asn1_bool(&session, &is_resumable_across_names,
+                                  kResumableAcrossNamesTag,
+                                  /*default_value=*/false) ||
       CBS_len(&session) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     return nullptr;
   }
   ret->is_quic = is_quic;
+  ret->is_resumable_across_names = is_resumable_across_names;
 
   // The two ALPS values and ALPN must be consistent.
   if (has_local_alps != has_peer_alps ||
diff --git a/src/ssl/ssl_credential.cc b/src/ssl/ssl_credential.cc
index fcd8ca5..59e2323 100644
--- a/src/ssl/ssl_credential.cc
+++ b/src/ssl/ssl_credential.cc
@@ -80,7 +80,22 @@
       }
     }
   }
-  // TODO(bbe): Other forms of issuer matching go here.
+  // If the credential has a trust anchor ID and it matches one sent by the
+  // peer, it is good.
+  if (!cred->trust_anchor_id.empty() && hs->peer_requested_trust_anchors) {
+    CBS cbs = CBS(*hs->peer_requested_trust_anchors), candidate;
+    while (CBS_len(&cbs) > 0) {
+      if (!CBS_get_u8_length_prefixed(&cbs, &candidate) ||
+          CBS_len(&candidate) == 0) {
+        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+        return false;
+      }
+      if (candidate == Span(cred->trust_anchor_id)) {
+        hs->matched_peer_trust_anchor = true;
+        return true;
+      }
+    }
+  }
 
   OPENSSL_PUT_ERROR(SSL, SSL_R_NO_MATCHING_ISSUER);
   return false;
@@ -596,14 +611,75 @@
   return CRYPTO_get_ex_data(&cred->ex_data, idx);
 }
 
-void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred) {
-  cred->must_match_issuer = true;
+void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred, int match) {
+  cred->must_match_issuer = !!match;
 }
 
-void SSL_CREDENTIAL_clear_must_match_issuer(SSL_CREDENTIAL *cred) {
-  cred->must_match_issuer = false;
+int SSL_CREDENTIAL_set1_trust_anchor_id(SSL_CREDENTIAL *cred, const uint8_t *id,
+                                        size_t id_len) {
+  // For now, this is only valid for X.509.
+  if (!cred->UsesX509()) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  if (!cred->trust_anchor_id.CopyFrom(Span(id, id_len))) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  return 1;
 }
 
-int SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL *cred) {
-  return cred->must_match_issuer ? 1 : 0;
+int SSL_CREDENTIAL_set1_certificate_properties(
+    SSL_CREDENTIAL *cred, CRYPTO_BUFFER *cert_property_list) {
+  std::optional<CBS> trust_anchor;
+  CBS cbs, cpl;
+  CRYPTO_BUFFER_init_CBS(cert_property_list, &cbs);
+
+  if (!CBS_get_u16_length_prefixed(&cbs, &cpl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
+    return 0;
+  }
+  while (CBS_len(&cpl) != 0) {
+    uint16_t cp_type;
+    CBS cp_data;
+    if (!CBS_get_u16(&cpl, &cp_type) ||
+        !CBS_get_u16_length_prefixed(&cpl, &cp_data)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
+      return 0;
+    }
+    switch (cp_type) {
+      case 0:  // trust anchor identifier.
+        if (trust_anchor.has_value()) {
+          OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
+          return 0;
+        }
+        trust_anchor = cp_data;
+        break;
+      default:
+        break;
+    }
+  }
+  if (CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
+    return 0;
+  }
+  // Certificate property list has parsed correctly.
+
+  // We do not currently retain |cert_property_list|, but if we define another
+  // property with larger fields (e.g. stapled SCTs), it may make sense for
+  // those fields to retain |cert_property_list| and alias into it.
+  if (trust_anchor.has_value()) {
+    if (!CBS_len(&trust_anchor.value())) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TRUST_ANCHOR_LIST);
+      return 0;
+    }
+    if (!SSL_CREDENTIAL_set1_trust_anchor_id(cred,
+                                             CBS_data(&trust_anchor.value()),
+                                             CBS_len(&trust_anchor.value()))) {
+      return 0;
+    }
+  }
+  return 1;
 }
diff --git a/src/ssl/ssl_internal_test.cc b/src/ssl/ssl_internal_test.cc
index 233af1d..469665a 100644
--- a/src/ssl/ssl_internal_test.cc
+++ b/src/ssl/ssl_internal_test.cc
@@ -673,7 +673,6 @@
   expect_queue({1, 2, 3});
 }
 
-#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
 TEST(SSLAEADContextTest, Lengths) {
   struct LengthTest {
     // All plaintext lengths from |min_plaintext_len| to |max_plaintext_len|
@@ -883,7 +882,6 @@
     }
   }
 }
-#endif  // !BORINGSSL_UNSAFE_FUZZER_MODE
 
 }  // namespace
 BSSL_NAMESPACE_END
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index e60016c..58a85ef 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -282,7 +282,7 @@
   KYBER_private_key kyber_private_key_;
 };
 
-// draft-kwiatkowski-tls-ecdhe-mlkem-01
+// draft-ietf-tls-ecdhe-mlkem-00
 class X25519MLKEM768KeyShare : public SSLKeyShare {
  public:
   X25519MLKEM768KeyShare() {}
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index c859ea6..1b8ab54 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -255,9 +255,7 @@
     }
   }
 
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-  return {1234, 1234};
-#elif defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_WINDOWS)
   struct _timeb time;
   _ftime(&time);
   if (time.time < 0) {
@@ -334,8 +332,9 @@
 bool SSL_get_traffic_secrets(const SSL *ssl,
                              Span<const uint8_t> *out_read_traffic_secret,
                              Span<const uint8_t> *out_write_traffic_secret) {
-  // This API is not well-defined for DTLS 1.3 (see https://crbug.com/42290608)
-  // or QUIC, where multiple epochs may be alive at once.
+  // This API is not well-defined for DTLS, where multiple epochs may be alive
+  // at once. Callers should use |SSL_get_dtls_*_traffic_secret| instead. In
+  // QUIC, the application is already handed the traffic secret.
   if (SSL_is_dtls(ssl) || SSL_is_quic(ssl)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
     return false;
@@ -401,7 +400,8 @@
       handoff(false),
       enable_early_data(false),
       aes_hw_override(false),
-      aes_hw_override_value(false) {
+      aes_hw_override_value(false),
+      resumption_across_names_enabled(false) {
   CRYPTO_MUTEX_init(&lock);
   CRYPTO_new_ex_data(&ex_data);
 }
@@ -478,7 +478,8 @@
       max_cert_list(ctx->max_cert_list),
       server(false),
       quiet_shutdown(ctx->quiet_shutdown),
-      enable_early_data(ctx->enable_early_data) {
+      enable_early_data(ctx->enable_early_data),
+      resumption_across_names_enabled(ctx->resumption_across_names_enabled) {
   CRYPTO_new_ex_data(&ex_data);
 }
 
@@ -531,6 +532,14 @@
     return nullptr;
   }
 
+  if (ctx->requested_trust_anchors) {
+    ssl->config->requested_trust_anchors.emplace();
+    if (!ssl->config->requested_trust_anchors->CopyFrom(
+            *ctx->requested_trust_anchors)) {
+      return nullptr;
+    }
+  }
+
   if (ctx->psk_identity_hint) {
     ssl->config->psk_identity_hint.reset(
         OPENSSL_strdup(ctx->psk_identity_hint.get()));
@@ -571,7 +580,7 @@
       jdk11_workaround(false),
       quic_use_legacy_codepoint(false),
       permute_extensions(false),
-      alps_use_new_codepoint(false) {
+      alps_use_new_codepoint(true) {
   assert(ssl);
 }
 
@@ -2805,17 +2814,8 @@
 
 uint64_t SSL_get_read_sequence(const SSL *ssl) {
   if (SSL_is_dtls(ssl)) {
-    // TODO(crbug.com/42290608): This API needs to reworked.
-    //
-    // In DTLS 1.2, right at an epoch transition, |read_epoch| may not have
-    // received any records. We will then return that sequence 0 is the highest
-    // received, but it's really -1, which is not representable. This is mostly
-    // moot because, after the handshake, we will never be in the state.
-    //
-    // In DTLS 1.3, epochs do not transition until the first record comes in.
-    // This avoids the DTLS 1.2 problem but introduces a different problem:
-    // during a KeyUpdate (which may occur in the steady state), both epochs are
-    // live. We'll likely need a new API for DTLS offload.
+    // TODO(crbug.com/42290608): This API should not be implemented for DTLS or
+    // QUIC. In QUIC we do not maintain a sequence number.
     const DTLSReadEpoch *read_epoch = &ssl->d1->read_epoch;
     return DTLSRecordNumber(read_epoch->epoch, read_epoch->bitmap.max_seq_num())
         .combined();
@@ -2824,6 +2824,10 @@
 }
 
 uint64_t SSL_get_write_sequence(const SSL *ssl) {
+  // TODO(crbug.com/42290608): This API should not be implemented for DTLS or
+  // QUIC. In QUIC we do not maintain a sequence number. In DTLS, this API isn't
+  // harmful per se, but the caller already needs to use a DTLS-specific API on
+  // the read side.
   if (SSL_is_dtls(ssl)) {
     return ssl->d1->write_epoch.next_record.combined();
   }
@@ -2831,6 +2835,109 @@
   return ssl->s3->write_sequence;
 }
 
+int SSL_is_dtls_handshake_idle(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+
+  return !SSL_in_init(ssl) &&
+         // No unacknowledged messages in DTLS 1.3. In DTLS 1.2, there no ACKs
+         // and we currently never clear |outgoing_messages| on the side that
+         // speaks last.
+         (ssl_protocol_version(ssl) < TLS1_3_VERSION ||
+          ssl->d1->outgoing_messages.empty()) &&
+         // No partial or out-of-order messages.
+         std::all_of(std::begin(ssl->d1->incoming_messages),
+                     std::end(ssl->d1->incoming_messages),
+                     [](const auto &msg) { return msg == nullptr; }) &&
+         // Not trying to send a KeyUpdate.
+         !ssl->s3->key_update_pending &&
+         ssl->d1->queued_key_update == bssl::QueuedKeyUpdate::kNone;
+}
+
+uint32_t SSL_get_dtls_handshake_read_seq(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->handshake_read_overflow
+             ? uint32_t{0x10000}
+             : uint32_t{ssl->d1->handshake_read_seq};
+}
+
+uint32_t SSL_get_dtls_handshake_write_seq(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->handshake_write_overflow
+             ? uint32_t{0x10000}
+             : uint32_t{ssl->d1->handshake_write_seq};
+}
+
+uint16_t SSL_get_dtls_read_epoch(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  // Return the highest available epoch.
+  return ssl->d1->next_read_epoch ? ssl->d1->next_read_epoch->epoch
+                                  : ssl->d1->read_epoch.epoch;
+}
+
+uint16_t SSL_get_dtls_write_epoch(const SSL *ssl) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  return ssl->d1->write_epoch.epoch();
+}
+
+uint64_t SSL_get_dtls_read_sequence(const SSL *ssl, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  const DTLSReadEpoch *read_epoch = dtls_get_read_epoch(ssl, epoch);
+  if (read_epoch == nullptr) {
+    return UINT64_MAX;
+  }
+  uint64_t max_seq_num = read_epoch->bitmap.max_seq_num();
+  assert(max_seq_num <= DTLSRecordNumber::kMaxSequence);
+  if (read_epoch->bitmap.ShouldDiscard(max_seq_num)) {
+    // Increment to get to an available sequence number.
+    max_seq_num++;
+  } else {
+    // If |max_seq_num| was available, the bitmap must have been empty.
+    assert(max_seq_num == 0);
+  }
+  return max_seq_num;
+}
+
+uint64_t SSL_get_dtls_write_sequence(const SSL *ssl, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  const DTLSWriteEpoch *write_epoch = dtls_get_write_epoch(ssl, epoch);
+  if (write_epoch == nullptr) {
+    return UINT64_MAX;
+  }
+  return write_epoch->next_record.sequence();
+}
+
+template <typename EpochState>
+static int get_dtls_traffic_secret(
+    const SSL *ssl, EpochState *(*get_epoch)(const SSL *, uint16_t),
+    const uint8_t **out_data, size_t *out_len, uint16_t epoch) {
+  BSSL_CHECK(SSL_is_dtls(ssl));
+  // This function only applies to encrypted DTLS 1.3 epochs.
+  if (epoch == 0 || ssl->s3->version == 0 ||
+      ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+    return 0;
+  }
+  const EpochState *epoch_state = get_epoch(ssl, epoch);
+  if (epoch_state == nullptr) {
+    return 0;
+  }
+  assert(!epoch_state->traffic_secret.empty());
+  *out_data = epoch_state->traffic_secret.data();
+  *out_len = epoch_state->traffic_secret.size();
+  return 1;
+}
+
+int SSL_get_dtls_read_traffic_secret(const SSL *ssl, const uint8_t **out_data,
+                                     size_t *out_len, uint16_t epoch) {
+  return get_dtls_traffic_secret(ssl, dtls_get_read_epoch, out_data, out_len,
+                                 epoch);
+}
+
+int SSL_get_dtls_write_traffic_secret(const SSL *ssl, const uint8_t **out_data,
+                                      size_t *out_len, uint16_t epoch) {
+  return get_dtls_traffic_secret(ssl, dtls_get_write_epoch, out_data, out_len,
+                                 epoch);
+}
+
 uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) {
   SSL_SESSION *session = SSL_get_session(ssl);
   if (session == NULL) {
@@ -3288,3 +3395,50 @@
 enum ssl_compliance_policy_t SSL_get_compliance_policy(const SSL *ssl) {
   return ssl->config->compliance_policy;
 }
+
+int SSL_peer_matched_trust_anchor(const SSL *ssl) {
+  return ssl->s3->hs != nullptr && ssl->s3->hs->peer_matched_trust_anchor;
+}
+
+void SSL_get0_peer_available_trust_anchors(const SSL *ssl, const uint8_t **out,
+                                           size_t *out_len) {
+  Span<const uint8_t> ret;
+  if (SSL_HANDSHAKE *hs = ssl->s3->hs.get(); hs != nullptr) {
+    ret = hs->peer_available_trust_anchors;
+  }
+  *out = ret.data();
+  *out_len = ret.size();
+}
+
+int SSL_CTX_set1_requested_trust_anchors(SSL_CTX *ctx, const uint8_t *ids,
+                                         size_t ids_len) {
+  auto span = Span(ids, ids_len);
+  if (!ssl_is_valid_trust_anchor_list(span)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TRUST_ANCHOR_LIST);
+    return 0;
+  }
+  Array<uint8_t> copy;
+  if (!copy.CopyFrom(span)) {
+    return 0;
+  }
+  ctx->requested_trust_anchors = std::move(copy);
+  return 1;
+}
+
+int SSL_set1_requested_trust_anchors(SSL *ssl, const uint8_t *ids,
+                                     size_t ids_len) {
+  if (!ssl->config) {
+    return 0;
+  }
+  auto span = Span(ids, ids_len);
+  if (!ssl_is_valid_trust_anchor_list(span)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TRUST_ANCHOR_LIST);
+    return 0;
+  }
+  Array<uint8_t> copy;
+  if (!copy.CopyFrom(span)) {
+    return 0;
+  }
+  ssl->config->requested_trust_anchors = std::move(copy);
+  return 1;
+}
diff --git a/src/ssl/ssl_privkey.cc b/src/ssl/ssl_privkey.cc
index 6d46f88..70b9f03 100644
--- a/src/ssl/ssl_privkey.cc
+++ b/src/ssl/ssl_privkey.cc
@@ -272,10 +272,10 @@
   }
   bool ok = EVP_DigestVerify(ctx.get(), signature.data(), signature.size(),
                              in.data(), in.size());
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  ok = true;
-  ERR_clear_error();
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    ok = true;
+    ERR_clear_error();
+  }
   return ok;
 }
 
@@ -519,18 +519,6 @@
   return alg != nullptr && alg->is_rsa_pss;
 }
 
-static int compare_uint16_t(const void *p1, const void *p2) {
-  uint16_t u1 = *((const uint16_t *)p1);
-  uint16_t u2 = *((const uint16_t *)p2);
-  if (u1 < u2) {
-    return -1;
-  } else if (u1 > u2) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
 static bool sigalgs_unique(Span<const uint16_t> in_sigalgs) {
   if (in_sigalgs.size() < 2) {
     return true;
@@ -541,8 +529,7 @@
     return false;
   }
 
-  qsort(sigalgs.data(), sigalgs.size(), sizeof(uint16_t), compare_uint16_t);
-
+  std::sort(sigalgs.begin(), sigalgs.end());
   for (size_t i = 1; i < sigalgs.size(); i++) {
     if (sigalgs[i - 1] == sigalgs[i]) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_SIGNATURE_ALGORITHM);
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 6a7fd5b..52c2807 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -364,21 +364,21 @@
   }
 
   size_t total = 0;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  OPENSSL_memcpy(ptr, session_buf, session_len);
-  total = session_len;
-#else
-  int len;
-  if (!EVP_EncryptUpdate(ctx.get(), ptr + total, &len, session_buf,
-                         session_len)) {
-    return 0;
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    OPENSSL_memcpy(ptr, session_buf, session_len);
+    total = session_len;
+  } else {
+    int len;
+    if (!EVP_EncryptUpdate(ctx.get(), ptr + total, &len, session_buf,
+                           session_len)) {
+      return 0;
+    }
+    total += len;
+    if (!EVP_EncryptFinal_ex(ctx.get(), ptr + total, &len)) {
+      return 0;
+    }
+    total += len;
   }
-  total += len;
-  if (!EVP_EncryptFinal_ex(ctx.get(), ptr + total, &len)) {
-    return 0;
-  }
-  total += len;
-#endif
   if (!CBB_did_write(out, total)) {
     return 0;
   }
@@ -815,7 +815,8 @@
       ticket_age_add_valid(false),
       is_server(false),
       is_quic(false),
-      has_application_settings(false) {
+      has_application_settings(false),
+      is_resumable_across_names(false) {
   CRYPTO_new_ex_data(&ex_data);
   time = ::time(nullptr);
 }
@@ -1000,6 +1001,10 @@
   }
 }
 
+int SSL_SESSION_is_resumable_across_names(const SSL_SESSION *session) {
+  return session->is_resumable_across_names;
+}
+
 int SSL_SESSION_early_data_capable(const SSL_SESSION *session) {
   return ssl_session_protocol_version(session) >= TLS1_3_VERSION &&
          session->ticket_max_early_data != 0;
@@ -1197,6 +1202,14 @@
   return ctx->get_session_cb;
 }
 
+void SSL_CTX_set_resumption_across_names_enabled(SSL_CTX *ctx, int enabled) {
+  ctx->resumption_across_names_enabled = !!enabled;
+}
+
+void SSL_set_resumption_across_names_enabled(SSL *ssl, int enabled) {
+  ssl->resumption_across_names_enabled = !!enabled;
+}
+
 void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,
                                                         int type, int value)) {
   ctx->info_callback = cb;
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index e7d83e4..ac2880e 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -49,9 +49,7 @@
 
 #if defined(OPENSSL_WINDOWS)
 // Windows defines struct timeval in winsock2.h.
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <sys/time.h>
 #endif
@@ -136,6 +134,17 @@
   int index_;
 };
 
+static timeval g_current_time;
+
+static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
+  *out_clock = g_current_time;
+}
+
+static void FrozenTimeCallback(const SSL *ssl, timeval *out_clock) {
+  out_clock->tv_sec = 1000;
+  out_clock->tv_usec = 0;
+}
+
 static const CipherTest kCipherTests[] = {
     // Selecting individual ciphers should work.
     {
@@ -1133,11 +1142,7 @@
     return nullptr;
   }
   // Fix up the timeout.
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
-  SSL_SESSION_set_time(session.get(), 1234);
-#else
   SSL_SESSION_set_time(session.get(), time(nullptr));
-#endif
   return session;
 }
 
@@ -2784,6 +2789,14 @@
                          });
 
 TEST_P(SSLVersionTest, SequenceNumber) {
+  // TODO(crbug.com/42290608): Once |SSL_get_read_sequence| and
+  // |SSL_get_write_sequence| are no longer implemented in DTLS 1.3, make this
+  // test TLS-only and remove the DTLS cases. For now, since we still care about
+  // their behavior in DTLS 1.2, continue testing this behavior.
+  if (is_dtls() && is_tls13()) {
+    return;
+  }
+
   ASSERT_TRUE(Connect());
 
   // Drain any post-handshake messages to ensure there are no unread records
@@ -2796,26 +2809,15 @@
   uint64_t server_write_seq = SSL_get_write_sequence(server_.get());
 
   if (is_dtls()) {
-    if (version() == DTLS1_3_VERSION) {
-      // Both client and server must be at epoch 3 (application data).
-      EXPECT_EQ(EpochFromSequence(client_write_seq), 3);
-      EXPECT_EQ(EpochFromSequence(server_write_seq), 3);
+    // Both client and server must be at epoch 1.
+    EXPECT_EQ(EpochFromSequence(client_read_seq), 1);
+    EXPECT_EQ(EpochFromSequence(client_write_seq), 1);
+    EXPECT_EQ(EpochFromSequence(server_read_seq), 1);
+    EXPECT_EQ(EpochFromSequence(server_write_seq), 1);
 
-      // TODO(crbug.com/42290608): Ideally we would check the read sequence
-      // numbers and compare them against each other, but
-      // |SSL_get_read_sequence| is ill-defined right after DTLS 1.3's key
-      // change. See that function for details.
-    } else {
-      // Both client and server must be at epoch 1.
-      EXPECT_EQ(EpochFromSequence(client_read_seq), 1);
-      EXPECT_EQ(EpochFromSequence(client_write_seq), 1);
-      EXPECT_EQ(EpochFromSequence(server_read_seq), 1);
-      EXPECT_EQ(EpochFromSequence(server_write_seq), 1);
-
-      // The next record to be written should exceed the largest received.
-      EXPECT_GT(client_write_seq, server_read_seq);
-      EXPECT_GT(server_write_seq, client_read_seq);
-    }
+    // The next record to be written should exceed the largest received.
+    EXPECT_GT(client_write_seq, server_read_seq);
+    EXPECT_GT(server_write_seq, client_read_seq);
   } else {
     // The next record to be written should equal the next to be received.
     EXPECT_EQ(client_write_seq, server_read_seq);
@@ -2827,20 +2829,266 @@
   EXPECT_EQ(SSL_write(client_.get(), &byte, 1), 1);
   EXPECT_EQ(SSL_read(server_.get(), &byte, 1), 1);
 
-  if (version() == DTLS1_3_VERSION) {
-    // TODO(crbug.com/42290608): Write an appropriate test for incrementing both
-    // sequence number and epoch in the following test. The server read seq was
-    // in epoch 2, but after the write it's in epoch 3, so adding 1 doesn't work
-    // any more.
-    return;
-  }
-
   // The client write and server read sequence numbers should have
   // incremented.
   EXPECT_EQ(client_write_seq + 1, SSL_get_write_sequence(client_.get()));
   EXPECT_EQ(server_read_seq + 1, SSL_get_read_sequence(server_.get()));
 }
 
+TEST_P(SSLVersionTest, RecordStateDTLS) {
+  if (!is_dtls()) {
+    return;
+  }
+
+  SSL_CTX_set_current_time_cb(client_ctx_.get(), CurrentTimeCallback);
+  SSL_CTX_set_current_time_cb(server_ctx_.get(), CurrentTimeCallback);
+
+  ASSERT_TRUE(CreateClientAndServer(&client_, &server_, client_ctx_.get(),
+                                    server_ctx_.get()));
+
+  // The handshake is incomplete.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // The initial epoch is zero.
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 0);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 0);
+
+  // We have not sent or received any records.
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 0), 0u);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 0), 0u);
+
+  // We have not sent or received any handshake messages.
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(client_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(server_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(server_.get()), 0u);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(client_.get()), 0u);
+
+  // Though it exists, epoch zero is unencrypted and does not have traffic
+  // secrets.
+  const uint8_t *data;
+  size_t len;
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 0));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 0));
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 0));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 0));
+
+  // Other epochs do not exist yet.
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), UINT64_MAX);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), UINT64_MAX);
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 1));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 1));
+  EXPECT_FALSE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 1));
+  EXPECT_FALSE(
+      SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 1));
+
+  ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+
+  // DTLS 1.0 and 1.2 are relative simple.
+  if (!is_tls13()) {
+    // This handshake is now idle.
+    EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+    EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+
+    // Both sides of both channels are at epoch 1.
+    EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 1);
+    EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 1);
+
+    // Both sides have sent one record at epoch 1 each (Finished).
+    EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), 1u);
+
+    // DTLS 1.2 does not use traffic secrets.
+    EXPECT_FALSE(
+        SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_write_traffic_secret(server_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 1));
+    EXPECT_FALSE(
+        SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len, 1));
+
+    // Send a record from client to server.
+    uint8_t byte = 0;
+    EXPECT_EQ(SSL_write(client_.get(), &byte, 1), 1);
+    EXPECT_EQ(SSL_read(server_.get(), &byte, 1), 1);
+
+    // Sequence numbers should have updated.
+    EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 1), 1u);
+    EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 1), 2u);
+    EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 1), 2u);
+    return;
+  }
+
+  // The client sent Finished, which the server ACKed, but the client hasn't
+  // consumed the ACK.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  // The server sent NewSessionTicket, which the client hasn't consumed yet.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // Both sides of both channels are at epoch 3.
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 3);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 3);
+
+  auto check_matching_secret = [&](SSL *reader, SSL *writer, uint16_t epoch) {
+    ASSERT_TRUE(SSL_get_dtls_read_traffic_secret(reader, &data, &len, epoch));
+    auto read_secret = Span(data, len);
+    ASSERT_TRUE(SSL_get_dtls_write_traffic_secret(writer, &data, &len, epoch));
+    auto write_secret = Span(data, len);
+    EXPECT_EQ(Bytes(read_secret), Bytes(write_secret));
+  };
+
+  // Traffic secrets at epoch 3 should match.
+  check_matching_secret(client_.get(), server_.get(), 3);
+  check_matching_secret(server_.get(), client_.get(), 3);
+
+  // Both sides retain read epoch 2 (but not write epoch 2). The server must
+  // retain epoch 2 because it does not know the client has seen the ACK and
+  // therefore must respond to retransmissions of the client's final flight.
+  // The client could discard epoch 2, but our implementation happens not to.
+  EXPECT_LT(SSL_get_dtls_read_sequence(client_.get(), 2), UINT64_MAX);
+  EXPECT_LT(SSL_get_dtls_read_sequence(server_.get(), 2), UINT64_MAX);
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 2));
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 2));
+
+  // The client has not sent anything over epoch 3.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 3), 0u);
+
+  // The server has (ACK and NewSessionTicket), but the client has not seen it.
+  EXPECT_GT(SSL_get_dtls_write_sequence(server_.get(), 3), 0u);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 3), 0u);
+
+  // Read from the client. No application data, but this will consume the
+  // records. We send ACKs on a timer, so advance the clock to flush it.
+  uint8_t byte;
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(client_.get()), 1);
+
+  // The client has now picked up the ACK and is idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+
+  // The client has caught up to what the server wrote.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 3),
+            SSL_get_dtls_read_sequence(client_.get(), 3));
+
+  // The client saw NewSessionTicket and sent an ACK.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3), 1u);
+
+  // Pick up the ACK from the server.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+
+  // Now the server is also idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+
+  // The server has seen the ACK and has caught up to the client.
+  EXPECT_EQ(SSL_get_dtls_write_sequence(client_.get(), 3),
+            SSL_get_dtls_read_sequence(server_.get(), 3));
+
+  // Exchange some data. Sequence numbers should increment.
+  uint64_t old_seq = SSL_get_dtls_write_sequence(server_.get(), 3);
+  byte = 42;
+  ASSERT_EQ(SSL_write(server_.get(), &byte, 1), 1);
+  ASSERT_EQ(SSL_read(client_.get(), &byte, 1), 1);
+  EXPECT_EQ(SSL_get_dtls_write_sequence(server_.get(), 3), old_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(client_.get(), 3), old_seq + 1);
+
+  // Now that everyone's caught up, handshake sequence numbers should be
+  // non-zero and match.
+  uint32_t client_hs_seq = SSL_get_dtls_handshake_write_seq(client_.get());
+  EXPECT_NE(client_hs_seq, 0u);
+  EXPECT_EQ(client_hs_seq, SSL_get_dtls_handshake_read_seq(server_.get()));
+  uint32_t server_hs_seq = SSL_get_dtls_handshake_write_seq(server_.get());
+  EXPECT_NE(server_hs_seq, 0u);
+  EXPECT_EQ(server_hs_seq, SSL_get_dtls_handshake_read_seq(client_.get()));
+
+  // Enqueue a KeyUpdate that requests the peer do the same. The client is now
+  // busy.
+  ASSERT_TRUE(SSL_key_update(client_.get(), SSL_KEY_UPDATE_REQUESTED));
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+  // Flush the KeyUpdate to the transport. (We currently flush incidental
+  // traffic on read because callers are expected to be constantly reading.)
+  // The client has an unacked message, so it is still busy.
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(client_.get()));
+
+  // KeyUpdates are driven by ACKs, so the client is still at epoch 3.
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 3);
+
+  // Consume the KeyUpdate on the server and wait for the ACK timer. The server
+  // has now ACKed the KeyUpdate, advanced to read epoch 4, and sent a KeyUpdate
+  // of its own.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(server_.get()), 1);
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_read_sequence(server_.get(), 4), 0u);
+
+  // The server has an outstanding unacked KeyUpdate, so it is busy.
+  EXPECT_FALSE(SSL_is_dtls_handshake_idle(server_.get()));
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 3);
+
+  // Consume the ACK and new KeyUpdate on the client. Wait the ACK timer for the
+  // client to flush its ACK.
+  EXPECT_EQ(SSL_read(client_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(client_.get(), -1), SSL_ERROR_WANT_READ);
+  g_current_time.tv_sec++;
+  EXPECT_EQ(DTLSv1_handle_timeout(client_.get()), 1);
+
+  // The client has now seen the ACK to its KeyUpdate, advancing its write
+  // state, and seen the server's KeyUpdate, advancing its read state. It is
+  // now idle.
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(client_.get()));
+  EXPECT_EQ(SSL_get_dtls_read_epoch(client_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(client_.get()), 4);
+
+  // Both sides now have epoch 4 of the client write channel.
+  check_matching_secret(/*reader=*/server_.get(), /*writer=*/client_.get(), 4);
+
+  // Finally, consume the ACK on the server. The server applies the KeyUpdate
+  // and is also idle.
+  EXPECT_EQ(SSL_read(server_.get(), &byte, 1), -1);
+  EXPECT_EQ(SSL_get_error(server_.get(), -1), SSL_ERROR_WANT_READ);
+  EXPECT_TRUE(SSL_is_dtls_handshake_idle(server_.get()));
+  EXPECT_EQ(SSL_get_dtls_read_epoch(server_.get()), 4);
+  EXPECT_EQ(SSL_get_dtls_write_epoch(server_.get()), 4);
+
+  // Both sides now have epoch 4 of the server write channel.
+  check_matching_secret(/*reader=*/client_.get(), /*writer=*/server_.get(), 4);
+
+  // Both sides still retain read epoch 3 because neither side has received data
+  // at epoch 4 and cannot be sure the ACK has gotten through.
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len, 3));
+  EXPECT_TRUE(SSL_get_dtls_read_traffic_secret(server_.get(), &data, &len, 3));
+
+  // Handshake sequence numbers should have incremented.
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(client_.get()), client_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(server_.get()), client_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_write_seq(server_.get()), server_hs_seq + 1);
+  EXPECT_EQ(SSL_get_dtls_handshake_read_seq(client_.get()), server_hs_seq + 1);
+}
+
 TEST_P(SSLVersionTest, OneSidedShutdown) {
   // SSL_shutdown is a no-op in DTLS.
   if (is_dtls()) {
@@ -3545,17 +3793,6 @@
                                   false /* expect session not reused */));
 }
 
-static timeval g_current_time;
-
-static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
-  *out_clock = g_current_time;
-}
-
-static void FrozenTimeCallback(const SSL *ssl, timeval *out_clock) {
-  out_clock->tv_sec = 1000;
-  out_clock->tv_usec = 0;
-}
-
 static int RenewTicketCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
                                EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
                                int encrypt) {
@@ -3590,10 +3827,6 @@
   size_t len = ticket_len - 16 - 16 - SHA256_DIGEST_LENGTH;
   auto plaintext = std::make_unique<uint8_t[]>(len);
 
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  // Fuzzer-mode tickets are unencrypted.
-  OPENSSL_memcpy(plaintext.get(), ciphertext, len);
-#else
   static const uint8_t kZeros[16] = {0};
   const uint8_t *iv = ticket + 16;
   bssl::ScopedEVP_CIPHER_CTX ctx;
@@ -3607,7 +3840,6 @@
   }
 
   len = static_cast<size_t>(len1 + len2);
-#endif
 
   bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
   if (!ssl_ctx) {
@@ -4876,8 +5108,8 @@
 
   ASSERT_TRUE(SSL_CREDENTIAL_set1_private_key(cred.get(), key.get()));
   ASSERT_TRUE(SSL_CREDENTIAL_set1_private_key(cred2.get(), testkey.get()));
-  SSL_CREDENTIAL_set_must_match_issuer(cred.get());
-  SSL_CREDENTIAL_set_must_match_issuer(cred2.get());
+  SSL_CREDENTIAL_set_must_match_issuer(cred.get(), 1);
+  SSL_CREDENTIAL_set_must_match_issuer(cred2.get(), 1);
   ASSERT_TRUE(SSL_CTX_add1_credential(ctx.get(), cred.get()));
   ASSERT_TRUE(SSL_CTX_add1_credential(ctx.get(), cred2.get()));
 
@@ -4951,6 +5183,102 @@
                            {leaf.get(), ca.get()}));
 }
 
+TEST(SSLTest, CredentialCertProperties) {
+  // A CertificatePropertyList containing a trust_anchors property, and an
+  // unknown property 0xbb with 0 bytes of data.
+  bssl::UniquePtr<SSL_CREDENTIAL> cred(SSL_CREDENTIAL_new_x509());
+  ASSERT_TRUE(cred);
+  static const uint8_t kTestProperties1[] = {0x00, 0x0b, 0x00, 0x00, 0x00,
+                                             0x03, 0xba, 0xdb, 0x0b, 0x00,
+                                             0xbb, 0x00, 0x00};
+  bssl::UniquePtr<CRYPTO_BUFFER> pl(
+      CRYPTO_BUFFER_new(kTestProperties1, sizeof(kTestProperties1), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_TRUE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+
+  // A CertificatePropertyList containing a trust_anchors property, and an
+  // unknown property 0xbb with 1 byte of data.
+  static const uint8_t kTestProperties2[] = {0x00, 0x0c, 0x00, 0x00, 0x00,
+                                             0x03, 0xba, 0xdb, 0x0b, 0x00,
+                                             0xbb, 0x00, 0x01, 0xba};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties2, sizeof(kTestProperties2), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_TRUE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+
+  // A CertificatePropertyList containing a trust_anchors property, and an
+  // unknown but malformed property 0xbb with missing data.
+  static const uint8_t kTestProperties3[] = {0x00, 0x09, 0x00, 0x00, 0x00, 0x03,
+                                      0xba, 0xdb, 0x0b, 0x00, 0xbb};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties3, sizeof(kTestProperties3), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_FALSE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_SSL,
+                          SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST));
+
+  // A CertificatePropertyList containing a trust_anchors property, and an
+  // unknown but malformed property 0xbb with incorrect length data.
+  static const uint8_t kTestProperties4[] = {0x00, 0x0c, 0x00, 0x00, 0x00,
+                                             0x03, 0xba, 0xdb, 0x0b, 0x00,
+                                             0xbb, 0x00, 0x03, 0xba};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties4, sizeof(kTestProperties4), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_FALSE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_SSL,
+                          SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST));
+
+  // A CertificatePropertyList containing a trust_anchors property with 0 bytes
+  // of data.
+  static const uint8_t kTestProperties5[] = {0x00, 0x04, 0x00,
+                                             0x00, 0x00, 0x00};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties5, sizeof(kTestProperties5), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_FALSE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_SSL,
+                          SSL_R_INVALID_TRUST_ANCHOR_LIST));
+
+  // A CertificatePropertyList containing a trust_anchors property with extra
+  // data.
+  static const uint8_t kTestProperties6[] = {0x00, 0x08, 0x00, 0x00, 0x00,
+                                             0x03, 0xba, 0xdb, 0x0b, 0xbb};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties6, sizeof(kTestProperties6), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_FALSE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_SSL,
+                          SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST));
+
+  // A CertificatePropertyList containing a trust_anchors property with missing
+  // data.
+  static const uint8_t kTestProperties7[] = {0x00, 0x06, 0x00, 0x00,
+                                             0x00, 0x03, 0xba, 0xdb};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties7, sizeof(kTestProperties7), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_FALSE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+  EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_SSL,
+                          SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST));
+
+  // A CertificatePropertyList containing only a trust_anchors property.
+  static const uint8_t kTestProperties8[] = {0x00, 0x07, 0x00, 0x00, 0x00,
+                                             0x03, 0xba, 0xdb, 0x0b};
+  pl.reset(
+      CRYPTO_BUFFER_new(kTestProperties8, sizeof(kTestProperties8), nullptr));
+  ASSERT_TRUE(pl);
+  EXPECT_TRUE(
+      SSL_CREDENTIAL_set1_certificate_properties(cred.get(), pl.get()));
+}
+
 TEST(SSLTest, SetChainAndKeyCtx) {
   bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_with_buffers_method()));
   ASSERT_TRUE(client_ctx);
@@ -8138,16 +8466,6 @@
 
   // Encrypt a HelloRequest.
   uint8_t in[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  // Fuzzer-mode records are unencrypted.
-  uint8_t record[5 + sizeof(in)];
-  record[0] = SSL3_RT_HANDSHAKE;
-  record[1] = 3;
-  record[2] = 3;  // TLS 1.2
-  record[3] = 0;
-  record[4] = sizeof(record) - 5;
-  memcpy(record + 5, in, sizeof(in));
-#else
   // Extract key material from |server|.
   static const size_t kKeyLen = 32;
   static const size_t kNonceLen = 12;
@@ -8189,7 +8507,6 @@
                                 sizeof(record) - 5, nonce.data(), nonce.size(),
                                 in, sizeof(in), ad, sizeof(ad)));
   ASSERT_EQ(sizeof(record) - 5, len);
-#endif  // BORINGSSL_UNSAFE_FUZZER_MODE
 
   ASSERT_EQ(int(sizeof(record)),
             BIO_write(SSL_get_wbio(server), record, sizeof(record)));
@@ -8585,6 +8902,32 @@
   ASSERT_TRUE(SSL_has_application_settings(client_.get()));
 }
 
+TEST_F(AlpsNewCodepointTest, ClientExplictServerDefault) {
+  SetUpExpectedNewCodePoint(server_ctx_.get());
+
+  ASSERT_TRUE(CreateClientAndServer(&client_, &server_, client_ctx_.get(),
+                                    server_ctx_.get()));
+
+  SSL_set_alps_use_new_codepoint(client_.get(), 1);
+
+  SetUpApplicationSetting();
+  ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+  ASSERT_TRUE(SSL_has_application_settings(client_.get()));
+}
+
+TEST_F(AlpsNewCodepointTest, ClientDefaultServerExplicit) {
+  SetUpExpectedNewCodePoint(server_ctx_.get());
+
+  ASSERT_TRUE(CreateClientAndServer(&client_, &server_, client_ctx_.get(),
+                                    server_ctx_.get()));
+
+  SSL_set_alps_use_new_codepoint(server_.get(), 1);
+
+  SetUpApplicationSetting();
+  ASSERT_TRUE(CompleteHandshakes(client_.get(), server_.get()));
+  ASSERT_TRUE(SSL_has_application_settings(client_.get()));
+}
+
 TEST_F(AlpsNewCodepointTest, Disabled) {
   // Both client and server disable alps new codepoint.
   SetUpExpectedOldCodePoint(server_ctx_.get());
@@ -9595,20 +9938,26 @@
                                         Key("SERVER_HANDSHAKE_TRAFFIC_SECRET"),
                                         Key("SERVER_TRAFFIC_SECRET_0")));
 
-    if (!is_dtls()) {
-      // Ideally we'd check the other values, but those are harder to check
-      // without actually decrypting the records.
-      //
-      // TODO(crbug.com/42290608): Check the secrets in DTLS, once we have an
-      // API for them.
-      Span<const uint8_t> read_secret, write_secret;
+    Span<const uint8_t> read_secret, write_secret;
+    if (is_dtls()) {
+      // The first application data epoch is 3.
+      const uint8_t *data;
+      size_t len;
+      ASSERT_TRUE(SSL_get_dtls_read_traffic_secret(client_.get(), &data, &len,
+                                                   /*epoch=*/3));
+      read_secret = Span(data, len);
+      ASSERT_TRUE(SSL_get_dtls_write_traffic_secret(client_.get(), &data, &len,
+                                                   /*epoch=*/3));
+      write_secret = Span(data, len);
+    } else {
       ASSERT_TRUE(
           SSL_get_traffic_secrets(client_.get(), &read_secret, &write_secret));
-      EXPECT_EQ(Bytes(read_secret),
-                Bytes(client_log["SERVER_TRAFFIC_SECRET_0"]));
-      EXPECT_EQ(Bytes(write_secret),
-                Bytes(client_log["CLIENT_TRAFFIC_SECRET_0"]));
     }
+    // Ideally we'd check the other values, but those are harder to check
+    // without actually decrypting the records.
+    EXPECT_EQ(Bytes(read_secret), Bytes(client_log["SERVER_TRAFFIC_SECRET_0"]));
+    EXPECT_EQ(Bytes(write_secret),
+              Bytes(client_log["CLIENT_TRAFFIC_SECRET_0"]));
   } else {
     EXPECT_THAT(client_log, ElementsAre(Key("CLIENT_RANDOM")));
 
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index 4399db1..9b1f624 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -199,7 +199,7 @@
   return generate_key_block(ssl, Span(out, out_len), SSL_get_session(ssl));
 }
 
-int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
+int SSL_export_keying_material(const SSL *ssl, uint8_t *out, size_t out_len,
                                const char *label, size_t label_len,
                                const uint8_t *context, size_t context_len,
                                int use_context) {
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 0e7068a..c0a30f8 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -57,7 +57,6 @@
 #include <vector>
 
 #include "../../crypto/internal.h"
-#include "../internal.h"
 #include "async_bio.h"
 #include "handshake_util.h"
 #include "mock_quic_transport.h"
@@ -1277,7 +1276,8 @@
     }
 
     if (expect_new_session) {
-      bool got_early_data = test_state->new_session->ticket_max_early_data != 0;
+      bool got_early_data =
+          !!SSL_SESSION_early_data_capable(test_state->new_session.get());
       if (config->expect_ticket_supports_early_data != got_early_data) {
         fprintf(stderr,
                 "new session did%s support early data, but we expected the "
@@ -1285,6 +1285,18 @@
                 got_early_data ? "" : " not");
         return false;
       }
+
+      if (config->expect_resumable_across_names.has_value()) {
+        bool actual = !!SSL_SESSION_is_resumable_across_names(
+            test_state->new_session.get());
+        if (config->expect_resumable_across_names.value() != actual) {
+          fprintf(stderr,
+                  "new session did%s support cross-name resumption, but we "
+                  "expected the opposite\n",
+                  actual ? "" : " not");
+          return false;
+        }
+      }
     }
   }
 
@@ -1311,7 +1323,7 @@
   }
 
   if (SSL_total_renegotiations(ssl) > 0) {
-    if (!SSL_get_session(ssl)->not_resumable) {
+    if (SSL_SESSION_is_resumable(SSL_get_session(ssl))) {
       fprintf(stderr,
               "Renegotiations should never produce resumable sessions.\n");
       return false;
@@ -1401,8 +1413,13 @@
 #endif
   }
 
-  bssl::UniquePtr<SSL_CTX> ssl_ctx;
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+  if (initial_config.fuzzer_mode) {
+    CRYPTO_set_fuzzer_mode(1);
+  }
+#endif
 
+  bssl::UniquePtr<SSL_CTX> ssl_ctx;
   bssl::UniquePtr<SSL_SESSION> session;
   for (int i = 0; i < initial_config.resume_count + 1; i++) {
     bool is_resume = i > 0;
diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h
index d01808f..79217e5 100644
--- a/src/ssl/test/fuzzer.h
+++ b/src/ssl/test/fuzzer.h
@@ -24,6 +24,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bytestring.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/hpke.h>
@@ -35,6 +36,13 @@
 #include "../../crypto/internal.h"
 #include "./fuzzer_tags.h"
 
+#if defined(OPENSSL_WINDOWS)
+// Windows defines struct timeval in winsock2.h.
+#include <winsock2.h>
+#else
+#include <sys/time.h>
+#endif
+
 namespace {
 
 const uint8_t kP256KeyPKCS8[] = {
@@ -275,10 +283,20 @@
     kServer,
   };
 
-  TLSFuzzer(Protocol protocol, Role role)
+  enum FuzzerMode {
+    kFuzzerModeOn,
+    kFuzzerModeOff,
+  };
+
+  TLSFuzzer(Protocol protocol, Role role, FuzzerMode fuzzer_mode)
       : debug_(getenv("BORINGSSL_FUZZER_DEBUG") != nullptr),
         protocol_(protocol),
         role_(role) {
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+    if (fuzzer_mode == kFuzzerModeOn) {
+      CRYPTO_set_fuzzer_mode(1);
+    }
+#endif
     if (!Init()) {
       abort();
     }
@@ -298,7 +316,9 @@
   }
 
   int TestOneInput(const uint8_t *buf, size_t len) {
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
     RAND_reset_for_fuzzing();
+#endif
 
     CBS cbs;
     CBS_init(&cbs, buf, len);
@@ -405,6 +425,12 @@
       return false;
     }
 
+    // Use a constant clock.
+    SSL_CTX_set_current_time_cb(ctx_.get(),
+                                [](const SSL *ssl, timeval *out_clock) {
+                                  *out_clock = {1234, 1234};
+                                });
+
     // When accepting peer certificates, allow any certificate.
     SSL_CTX_set_cert_verify_callback(
         ctx_.get(),
diff --git a/src/ssl/test/handshaker.cc b/src/ssl/test/handshaker.cc
index 5141312..5942666 100644
--- a/src/ssl/test/handshaker.cc
+++ b/src/ssl/test/handshaker.cc
@@ -233,7 +233,10 @@
   }
   const TestConfig *config =
       initial_config.handshaker_resume ? &resume_config : &initial_config;
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+  if (initial_config.fuzzer_mode) {
+    CRYPTO_set_fuzzer_mode(1);
+  }
   if (initial_config.handshaker_resume) {
     // If the PRNG returns exactly the same values when trying to resume then a
     // "random" session ID will happen to exactly match the session ID
@@ -242,7 +245,7 @@
     uint8_t byte;
     RAND_bytes(&byte, 1);
   }
-#endif  // BORINGSSL_UNSAFE_DETERMINISTIC_MODE
+#endif  // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 
   // read() will return the entire message in one go, because it's a datagram
   // socket.
diff --git a/src/ssl/test/packeted_bio.h b/src/ssl/test/packeted_bio.h
index 3591c05..cec7098 100644
--- a/src/ssl/test/packeted_bio.h
+++ b/src/ssl/test/packeted_bio.h
@@ -21,9 +21,7 @@
 #include <openssl/bio.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <sys/time.h>
 #endif
diff --git a/src/ssl/test/runner/basic_tests.go b/src/ssl/test/runner/basic_tests.go
new file mode 100644
index 0000000..08de8fa
--- /dev/null
+++ b/src/ssl/test/runner/basic_tests.go
@@ -0,0 +1,1971 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "strconv"
+
+func addBasicTests() {
+	basicTests := []testCase{
+		{
+			name: "NoFallbackSCSV",
+			config: Config{
+				Bugs: ProtocolBugs{
+					FailIfNotFallbackSCSV: true,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "no fallback SCSV found",
+		},
+		{
+			name: "SendFallbackSCSV",
+			config: Config{
+				Bugs: ProtocolBugs{
+					FailIfNotFallbackSCSV: true,
+				},
+			},
+			flags: []string{"-fallback-scsv"},
+		},
+		{
+			name: "ClientCertificateTypes",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequestClientCert,
+				ClientCertificateTypes: []byte{
+					CertTypeDSSSign,
+					CertTypeRSASign,
+					CertTypeECDSASign,
+				},
+			},
+			flags: []string{
+				"-expect-certificate-types",
+				base64FlagValue([]byte{
+					CertTypeDSSSign,
+					CertTypeRSASign,
+					CertTypeECDSASign,
+				}),
+			},
+		},
+		{
+			name: "CheckClientCertificateTypes",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				ClientAuth:             RequestClientCert,
+				ClientCertificateTypes: []byte{CertTypeECDSASign},
+			},
+			shimCertificate: &rsaCertificate,
+			shouldFail:      true,
+			expectedError:   ":UNKNOWN_CERTIFICATE_TYPE:",
+		},
+		{
+			name: "UnauthenticatedECDH",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					UnauthenticatedECDH: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_MESSAGE:",
+		},
+		{
+			name: "SkipCertificateStatus",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					SkipCertificateStatus: true,
+				},
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				// This test involves an optional message. Test the message callback
+				// trace to ensure we do not miss or double-report any.
+				"-expect-msg-callback",
+				`write hs 1
+read hs 2
+read hs 11
+read hs 12
+read hs 14
+write hs 16
+write ccs
+write hs 20
+read hs 4
+read ccs
+read hs 20
+read alert 1 0
+`,
+			},
+		},
+		{
+			protocol: dtls,
+			name:     "SkipCertificateStatus-DTLS",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					SkipCertificateStatus: true,
+				},
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				// This test involves an optional message. Test the message callback
+				// trace to ensure we do not miss or double-report any.
+				"-expect-msg-callback",
+				`write hs 1
+read hs 3
+write hs 1
+read hs 2
+read hs 11
+read hs 12
+read hs 14
+write hs 16
+write ccs
+write hs 20
+read hs 4
+read ccs
+read hs 20
+read alert 1 0
+`,
+			},
+		},
+		{
+			name: "SkipServerKeyExchange",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					SkipServerKeyExchange: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_MESSAGE:",
+		},
+		{
+			testType: serverTest,
+			name:     "ServerSkipCertificateVerify",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Credential: &rsaCertificate,
+				Bugs: ProtocolBugs{
+					SkipCertificateVerify: true,
+				},
+			},
+			expectations: connectionExpectations{
+				peerCertificate: &rsaCertificate,
+			},
+			flags: []string{
+				"-require-any-client-certificate",
+			},
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_RECORD:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			testType: serverTest,
+			name:     "Alert",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "Alert-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+		},
+		{
+			testType: serverTest,
+			name:     "FragmentAlert",
+			config: Config{
+				Bugs: ProtocolBugs{
+					FragmentAlert:     true,
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_ALERT:",
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "FragmentAlert-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					FragmentAlert:     true,
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_ALERT:",
+		},
+		{
+			testType: serverTest,
+			name:     "DoubleAlert",
+			config: Config{
+				Bugs: ProtocolBugs{
+					DoubleAlert:       true,
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_ALERT:",
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "DoubleAlert-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					DoubleAlert:       true,
+					SendSpuriousAlert: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_ALERT:",
+		},
+		{
+			name: "SkipNewSessionTicket",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SkipNewSessionTicket: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			testType: serverTest,
+			name:     "FallbackSCSV",
+			config: Config{
+				MaxVersion: VersionTLS11,
+				Bugs: ProtocolBugs{
+					SendFallbackSCSV: true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INAPPROPRIATE_FALLBACK:",
+			expectedLocalError: "remote error: inappropriate fallback",
+		},
+		{
+			testType: serverTest,
+			name:     "FallbackSCSV-VersionMatch-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendFallbackSCSV: true,
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			name:     "FallbackSCSV-VersionMatch-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendFallbackSCSV: true,
+				},
+			},
+			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+		},
+		// Regression test for CVE-2014-3511. Even when the ClientHello is
+		// maximally fragmented, version negotiation works correctly.
+		{
+			testType: serverTest,
+			name:     "FragmentedClientVersion",
+			config: Config{
+				Bugs: ProtocolBugs{
+					MaxHandshakeRecordLength: 1,
+				},
+			},
+			expectations: connectionExpectations{
+				version: VersionTLS13,
+			},
+		},
+		{
+			testType:      serverTest,
+			name:          "HttpGET",
+			sendPrefix:    "GET / HTTP/1.0\n",
+			shouldFail:    true,
+			expectedError: ":HTTP_REQUEST:",
+		},
+		{
+			testType:      serverTest,
+			name:          "HttpPOST",
+			sendPrefix:    "POST / HTTP/1.0\n",
+			shouldFail:    true,
+			expectedError: ":HTTP_REQUEST:",
+		},
+		{
+			testType:      serverTest,
+			name:          "HttpHEAD",
+			sendPrefix:    "HEAD / HTTP/1.0\n",
+			shouldFail:    true,
+			expectedError: ":HTTP_REQUEST:",
+		},
+		{
+			testType:      serverTest,
+			name:          "HttpPUT",
+			sendPrefix:    "PUT / HTTP/1.0\n",
+			shouldFail:    true,
+			expectedError: ":HTTP_REQUEST:",
+		},
+		{
+			testType:      serverTest,
+			name:          "HttpCONNECT",
+			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
+			shouldFail:    true,
+			expectedError: ":HTTPS_PROXY_REQUEST:",
+		},
+		{
+			testType:      serverTest,
+			name:          "Garbage",
+			sendPrefix:    "blah",
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		},
+		{
+			name: "RSAEphemeralKey",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+				Bugs: ProtocolBugs{
+					RSAEphemeralKey: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_MESSAGE:",
+		},
+		{
+			name:          "DisableEverything",
+			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
+			shouldFail:    true,
+			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
+		},
+		{
+			protocol:      dtls,
+			name:          "DisableEverything-DTLS",
+			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls1"},
+			shouldFail:    true,
+			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "MTU-DTLS12-AEAD",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					MaxPacketLength: 256,
+				},
+			},
+			flags: []string{"-mtu", "256"},
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "MTU-DTLS12-AES-CBC",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+				Bugs: ProtocolBugs{
+					MaxPacketLength: 256,
+				},
+			},
+			flags: []string{"-mtu", "256"},
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "MTU-DTLS12-3DES-CBC",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+				Bugs: ProtocolBugs{
+					MaxPacketLength: 256,
+				},
+			},
+			flags: []string{"-mtu", "256", "-cipher", "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "MTU-DTLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					MaxPacketLength: 256,
+				},
+			},
+			flags: []string{"-mtu", "256"},
+		},
+		{
+			name: "EmptyCertificateList",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					EmptyCertificateList: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECODE_ERROR:",
+		},
+		{
+			name: "EmptyCertificateList-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					EmptyCertificateList: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+		},
+		{
+			name:             "TLSFatalBadPackets",
+			damageFirstWrite: true,
+			shouldFail:       true,
+			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+		},
+		{
+			protocol:         dtls,
+			name:             "DTLSIgnoreBadPackets",
+			damageFirstWrite: true,
+		},
+		{
+			protocol:         dtls,
+			name:             "DTLSIgnoreBadPackets-Async",
+			damageFirstWrite: true,
+			flags:            []string{"-async"},
+		},
+		{
+			name: "AppDataBeforeHandshake",
+			config: Config{
+				Bugs: ProtocolBugs{
+					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			name: "AppDataBeforeHandshake-Empty",
+			config: Config{
+				Bugs: ProtocolBugs{
+					AppDataBeforeHandshake: []byte{},
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataBeforeHandshake-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataBeforeHandshake-DTLS-Empty",
+			config: Config{
+				Bugs: ProtocolBugs{
+					AppDataBeforeHandshake: []byte{},
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			name: "AppDataBeforeTLS13KeyChange",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"),
+				},
+			},
+			// The shim should fail to decrypt this record.
+			shouldFail:         true,
+			expectedError:      ":BAD_DECRYPT:",
+			expectedLocalError: "remote error: bad record MAC",
+		},
+		{
+			name: "AppDataBeforeTLS13KeyChange-Empty",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AppDataBeforeTLS13KeyChange: []byte{},
+				},
+			},
+			// The shim should fail to decrypt this record.
+			shouldFail:         true,
+			expectedError:      ":BAD_DECRYPT:",
+			expectedLocalError: "remote error: bad record MAC",
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataBeforeTLS13KeyChange-DTLS",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"),
+				},
+			},
+			// The shim will decrypt the record, because it has not
+			// yet applied the key change, but it should know to
+			// reject the record.
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_RECORD:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataBeforeTLS13KeyChange-DTLS-Empty",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AppDataBeforeTLS13KeyChange: []byte{},
+				},
+			},
+			// The shim will decrypt the record, because it has not
+			// yet applied the key change, but it should know to
+			// reject the record.
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_RECORD:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			name: "UnencryptedEncryptedExtensions",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					UnencryptedEncryptedExtensions: true,
+				},
+			},
+			// The shim should fail to decrypt this record.
+			shouldFail:         true,
+			expectedError:      ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+			expectedLocalError: "remote error: bad record MAC",
+		},
+		{
+			protocol: dtls,
+			name:     "UnencryptedEncryptedExtensions-DTLS",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					UnencryptedEncryptedExtensions: true,
+				},
+			},
+			// The shim will decrypt the record, because it has not
+			// yet applied the key change, but it should know to
+			// reject new handshake data on the previous epoch.
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			name: "AppDataAfterChangeCipherSpec",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			name: "AppDataAfterChangeCipherSpec-Empty",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AppDataAfterChangeCipherSpec: []byte{},
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataAfterChangeCipherSpec-DTLS",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+				},
+			},
+			// BoringSSL's DTLS implementation will drop the out-of-order
+			// application data.
+		},
+		{
+			protocol: dtls,
+			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AppDataAfterChangeCipherSpec: []byte{},
+				},
+			},
+			// BoringSSL's DTLS implementation will drop the out-of-order
+			// application data.
+		},
+		{
+			name: "AlertAfterChangeCipherSpec",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AlertAfterChangeCipherSpec: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+		},
+		{
+			protocol: dtls,
+			name:     "AlertAfterChangeCipherSpec-DTLS",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					AlertAfterChangeCipherSpec: alertRecordOverflow,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+		},
+		{
+			name: "SendInvalidRecordType",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendInvalidRecordType: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "SendInvalidRecordType-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendInvalidRecordType: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			name: "FalseStart-SkipServerSecondLeg",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					SkipNewSessionTicket: true,
+					SkipChangeCipherSpec: true,
+					SkipFinished:         true,
+					ExpectFalseStart:     true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-handshake-never-done",
+				"-advertise-alpn", "\x03foo",
+				"-expect-alpn", "foo",
+			},
+			shimWritesFirst: true,
+			shouldFail:      true,
+			expectedError:   ":UNEXPECTED_RECORD:",
+		},
+		{
+			name: "FalseStart-SkipServerSecondLeg-Implicit",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					SkipNewSessionTicket: true,
+					SkipChangeCipherSpec: true,
+					SkipFinished:         true,
+				},
+			},
+			flags: []string{
+				"-implicit-handshake",
+				"-false-start",
+				"-handshake-never-done",
+				"-advertise-alpn", "\x03foo",
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			testType:           serverTest,
+			name:               "FailEarlyCallback",
+			flags:              []string{"-fail-early-callback"},
+			shouldFail:         true,
+			expectedError:      ":CONNECTION_REJECTED:",
+			expectedLocalError: "remote error: handshake failure",
+		},
+		{
+			name: "FailCertCallback-Client-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequestClientCert,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			testType: serverTest,
+			name:     "FailCertCallback-Server-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			name: "FailCertCallback-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				ClientAuth: RequestClientCert,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			testType: serverTest,
+			name:     "FailCertCallback-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			protocol: dtls,
+			name:     "FragmentMessageTypeMismatch-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+						f1 := next[0].Fragment(0, 1)
+						f2 := next[0].Fragment(1, 1)
+						f2.Type++
+						c.WriteFragments([]DTLSFragment{f1, f2})
+					},
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":FRAGMENT_MISMATCH:",
+		},
+		{
+			protocol: dtls,
+			name:     "FragmentMessageLengthMismatch-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+						f1 := next[0].Fragment(0, 1)
+						f2 := next[0].Fragment(1, 1)
+						f2.TotalLength++
+						c.WriteFragments([]DTLSFragment{f1, f2})
+					},
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":FRAGMENT_MISMATCH:",
+		},
+		{
+			protocol: dtls,
+			name:     "SplitFragments-Header-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SplitFragments: 2,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "SplitFragments-Boundary-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SplitFragments: dtlsMaxRecordHeaderLen,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "SplitFragments-Body-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SplitFragments: dtlsMaxRecordHeaderLen + 1,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "SendEmptyFragments-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendEmptyFragments: true,
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			protocol: dtls,
+			name:     "SendEmptyFragments-Padded-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					// Test empty fragments for a message with a
+					// nice power-of-two length.
+					PadClientHello:     64,
+					SendEmptyFragments: true,
+				},
+			},
+		},
+		{
+			name: "BadFinished-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					BadFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			name: "BadFinished-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					BadFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			testType: serverTest,
+			name:     "BadFinished-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					BadFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			testType: serverTest,
+			name:     "BadFinished-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					BadFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			name: "FalseStart-BadFinished",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					BadFinished:      true,
+					ExpectFalseStart: true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-handshake-never-done",
+				"-advertise-alpn", "\x03foo",
+				"-expect-alpn", "foo",
+			},
+			shimWritesFirst: true,
+			shouldFail:      true,
+			expectedError:   ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			name: "NoFalseStart-NoALPN",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart:          true,
+					AlertBeforeFalseStartTest: alertAccessDenied,
+				},
+			},
+			flags: []string{
+				"-false-start",
+			},
+			shimWritesFirst:    true,
+			shouldFail:         true,
+			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+			expectedLocalError: "tls: peer did not false start: EOF",
+		},
+		{
+			name: "FalseStart-NoALPNAllowed",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart: true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-allow-false-start-without-alpn",
+			},
+			shimWritesFirst: true,
+		},
+		{
+			name: "NoFalseStart-NoAEAD",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart:          true,
+					AlertBeforeFalseStartTest: alertAccessDenied,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-advertise-alpn", "\x03foo",
+			},
+			shimWritesFirst:    true,
+			shouldFail:         true,
+			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+			expectedLocalError: "tls: peer did not false start: EOF",
+		},
+		{
+			name: "NoFalseStart-RSA",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart:          true,
+					AlertBeforeFalseStartTest: alertAccessDenied,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-advertise-alpn", "\x03foo",
+			},
+			shimWritesFirst:    true,
+			shouldFail:         true,
+			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+			expectedLocalError: "tls: peer did not false start: EOF",
+		},
+		{
+			protocol: dtls,
+			name:     "SendSplitAlert-Sync",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendSplitAlert: true,
+				},
+			},
+		},
+		{
+			protocol: dtls,
+			name:     "SendSplitAlert-Async",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendSplitAlert: true,
+				},
+			},
+			flags: []string{"-async"},
+		},
+		{
+			name:             "SendEmptyRecords-Pass",
+			sendEmptyRecords: 32,
+		},
+		{
+			name:             "SendEmptyRecords",
+			sendEmptyRecords: 33,
+			shouldFail:       true,
+			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
+		},
+		{
+			name:             "SendEmptyRecords-Async",
+			sendEmptyRecords: 33,
+			flags:            []string{"-async"},
+			shouldFail:       true,
+			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
+		},
+		{
+			name: "SendWarningAlerts-Pass",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			sendWarningAlerts: 4,
+		},
+		{
+			protocol: dtls,
+			name:     "SendWarningAlerts-DTLS-Pass",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			sendWarningAlerts: 4,
+		},
+		{
+			name: "SendWarningAlerts-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendWarningAlerts:  4,
+			shouldFail:         true,
+			expectedError:      ":BAD_ALERT:",
+			expectedLocalError: "remote error: error decoding message",
+		},
+		// Although TLS 1.3 intended to remove warning alerts, it left in
+		// user_canceled. JDK11 misuses this alert as a post-handshake
+		// full-duplex signal. As a workaround, skip user_canceled as in
+		// TLS 1.2, which is consistent with NSS and OpenSSL.
+		{
+			name: "SendUserCanceledAlerts-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendUserCanceledAlerts: 4,
+		},
+		{
+			name: "SendUserCanceledAlerts-TooMany-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendUserCanceledAlerts: 5,
+			shouldFail:             true,
+			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
+		},
+		{
+			name: "SendWarningAlerts-TooMany",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			sendWarningAlerts: 5,
+			shouldFail:        true,
+			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
+		},
+		{
+			name: "SendWarningAlerts-TooMany-Async",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			sendWarningAlerts: 5,
+			flags:             []string{"-async"},
+			shouldFail:        true,
+			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
+		},
+		{
+			name:               "SendBogusAlertType",
+			sendBogusAlertType: true,
+			shouldFail:         true,
+			expectedError:      ":UNKNOWN_ALERT_TYPE:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			protocol:           dtls,
+			name:               "SendBogusAlertType-DTLS",
+			sendBogusAlertType: true,
+			shouldFail:         true,
+			expectedError:      ":UNKNOWN_ALERT_TYPE:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			name: "TooManyKeyUpdates",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   33,
+			keyUpdateRequest: keyUpdateNotRequested,
+			shouldFail:       true,
+			expectedError:    ":TOO_MANY_KEY_UPDATES:",
+		},
+		{
+			name: "EmptySessionID",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+			noSessionCache: true,
+			flags:          []string{"-expect-no-session"},
+		},
+		{
+			name: "Unclean-Shutdown",
+			config: Config{
+				Bugs: ProtocolBugs{
+					NoCloseNotify:     true,
+					ExpectCloseNotify: true,
+				},
+			},
+			shimShutsDown: true,
+			flags:         []string{"-check-close-notify"},
+			shouldFail:    true,
+			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
+		},
+		{
+			name: "Unclean-Shutdown-Ignored",
+			config: Config{
+				Bugs: ProtocolBugs{
+					NoCloseNotify: true,
+				},
+			},
+			shimShutsDown: true,
+		},
+		{
+			name: "Unclean-Shutdown-Alert",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendAlertOnShutdown: alertDecompressionFailure,
+					ExpectCloseNotify:   true,
+				},
+			},
+			shimShutsDown: true,
+			flags:         []string{"-check-close-notify"},
+			shouldFail:    true,
+			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
+		},
+		{
+			name: "LargePlaintext",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendLargeRecords: true,
+				},
+			},
+			messageLen:         maxPlaintext + 1,
+			shouldFail:         true,
+			expectedError:      ":DATA_LENGTH_TOO_LONG:",
+			expectedLocalError: "remote error: record overflow",
+		},
+		{
+			protocol: dtls,
+			name:     "LargePlaintext-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendLargeRecords: true,
+				},
+			},
+			messageLen:         maxPlaintext + 1,
+			shouldFail:         true,
+			expectedError:      ":DATA_LENGTH_TOO_LONG:",
+			expectedLocalError: "remote error: record overflow",
+		},
+		{
+			name: "LargePlaintext-TLS13-Padded-8192-8192",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					RecordPadding:    8192,
+					SendLargeRecords: true,
+				},
+			},
+			messageLen: 8192,
+		},
+		{
+			name: "LargePlaintext-TLS13-Padded-8193-8192",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					RecordPadding:    8193,
+					SendLargeRecords: true,
+				},
+			},
+			messageLen:         8192,
+			shouldFail:         true,
+			expectedError:      ":DATA_LENGTH_TOO_LONG:",
+			expectedLocalError: "remote error: record overflow",
+		},
+		{
+			name: "LargePlaintext-TLS13-Padded-16383-1",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					RecordPadding:    1,
+					SendLargeRecords: true,
+				},
+			},
+			messageLen: 16383,
+		},
+		{
+			name: "LargePlaintext-TLS13-Padded-16384-1",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					RecordPadding:    1,
+					SendLargeRecords: true,
+				},
+			},
+			messageLen:         16384,
+			shouldFail:         true,
+			expectedError:      ":DATA_LENGTH_TOO_LONG:",
+			expectedLocalError: "remote error: record overflow",
+		},
+		{
+			name: "LargeCiphertext",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendLargeRecords: true,
+				},
+			},
+			messageLen:    maxPlaintext * 2,
+			shouldFail:    true,
+			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
+		},
+		{
+			protocol: dtls,
+			name:     "LargeCiphertext-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendLargeRecords: true,
+				},
+			},
+			messageLen: maxPlaintext * 2,
+			// Unlike the other four cases, DTLS drops records which
+			// are invalid before authentication, so the connection
+			// does not fail.
+			expectMessageDropped: true,
+		},
+		{
+			name:        "BadHelloRequest-1",
+			renegotiate: 1,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
+				},
+			},
+			flags: []string{
+				"-renegotiate-freely",
+				"-expect-total-renegotiations", "1",
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_HELLO_REQUEST:",
+		},
+		{
+			name:        "BadHelloRequest-2",
+			renegotiate: 1,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
+				},
+			},
+			flags: []string{
+				"-renegotiate-freely",
+				"-expect-total-renegotiations", "1",
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_HELLO_REQUEST:",
+		},
+		{
+			testType: serverTest,
+			name:     "SupportTicketsWithSessionID",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS12-SendExtraFinished",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendExtraFinished: true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_RECORD:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS12-SendExtraFinished-Reordered",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					MaxHandshakeRecordLength:  2,
+					ReorderHandshakeFragments: true,
+					SendExtraFinished:         true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS12-SendExtraFinished-Packed",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendExtraFinished:      true,
+					PackHandshakeFragments: 1000,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS13-SendExtraFinished",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendExtraFinished: true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS13-SendExtraFinished-Reordered",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					MaxHandshakeRecordLength:  2,
+					ReorderHandshakeFragments: true,
+					SendExtraFinished:         true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS13-SendExtraFinished-Packed",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendExtraFinished:      true,
+					PackHandshakeFragments: 1000,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+		},
+		{
+			protocol: dtls,
+			testType: serverTest,
+			name:     "DTLS13-SendExtraFinished-AfterAppData",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SkipImplicitACKRead: true,
+					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+						if next[len(next)-1].Type != typeFinished {
+							c.WriteFlight(next)
+							return
+						}
+
+						// Complete the handshake.
+						c.WriteFlight(next)
+						c.ReadACK(c.InEpoch())
+
+						// Send some application data. The shim is now on epoch 3.
+						msg := []byte("hello")
+						c.WriteAppData(c.OutEpoch(), msg)
+						c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+						// The shim is still accepting data from epoch 2, so it can
+						// ACK a retransmit if needed, but it should not accept new
+						// messages at epoch three.
+						extraFinished := next[len(next)-1]
+						extraFinished.Sequence++
+						c.WriteFlight([]DTLSMessage{extraFinished})
+					},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+			expectedLocalError: "remote error: unexpected message",
+			// Disable tickets on the shim to avoid NewSessionTicket
+			// interfering with the test callback.
+			flags: []string{"-no-ticket"},
+		},
+		{
+			testType: serverTest,
+			name:     "V2ClientHello-EmptyRecordPrefix",
+			config: Config{
+				// Choose a cipher suite that does not involve
+				// elliptic curves, so no extensions are
+				// involved.
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+				Bugs: ProtocolBugs{
+					SendV2ClientHello: true,
+				},
+			},
+			sendPrefix: string([]byte{
+				byte(recordTypeHandshake),
+				3, 1, // version
+				0, 0, // length
+			}),
+			// A no-op empty record may not be sent before V2ClientHello.
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		},
+		{
+			testType: serverTest,
+			name:     "V2ClientHello-WarningAlertPrefix",
+			config: Config{
+				// Choose a cipher suite that does not involve
+				// elliptic curves, so no extensions are
+				// involved.
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+				Bugs: ProtocolBugs{
+					SendV2ClientHello: true,
+				},
+			},
+			sendPrefix: string([]byte{
+				byte(recordTypeAlert),
+				3, 1, // version
+				0, 2, // length
+				alertLevelWarning, byte(alertDecompressionFailure),
+			}),
+			// A no-op warning alert may not be sent before V2ClientHello.
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		},
+		{
+			name: "SendSNIWarningAlert",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendSNIWarningAlert: true,
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			name:     "ExtraCompressionMethods-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			name:     "ExtraCompressionMethods-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			testType: serverTest,
+			name:     "NoNullCompression-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			testType: serverTest,
+			name:     "NoNullCompression-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		// Test that the client rejects invalid compression methods
+		// from the server.
+		{
+			testType: clientTest,
+			name:     "InvalidCompressionMethod",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCompressionMethod: 1,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			testType: clientTest,
+			name:     "TLS13-InvalidCompressionMethod",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendCompressionMethod: 1,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECODE_ERROR:",
+		},
+		{
+			testType: clientTest,
+			name:     "TLS13-HRR-InvalidCompressionMethod",
+			config: Config{
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					SendCompressionMethod: 1,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":DECODE_ERROR:",
+			expectedLocalError: "remote error: error decoding message",
+		},
+		{
+			name: "GREASE-Client-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{"-enable-grease"},
+		},
+		{
+			name: "GREASE-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{"-enable-grease"},
+		},
+		{
+			testType: serverTest,
+			name:     "GREASE-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					// TLS 1.3 servers are expected to
+					// always enable GREASE. TLS 1.3 is new,
+					// so there is no existing ecosystem to
+					// worry about.
+					ExpectGREASE: true,
+				},
+			},
+		},
+		{
+			// Test the TLS 1.2 server so there is a large
+			// unencrypted certificate as well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					MaxReceivePlaintext: 512,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+		},
+		{
+			// Test the TLS 1.2 server so there is a large
+			// unencrypted certificate as well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment-TLS12-TooLarge",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					// Ensure that some of the records are
+					// 512.
+					MaxReceivePlaintext: 511,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+			shouldFail:         true,
+			expectedLocalError: "local error: record overflow",
+		},
+		{
+			// Test the TLS 1.3 server so there is a large encrypted
+			// certificate as well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					MaxReceivePlaintext:            512,
+					ExpectPackedEncryptedHandshake: 512,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+		},
+		{
+			// Test the TLS 1.3 server so there is a large encrypted
+			// certificate as well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment-TLS13-TooLarge",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					// Ensure that some of the records are
+					// 512.
+					MaxReceivePlaintext: 511,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+			shouldFail:         true,
+			expectedLocalError: "local error: record overflow",
+		},
+		{
+			// Test that handshake data is tightly packed in TLS 1.3.
+			testType: serverTest,
+			name:     "PackedEncryptedHandshake-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectPackedEncryptedHandshake: 16384,
+				},
+			},
+		},
+		{
+			// Test that DTLS can handle multiple application data
+			// records in a single packet.
+			protocol: dtls,
+			name:     "SplitAndPackAppData-DTLS",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SplitAndPackAppData: true,
+				},
+			},
+		},
+		{
+			protocol: dtls,
+			name:     "SplitAndPackAppData-DTLS-Async",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SplitAndPackAppData: true,
+				},
+			},
+			flags: []string{"-async"},
+		},
+		{
+			// DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which
+			// is the largest encodable value.
+			protocol: dtls,
+			name:     "DTLS-HelloVerifyRequest-255",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					HelloVerifyRequestCookieLength: 255,
+				},
+			},
+		},
+		{
+			// DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which
+			// was probably a mistake in the spec but test that it works
+			// nonetheless.
+			protocol: dtls,
+			name:     "DTLS-HelloVerifyRequest-0",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					EmptyHelloVerifyRequestCookie: true,
+				},
+			},
+		},
+	}
+	testCases = append(testCases, basicTests...)
+
+	// Test that very large messages can be received.
+	cert := rsaCertificate
+	for i := 0; i < 50; i++ {
+		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
+	}
+	testCases = append(testCases, testCase{
+		name: "LargeMessage",
+		config: Config{
+			Credential: &cert,
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "LargeMessage-DTLS",
+		config: Config{
+			Credential: &cert,
+		},
+	})
+
+	// They are rejected if the maximum certificate chain length is capped.
+	testCases = append(testCases, testCase{
+		name: "LargeMessage-Reject",
+		config: Config{
+			Credential: &cert,
+		},
+		flags:         []string{"-max-cert-list", "16384"},
+		shouldFail:    true,
+		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "LargeMessage-Reject-DTLS",
+		config: Config{
+			Credential: &cert,
+		},
+		flags:         []string{"-max-cert-list", "16384"},
+		shouldFail:    true,
+		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+	})
+
+	// Servers echoing the TLS 1.3 compatibility mode session ID should be
+	// rejected.
+	testCases = append(testCases, testCase{
+		name: "EchoTLS13CompatibilitySessionID",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EchoSessionIDInFullHandshake: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	// Servers should reject QUIC client hellos that have a legacy
+	// session ID.
+	testCases = append(testCases, testCase{
+		name:     "QUICCompatibilityMode",
+		testType: serverTest,
+		protocol: quic,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CompatModeWithQUIC: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
+	})
+
+	// Clients should reject DTLS 1.3 ServerHellos that echo the legacy
+	// session ID.
+	testCases = append(testCases, testCase{
+		protocol:      dtls,
+		name:          "DTLS13CompatibilityMode-EchoSessionID",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeConfig: &Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				DTLS13EchoSessionID: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	// DTLS 1.3 should work with record headers that don't set the
+	// length bit or that use the short sequence number format.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-NoLength-Client",
+		config: Config{
+			MinVersion:                 VersionTLS13,
+			DTLSRecordHeaderOmitLength: true,
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-NoLength-Server",
+		config: Config{
+			MinVersion:                 VersionTLS13,
+			DTLSRecordHeaderOmitLength: true,
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-ShortSeqNums-Client",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			DTLSUseShortSeqNums: true,
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-ShortSeqNums-Server",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			DTLSUseShortSeqNums: true,
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-OldHeader",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				DTLSUsePlaintextRecordHeader: true,
+			},
+		},
+		expectMessageDropped: true,
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "DTLS13RecordHeader-CIDBit",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				DTLS13RecordHeaderSetCIDBit: true,
+			},
+		},
+		expectMessageDropped: true,
+	})
+
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "DTLS13-MessageCallback-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-expect-msg-callback",
+			`write hs 1
+read hs 2
+read hs 8
+read hs 11
+read hs 15
+read hs 20
+write hs 20
+read ack
+read hs 4
+read hs 4
+read alert 1 0
+`,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "DTLS13-MessageCallback-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-expect-msg-callback",
+			`read hs 1
+write hs 2
+write hs 8
+write hs 11
+write hs 15
+write hs 20
+read hs 20
+write ack
+write hs 4
+write hs 4
+read ack
+read ack
+read alert 1 0
+`,
+		},
+	})
+}
diff --git a/src/ssl/test/runner/cbc_tests.go b/src/ssl/test/runner/cbc_tests.go
new file mode 100644
index 0000000..6f49d12
--- /dev/null
+++ b/src/ssl/test/runner/cbc_tests.go
@@ -0,0 +1,110 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addCBCPaddingTests() {
+	testCases = append(testCases, testCase{
+		name: "MaxCBCPadding",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				MaxPadding: true,
+			},
+		},
+		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
+	})
+	testCases = append(testCases, testCase{
+		name: "BadCBCPadding",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				PaddingFirstByteBad: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+	// OpenSSL previously had an issue where the first byte of padding in
+	// 255 bytes of padding wasn't checked.
+	testCases = append(testCases, testCase{
+		name: "BadCBCPadding255",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				MaxPadding:               true,
+				PaddingFirstByteBadIf255: true,
+			},
+		},
+		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+}
+
+func addCBCSplittingTests() {
+	cbcCiphers := []struct {
+		name   string
+		cipher uint16
+	}{
+		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+	}
+	for _, t := range cbcCiphers {
+		testCases = append(testCases, testCase{
+			name: "CBCRecordSplitting-" + t.name,
+			config: Config{
+				MaxVersion:   VersionTLS10,
+				MinVersion:   VersionTLS10,
+				CipherSuites: []uint16{t.cipher},
+				Bugs: ProtocolBugs{
+					ExpectRecordSplitting: true,
+				},
+			},
+			messageLen:    -1, // read until EOF
+			resumeSession: true,
+			flags: []string{
+				"-async",
+				"-write-different-record-sizes",
+				"-cbc-record-splitting",
+				// BoringSSL disables 3DES by default.
+				"-cipher", "ALL:3DES",
+			},
+		})
+		testCases = append(testCases, testCase{
+			name: "CBCRecordSplittingPartialWrite-" + t.name,
+			config: Config{
+				MaxVersion:   VersionTLS10,
+				MinVersion:   VersionTLS10,
+				CipherSuites: []uint16{t.cipher},
+				Bugs: ProtocolBugs{
+					ExpectRecordSplitting: true,
+				},
+			},
+			messageLen: -1, // read until EOF
+			flags: []string{
+				"-async",
+				"-write-different-record-sizes",
+				"-cbc-record-splitting",
+				"-partial-write",
+				// BoringSSL disables 3DES by default.
+				"-cipher", "ALL:3DES",
+			},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/cert_compression_tests.go b/src/ssl/test/runner/cert_compression_tests.go
new file mode 100644
index 0000000..e74dedc
--- /dev/null
+++ b/src/ssl/test/runner/cert_compression_tests.go
@@ -0,0 +1,323 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"bytes"
+	"crypto/rand"
+	"fmt"
+	"strconv"
+)
+
+const (
+	shrinkingCompressionAlgID = 0xff01
+	expandingCompressionAlgID = 0xff02
+	randomCompressionAlgID    = 0xff03
+)
+
+var (
+	// shrinkingPrefix is the first two bytes of a Certificate message.
+	shrinkingPrefix = []byte{0, 0}
+	// expandingPrefix is just some arbitrary byte string. This has to match the
+	// value in the shim.
+	expandingPrefix = []byte{1, 2, 3, 4}
+)
+
+var shrinkingCompression = CertCompressionAlg{
+	Compress: func(uncompressed []byte) []byte {
+		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
+			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
+		}
+		return uncompressed[len(shrinkingPrefix):]
+	},
+	Decompress: func(out []byte, compressed []byte) bool {
+		if len(out) != len(shrinkingPrefix)+len(compressed) {
+			return false
+		}
+
+		copy(out, shrinkingPrefix)
+		copy(out[len(shrinkingPrefix):], compressed)
+		return true
+	},
+}
+
+var expandingCompression = CertCompressionAlg{
+	Compress: func(uncompressed []byte) []byte {
+		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
+		ret = append(ret, expandingPrefix...)
+		return append(ret, uncompressed...)
+	},
+	Decompress: func(out []byte, compressed []byte) bool {
+		if !bytes.HasPrefix(compressed, expandingPrefix) {
+			return false
+		}
+		copy(out, compressed[len(expandingPrefix):])
+		return true
+	},
+}
+
+var randomCompression = CertCompressionAlg{
+	Compress: func(uncompressed []byte) []byte {
+		ret := make([]byte, 1+len(uncompressed))
+		if _, err := rand.Read(ret[:1]); err != nil {
+			panic(err)
+		}
+		copy(ret[1:], uncompressed)
+		return ret
+	},
+	Decompress: func(out []byte, compressed []byte) bool {
+		if len(compressed) != 1+len(out) {
+			return false
+		}
+		copy(out, compressed[1:])
+		return true
+	},
+}
+
+func addCertCompressionTests() {
+	for _, ver := range tlsVersions {
+		if ver.version < VersionTLS12 {
+			continue
+		}
+
+		// Duplicate compression algorithms is an error, even if nothing is
+		// configured.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "DuplicateCertCompressionExt-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					DuplicateCompressedCertAlgs: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":ERROR_PARSING_EXTENSION:",
+		})
+
+		// With compression algorithms configured, an duplicate values should still
+		// be an error.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "DuplicateCertCompressionExt2-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					DuplicateCompressedCertAlgs: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":ERROR_PARSING_EXTENSION:",
+		})
+
+		if ver.version < VersionTLS13 {
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "CertCompressionIgnoredBefore13-" + ver.name,
+				flags:    []string{"-install-cert-compression-algs"},
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					CertCompressionAlgs: map[uint16]CertCompressionAlg{
+						expandingCompressionAlgID: expandingCompression,
+					},
+				},
+			})
+
+			continue
+		}
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CertCompressionExpands-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					expandingCompressionAlgID: expandingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: expandingCompressionAlgID,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CertCompressionShrinks-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: shrinkingCompressionAlgID,
+				},
+			},
+		})
+
+		// Test that the shim behaves consistently if the compression function
+		// is non-deterministic. This is intended to model version differences
+		// between the shim and handshaker with handshake hints, but it is also
+		// useful in confirming we only call the callbacks once.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CertCompressionRandom-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					randomCompressionAlgID: randomCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: randomCompressionAlgID,
+				},
+			},
+		})
+
+		// With both algorithms configured, the server should pick its most
+		// preferable. (Which is expandingCompressionAlgID.)
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CertCompressionPriority-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+					expandingCompressionAlgID: expandingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: expandingCompressionAlgID,
+				},
+			},
+		})
+
+		// With no common algorithms configured, the server should decline
+		// compression.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CertCompressionNoCommonAlgs-" + ver.name,
+			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					expandingCompressionAlgID: expandingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectUncompressedCert: true,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "CertCompressionExpandsClient-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					expandingCompressionAlgID: expandingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: expandingCompressionAlgID,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "CertCompressionShrinksClient-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: shrinkingCompressionAlgID,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "CertCompressionBadAlgIDClient-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert:   shrinkingCompressionAlgID,
+					SendCertCompressionAlgID: 1234,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "CertCompressionTooSmallClient-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert:     shrinkingCompressionAlgID,
+					SendCertUncompressedLength: 12,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":CERT_DECOMPRESSION_FAILED:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "CertCompressionTooLargeClient-" + ver.name,
+			flags:    []string{"-install-cert-compression-algs"},
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert:     shrinkingCompressionAlgID,
+					SendCertUncompressedLength: 1 << 20,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
+		})
+	}
+}
diff --git a/src/ssl/test/runner/certificate_selection_tests.go b/src/ssl/test/runner/certificate_selection_tests.go
new file mode 100644
index 0000000..ea64ae9
--- /dev/null
+++ b/src/ssl/test/runner/certificate_selection_tests.go
@@ -0,0 +1,688 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"strconv"
+)
+
+func canBeShimCertificate(c *Credential) bool {
+	// Some options can only be set with the credentials API.
+	return c.Type == CredentialTypeX509 && !c.MustMatchIssuer && c.TrustAnchorID == nil
+}
+
+func addCertificateSelectionTests() {
+	// Combinatorially test each selection criteria at different versions,
+	// protocols, and with the matching certificate before and after the
+	// mismatching one.
+	type certSelectTest struct {
+		name          string
+		testType      testType
+		minVersion    uint16
+		maxVersion    uint16
+		config        Config
+		match         *Credential
+		mismatch      *Credential
+		flags         []string
+		expectedError string
+	}
+	certSelectTests := []certSelectTest{
+		// TLS 1.0 through TLS 1.2 servers should incorporate TLS cipher suites
+		// into certificate selection.
+		{
+			name:       "Server-CipherSuite-ECDHE_ECDSA",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+		{
+			name:       "Server-CipherSuite-ECDHE_RSA",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &rsaCertificate,
+			mismatch:      &ecdsaP256Certificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+		{
+			name:       "Server-CipherSuite-RSA",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &rsaCertificate,
+			mismatch:      &ecdsaP256Certificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+
+		// Ed25519 counts as ECDSA for purposes of cipher suite matching.
+		{
+			name:       "Server-CipherSuite-ECDHE_ECDSA-Ed25519",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &ed25519Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+		{
+			name:       "Server-CipherSuite-ECDHE_RSA-Ed25519",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &rsaCertificate,
+			mismatch:      &ed25519Certificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+
+		// If there is no ECDHE curve match, ECDHE cipher suites are
+		// disqualified in TLS 1.2 and below. This, in turn, impacts the
+		// available cipher suites for each credential.
+		{
+			name:       "Server-CipherSuite-NoECDHE",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CurvePreferences: []CurveID{CurveP256},
+			},
+			flags:         []string{"-curves", strconv.Itoa(int(CurveX25519))},
+			match:         &rsaCertificate,
+			mismatch:      &ecdsaP256Certificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+
+		// If the client offered a cipher that would allow a certificate, but it
+		// wasn't one of the ones we configured, the certificate should be
+		// skipped in favor of another one.
+		{
+			name:       "Server-CipherSuite-Prefs",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CipherSuites: []uint16{
+					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			flags:         []string{"-cipher", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
+			match:         &rsaCertificate,
+			mismatch:      &ecdsaP256Certificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+
+		// TLS 1.0 through 1.2 servers should incorporate the curve list into
+		// ECDSA certificate selection.
+		{
+			name:       "Server-Curve",
+			testType:   serverTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				CurvePreferences: []CurveID{CurveP256},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &ecdsaP384Certificate,
+			expectedError: ":WRONG_CURVE:",
+		},
+
+		// TLS 1.3 servers ignore the curve list. ECDSA certificate selection is
+		// solely determined by the signature algorithm list.
+		{
+			name:       "Server-IgnoreCurve",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				CurvePreferences: []CurveID{CurveP256},
+			},
+			match: &ecdsaP384Certificate,
+		},
+
+		// TLS 1.2 servers also ignore the curve list for Ed25519. The signature
+		// algorithm list is sufficient for Ed25519.
+		{
+			name:       "Server-IgnoreCurveEd25519",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			config: Config{
+				CurvePreferences: []CurveID{CurveP256},
+			},
+			match: &ed25519Certificate,
+		},
+
+		// Without signature algorithm negotiation, Ed25519 is not usable in TLS
+		// 1.1 and below.
+		{
+			name:       "Server-NoEd25519",
+			testType:   serverTest,
+			maxVersion: VersionTLS11,
+			match:      &rsaCertificate,
+			mismatch:   &ed25519Certificate,
+		},
+
+		// TLS 1.2 and up should incorporate the signature algorithm list into
+		// certificate selection.
+		{
+			name:       "Server-SignatureAlgorithm",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+				CipherSuites: []uint16{
+					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+		{
+			name:       "Server-SignatureAlgorithm",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// TLS 1.2's use of the signature algorithm list only disables the
+		// signing-based algorithms. If an RSA key exchange cipher suite is
+		// eligible, that is fine. (This is not a realistic configuration,
+		// however. No one would configure RSA before ECDSA.)
+		{
+			name:       "Server-SignatureAlgorithmImpactsECDHEOnly",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+				CipherSuites: []uint16{
+					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+					TLS_RSA_WITH_AES_128_CBC_SHA,
+				},
+			},
+			match: &rsaCertificate,
+		},
+
+		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
+		// embedded in the signature algorithm.
+		{
+			name:       "Server-SignatureAlgorithmECDSACurve",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &ecdsaP384Certificate,
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// TLS 1.2's use does not.
+		{
+			name:       "Server-SignatureAlgorithmECDSACurve",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match: &ecdsaP384Certificate,
+		},
+
+		// TLS 1.0 and 1.1 do not look at the signature algorithm.
+		{
+			name:       "Server-IgnoreSignatureAlgorithm",
+			testType:   serverTest,
+			maxVersion: VersionTLS11,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match: &rsaCertificate,
+		},
+
+		// Signature algorithm matches take preferences on the keys into
+		// consideration.
+		{
+			name:       "Server-SignatureAlgorithmKeyPrefs",
+			testType:   serverTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
+				CipherSuites:              []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			},
+			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
+			expectedError: ":NO_SHARED_CIPHER:",
+		},
+		{
+			name:       "Server-SignatureAlgorithmKeyPrefs",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
+			},
+			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// TLS 1.2 clients and below check the certificate against the old
+		// client certificate types field.
+		{
+			name:       "Client-ClientCertificateTypes-RSA",
+			testType:   clientTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:             RequestClientCert,
+				ClientCertificateTypes: []uint8{CertTypeRSASign},
+			},
+			match:         &rsaCertificate,
+			mismatch:      &ecdsaP256Certificate,
+			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
+		},
+		{
+			name:       "Client-ClientCertificateTypes-ECDSA",
+			testType:   clientTest,
+			maxVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:             RequestClientCert,
+				ClientCertificateTypes: []uint8{CertTypeECDSASign},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
+		},
+
+		// Ed25519 is considered ECDSA for purposes of client certificate types.
+		{
+			name:       "Client-ClientCertificateTypes-RSA-Ed25519",
+			testType:   clientTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:             RequestClientCert,
+				ClientCertificateTypes: []uint8{CertTypeRSASign},
+			},
+			match:         &rsaCertificate,
+			mismatch:      &ed25519Certificate,
+			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
+		},
+		{
+			name:       "Client-ClientCertificateTypes-ECDSA-Ed25519",
+			testType:   clientTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:             RequestClientCert,
+				ClientCertificateTypes: []uint8{CertTypeECDSASign},
+			},
+			match:         &ed25519Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
+		},
+
+		// TLS 1.2 and up should incorporate the signature algorithm list into
+		// certificate selection. (There is no signature algorithm list to look
+		// at in TLS 1.0 and 1.1.)
+		{
+			name:       "Client-SignatureAlgorithm",
+			testType:   clientTest,
+			minVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:                RequestClientCert,
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &rsaCertificate,
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
+		// embedded in the signature algorithm.
+		{
+			name:       "Client-SignatureAlgorithmECDSACurve",
+			testType:   clientTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				ClientAuth:                RequestClientCert,
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match:         &ecdsaP256Certificate,
+			mismatch:      &ecdsaP384Certificate,
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// TLS 1.2's use does not. It is not possible to determine what ECDSA
+		// curves are allowed by the server.
+		{
+			name:       "Client-SignatureAlgorithmECDSACurve",
+			testType:   clientTest,
+			minVersion: VersionTLS12,
+			maxVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:                RequestClientCert,
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			},
+			match: &ecdsaP384Certificate,
+		},
+
+		// Signature algorithm matches take preferences on the keys into
+		// consideration.
+		{
+			name:       "Client-SignatureAlgorithmKeyPrefs",
+			testType:   clientTest,
+			minVersion: VersionTLS12,
+			config: Config{
+				ClientAuth:                RequestClientCert,
+				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
+			},
+			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
+			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+		},
+
+		// By default, certificate selection does not take issuers
+		// into account.
+		{
+			name:     "Client-DontCheckIssuer",
+			testType: clientTest,
+			config: Config{
+				ClientAuth: RequestClientCert,
+				ClientCAs:  makeCertPoolFromRoots(&rsaChainCertificate, &ecdsaP384Certificate),
+			},
+			match: &ecdsaP256Certificate,
+		},
+		{
+			name:     "Server-DontCheckIssuer",
+			testType: serverTest,
+			config: Config{
+				RootCAs:     makeCertPoolFromRoots(&rsaChainCertificate, &ecdsaP384Certificate),
+				SendRootCAs: true,
+			},
+			match: &ecdsaP256Certificate,
+		},
+
+		// If requested, certificate selection will match against the
+		// requested issuers.
+		{
+			name:     "Client-CheckIssuer",
+			testType: clientTest,
+			config: Config{
+				ClientAuth: RequestClientCert,
+				ClientCAs:  makeCertPoolFromRoots(&rsaChainCertificate, &ecdsaP384Certificate),
+			},
+			match:         rsaChainCertificate.WithMustMatchIssuer(true),
+			mismatch:      ecdsaP256Certificate.WithMustMatchIssuer(true),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+		{
+			name:     "Server-CheckIssuer",
+			testType: serverTest,
+			config: Config{
+				RootCAs:     makeCertPoolFromRoots(&rsaChainCertificate, &ecdsaP384Certificate),
+				SendRootCAs: true,
+			},
+			match:         rsaChainCertificate.WithMustMatchIssuer(true),
+			mismatch:      ecdsaP256Certificate.WithMustMatchIssuer(true),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+
+		// Trust anchor IDs can also be used to match issuers.
+		// TODO(crbug.com/398275713): Implement this for client certificates.
+		{
+			name:       "Server-CheckIssuer-TrustAnchorIDs",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				RequestTrustAnchors: [][]byte{{1, 1, 1}},
+			},
+			match:         rsaChainCertificate.WithTrustAnchorID([]byte{1, 1, 1}),
+			mismatch:      ecdsaP256Certificate.WithTrustAnchorID([]byte{2, 2, 2}),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+
+		// When an issuer-gated credential fails, a normal credential may be
+		// selected instead.
+		{
+			name:     "Client-CheckIssuerFallback",
+			testType: clientTest,
+			config: Config{
+				ClientAuth: RequestClientCert,
+				ClientCAs:  makeCertPoolFromRoots(&ecdsaP384Certificate),
+			},
+			match:         &rsaChainCertificate,
+			mismatch:      ecdsaP256Certificate.WithMustMatchIssuer(true),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+		{
+			name:     "Server-CheckIssuerFallback",
+			testType: serverTest,
+			config: Config{
+				RootCAs:     makeCertPoolFromRoots(&ecdsaP384Certificate),
+				SendRootCAs: true,
+			},
+			match:         &rsaChainCertificate,
+			mismatch:      ecdsaP256Certificate.WithMustMatchIssuer(true),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+		{
+			name:       "Server-CheckIssuerFallback-TrustAnchorIDs",
+			testType:   serverTest,
+			minVersion: VersionTLS13,
+			config: Config{
+				RequestTrustAnchors: [][]byte{{1, 1, 1}},
+			},
+			match:         &rsaChainCertificate,
+			mismatch:      ecdsaP256Certificate.WithTrustAnchorID([]byte{2, 2, 2}),
+			expectedError: ":NO_MATCHING_ISSUER:",
+		},
+	}
+
+	for _, protocol := range []protocol{tls, dtls} {
+		for _, vers := range allVersions(protocol) {
+			suffix := fmt.Sprintf("%s-%s", protocol, vers)
+
+			// Test that the credential list is interpreted in preference order,
+			// with the default credential, if any, at the end.
+			testCases = append(testCases, testCase{
+				name:     fmt.Sprintf("CertificateSelection-Client-PreferenceOrder-%s", suffix),
+				testType: clientTest,
+				protocol: protocol,
+				config: Config{
+					MinVersion: vers.version,
+					MaxVersion: vers.version,
+					ClientAuth: RequestClientCert,
+				},
+				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
+				shimCertificate: &rsaCertificate,
+				flags:           []string{"-expect-selected-credential", "0"},
+				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
+			})
+			testCases = append(testCases, testCase{
+				name:     fmt.Sprintf("CertificateSelection-Server-PreferenceOrder-%s", suffix),
+				testType: serverTest,
+				protocol: protocol,
+				config: Config{
+					MinVersion: vers.version,
+					MaxVersion: vers.version,
+				},
+				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
+				shimCertificate: &rsaCertificate,
+				flags:           []string{"-expect-selected-credential", "0"},
+				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
+			})
+
+			// Test that the selected credential contributes the certificate chain, OCSP response,
+			// and SCT list.
+			testCases = append(testCases, testCase{
+				name:     fmt.Sprintf("CertificateSelection-Server-OCSP-SCT-%s", suffix),
+				testType: serverTest,
+				protocol: protocol,
+				config: Config{
+					MinVersion: vers.version,
+					MaxVersion: vers.version,
+					// Configure enough options so that, at all TLS versions, only an RSA
+					// certificate will be accepted.
+					CipherSuites: []uint16{
+						TLS_AES_128_GCM_SHA256,
+						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+					},
+					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
+				},
+				shimCredentials: []*Credential{
+					ecdsaP256Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
+					rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+				},
+				shimCertificate: ecdsaP384Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
+				flags:           []string{"-expect-selected-credential", "1"},
+				expectations: connectionExpectations{
+					peerCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+				},
+			})
+
+			// Test that the credentials API works asynchronously. This tests both deferring the
+			// configuration to the certificate callback, and using a custom, async private key.
+			testCases = append(testCases, testCase{
+				name:     fmt.Sprintf("CertificateSelection-Client-Async-%s", suffix),
+				testType: clientTest,
+				protocol: protocol,
+				config: Config{
+					MinVersion: vers.version,
+					MaxVersion: vers.version,
+					ClientAuth: RequestClientCert,
+				},
+				shimCredentials: []*Credential{&ecdsaP256Certificate},
+				shimCertificate: &rsaCertificate,
+				flags:           []string{"-async", "-expect-selected-credential", "0"},
+				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
+			})
+			testCases = append(testCases, testCase{
+				name:     fmt.Sprintf("CertificateSelection-Server-Async-%s", suffix),
+				testType: serverTest,
+				protocol: protocol,
+				config: Config{
+					MinVersion: vers.version,
+					MaxVersion: vers.version,
+				},
+				shimCredentials: []*Credential{&ecdsaP256Certificate},
+				shimCertificate: &rsaCertificate,
+				flags:           []string{"-async", "-expect-selected-credential", "0"},
+				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
+			})
+
+			for _, test := range certSelectTests {
+				if test.minVersion != 0 && vers.version < test.minVersion {
+					continue
+				}
+				if test.maxVersion != 0 && vers.version > test.maxVersion {
+					continue
+				}
+
+				config := test.config
+				config.MinVersion = vers.version
+				config.MaxVersion = vers.version
+
+				// If the mismatch field is omitted, this is a positive test,
+				// just to confirm that the selection logic does not block a
+				// particular certificate.
+				if test.mismatch == nil {
+					testCases = append(testCases, testCase{
+						name:            fmt.Sprintf("CertificateSelection-%s-%s", test.name, suffix),
+						protocol:        protocol,
+						testType:        test.testType,
+						config:          config,
+						shimCredentials: []*Credential{test.match},
+						flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
+						expectations:    connectionExpectations{peerCertificate: test.match},
+					})
+					continue
+				}
+
+				testCases = append(testCases, testCase{
+					name:            fmt.Sprintf("CertificateSelection-%s-MatchFirst-%s", test.name, suffix),
+					protocol:        protocol,
+					testType:        test.testType,
+					config:          config,
+					shimCredentials: []*Credential{test.match, test.mismatch},
+					flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
+					expectations:    connectionExpectations{peerCertificate: test.match},
+				})
+				testCases = append(testCases, testCase{
+					name:            fmt.Sprintf("CertificateSelection-%s-MatchSecond-%s", test.name, suffix),
+					protocol:        protocol,
+					testType:        test.testType,
+					config:          config,
+					shimCredentials: []*Credential{test.mismatch, test.match},
+					flags:           append([]string{"-expect-selected-credential", "1"}, test.flags...),
+					expectations:    connectionExpectations{peerCertificate: test.match},
+				})
+				if canBeShimCertificate(test.match) {
+					testCases = append(testCases, testCase{
+						name:            fmt.Sprintf("CertificateSelection-%s-MatchDefault-%s", test.name, suffix),
+						protocol:        protocol,
+						testType:        test.testType,
+						config:          config,
+						shimCredentials: []*Credential{test.mismatch},
+						shimCertificate: test.match,
+						flags:           append([]string{"-expect-selected-credential", "-1"}, test.flags...),
+						expectations:    connectionExpectations{peerCertificate: test.match},
+					})
+				}
+				testCases = append(testCases, testCase{
+					name:               fmt.Sprintf("CertificateSelection-%s-MatchNone-%s", test.name, suffix),
+					protocol:           protocol,
+					testType:           test.testType,
+					config:             config,
+					shimCredentials:    []*Credential{test.mismatch, test.mismatch, test.mismatch},
+					flags:              test.flags,
+					shouldFail:         true,
+					expectedLocalError: "remote error: handshake failure",
+					expectedError:      test.expectedError,
+				})
+			}
+		}
+	}
+}
diff --git a/src/ssl/test/runner/certificate_tests.go b/src/ssl/test/runner/certificate_tests.go
new file mode 100644
index 0000000..7f6c4b8
--- /dev/null
+++ b/src/ssl/test/runner/certificate_tests.go
@@ -0,0 +1,409 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "crypto/x509"
+
+func makeCertPoolFromRoots(creds ...*Credential) *x509.CertPool {
+	certPool := x509.NewCertPool()
+	for _, cred := range creds {
+		cert, err := x509.ParseCertificate(cred.RootCertificate)
+		if err != nil {
+			panic(err)
+		}
+		certPool.AddCert(cert)
+	}
+	return certPool
+}
+
+func addClientAuthTests() {
+	// Add a dummy cert pool to stress certificate authority parsing.
+	certPool := makeCertPoolFromRoots(&rsaCertificate, &rsa1024Certificate)
+	caNames := certPool.Subjects()
+
+	for _, ver := range tlsVersions {
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     ver.name + "-Client-ClientAuth-RSA",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				ClientAuth: RequireAnyClientCert,
+				ClientCAs:  certPool,
+			},
+			shimCertificate: &rsaCertificate,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-Server-ClientAuth-RSA",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-Server-ClientAuth-ECDSA",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &ecdsaP256Certificate,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     ver.name + "-Client-ClientAuth-ECDSA",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				ClientAuth: RequireAnyClientCert,
+				ClientCAs:  certPool,
+			},
+			shimCertificate: &ecdsaP256Certificate,
+		})
+
+		testCases = append(testCases, testCase{
+			name: "NoClientCertificate-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				ClientAuth: RequireAnyClientCert,
+			},
+			shouldFail:         true,
+			expectedLocalError: "client didn't provide a certificate",
+		})
+
+		testCases = append(testCases, testCase{
+			// Even if not configured to expect a certificate, OpenSSL will
+			// return X509_V_OK as the verify_result.
+			testType: serverTest,
+			name:     "NoClientCertificateRequested-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-expect-verify-result",
+			},
+			resumeSession: true,
+		})
+
+		testCases = append(testCases, testCase{
+			// If a client certificate is not provided, OpenSSL will still
+			// return X509_V_OK as the verify_result.
+			testType: serverTest,
+			name:     "NoClientCertificate-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-expect-verify-result",
+				"-verify-peer",
+			},
+			resumeSession: true,
+		})
+
+		certificateRequired := "remote error: certificate required"
+		if ver.version < VersionTLS13 {
+			// Prior to TLS 1.3, the generic handshake_failure alert
+			// was used.
+			certificateRequired = "remote error: handshake failure"
+		}
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RequireAnyClientCertificate-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			expectedLocalError: certificateRequired,
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "SkipClientCertificate-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SkipClientCertificate: true,
+				},
+			},
+			// Setting SSL_VERIFY_PEER allows anonymous clients.
+			flags:         []string{"-verify-peer"},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_MESSAGE:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-Server-CertReq-CA-List",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+				Bugs: ProtocolBugs{
+					ExpectCertificateReqNames: caNames,
+				},
+			},
+			flags: []string{
+				"-require-any-client-certificate",
+				"-use-client-ca-list", encodeDERValues(caNames),
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     ver.name + "-Client-CertReq-CA-List",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+				ClientAuth: RequireAnyClientCert,
+				ClientCAs:  certPool,
+			},
+			shimCertificate: &rsaCertificate,
+			flags: []string{
+				"-expect-client-ca-list", encodeDERValues(caNames),
+			},
+		})
+	}
+
+	// Client auth is only legal in certificate-based ciphers.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-PSK",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			ClientAuth:   RequireAnyClientCert,
+		},
+		shimCertificate: &rsaCertificate,
+		flags: []string{
+			"-psk", "secret",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-ECDHE_PSK",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			ClientAuth:   RequireAnyClientCert,
+		},
+		shimCertificate: &rsaCertificate,
+		flags: []string{
+			"-psk", "secret",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Regression test for a bug where the client CA list, if explicitly
+	// set to NULL, was mis-encoded.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Null-Client-CA-List",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: &rsaCertificate,
+			Bugs: ProtocolBugs{
+				ExpectCertificateReqNames: [][]byte{},
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+			"-use-client-ca-list", "<NULL>",
+		},
+	})
+
+	// Test that an empty client CA list doesn't send a CA extension.
+	// (This is implicitly tested by the parser. An empty CA extension is
+	// a syntax error.)
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-Empty-Client-CA-List",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &rsaCertificate,
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+			"-use-client-ca-list", "<EMPTY>",
+		},
+	})
+}
+
+func addCertificateTests() {
+	for _, ver := range tlsVersions {
+		// Test that a certificate chain with intermediate may be sent
+		// and received as both client and server.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "SendReceiveIntermediate-Client-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaChainCertificate,
+				ClientAuth: RequireAnyClientCert,
+			},
+			expectations: connectionExpectations{
+				peerCertificate: &rsaChainCertificate,
+			},
+			shimCertificate: &rsaChainCertificate,
+			flags: []string{
+				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "SendReceiveIntermediate-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaChainCertificate,
+			},
+			expectations: connectionExpectations{
+				peerCertificate: &rsaChainCertificate,
+			},
+			shimCertificate: &rsaChainCertificate,
+			flags: []string{
+				"-require-any-client-certificate",
+				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
+			},
+		})
+
+		// Test that garbage leaf certificates are properly rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "GarbageCertificate-Client-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &garbageCertificate,
+			},
+			shouldFail:         true,
+			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
+			expectedLocalError: "remote error: error decoding message",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "GarbageCertificate-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &garbageCertificate,
+			},
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
+			expectedLocalError: "remote error: error decoding message",
+		})
+	}
+}
+
+func addRetainOnlySHA256ClientCertTests() {
+	for _, ver := range tlsVersions {
+		// Test that enabling
+		// SSL_CTX_set_retain_only_sha256_of_client_certs without
+		// actually requesting a client certificate is a no-op.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-NoCert-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-on-initial-retain-only-sha256-client-cert",
+				"-on-resume-retain-only-sha256-client-cert",
+			},
+			resumeSession: true,
+		})
+
+		// Test that when retaining only a SHA-256 certificate is
+		// enabled, the hash appears as expected.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-Cert-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-verify-peer",
+				"-on-initial-retain-only-sha256-client-cert",
+				"-on-resume-retain-only-sha256-client-cert",
+				"-on-initial-expect-sha256-client-cert",
+				"-on-resume-expect-sha256-client-cert",
+			},
+			resumeSession: true,
+		})
+
+		// Test that when the config changes from on to off, a
+		// resumption is rejected because the server now wants the full
+		// certificate chain.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-OnOff-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-verify-peer",
+				"-on-initial-retain-only-sha256-client-cert",
+				"-on-initial-expect-sha256-client-cert",
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+
+		// Test that when the config changes from off to on, a
+		// resumption is rejected because the server now wants just the
+		// hash.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-OffOn-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-verify-peer",
+				"-on-resume-retain-only-sha256-client-cert",
+				"-on-resume-expect-sha256-client-cert",
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+	}
+}
diff --git a/src/ssl/test/runner/change_cipher_spec_tests.go b/src/ssl/test/runner/change_cipher_spec_tests.go
new file mode 100644
index 0000000..0b28525
--- /dev/null
+++ b/src/ssl/test/runner/change_cipher_spec_tests.go
@@ -0,0 +1,360 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "slices"
+
+func addChangeCipherSpecTests() {
+	// Test missing ChangeCipherSpecs.
+	testCases = append(testCases, testCase{
+		name: "SkipChangeCipherSpec-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipChangeCipherSpec-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipChangeCipherSpec-Server-NPN",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			NextProtos: []string{"bar"},
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		flags: []string{
+			"-advertise-npn", "\x03foo\x03bar\x03baz",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+
+	// Test synchronization between the handshake and ChangeCipherSpec.
+	// Partial post-CCS handshake messages before ChangeCipherSpec should be
+	// rejected. Test both with and without handshake packing to handle both
+	// when the partial post-CCS message is in its own record and when it is
+	// attached to the pre-CCS message.
+	for _, packed := range []bool{false, true} {
+		var suffix string
+		if packed {
+			suffix = "-Packed"
+		}
+
+		testCases = append(testCases, testCase{
+			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"bar"},
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			flags: []string{
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+	}
+
+	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
+	// and ChangeCipherSpec + Finished in the second flight. Test the server's
+	// behavior when the Finished message is fragmented across not only
+	// ChangeCipherSpec but also the flight boundary.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PartialClientFinishedWithClientHello: true,
+			},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
+	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
+	// Test the client's behavior when the Finished message is fragmented across
+	// not only ChangeCipherSpec but also the flight boundary.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "PartialFinishedWithServerHelloDone",
+		config: Config{
+			MaxVersion:             VersionTLS12,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				PartialFinishedWithServerHelloDone: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// Test that, in DTLS 1.2, key changes are not allowed when there are
+	// buffered messages. Do this sending all messages in reverse, so that later
+	// ones are buffered, and leaving Finished unencrypted.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "KeyChangeWithBufferedMessages-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					next = slices.Clone(next)
+					slices.Reverse(next)
+					for i := range next {
+						next[i].Epoch = 0
+					}
+					c.WriteFlight(next)
+				},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":EXCESS_HANDSHAKE_DATA:",
+	})
+
+	// Test synchronization between encryption changes and the handshake in
+	// TLS 1.3, where ChangeCipherSpec is implicit.
+	testCases = append(testCases, testCase{
+		name: "PartialEncryptedExtensionsWithServerHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PartialEncryptedExtensionsWithServerHello: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":EXCESS_HANDSHAKE_DATA:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialClientFinishedWithClientHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PartialClientFinishedWithClientHello: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":EXCESS_HANDSHAKE_DATA:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialClientFinishedWithSecondClientHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Trigger a curve-based HelloRetryRequest.
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				PartialClientFinishedWithSecondClientHello: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":EXCESS_HANDSHAKE_DATA:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialEndOfEarlyDataWithClientHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PartialEndOfEarlyDataWithClientHello: true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":EXCESS_HANDSHAKE_DATA:",
+	})
+
+	// Test that early ChangeCipherSpecs are handled correctly.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyChangeCipherSpec-server-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EarlyChangeCipherSpec: 1,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyChangeCipherSpec-server-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EarlyChangeCipherSpec: 2,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "StrayChangeCipherSpec",
+		config: Config{
+			// TODO(davidben): Once DTLS 1.3 exists, test
+			// that stray ChangeCipherSpec messages are
+			// rejected.
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					c.WriteFragments([]DTLSFragment{{IsChangeCipherSpec: true, Data: []byte{1}}})
+					c.WriteFlight(next)
+				},
+			},
+		},
+	})
+
+	// Test that the contents of ChangeCipherSpec are checked.
+	testCases = append(testCases, testCase{
+		name: "BadChangeCipherSpec-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{2},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		name: "BadChangeCipherSpec-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{1, 1},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "BadChangeCipherSpec-DTLS-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{2},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "BadChangeCipherSpec-DTLS-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{1, 1},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+}
diff --git a/src/ssl/test/runner/cipher_suite_tests.go b/src/ssl/test/runner/cipher_suite_tests.go
new file mode 100644
index 0000000..5ae63ca
--- /dev/null
+++ b/src/ssl/test/runner/cipher_suite_tests.go
@@ -0,0 +1,575 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+type testCipherSuite struct {
+	name string
+	id   uint16
+}
+
+var testCipherSuites = []testCipherSuite{
+	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
+	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
+	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
+	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
+	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
+	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
+	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
+	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
+	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+	{"ECDHE_RSA_WITH_AES_128_CBC_SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
+	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
+	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
+	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
+	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
+	{"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},
+}
+
+func hasComponent(suiteName, component string) bool {
+	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
+}
+
+func isTLS12Only(suiteName string) bool {
+	return hasComponent(suiteName, "GCM") ||
+		hasComponent(suiteName, "SHA256") ||
+		hasComponent(suiteName, "SHA384") ||
+		hasComponent(suiteName, "POLY1305")
+}
+
+func isTLS13Suite(suiteName string) bool {
+	return !hasComponent(suiteName, "WITH")
+}
+
+func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
+	const psk = "12345"
+	const pskIdentity = "luggage combo"
+
+	if !ver.supportsProtocol(protocol) {
+		return
+	}
+	prefix := protocol.String() + "-"
+
+	var cert *Credential
+	if isTLS13Suite(suite.name) {
+		cert = &rsaCertificate
+	} else if hasComponent(suite.name, "ECDSA") {
+		cert = &ecdsaP256Certificate
+	} else if hasComponent(suite.name, "RSA") {
+		cert = &rsaCertificate
+	}
+
+	var flags []string
+	if hasComponent(suite.name, "PSK") {
+		flags = append(flags,
+			"-psk", psk,
+			"-psk-identity", pskIdentity)
+	}
+
+	if hasComponent(suite.name, "3DES") {
+		// BoringSSL disables 3DES ciphers by default.
+		flags = append(flags, "-cipher", "3DES")
+	}
+
+	var shouldFail bool
+	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
+		shouldFail = true
+	}
+	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
+		shouldFail = true
+	}
+	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
+		shouldFail = true
+	}
+
+	var sendCipherSuite uint16
+	var expectedServerError, expectedClientError string
+	serverCipherSuites := []uint16{suite.id}
+	if shouldFail {
+		expectedServerError = ":NO_SHARED_CIPHER:"
+		if ver.version >= VersionTLS13 && cert == nil {
+			// TLS 1.2 PSK ciphers won't configure a server certificate, but we
+			// require one in TLS 1.3.
+			expectedServerError = ":NO_CERTIFICATE_SET:"
+		}
+		expectedClientError = ":WRONG_CIPHER_RETURNED:"
+		// Configure the server to select ciphers as normal but
+		// select an incompatible cipher in ServerHello.
+		serverCipherSuites = nil
+		sendCipherSuite = suite.id
+	}
+
+	// Verify exporters interoperate.
+	exportKeyingMaterial := 1024
+
+	if ver.version != VersionTLS13 || !ver.hasDTLS {
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + ver.name + "-" + suite.name + "-server",
+			config: Config{
+				MinVersion:           ver.version,
+				MaxVersion:           ver.version,
+				CipherSuites:         []uint16{suite.id},
+				Credential:           cert,
+				PreSharedKey:         []byte(psk),
+				PreSharedKeyIdentity: pskIdentity,
+				Bugs: ProtocolBugs{
+					AdvertiseAllConfiguredCiphers: true,
+				},
+			},
+			shimCertificate:      cert,
+			flags:                flags,
+			resumeSession:        true,
+			shouldFail:           shouldFail,
+			expectedError:        expectedServerError,
+			exportKeyingMaterial: exportKeyingMaterial,
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + ver.name + "-" + suite.name + "-client",
+			config: Config{
+				MinVersion:           ver.version,
+				MaxVersion:           ver.version,
+				CipherSuites:         serverCipherSuites,
+				Credential:           cert,
+				PreSharedKey:         []byte(psk),
+				PreSharedKeyIdentity: pskIdentity,
+				Bugs: ProtocolBugs{
+					IgnorePeerCipherPreferences: shouldFail,
+					SendCipherSuite:             sendCipherSuite,
+				},
+			},
+			flags:                flags,
+			resumeSession:        true,
+			shouldFail:           shouldFail,
+			expectedError:        expectedClientError,
+			exportKeyingMaterial: exportKeyingMaterial,
+		})
+	}
+
+	if shouldFail {
+		return
+	}
+
+	// Ensure the maximum record size is accepted.
+	testCases = append(testCases, testCase{
+		protocol: protocol,
+		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
+		config: Config{
+			MinVersion:           ver.version,
+			MaxVersion:           ver.version,
+			CipherSuites:         []uint16{suite.id},
+			Credential:           cert,
+			PreSharedKey:         []byte(psk),
+			PreSharedKeyIdentity: pskIdentity,
+		},
+		flags:      flags,
+		messageLen: maxPlaintext,
+	})
+
+	// Test bad records for all ciphers. Bad records are fatal in TLS
+	// and ignored in DTLS.
+	shouldFail = protocol == tls
+	var expectedError string
+	if shouldFail {
+		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
+	}
+
+	// When QUIC is used, the QUIC stack handles record encryption/decryption.
+	// Thus it is not possible for the TLS stack in QUIC mode to receive a
+	// bad record (i.e. one that fails to decrypt).
+	if protocol != quic {
+		testCases = append(testCases, testCase{
+			protocol: protocol,
+			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
+			config: Config{
+				MinVersion:           ver.version,
+				MaxVersion:           ver.version,
+				CipherSuites:         []uint16{suite.id},
+				Credential:           cert,
+				PreSharedKey:         []byte(psk),
+				PreSharedKeyIdentity: pskIdentity,
+			},
+			flags:            flags,
+			damageFirstWrite: true,
+			messageLen:       maxPlaintext,
+			shouldFail:       shouldFail,
+			expectedError:    expectedError,
+		})
+	}
+}
+
+func addCipherSuiteTests() {
+	const bogusCipher = 0xfe00
+
+	for _, suite := range testCipherSuites {
+		for _, ver := range tlsVersions {
+			for _, protocol := range []protocol{tls, dtls, quic} {
+				addTestForCipherSuite(suite, ver, protocol)
+			}
+		}
+	}
+
+	testCases = append(testCases, testCase{
+		name: "NoSharedCipher",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{},
+		},
+		shouldFail:    true,
+		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "NoSharedCipher-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{},
+		},
+		shouldFail:    true,
+		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnsupportedCipherSuite",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				IgnorePeerCipherPreferences: true,
+			},
+		},
+		flags:         []string{"-cipher", "DEFAULT:!AES"},
+		shouldFail:    true,
+		expectedError: ":WRONG_CIPHER_RETURNED:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerHelloBogusCipher",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: bogusCipher,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CIPHER_RETURNED:",
+	})
+	testCases = append(testCases, testCase{
+		name: "ServerHelloBogusCipher-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: bogusCipher,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CIPHER_RETURNED:",
+	})
+
+	// The server must be tolerant to bogus ciphers.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCipher",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				AdvertiseAllConfiguredCiphers: true,
+			},
+		},
+	})
+
+	// The server must be tolerant to bogus ciphers.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCipher-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				AdvertiseAllConfiguredCiphers: true,
+			},
+		},
+	})
+
+	// Test empty ECDHE_PSK identity hints work as expected.
+	testCases = append(testCases, testCase{
+		name: "EmptyECDHEPSKHint",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+		},
+		flags: []string{"-psk", "secret"},
+	})
+
+	// Test empty PSK identity hints work as expected, even if an explicit
+	// ServerKeyExchange is sent.
+	testCases = append(testCases, testCase{
+		name: "ExplicitEmptyPSKHint",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			Bugs: ProtocolBugs{
+				AlwaysSendPreSharedKeyIdentityHint: true,
+			},
+		},
+		flags: []string{"-psk", "secret"},
+	})
+
+	// Test that clients enforce that the server-sent certificate and cipher
+	// suite match in TLS 1.2.
+	testCases = append(testCases, testCase{
+		name: "CertificateCipherMismatch-RSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Credential:   &rsaCertificate,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CERTIFICATE_TYPE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "CertificateCipherMismatch-ECDSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Credential:   &ecdsaP256Certificate,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CERTIFICATE_TYPE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "CertificateCipherMismatch-Ed25519",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Credential:   &ed25519Certificate,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CERTIFICATE_TYPE:",
+	})
+
+	// Test that servers decline to select a cipher suite which is
+	// inconsistent with their configured certificate.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerCipherFilter-RSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+		},
+		shimCertificate: &rsaCertificate,
+		shouldFail:      true,
+		expectedError:   ":NO_SHARED_CIPHER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerCipherFilter-ECDSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		shimCertificate: &ecdsaP256Certificate,
+		shouldFail:      true,
+		expectedError:   ":NO_SHARED_CIPHER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerCipherFilter-Ed25519",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		shimCertificate: &ed25519Certificate,
+		shouldFail:      true,
+		expectedError:   ":NO_SHARED_CIPHER:",
+	})
+
+	// Test cipher suite negotiation works as expected. Configure a
+	// complicated cipher suite configuration.
+	const negotiationTestCiphers = "" +
+		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
+		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
+		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
+		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
+		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
+	negotiationTests := []struct {
+		ciphers  []uint16
+		expected uint16
+	}{
+		// Server preferences are honored, including when
+		// equipreference groups are involved.
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+			},
+			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+		},
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+			},
+			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+		},
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+			},
+			TLS_RSA_WITH_AES_128_GCM_SHA256,
+		},
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_128_CBC_SHA,
+			},
+			TLS_RSA_WITH_AES_128_CBC_SHA,
+		},
+		// Equipreference groups use the client preference.
+		{
+			[]uint16{
+				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+			},
+			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+		},
+		{
+			[]uint16{
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+			},
+			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+		},
+		{
+			[]uint16{
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+			},
+			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+		},
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_256_CBC_SHA,
+			},
+			TLS_RSA_WITH_AES_256_GCM_SHA384,
+		},
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_CBC_SHA,
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+			},
+			TLS_RSA_WITH_AES_256_CBC_SHA,
+		},
+		// If there are two equipreference groups, the preferred one
+		// takes precedence.
+		{
+			[]uint16{
+				TLS_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_RSA_WITH_AES_256_CBC_SHA,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+			},
+			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+		},
+	}
+	for i, t := range negotiationTests {
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CipherNegotiation-" + strconv.Itoa(i),
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: t.ciphers,
+			},
+			flags: []string{"-cipher", negotiationTestCiphers},
+			expectations: connectionExpectations{
+				cipher: t.expected,
+			},
+		})
+	}
+}
+
+func addRSAClientKeyExchangeTests() {
+	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
+			config: Config{
+				// Ensure the ClientHello version and final
+				// version are different, to detect if the
+				// server uses the wrong one.
+				MaxVersion:   VersionTLS11,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+				Bugs: ProtocolBugs{
+					BadRSAClientKeyExchange: bad,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+		})
+	}
+
+	// The server must compare whatever was in ClientHello.version for the
+	// RSA premaster.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendClientVersion-RSA",
+		config: Config{
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendClientVersion: 0x1234,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+}
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index ee65687..925d390 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -172,6 +172,7 @@
 	extensionSignatureAlgorithmsCert    uint16 = 50
 	extensionKeyShare                   uint16 = 51
 	extensionQUICTransportParams        uint16 = 57
+	extensionTLSFlags                   uint16 = 62
 	extensionCustom                     uint16 = 1234  // not IANA assigned
 	extensionNextProtoNeg               uint16 = 13172 // not IANA assigned
 	extensionApplicationSettingsOld     uint16 = 17513 // not IANA assigned
@@ -180,11 +181,16 @@
 	extensionQUICTransportParamsLegacy  uint16 = 0xffa5 // draft-ietf-quic-tls-32 and earlier
 	extensionChannelID                  uint16 = 30032  // not IANA assigned
 	extensionPAKE                       uint16 = 35387  // not IANA assigned
+	extensionTrustAnchors               uint16 = 0xca34 // not IANA assigned
 	extensionDuplicate                  uint16 = 0xffff // not IANA assigned
 	extensionEncryptedClientHello       uint16 = 0xfe0d // not IANA assigned
 	extensionECHOuterExtensions         uint16 = 0xfd00 // not IANA assigned
 )
 
+const (
+	flagResumptionAcrossNames = 8
+)
+
 // TLS signaling cipher suite values
 const (
 	scsvRenegotiation uint16 = 0x00ff
@@ -381,6 +387,7 @@
 	hasApplicationSettingsOld   bool
 	localApplicationSettingsOld []byte
 	peerApplicationSettingsOld  []byte
+	resumptionAcrossNames       bool
 }
 
 // ClientSessionCache is a cache of ClientSessionState objects that can be used
@@ -509,6 +516,10 @@
 	// If RootCAs is nil, TLS uses the host's root CA set.
 	RootCAs *x509.CertPool
 
+	// SendRootCAs, if true, causes the client to send the list of
+	// supported root CAs in the certificate_authorities extension.
+	SendRootCAs bool
+
 	// NextProtos is a list of supported, application level protocols.
 	NextProtos []string
 
@@ -679,6 +690,18 @@
 	// field.
 	DTLSRecordHeaderOmitLength bool
 
+	// RequestTrustAnchors, if not nil, is the list of trust anchor IDs to
+	// request in ClientHello.
+	RequestTrustAnchors [][]byte
+
+	// AvailableTrustAnchors, if not empty, is the list of trust anchor IDs
+	// to report as available in EncryptedExtensions.
+	AvailableTrustAnchors [][]byte
+
+	// ResumptionAcrossNames specifies whether session tickets issued by the TLS
+	// server should be marked as compatable with cross-name resumption.
+	ResumptionAcrossNames bool
+
 	// Bugs specifies optional misbehaviour to be used for testing other
 	// implementations.
 	Bugs ProtocolBugs
@@ -1903,6 +1926,37 @@
 	// request signed certificate timestamps.
 	NoSignedCertificateTimestamps bool
 
+	// ExpectPeerRequestedTrustAnchors, if not nil, causes the server to
+	// require the client to request the specified trust anchors in the
+	// ClientHello.
+	ExpectPeerRequestedTrustAnchors [][]byte
+
+	// ExpectPeerAvailableTrustAnchors, if not nil, causes the client to
+	// require the server to list the specified trust anchors as available
+	// in EncryptedExtensions.
+	ExpectPeerAvailableTrustAnchors [][]byte
+
+	// ExpectPeerMatchTrustAnchor, if not nil, causes the client to require the
+	// server to acknowledge, or not acknowledge the trust_anchors extension in
+	// Certificate.
+	ExpectPeerMatchTrustAnchor *bool
+
+	// AlwaysMatchTrustAnchorID, if true, causes the server to always indicate
+	// a trust anchor ID match in the Certificate message.
+	AlwaysMatchTrustAnchorID bool
+
+	// SendTrustAnchorWrongCertificate sends a trust anchor ID extension
+	// on the second certificate in the Certificate message.
+	SendTrustAnchorWrongCertificate bool
+
+	// SendNonEmptyTrustAnchorMatch sends a non-empty trust anchor ID
+	// extension to indicate a match.
+	SendNonEmptyTrustAnchorMatch bool
+
+	// AlwaysSendAvailableTrustAnchors, if true, causese the server to always
+	// send available trust anchors in EncryptedExtensions, even if unsolicited.
+	AlwaysSendAvailableTrustAnchors bool
+
 	// SendSupportedPointFormats, if not nil, is the list of supported point
 	// formats to send in ClientHello or ServerHello. If set to a non-nil
 	// empty slice, no extension will be sent.
@@ -1941,10 +1995,6 @@
 	// renegotiation handshakes.
 	RenegotiationCertificate *Credential
 
-	// ExpectNoCertificateAuthoritiesExtension, if true, causes the client to
-	// reject CertificateRequest with the CertificateAuthorities extension.
-	ExpectNoCertificateAuthoritiesExtension bool
-
 	// SigningAlgorithmForLegacyVersions, if non-zero, is the signature algorithm
 	// to use when signing in TLS 1.1 and earlier where algorithms are not
 	// negotiated.
@@ -2106,6 +2156,24 @@
 	// CheckClientHello is called on the initial ClientHello received from the
 	// peer, to implement extra checks.
 	CheckClientHello func(*clientHelloMsg) error
+
+	// SendTicketFlags contains a list of flags, represented by bit index, that
+	// the server will send in TLS 1.3 NewSessionTicket.
+	SendTicketFlags []uint
+
+	// AlwaysSendTicketFlags causes the server to send the flags extension in
+	// TLS 1.3 NewSessionTicket even if empty.
+	AlwaysSendTicketFlags bool
+
+	// TicketFlagPadding is the number of extra bytes of padding (giving a
+	// non-minimal encoding) to include in the flags extension in TLS 1.3
+	// NewSessionTicket.
+	TicketFlagPadding int
+
+	// ExpectResumptionAcrossNames, if not nil, causes the client to require all
+	// NewSessionTicket messages to have or not have the resumption_across_names
+	// flag set.
+	ExpectResumptionAcrossNames *bool
 }
 
 func (c *Config) serverInit() {
@@ -2286,7 +2354,9 @@
 	Type CredentialType
 	// Certificate is a chain of one or more certificates, leaf first.
 	Certificate [][]byte
-	PrivateKey  crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
+	// RootCertificate is the certificate that issued this chain.
+	RootCertificate []byte
+	PrivateKey      crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
 	// OCSPStaple contains an optional OCSP response which will be served
 	// to clients that request it.
 	OCSPStaple []byte
@@ -2317,6 +2387,9 @@
 	// SignSignatureAlgorithms, if not nil, overrides the default set of
 	// supported signature algorithms to sign with.
 	SignSignatureAlgorithms []signatureAlgorithm
+	// MustMatchIssuer, if set, causes the shim to only consider this
+	// credential when the issuer matches a peer-requested CA.
+	MustMatchIssuer bool
 	// The following fields are used for PAKE credentials. For simplicity,
 	// we specify the password directly and expect the shim and runner to
 	// compute the client- and server-specific halves as needed.
@@ -2330,6 +2403,9 @@
 	// OverridePAKECodepoint, if non-zero, causes the runner to send the
 	// specified value instead of the actual PAKE codepoint.
 	OverridePAKECodepoint uint16
+	// TrustAnchorID, if not empty, is the trust anchor ID for the issuer
+	// of the certificate chain.
+	TrustAnchorID []byte
 }
 
 func (c *Credential) WithSignatureAlgorithms(sigAlgs ...signatureAlgorithm) *Credential {
@@ -2350,6 +2426,12 @@
 	return &ret
 }
 
+func (c *Credential) WithMustMatchIssuer(mustMatch bool) *Credential {
+	ret := *c
+	ret.MustMatchIssuer = mustMatch
+	return &ret
+}
+
 func (c *Credential) signatureAlgorithms() []signatureAlgorithm {
 	if c != nil && c.SignatureAlgorithms != nil {
 		return c.SignatureAlgorithms
@@ -2357,6 +2439,13 @@
 	return supportedSignatureAlgorithms
 }
 
+func (c *Credential) WithTrustAnchorID(id []byte) *Credential {
+	ret := *c
+	ret.TrustAnchorID = id
+	ret.MustMatchIssuer = true
+	return &ret
+}
+
 type handshakeMessage interface {
 	marshal() []byte
 	unmarshal([]byte) bool
@@ -2572,12 +2661,13 @@
 	cert := generateTestCert(template, nil, key)
 	tmpCertPath, tmpKeyPath := writeTempCertFile([]*x509.Certificate{cert}), writeTempKeyFile(key)
 	return Credential{
-		Certificate: [][]byte{cert.Raw},
-		PrivateKey:  key,
-		Leaf:        cert,
-		ChainPath:   tmpCertPath,
-		KeyPath:     tmpKeyPath,
-		RootPath:    tmpCertPath,
+		Certificate:     [][]byte{cert.Raw},
+		RootCertificate: cert.Raw,
+		PrivateKey:      key,
+		Leaf:            cert,
+		ChainPath:       tmpCertPath,
+		KeyPath:         tmpKeyPath,
+		RootPath:        tmpCertPath,
 	}
 }
 
@@ -2635,3 +2725,6 @@
 
 	return cert
 }
+
+// https://github.com/golang/go/issues/45624
+func ptrTo[T any](t T) *T { return &t }
diff --git a/src/ssl/test/runner/compliance_policy_tests.go b/src/ssl/test/runner/compliance_policy_tests.go
new file mode 100644
index 0000000..f0ccf9e
--- /dev/null
+++ b/src/ssl/test/runner/compliance_policy_tests.go
@@ -0,0 +1,290 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addCompliancePolicyTests() {
+	for _, protocol := range []protocol{tls, quic} {
+		for _, suite := range testCipherSuites {
+			var isFIPSCipherSuite bool
+			switch suite.id {
+			case TLS_AES_128_GCM_SHA256,
+				TLS_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+				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 cert Credential
+			if hasComponent(suite.name, "ECDSA") {
+				cert = ecdsaP384Certificate
+			} else {
+				cert = rsaCertificate
+			}
+
+			maxVersion := uint16(VersionTLS13)
+			if !isTLS13Suite(suite.name) {
+				if protocol == quic {
+					continue
+				}
+				maxVersion = VersionTLS12
+			}
+
+			policies := []struct {
+				flag          string
+				cipherSuiteOk bool
+			}{
+				{"-fips-202205", isFIPSCipherSuite},
+				{"-wpa-202304", isWPACipherSuite},
+			}
+
+			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},
+					},
+					shimCertificate: &cert,
+					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},
+						Credential:   &cert,
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.cipherSuiteOk,
+				})
+			}
+		}
+
+		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
+		// picks it without it being in the client's cipher list.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     "Compliance-fips202205-" + protocol.String() + "-Client-ReallyWontAcceptChaCha",
+			config: Config{
+				MinVersion: VersionTLS12,
+				MaxVersion: maxVersion,
+				Bugs: ProtocolBugs{
+					SendCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
+				},
+			},
+			flags: []string{
+				"-fips-202205",
+			},
+			shouldFail:    true,
+			expectedError: ":WRONG_CIPHER_RETURNED:",
+		})
+
+		for _, curve := range testCurves {
+			var isFIPSCurve bool
+			switch curve.id {
+			case CurveP256, CurveP384:
+				isFIPSCurve = true
+			}
+
+			var isWPACurve bool
+			switch curve.id {
+			case CurveP384:
+				isWPACurve = true
+			}
+
+			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 {
+			// The TLS 1.0 and TLS 1.1 default signature algorithm does not
+			// apply to these tests.
+			if sigalg.id == 0 {
+				continue
+			}
+
+			var isFIPSSigAlg bool
+			switch sigalg.id {
+			case signatureRSAPKCS1WithSHA256,
+				signatureRSAPKCS1WithSHA384,
+				signatureRSAPKCS1WithSHA512,
+				signatureECDSAWithP256AndSHA256,
+				signatureECDSAWithP384AndSHA384,
+				signatureRSAPSSWithSHA256,
+				signatureRSAPSSWithSHA384,
+				signatureRSAPSSWithSHA512:
+				isFIPSSigAlg = true
+			}
+
+			var isWPASigAlg bool
+			switch sigalg.id {
+			case signatureRSAPKCS1WithSHA384,
+				signatureRSAPKCS1WithSHA512,
+				signatureECDSAWithP384AndSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureRSAPSSWithSHA512:
+				isWPASigAlg = true
+			}
+
+			if sigalg.curve == CurveP224 {
+				// This can work in TLS 1.2, but not with TLS 1.3.
+				// For consistency it's not permitted in FIPS mode.
+				isFIPSSigAlg = false
+			}
+
+			maxVersion := uint16(VersionTLS13)
+			if hasComponent(sigalg.name, "PKCS1") {
+				if protocol == quic {
+					continue
+				}
+				maxVersion = VersionTLS12
+			}
+
+			policies := []struct {
+				flag     string
+				sigAlgOk bool
+			}{
+				{"-fips-202205", isFIPSSigAlg},
+				{"-wpa-202304", isWPASigAlg},
+			}
+
+			cert := sigalg.baseCert.WithSignatureAlgorithms(sigalg.id)
+			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},
+					},
+					// Use the base certificate. We wish to pick up the signature algorithm
+					// preferences from the FIPS policy.
+					shimCertificate: sigalg.baseCert,
+					flags:           []string{policy.flag},
+					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,
+						Credential: cert,
+					},
+					flags: []string{
+						policy.flag,
+					},
+					shouldFail: !policy.sigAlgOk,
+				})
+			}
+		}
+
+		// AES-256-GCM is the most preferred.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     "Compliance-cnsa202407-" + protocol.String() + "-AES-256-preferred",
+			config: Config{
+				MinVersion:   VersionTLS13,
+				MaxVersion:   VersionTLS13,
+				CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384},
+			},
+			flags: []string{
+				"-cnsa-202407",
+			},
+			expectations: connectionExpectations{cipher: TLS_AES_256_GCM_SHA384},
+		})
+
+		// AES-128-GCM is preferred over ChaCha20-Poly1305.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     "Compliance-cnsa202407-" + protocol.String() + "-AES-128-preferred",
+			config: Config{
+				MinVersion:   VersionTLS13,
+				MaxVersion:   VersionTLS13,
+				CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
+			},
+			flags: []string{
+				"-cnsa-202407",
+			},
+			expectations: connectionExpectations{cipher: TLS_AES_128_GCM_SHA256},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index a3ca817..71a45fe 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -1518,8 +1518,8 @@
 
 	if data[0] == typeServerHello && len(data) >= 38 {
 		vers := uint16(data[4])<<8 | uint16(data[5])
-		if vers == VersionTLS12 && bytes.Equal(data[6:38], tls13HelloRetryRequest) {
-			m = new(helloRetryRequestMsg)
+		if (vers == VersionDTLS12 || vers == VersionTLS12) && bytes.Equal(data[6:38], tls13HelloRetryRequest) {
+			m = &helloRetryRequestMsg{isDTLS: c.isDTLS}
 		}
 	}
 
@@ -1615,22 +1615,6 @@
 }
 
 func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMsg, cipherSuite *cipherSuite) error {
-	if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
-		return errors.New("tls: no GREASE ticket extension found")
-	}
-
-	if c.config.Bugs.ExpectTicketEarlyData && newSessionTicket.maxEarlyDataSize == 0 {
-		return errors.New("tls: no early_data ticket extension found")
-	}
-
-	if c.config.Bugs.ExpectNoNewSessionTicket || c.config.Bugs.ExpectNoNonEmptyNewSessionTicket {
-		return errors.New("tls: received unexpected NewSessionTicket")
-	}
-
-	if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
-		return nil
-	}
-
 	session := &ClientSessionState{
 		sessionTicket:               newSessionTicket.ticket,
 		vers:                        c.vers,
@@ -1651,6 +1635,27 @@
 		hasApplicationSettingsOld:   c.hasApplicationSettingsOld,
 		localApplicationSettingsOld: c.localApplicationSettingsOld,
 		peerApplicationSettingsOld:  c.peerApplicationSettingsOld,
+		resumptionAcrossNames:       newSessionTicket.flags.hasFlag(flagResumptionAcrossNames),
+	}
+
+	if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
+		return errors.New("tls: no GREASE ticket extension found")
+	}
+
+	if c.config.Bugs.ExpectTicketEarlyData && newSessionTicket.maxEarlyDataSize == 0 {
+		return errors.New("tls: no early_data ticket extension found")
+	}
+
+	if c.config.Bugs.ExpectNoNewSessionTicket || c.config.Bugs.ExpectNoNonEmptyNewSessionTicket {
+		return errors.New("tls: received unexpected NewSessionTicket")
+	}
+
+	if expect := c.config.Bugs.ExpectResumptionAcrossNames; expect != nil && session.resumptionAcrossNames != *expect {
+		return errors.New("tls: resumption_across_names status of ticket did not match expectation")
+	}
+
+	if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
+		return nil
 	}
 
 	cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
@@ -2030,6 +2035,10 @@
 		ticketAgeAdd:                ticketAgeAdd,
 		ticketNonce:                 nonce,
 		maxEarlyDataSize:            c.config.MaxEarlyDataSize,
+		flags: flagSet{
+			mustInclude: c.config.Bugs.AlwaysSendTicketFlags,
+			padding:     c.config.Bugs.TicketFlagPadding,
+		},
 	}
 	if c.config.Bugs.MockQUICTransport != nil && m.maxEarlyDataSize > 0 {
 		m.maxEarlyDataSize = 0xffffffff
@@ -2038,6 +2047,12 @@
 	if c.config.Bugs.SendTicketLifetime != 0 {
 		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
 	}
+	if c.config.ResumptionAcrossNames {
+		m.flags.setFlag(flagResumptionAcrossNames)
+	}
+	for _, flag := range c.config.Bugs.SendTicketFlags {
+		m.flags.setFlag(flag)
+	}
 
 	state := sessionState{
 		vers:                        c.vers,
diff --git a/src/ssl/test/runner/curve_tests.go b/src/ssl/test/runner/curve_tests.go
new file mode 100644
index 0000000..5afad08
--- /dev/null
+++ b/src/ssl/test/runner/curve_tests.go
@@ -0,0 +1,736 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"strconv"
+)
+
+var testCurves = []struct {
+	name string
+	id   CurveID
+}{
+	{"P-224", CurveP224},
+	{"P-256", CurveP256},
+	{"P-384", CurveP384},
+	{"P-521", CurveP521},
+	{"X25519", CurveX25519},
+	{"Kyber", CurveX25519Kyber768},
+	{"MLKEM", CurveX25519MLKEM768},
+}
+
+const bogusCurve = 0x1234
+
+func isPqGroup(r CurveID) bool {
+	return r == CurveX25519Kyber768 || r == CurveX25519MLKEM768
+}
+
+func isECDHGroup(r CurveID) bool {
+	return r == CurveP224 || r == CurveP256 || r == CurveP384 || r == CurveP521
+}
+
+func isX25519Group(r CurveID) bool {
+	return r == CurveX25519 || r == CurveX25519Kyber768 || r == CurveX25519MLKEM768
+}
+
+func addCurveTests() {
+	// A set of cipher suites that ensures some curve-using mode is used.
+	// Without this, servers may fall back to RSA key exchange.
+	ecdheCiphers := []uint16{
+		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+		TLS_AES_256_GCM_SHA384,
+	}
+
+	for _, curve := range testCurves {
+		for _, ver := range tlsVersions {
+			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
+				continue
+			}
+			for _, testType := range []testType{clientTest, serverTest} {
+				suffix := fmt.Sprintf("%s-%s-%s", testType, curve.name, ver.name)
+
+				testCases = append(testCases, testCase{
+					testType: testType,
+					name:     "CurveTest-" + suffix,
+					config: Config{
+						MaxVersion:       ver.version,
+						CipherSuites:     ecdheCiphers,
+						CurvePreferences: []CurveID{curve.id},
+					},
+					flags: append(
+						[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
+						flagInts("-curves", shimConfig.AllCurves)...,
+					),
+					expectations: connectionExpectations{
+						curveID: curve.id,
+					},
+				})
+
+				badKeyShareLocalError := "remote error: illegal parameter"
+				if testType == clientTest && ver.version >= VersionTLS13 {
+					// If the shim is a TLS 1.3 client and the runner sends a bad
+					// key share, the runner never reads the client's cleartext
+					// alert because the runner has already started encrypting by
+					// the time the client sees it.
+					badKeyShareLocalError = "local error: bad record MAC"
+				}
+
+				testCases = append(testCases, testCase{
+					testType: testType,
+					name:     "CurveTest-Invalid-TruncateKeyShare-" + suffix,
+					config: Config{
+						MaxVersion:       ver.version,
+						CipherSuites:     ecdheCiphers,
+						CurvePreferences: []CurveID{curve.id},
+						Bugs: ProtocolBugs{
+							TruncateKeyShare: true,
+						},
+					},
+					flags:              flagInts("-curves", shimConfig.AllCurves),
+					shouldFail:         true,
+					expectedError:      ":BAD_ECPOINT:",
+					expectedLocalError: badKeyShareLocalError,
+				})
+
+				testCases = append(testCases, testCase{
+					testType: testType,
+					name:     "CurveTest-Invalid-PadKeyShare-" + suffix,
+					config: Config{
+						MaxVersion:       ver.version,
+						CipherSuites:     ecdheCiphers,
+						CurvePreferences: []CurveID{curve.id},
+						Bugs: ProtocolBugs{
+							PadKeyShare: true,
+						},
+					},
+					flags:              flagInts("-curves", shimConfig.AllCurves),
+					shouldFail:         true,
+					expectedError:      ":BAD_ECPOINT:",
+					expectedLocalError: badKeyShareLocalError,
+				})
+
+				if isECDHGroup(curve.id) {
+					testCases = append(testCases, testCase{
+						testType: testType,
+						name:     "CurveTest-Invalid-Compressed-" + suffix,
+						config: Config{
+							MaxVersion:       ver.version,
+							CipherSuites:     ecdheCiphers,
+							CurvePreferences: []CurveID{curve.id},
+							Bugs: ProtocolBugs{
+								SendCompressedCoordinates: true,
+							},
+						},
+						flags:              flagInts("-curves", shimConfig.AllCurves),
+						shouldFail:         true,
+						expectedError:      ":BAD_ECPOINT:",
+						expectedLocalError: badKeyShareLocalError,
+					})
+					testCases = append(testCases, testCase{
+						testType: testType,
+						name:     "CurveTest-Invalid-NotOnCurve-" + suffix,
+						config: Config{
+							MaxVersion:       ver.version,
+							CipherSuites:     ecdheCiphers,
+							CurvePreferences: []CurveID{curve.id},
+							Bugs: ProtocolBugs{
+								ECDHPointNotOnCurve: true,
+							},
+						},
+						flags:              flagInts("-curves", shimConfig.AllCurves),
+						shouldFail:         true,
+						expectedError:      ":BAD_ECPOINT:",
+						expectedLocalError: badKeyShareLocalError,
+					})
+				}
+
+				if isX25519Group(curve.id) {
+					// Implementations should mask off the high order bit in X25519.
+					testCases = append(testCases, testCase{
+						testType: testType,
+						name:     "CurveTest-SetX25519HighBit-" + suffix,
+						config: Config{
+							MaxVersion:       ver.version,
+							CipherSuites:     ecdheCiphers,
+							CurvePreferences: []CurveID{curve.id},
+							Bugs: ProtocolBugs{
+								SetX25519HighBit: true,
+							},
+						},
+						flags: flagInts("-curves", shimConfig.AllCurves),
+						expectations: connectionExpectations{
+							curveID: curve.id,
+						},
+					})
+
+					// Implementations should reject low order points.
+					testCases = append(testCases, testCase{
+						testType: testType,
+						name:     "CurveTest-Invalid-LowOrderX25519Point-" + suffix,
+						config: Config{
+							MaxVersion:       ver.version,
+							CipherSuites:     ecdheCiphers,
+							CurvePreferences: []CurveID{curve.id},
+							Bugs: ProtocolBugs{
+								LowOrderX25519Point: true,
+							},
+						},
+						flags:              flagInts("-curves", shimConfig.AllCurves),
+						shouldFail:         true,
+						expectedError:      ":BAD_ECPOINT:",
+						expectedLocalError: badKeyShareLocalError,
+					})
+				}
+
+				if curve.id == CurveX25519MLKEM768 && testType == serverTest {
+					testCases = append(testCases, testCase{
+						testType: testType,
+						name:     "CurveTest-Invalid-MLKEMEncapKeyNotReduced-" + suffix,
+						config: Config{
+							MaxVersion:       ver.version,
+							CipherSuites:     ecdheCiphers,
+							CurvePreferences: []CurveID{curve.id},
+							Bugs: ProtocolBugs{
+								MLKEMEncapKeyNotReduced: true,
+							},
+						},
+						flags:              flagInts("-curves", shimConfig.AllCurves),
+						shouldFail:         true,
+						expectedError:      ":BAD_ECPOINT:",
+						expectedLocalError: badKeyShareLocalError,
+					})
+				}
+			}
+		}
+	}
+
+	// The server must be tolerant to bogus curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCurve",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{bogusCurve, CurveP256},
+		},
+	})
+
+	// The server must be tolerant to bogus curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCurve-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{bogusCurve, CurveP256},
+		},
+	})
+
+	// The server must not consider ECDHE ciphers when there are no
+	// supported curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedCurves",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				NoSupportedCurves: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_SHARED_CIPHER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedCurves-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NoSupportedCurves: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_SHARED_GROUP:",
+	})
+
+	// The server must fall back to another cipher when there are no
+	// supported curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoCommonCurves",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			CipherSuites: []uint16{
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+			},
+			CurvePreferences: []CurveID{CurveP224},
+		},
+		expectations: connectionExpectations{
+			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
+		},
+	})
+
+	// The client must reject bogus curves and disabled curves.
+	testCases = append(testCases, testCase{
+		name: "BadECDHECurve",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "BadECDHECurve-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnsupportedCurve",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				IgnorePeerCurvePreferences: true,
+			},
+		},
+		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		// TODO(davidben): Add a TLS 1.3 version where
+		// HelloRetryRequest requests an unsupported curve.
+		name: "UnsupportedCurve-ServerHello-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendCurve: CurveP256,
+			},
+		},
+		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	// The previous curve ID should be reported on TLS 1.2 resumption.
+	testCases = append(testCases, testCase{
+		name: "CurveID-Resume-Client",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CurveID-Resume-Server",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
+		resumeSession: true,
+	})
+
+	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
+	// one should be reported.
+	testCases = append(testCases, testCase{
+		name: "CurveID-Resume-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+		},
+		flags: []string{
+			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
+		},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CurveID-Resume-Server-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+		},
+		flags: []string{
+			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
+		},
+		resumeSession: true,
+	})
+
+	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-ServerHello-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatUncompressed},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "PointFormat-EncryptedExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatUncompressed},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+
+	// Server-sent supported groups/curves are legal in TLS 1.3. They are
+	// illegal in TLS 1.2, but some servers send them anyway, so we must
+	// tolerate them.
+	testCases = append(testCases, testCase{
+		name: "SupportedCurves-ServerHello-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendServerSupportedCurves: true,
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "SupportedCurves-EncryptedExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendServerSupportedCurves: true,
+			},
+		},
+	})
+
+	// Test that we tolerate unknown point formats, as long as
+	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
+	// check they are still functional.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-Tolerance",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-Tolerance",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+			},
+		},
+	})
+
+	// Test TLS 1.2 does not require the point format extension to be
+	// present.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-Missing",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-Missing",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{},
+			},
+		},
+	})
+
+	// If the point format extension is present, uncompressed points must be
+	// offered. BoringSSL requires this whether or not ECDHE is used.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-MissingUncompressed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-MissingUncompressed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+
+	// Post-quantum groups require TLS 1.3.
+	for _, curve := range testCurves {
+		if !isPqGroup(curve.id) {
+			continue
+		}
+
+		// Post-quantum groups should not be offered by a TLS 1.2 client.
+		testCases = append(testCases, testCase{
+			name: "TLS12ClientShouldNotOffer-" + curve.name,
+			config: Config{
+				Bugs: ProtocolBugs{
+					FailIfPostQuantumOffered: true,
+				},
+			},
+			flags: []string{
+				"-max-version", strconv.Itoa(VersionTLS12),
+				"-curves", strconv.Itoa(int(curve.id)),
+				"-curves", strconv.Itoa(int(CurveX25519)),
+			},
+		})
+
+		// Post-quantum groups should not be selected by a TLS 1.2 server.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "TLS12ServerShouldNotSelect-" + curve.name,
+			flags: []string{
+				"-max-version", strconv.Itoa(VersionTLS12),
+				"-curves", strconv.Itoa(int(curve.id)),
+				"-curves", strconv.Itoa(int(CurveX25519)),
+			},
+			expectations: connectionExpectations{
+				curveID: CurveX25519,
+			},
+		})
+
+		// If a TLS 1.2 server selects a post-quantum group anyway, the client
+		// should not accept it.
+		testCases = append(testCases, testCase{
+			name: "ClientShouldNotAllowInTLS12-" + curve.name,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCurve: curve.id,
+				},
+			},
+			flags: []string{
+				"-curves", strconv.Itoa(int(curve.id)),
+				"-curves", strconv.Itoa(int(CurveX25519)),
+			},
+			shouldFail:         true,
+			expectedError:      ":WRONG_CURVE:",
+			expectedLocalError: "remote error: illegal parameter",
+		})
+	}
+
+	// ML-KEM and Kyber should not be offered by default as a client.
+	testCases = append(testCases, testCase{
+		name: "PostQuantumNotEnabledByDefaultInClients",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				FailIfPostQuantumOffered: true,
+			},
+		},
+	})
+
+	// If ML-KEM is offered, both X25519 and ML-KEM should have a key-share.
+	testCases = append(testCases, testCase{
+		name: "NotJustMLKEMKeyShare",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768, CurveX25519},
+			},
+		},
+		flags: []string{
+			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+			"-curves", strconv.Itoa(int(CurveX25519)),
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
+		},
+	})
+
+	// ... and the other way around
+	testCases = append(testCases, testCase{
+		name: "MLKEMKeyShareIncludedSecond",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519MLKEM768},
+			},
+		},
+		flags: []string{
+			"-curves", strconv.Itoa(int(CurveX25519)),
+			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+			"-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.
+	testCases = append(testCases, testCase{
+		name: "MLKEMKeyShareIncludedThird",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519MLKEM768},
+			},
+		},
+		flags: []string{
+			"-curves", strconv.Itoa(int(CurveX25519)),
+			"-curves", strconv.Itoa(int(CurveP256)),
+			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+		},
+	})
+
+	// If ML-KEM is the only configured curve, the key share is sent.
+	testCases = append(testCases, testCase{
+		name: "JustConfiguringMLKEMWorks",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768},
+			},
+		},
+		flags: []string{
+			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
+		},
+	})
+
+	// If both ML-KEM and Kyber are configured, only the preferred one's
+	// key share should be sent.
+	testCases = append(testCases, testCase{
+		name: "BothMLKEMAndKyber",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768},
+			},
+		},
+		flags: []string{
+			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
+		},
+	})
+
+	// As a server, ML-KEM is not yet supported by default.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PostQuantumNotEnabledByDefaultForAServer",
+		config: Config{
+			MinVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519MLKEM768, CurveX25519Kyber768, CurveX25519},
+			DefaultCurves:    []CurveID{CurveX25519MLKEM768, CurveX25519Kyber768},
+		},
+		flags: []string{
+			"-server-preference",
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+		},
+	})
+
+	// In TLS 1.2, the curve list is also used to signal ECDSA curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CheckECDSACurve-TLS12",
+		config: Config{
+			MinVersion:       VersionTLS12,
+			MaxVersion:       VersionTLS12,
+			CurvePreferences: []CurveID{CurveP384},
+		},
+		shimCertificate: &ecdsaP256Certificate,
+		shouldFail:      true,
+		expectedError:   ":WRONG_CURVE:",
+	})
+
+	// If the ECDSA certificate is ineligible due to a curve mismatch, the
+	// server may still consider a PSK cipher suite.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CheckECDSACurve-PSK-TLS12",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+			CipherSuites: []uint16{
+				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+				TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+			},
+			CurvePreferences:     []CurveID{CurveP384},
+			PreSharedKey:         []byte("12345"),
+			PreSharedKeyIdentity: "luggage combo",
+		},
+		shimCertificate: &ecdsaP256Certificate,
+		expectations: connectionExpectations{
+			cipher: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+		},
+		flags: []string{
+			"-psk", "12345",
+			"-psk-identity", "luggage combo",
+		},
+	})
+
+	// In TLS 1.3, the curve list only controls ECDH.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CheckECDSACurve-NotApplicable-TLS13",
+		config: Config{
+			MinVersion:       VersionTLS13,
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP384},
+		},
+		shimCertificate: &ecdsaP256Certificate,
+	})
+}
diff --git a/src/ssl/test/runner/ddos_callback_tests.go b/src/ssl/test/runner/ddos_callback_tests.go
new file mode 100644
index 0000000..ad292de
--- /dev/null
+++ b/src/ssl/test/runner/ddos_callback_tests.go
@@ -0,0 +1,73 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addDDoSCallbackTests() {
+	// DDoS callback.
+	for _, resume := range []bool{false, true} {
+		suffix := "Resume"
+		if resume {
+			suffix = "No" + suffix
+		}
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-OK-" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:         []string{"-install-ddos-callback"},
+			resumeSession: resume,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			flags:         []string{"-install-ddos-callback"},
+			resumeSession: resume,
+		})
+
+		failFlag := "-fail-ddos-callback"
+		if resume {
+			failFlag = "-on-resume-fail-ddos-callback"
+		}
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-Reject-" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:              []string{"-install-ddos-callback", failFlag},
+			resumeSession:      resume,
+			shouldFail:         true,
+			expectedError:      ":CONNECTION_REJECTED:",
+			expectedLocalError: "remote error: internal error",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			flags:              []string{"-install-ddos-callback", failFlag},
+			resumeSession:      resume,
+			shouldFail:         true,
+			expectedError:      ":CONNECTION_REJECTED:",
+			expectedLocalError: "remote error: internal error",
+		})
+	}
+}
diff --git a/src/ssl/test/runner/delegated_credential_tests.go b/src/ssl/test/runner/delegated_credential_tests.go
new file mode 100644
index 0000000..a39c3ed
--- /dev/null
+++ b/src/ssl/test/runner/delegated_credential_tests.go
@@ -0,0 +1,300 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/x509"
+	"fmt"
+	"time"
+
+	"golang.org/x/crypto/cryptobyte"
+)
+
+// delegatedCredentialConfig specifies the shape of a delegated credential, not
+// including the keys themselves.
+type delegatedCredentialConfig struct {
+	// lifetime is the amount of time, from the notBefore of the parent
+	// certificate, that the delegated credential is valid for. If zero, then 24
+	// hours is assumed.
+	lifetime time.Duration
+	// dcAlgo is the signature scheme that should be used with this delegated
+	// credential. If zero, ECDSA with P-256 is assumed.
+	dcAlgo signatureAlgorithm
+	// algo is the signature algorithm that the delegated credential itself is
+	// signed with. Cannot be zero.
+	algo signatureAlgorithm
+}
+
+func createDelegatedCredential(parent *Credential, config delegatedCredentialConfig) *Credential {
+	if parent.Type != CredentialTypeX509 {
+		panic("delegated credentials must be issued by X.509 credentials")
+	}
+
+	dcAlgo := config.dcAlgo
+	if dcAlgo == 0 {
+		dcAlgo = signatureECDSAWithP256AndSHA256
+	}
+
+	var dcPriv crypto.Signer
+	switch dcAlgo {
+	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
+		dcPriv = &rsa2048Key
+
+	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
+		var curve elliptic.Curve
+		switch dcAlgo {
+		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
+			curve = elliptic.P256()
+		case signatureECDSAWithP384AndSHA384:
+			curve = elliptic.P384()
+		case signatureECDSAWithP521AndSHA512:
+			curve = elliptic.P521()
+		default:
+			panic("internal error")
+		}
+
+		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
+		if err != nil {
+			panic(err)
+		}
+		dcPriv = priv
+
+	default:
+		panic(fmt.Errorf("unsupported DC signature algorithm: %x", dcAlgo))
+	}
+
+	lifetime := config.lifetime
+	if lifetime == 0 {
+		lifetime = 24 * time.Hour
+	}
+	lifetimeSecs := int64(lifetime.Seconds())
+	if lifetimeSecs < 0 || lifetimeSecs > 1<<32 {
+		panic(fmt.Errorf("lifetime %s is too long to be expressed", lifetime))
+	}
+
+	// https://www.rfc-editor.org/rfc/rfc9345.html#section-4
+	dc := cryptobyte.NewBuilder(nil)
+	dc.AddUint32(uint32(lifetimeSecs))
+	dc.AddUint16(uint16(dcAlgo))
+
+	pubBytes, err := x509.MarshalPKIXPublicKey(dcPriv.Public())
+	if err != nil {
+		panic(err)
+	}
+	addUint24LengthPrefixedBytes(dc, pubBytes)
+
+	var dummyConfig Config
+	parentSignature, err := signMessage(false /* server */, VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
+	if err != nil {
+		panic(err)
+	}
+
+	dc.AddUint16(uint16(config.algo))
+	addUint16LengthPrefixedBytes(dc, parentSignature)
+
+	dcCred := *parent
+	dcCred.Type = CredentialTypeDelegated
+	dcCred.DelegatedCredential = dc.BytesOrPanic()
+	dcCred.PrivateKey = dcPriv
+	dcCred.KeyPath = writeTempKeyFile(dcPriv)
+	return &dcCred
+}
+
+func addDelegatedCredentialTests() {
+	p256DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
+		dcAlgo: signatureECDSAWithP256AndSHA256,
+		algo:   signatureRSAPSSWithSHA256,
+	})
+	p256DCFromECDSA := createDelegatedCredential(&ecdsaP256Certificate, delegatedCredentialConfig{
+		dcAlgo: signatureECDSAWithP256AndSHA256,
+		algo:   signatureECDSAWithP256AndSHA256,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-NoClientSupport",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-Basic",
+		config: Config{
+			MinVersion:                    VersionTLS13,
+			MaxVersion:                    VersionTLS13,
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "0"},
+		expectations: connectionExpectations{
+			peerCertificate: p256DC,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-ExactAlgorithmMatch",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			// Test that the server doesn't mix up the two signature algorithm
+			// fields. These options are a match because the signature_algorithms
+			// extension matches against the signature on the delegated
+			// credential, while the delegated_credential extension matches
+			// against the signature made by the delegated credential.
+			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "0"},
+		expectations: connectionExpectations{
+			peerCertificate: p256DC,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-SigAlgoMissing",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			// If the client doesn't support the signature in the delegated credential,
+			// the server should not use delegated credentials.
+			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA384},
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-CertVerifySigAlgoMissing",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			// If the client doesn't support the delegated credential's
+			// CertificateVerify algorithm, the server should not use delegated
+			// credentials.
+			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+	})
+
+	// Delegated credentials are not supported at TLS 1.2, even if the client
+	// sends the extension.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-TLS12-Forbidden",
+		config: Config{
+			MinVersion:                    VersionTLS12,
+			MaxVersion:                    VersionTLS12,
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+		},
+		shimCredentials: []*Credential{p256DC, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+	})
+
+	// Generate another delegated credential, so we can get the keys out of sync.
+	dcWrongKey := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
+		algo: signatureRSAPSSWithSHA256,
+	})
+	dcWrongKey.DelegatedCredential = p256DC.DelegatedCredential
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-KeyMismatch",
+		// The handshake hints version of the test will, as a side effect, use a
+		// custom private key. Custom private keys can't be checked for key
+		// mismatches.
+		skipHints:       true,
+		shimCredentials: []*Credential{dcWrongKey},
+		shouldFail:      true,
+		expectedError:   ":KEY_VALUES_MISMATCH:",
+	})
+
+	// RSA delegated credentials should be rejected at configuration time.
+	rsaDC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
+		algo:   signatureRSAPSSWithSHA256,
+		dcAlgo: signatureRSAPSSWithSHA256,
+	})
+	testCases = append(testCases, testCase{
+		testType:        serverTest,
+		name:            "DelegatedCredentials-NoRSA",
+		shimCredentials: []*Credential{rsaDC},
+		shouldFail:      true,
+		expectedError:   ":INVALID_SIGNATURE_ALGORITHM:",
+	})
+
+	// If configured with multiple delegated credentials, the server can cleanly
+	// select the first one that works.
+	p384DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
+		dcAlgo: signatureECDSAWithP384AndSHA384,
+		algo:   signatureRSAPSSWithSHA256,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-Multiple",
+		config: Config{
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
+		},
+		shimCredentials: []*Credential{p256DC, p384DC},
+		flags:           []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: p384DC,
+		},
+	})
+
+	// Delegated credentials participate in issuer-based certificate selection.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DelegatedCredentials-MatchIssuer",
+		config: Config{
+			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
+			// The client requested p256DCFromECDSA's issuer.
+			RootCAs:     makeCertPoolFromRoots(p256DCFromECDSA),
+			SendRootCAs: true,
+		},
+		shimCredentials: []*Credential{
+			p256DC.WithMustMatchIssuer(true), p256DCFromECDSA.WithMustMatchIssuer(true)},
+		flags: []string{"-expect-selected-credential", "1"},
+		expectations: connectionExpectations{
+			peerCertificate: p256DCFromECDSA,
+		},
+	})
+
+}
diff --git a/src/ssl/test/runner/dtls_tests.go b/src/ssl/test/runner/dtls_tests.go
new file mode 100644
index 0000000..8ad208d
--- /dev/null
+++ b/src/ssl/test/runner/dtls_tests.go
@@ -0,0 +1,1416 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"slices"
+	"strconv"
+	"time"
+)
+
+func addDTLSReplayTests() {
+	for _, vers := range allVersions(dtls) {
+		// Test that sequence number replays are detected.
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "DTLS-Replay-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+			},
+			messageCount: 200,
+			replayWrites: true,
+		})
+
+		// Test the incoming sequence number skipping by values larger
+		// than the retransmit window.
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "DTLS-Replay-LargeGaps-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Bugs: ProtocolBugs{
+					SequenceNumberMapping: func(in uint64) uint64 {
+						return in * 1023
+					},
+				},
+			},
+			messageCount: 200,
+			replayWrites: true,
+		})
+
+		// Test the incoming sequence number changing non-monotonically.
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "DTLS-Replay-NonMonotonic-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Bugs: ProtocolBugs{
+					SequenceNumberMapping: func(in uint64) uint64 {
+						// This mapping has numbers counting backwards in groups
+						// of 256, and then jumping forwards 511 numbers.
+						return in ^ 255
+					},
+				},
+			},
+			// This messageCount is large enough to make sure that the SequenceNumberMapping
+			// will reach the point where it jumps forwards after stepping backwards.
+			messageCount: 500,
+			replayWrites: true,
+		})
+	}
+}
+
+// timeouts is the default retransmit schedule for BoringSSL. It doubles and
+// caps at 60 seconds. On the 13th timeout, it gives up.
+var timeouts = []time.Duration{
+	400 * time.Millisecond,
+	800 * time.Millisecond,
+	1600 * time.Millisecond,
+	3200 * time.Millisecond,
+	6400 * time.Millisecond,
+	12800 * time.Millisecond,
+	25600 * time.Millisecond,
+	51200 * time.Millisecond,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+}
+
+// shortTimeouts is an alternate set of timeouts which would occur if the
+// initial timeout duration was set to 250ms.
+var shortTimeouts = []time.Duration{
+	250 * time.Millisecond,
+	500 * time.Millisecond,
+	1 * time.Second,
+	2 * time.Second,
+	4 * time.Second,
+	8 * time.Second,
+	16 * time.Second,
+	32 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+}
+
+// dtlsPrevEpochExpiration is how long before the shim releases old epochs. Add
+// an extra second to allow the shim to be less precise.
+const dtlsPrevEpochExpiration = 4*time.Minute + 1*time.Second
+
+func addDTLSRetransmitTests() {
+	for _, shortTimeout := range []bool{false, true} {
+		for _, vers := range allVersions(dtls) {
+			suffix := "-" + vers.name
+			flags := []string{"-async"} // Retransmit tests require async.
+			useTimeouts := timeouts
+			if shortTimeout {
+				suffix += "-Short"
+				flags = append(flags, "-initial-timeout-duration-ms", "250")
+				useTimeouts = shortTimeouts
+			}
+
+			// Testing NewSessionTicket is tricky. First, BoringSSL sends two
+			// tickets in a row. These are conceptually separate flights, but we
+			// test them as one flight. Second, these tickets are sent
+			// concurrently with the runner's first test message. The shim's
+			// reply will come in before any retransmit challenges.
+			// handleNewSessionTicket corrects for both effects.
+			handleNewSessionTicket := func(f ACKFlightFunc) ACKFlightFunc {
+				if vers.version < VersionTLS13 {
+					return f
+				}
+				return func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+					// BoringSSL sends two NewSessionTickets in a row.
+					if received[0].Type == typeNewSessionTicket && len(received) < 2 {
+						c.MergeIntoNextFlight()
+						return
+					}
+					// NewSessionTicket is sent in parallel with the runner's
+					// first application data. Consume the shim's reply.
+					testMessage := makeTestMessage(0, 32)
+					if received[0].Type == typeNewSessionTicket {
+						c.ReadAppData(c.InEpoch(), expectedReply(testMessage))
+					}
+					// Run the test, without any stray messages in the way.
+					f(c, prev, received, records)
+					// The test loop is expecting a reply to the first message.
+					// Prime the shim to send it again.
+					if received[0].Type == typeNewSessionTicket {
+						c.WriteAppData(c.OutEpoch(), testMessage)
+					}
+				}
+			}
+
+			// In all versions, the sender will retransmit the whole flight if
+			// it times out and hears nothing.
+			writeFlightBasic := func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+				if len(received) > 0 {
+					// Exercise every timeout but the last one (which would fail the
+					// connection).
+					for _, t := range useTimeouts[:len(useTimeouts)-1] {
+						c.ExpectNextTimeout(t)
+						c.AdvanceClock(t)
+						c.ReadRetransmit()
+					}
+					c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
+				}
+				// Finally release the whole flight to the shim.
+				c.WriteFlight(next)
+			}
+			ackFlightBasic := handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+				if vers.version >= VersionTLS13 {
+					// In DTLS 1.3, final flights (either handshake or post-handshake)
+					// are retransmited until ACKed. Exercise every timeout but
+					// the last one (which would fail the connection).
+					for _, t := range useTimeouts[:len(useTimeouts)-1] {
+						c.ExpectNextTimeout(t)
+						c.AdvanceClock(t)
+						c.ReadRetransmit()
+					}
+					c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
+					// Finally ACK the flight.
+					c.WriteACK(c.OutEpoch(), records)
+					return
+				}
+				// In DTLS 1.2, the final flight is retransmitted on receipt of
+				// the previous flight. Test the peer is willing to retransmit
+				// it several times.
+				for i := 0; i < 5; i++ {
+					c.WriteFlight(prev)
+					c.ReadRetransmit()
+				}
+			})
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "DTLS-Retransmit-Client-Basic" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						WriteFlightDTLS: writeFlightBasic,
+						ACKFlightDTLS:   ackFlightBasic,
+					},
+				},
+				resumeSession: true,
+				flags:         flags,
+			})
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				testType: serverTest,
+				name:     "DTLS-Retransmit-Server-Basic" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						WriteFlightDTLS: writeFlightBasic,
+						ACKFlightDTLS:   ackFlightBasic,
+					},
+				},
+				resumeSession: true,
+				flags:         flags,
+			})
+
+			if vers.version <= VersionTLS12 {
+				// In DTLS 1.2, receiving a part of the next flight should not stop
+				// the retransmission timer.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-PartialProgress" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								// Send a portion of the first message. The rest was lost.
+								msg := next[0]
+								split := len(msg.Data) / 2
+								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
+								// If we time out, the shim should still retransmit. It knows
+								// we received the whole flight, but the shim should use a
+								// retransmit to request the runner try again.
+								c.AdvanceClock(useTimeouts[0])
+								c.ReadRetransmit()
+								// "Retransmit" the rest of the flight. The shim should remember
+								// the portion that was already sent.
+								rest := []DTLSFragment{msg.Fragment(split, len(msg.Data)-split)}
+								for _, m := range next[1:] {
+									rest = append(rest, m.Fragment(0, len(m.Data)))
+								}
+								c.WriteFragments(rest)
+							},
+						},
+					},
+					flags: flags,
+				})
+			} else {
+				// In DTLS 1.3, receiving a part of the next flight implicitly ACKs
+				// the previous flight.
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: dtls,
+					name:     "DTLS-Retransmit-PartialProgress-Server" + suffix,
+					config: Config{
+						MaxVersion:    vers.version,
+						DefaultCurves: []CurveID{}, // Force HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) == 0 && next[0].Type == typeClientHello {
+									// Send the initial ClientHello as-is.
+									c.WriteFlight(next)
+									return
+								}
+
+								// Send a portion of the first message. The rest was lost.
+								msg := next[0]
+								split := len(msg.Data) / 2
+								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
+								// After waiting the current timeout, the shim should ACK
+								// the partial flight.
+								c.ExpectNextTimeout(useTimeouts[0] / 4)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+								// The partial flight is enough to ACK the previous flight.
+								// The shim should stop retransmitting and even stop the
+								// retransmit timer.
+								c.ExpectNoNextTimeout()
+								for _, t := range useTimeouts {
+									c.AdvanceClock(t)
+								}
+								// "Retransmit" the rest of the flight. The shim should remember
+								// the portion that was already sent.
+								rest := []DTLSFragment{msg.Fragment(split, len(msg.Data)-split)}
+								for _, m := range next[1:] {
+									rest = append(rest, m.Fragment(0, len(m.Data)))
+								}
+								c.WriteFragments(rest)
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				// When the shim is a client, receiving fragments before the version is
+				// known does not trigger this behavior.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-PartialProgress-Client" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								msg := next[0]
+								if msg.Type != typeServerHello {
+									// Post-handshake is tested separately.
+									c.WriteFlight(next)
+									return
+								}
+								// Send a portion of the ServerHello. The rest was lost.
+								split := len(msg.Data) / 2
+								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
+
+								// The shim did not know this was DTLS 1.3, so it still
+								// retransmits ClientHello.
+								c.ExpectNextTimeout(useTimeouts[0])
+								c.AdvanceClock(useTimeouts[0])
+								c.ReadRetransmit()
+
+								// Finish the ServerHello. The version is still not known,
+								// at the time the ServerHello fragment is processed, This
+								// is not as efficient as we could be; we could go back and
+								// implicitly ACK once the version is known. But the last
+								// byte of ServerHello will almost certainly be in the same
+								// packet as EncryptedExtensions, which will trigger the case
+								// below.
+								c.WriteFragments([]DTLSFragment{msg.Fragment(split, len(msg.Data)-split)})
+								c.ExpectNextTimeout(useTimeouts[1])
+								c.AdvanceClock(useTimeouts[1])
+								c.ReadRetransmit()
+
+								// Send EncryptedExtensions. The shim now knows the version.
+								c.WriteFragments([]DTLSFragment{next[1].Fragment(0, len(next[1].Data))})
+
+								// The shim should ACK the partial flight. The shim hasn't
+								// gotten to epoch 3 yet, so the ACK will come in epoch 2.
+								c.AdvanceClock(useTimeouts[2] / 4)
+								c.ReadACK(uint16(encryptionHandshake))
+
+								// This is enough to ACK the previous flight. The shim
+								// should stop retransmitting and even stop the timer.
+								c.ExpectNoNextTimeout()
+								for _, t := range useTimeouts[2:] {
+									c.AdvanceClock(t)
+								}
+
+								// "Retransmit" the rest of the flight. The shim should remember
+								// the portion that was already sent.
+								var rest []DTLSFragment
+								for _, m := range next[2:] {
+									rest = append(rest, m.Fragment(0, len(m.Data)))
+								}
+								c.WriteFragments(rest)
+							},
+						},
+					},
+					flags: flags,
+				})
+			}
+
+			// Test that exceeding the timeout schedule hits a read
+			// timeout.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "DTLS-Retransmit-Timeout" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+							for _, t := range useTimeouts[:len(useTimeouts)-1] {
+								c.ExpectNextTimeout(t)
+								c.AdvanceClock(t)
+								c.ReadRetransmit()
+							}
+							c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
+							c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
+							// The shim should give up at this point.
+						},
+					},
+				},
+				resumeSession: true,
+				flags:         flags,
+				shouldFail:    true,
+				expectedError: ":READ_TIMEOUT_EXPIRED:",
+			})
+
+			// Test that timeout handling has a fudge factor, due to API
+			// problems.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "DTLS-Retransmit-Fudge" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+							if len(received) > 0 {
+								c.ExpectNextTimeout(useTimeouts[0])
+								c.AdvanceClock(useTimeouts[0] - 10*time.Millisecond)
+								c.ReadRetransmit()
+							}
+							c.WriteFlight(next)
+						},
+					},
+				},
+				resumeSession: true,
+				flags:         flags,
+			})
+
+			// Test that the shim can retransmit at different MTUs.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "DTLS-Retransmit-ChangeMTU" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					// Request a client certificate, so the shim has more to send.
+					ClientAuth: RequireAnyClientCert,
+					Bugs: ProtocolBugs{
+						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+							for i, mtu := range []int{300, 301, 302, 303, 299, 298, 297} {
+								c.SetMTU(mtu)
+								c.AdvanceClock(useTimeouts[i])
+								c.ReadRetransmit()
+							}
+							c.WriteFlight(next)
+						},
+					},
+				},
+				shimCertificate: &rsaChainCertificate,
+				flags:           flags,
+			})
+
+			// DTLS 1.3 uses explicit ACKs.
+			if vers.version >= VersionTLS13 {
+				// The two server flights (HelloRetryRequest and ServerHello..Finished)
+				// happen after the shim has learned the version, so they are more
+				// straightforward. In these tests, we trigger HelloRetryRequest,
+				// and also use ML-KEM with rsaChainCertificate and a limited MTU,
+				// to increase the number of records and exercise more complex
+				// ACK patterns.
+
+				// After ACKing everything, the shim should stop retransmitting.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKEverything" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						Credential:       &rsaChainCertificate,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							// Send smaller packets to exercise more ACK cases.
+							MaxPacketLength:          512,
+							MaxHandshakeRecordLength: 512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									c.ExpectNextTimeout(useTimeouts[0])
+									c.WriteACK(ackEpoch, records)
+									// After everything is ACKed, the shim should stop the timer
+									// and wait for the next flight.
+									c.ExpectNoNextTimeout()
+									for _, t := range useTimeouts {
+										c.AdvanceClock(t)
+									}
+								}
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								ackEpoch := received[len(received)-1].Epoch
+								c.ExpectNextTimeout(useTimeouts[0])
+								c.WriteACK(ackEpoch, records)
+								// After everything is ACKed, the shim should stop the timer.
+								c.ExpectNoNextTimeout()
+								for _, t := range useTimeouts {
+									c.AdvanceClock(t)
+								}
+							}),
+							SequenceNumberMapping: func(in uint64) uint64 {
+								// Perturb sequence numbers to test that ACKs are sorted.
+								return in ^ 63
+							},
+						},
+					},
+					shimCertificate: &rsaChainCertificate,
+					flags: slices.Concat(flags, []string{
+						"-mtu", "512",
+						"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
+						// Request a client certificate so the client final flight is
+						// larger.
+						"-require-any-client-certificate",
+					}),
+				})
+
+				// ACK packets one by one, in reverse.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKReverse" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							MaxPacketLength: 512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									for _, t := range useTimeouts[:len(useTimeouts)-1] {
+										if len(records) > 0 {
+											c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[len(records)-1]})
+										}
+										c.AdvanceClock(t)
+										records = c.ReadRetransmit()
+									}
+								}
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								ackEpoch := received[len(received)-1].Epoch
+								for _, t := range useTimeouts[:len(useTimeouts)-1] {
+									if len(records) > 0 {
+										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[len(records)-1]})
+									}
+									c.AdvanceClock(t)
+									records = c.ReadRetransmit()
+								}
+							}),
+						},
+					},
+					shimCertificate: &rsaChainCertificate,
+					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// ACK packets one by one, forwards.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKForwards" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							MaxPacketLength: 512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									for _, t := range useTimeouts[:len(useTimeouts)-1] {
+										if len(records) > 0 {
+											c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
+										}
+										c.AdvanceClock(t)
+										records = c.ReadRetransmit()
+									}
+								}
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								ackEpoch := received[len(received)-1].Epoch
+								for _, t := range useTimeouts[:len(useTimeouts)-1] {
+									if len(records) > 0 {
+										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
+									}
+									c.AdvanceClock(t)
+									records = c.ReadRetransmit()
+								}
+							}),
+						},
+					},
+					shimCertificate: &rsaChainCertificate,
+					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// ACK 1/3 the packets each time.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKIterate" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							MaxPacketLength: 512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									for i, t := range useTimeouts[:len(useTimeouts)-1] {
+										if len(records) > 0 {
+											ack := make([]DTLSRecordNumberInfo, 0, (len(records)+2)/3)
+											for i := 0; i < len(records); i += 3 {
+												ack = append(ack, records[i])
+											}
+											c.WriteACK(ackEpoch, ack)
+										}
+										// Change the MTU every iteration, to make the fragment
+										// patterns more complex.
+										c.SetMTU(512 + i)
+										c.AdvanceClock(t)
+										records = c.ReadRetransmit()
+									}
+								}
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								ackEpoch := received[len(received)-1].Epoch
+								for _, t := range useTimeouts[:len(useTimeouts)-1] {
+									if len(records) > 0 {
+										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
+									}
+									c.AdvanceClock(t)
+									records = c.ReadRetransmit()
+								}
+							}),
+						},
+					},
+					shimCertificate: &rsaChainCertificate,
+					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// ACKing packets that have already been ACKed is a no-op.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKDuplicate" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							SendHelloRetryRequestCookie: []byte("cookie"),
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									// Keep ACKing the same record over and over.
+									c.WriteACK(ackEpoch, records[:1])
+									c.AdvanceClock(useTimeouts[0])
+									c.ReadRetransmit()
+									c.WriteACK(ackEpoch, records[:1])
+									c.AdvanceClock(useTimeouts[1])
+									c.ReadRetransmit()
+								}
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								ackEpoch := received[len(received)-1].Epoch
+								// Keep ACKing the same record over and over.
+								c.WriteACK(ackEpoch, records[:1])
+								c.AdvanceClock(useTimeouts[0])
+								c.ReadRetransmit()
+								c.WriteACK(ackEpoch, records[:1])
+								c.AdvanceClock(useTimeouts[1])
+								c.ReadRetransmit()
+								// ACK everything to clear the timer.
+								c.WriteACK(ackEpoch, records)
+							}),
+						},
+					},
+					flags: flags,
+				})
+
+				// When ACKing ServerHello..Finished, the ServerHello might be
+				// ACKed at epoch 0 or epoch 2, depending on how far the client
+				// received. Test that epoch 0 is allowed by ACKing each packet
+				// at the record it was received.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKMatchingEpoch" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									for _, t := range useTimeouts[:len(useTimeouts)-1] {
+										if len(records) > 0 {
+											c.WriteACK(uint16(records[0].Epoch), []DTLSRecordNumberInfo{records[0]})
+										}
+										c.AdvanceClock(t)
+										records = c.ReadRetransmit()
+									}
+								}
+								c.WriteFlight(next)
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				// However, records in the handshake may not be ACKed at lower
+				// epoch than they were received.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKBadEpoch" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) == 0 {
+									// Send the ClientHello.
+									c.WriteFlight(next)
+								} else {
+									// Try to ACK ServerHello..Finished at epoch 0. The shim should reject this.
+									c.WriteACK(0, records)
+								}
+							},
+						},
+					},
+					flags:         flags,
+					shouldFail:    true,
+					expectedError: ":DECODE_ERROR:",
+				})
+
+				// The bad epoch check should notice when the epoch number
+				// would overflow 2^16.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKEpochOverflow" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) == 0 {
+									// Send the ClientHello.
+									c.WriteFlight(next)
+								} else {
+									r := records[0]
+									r.Epoch += 1 << 63
+									c.WriteACK(0, []DTLSRecordNumberInfo{r})
+								}
+							},
+						},
+					},
+					flags:         flags,
+					shouldFail:    true,
+					expectedError: ":DECODE_ERROR:",
+				})
+
+				// ACK some records from the first transmission, trigger a
+				// retransmit, but then ACK the rest of the first transmission.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKOldRecords" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						Bugs: ProtocolBugs{
+							MaxPacketLength: 512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									ackEpoch := received[len(received)-1].Epoch
+									c.WriteACK(ackEpoch, records[len(records)/2:])
+									c.AdvanceClock(useTimeouts[0])
+									c.ReadRetransmit()
+									c.WriteACK(ackEpoch, records[:len(records)/2])
+									// Everything should be ACKed now. The shim should not
+									// retransmit anything.
+									c.AdvanceClock(useTimeouts[1])
+									c.AdvanceClock(useTimeouts[2])
+									c.AdvanceClock(useTimeouts[3])
+								}
+								c.WriteFlight(next)
+							},
+						},
+					},
+					flags: slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// If the shim sends too many records, it will eventually forget them.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKForgottenRecords" + suffix,
+					config: Config{
+						MaxVersion:       vers.version,
+						CurvePreferences: []CurveID{CurveX25519MLKEM768},
+						Bugs: ProtocolBugs{
+							MaxPacketLength: 256,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) > 0 {
+									// Make the peer retransmit many times, with a small MTU.
+									for _, t := range useTimeouts[:len(useTimeouts)-2] {
+										c.AdvanceClock(t)
+										c.ReadRetransmit()
+									}
+									// ACK the first record the shim ever sent. It will have
+									// fallen off the queue by now, so it is expected to not
+									// impact the shim's retransmissions.
+									c.WriteACK(c.OutEpoch(), []DTLSRecordNumberInfo{{DTLSRecordNumber: records[0].DTLSRecordNumber}})
+									c.AdvanceClock(useTimeouts[len(useTimeouts)-2])
+									c.ReadRetransmit()
+								}
+								c.WriteFlight(next)
+							},
+						},
+					},
+					flags: slices.Concat(flags, []string{"-mtu", "256", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// The shim should ignore ACKs for a previous flight, and not get its
+				// internal state confused.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKPreviousFlight" + suffix,
+					config: Config{
+						MaxVersion:    vers.version,
+						DefaultCurves: []CurveID{}, // Force a HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[len(next)-1].Type == typeFinished {
+									// We are now sending client Finished, in response
+									// to the shim's ServerHello. ACK the shim's first
+									// record, which would have been part of
+									// HelloRetryRequest. This should not impact retransmit.
+									c.WriteACK(c.OutEpoch(), []DTLSRecordNumberInfo{{DTLSRecordNumber: DTLSRecordNumber{Epoch: 0, Sequence: 0}}})
+									c.AdvanceClock(useTimeouts[0])
+									c.ReadRetransmit()
+								}
+								c.WriteFlight(next)
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				// Records that contain a mix of discarded and processed fragments should
+				// not be ACKed.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-DoNotACKDiscardedFragments" + suffix,
+					config: Config{
+						MaxVersion:    vers.version,
+						DefaultCurves: []CurveID{}, // Force a HelloRetryRequest.
+						Bugs: ProtocolBugs{
+							PackHandshakeFragments: 4096,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								// Send the flight, but combine every fragment with a far future
+								// fragment, which the shim will discard. During the handshake,
+								// the shim has enough information to reject this entirely, but
+								// that would require coordinating with the handshake state
+								// machine. Instead, BoringSSL discards the fragment and skips
+								// ACKing the packet.
+								//
+								// runner implicitly tests that the shim ACKs the Finished flight
+								// (or, in case, that it is does not), so this exercises the final
+								// ACK.
+								for _, msg := range next {
+									shouldDiscard := DTLSFragment{Epoch: msg.Epoch, Sequence: 1000, ShouldDiscard: true}
+									c.WriteFragments([]DTLSFragment{shouldDiscard, msg.Fragment(0, len(msg.Data))})
+									// The shim has nothing to ACK and thus no ACK timer (which
+									// would be 1/4 of this value).
+									c.ExpectNextTimeout(useTimeouts[0])
+								}
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				// The server must continue to ACK the Finished flight even after
+				// receiving application data from the client.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					testType: serverTest,
+					name:     "DTLS-Retransmit-Server-ACKFinishedAfterAppData" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							// WriteFlightDTLS will handle consuming ACKs.
+							SkipImplicitACKRead: true,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[len(next)-1].Type != typeFinished {
+									c.WriteFlight(next)
+									return
+								}
+
+								// Write Finished. The shim should ACK it immediately.
+								c.WriteFlight(next)
+								c.ReadACK(c.InEpoch())
+
+								// Exchange some application data.
+								msg := []byte("hello")
+								c.WriteAppData(c.OutEpoch(), msg)
+								c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+								// Act as if the ACK was dropped and retransmit Finished.
+								// The shim should process the retransmit from epoch 2 and
+								// ACK, although it has already received data at epoch 3.
+								c.WriteFlight(next)
+								ackTimeout := useTimeouts[0] / 4
+								c.AdvanceClock(ackTimeout)
+								c.ReadACK(c.InEpoch())
+
+								// Partially retransmit Finished. The shim should continue
+								// to ACK.
+								c.WriteFragments([]DTLSFragment{next[0].Fragment(0, 1)})
+								c.WriteFragments([]DTLSFragment{next[0].Fragment(1, 1)})
+								c.AdvanceClock(ackTimeout)
+								c.ReadACK(c.InEpoch())
+
+								// Eventually, the shim assumes we have received the ACK
+								// and drops epoch 2. Retransmits now go unanswered.
+								c.AdvanceClock(dtlsPrevEpochExpiration)
+								c.WriteFlight(next)
+							},
+						},
+					},
+					// Disable tickets on the shim to avoid NewSessionTicket
+					// interfering with the test callback.
+					flags: slices.Concat(flags, []string{"-no-ticket"}),
+				})
+
+				// As a client, the shim must tolerate ACKs in response to its
+				// initial ClientHello, but it will not process them because the
+				// version is not yet known. The second ClientHello, in response
+				// to HelloRetryRequest, however, is ACKed.
+				//
+				// The shim must additionally process ACKs and retransmit its
+				// Finished flight, possibly interleaved with application data.
+				// (The server may send half-RTT data without Finished.)
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Client" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						// Require a client certificate, so the Finished flight
+						// is large.
+						ClientAuth: RequireAnyClientCert,
+						Bugs: ProtocolBugs{
+							SendHelloRetryRequestCookie: []byte("cookie"), // Send HelloRetryRequest
+							MaxPacketLength:             512,
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if len(received) == 0 || received[0].Type != typeClientHello {
+									// We test post-handshake flights separately.
+									c.WriteFlight(next)
+									return
+								}
+
+								// This is either HelloRetryRequest in response to ClientHello1,
+								// or ServerHello..Finished in response to ClientHello2.
+								first := records[0]
+								if len(prev) == 0 {
+									// This is HelloRetryRequest in response to ClientHello1. The client
+									// will accept the ACK, but it will ignore it. Do not expect
+									// retransmits to be impacted.
+									first.MessageStartSequence = 0
+									first.MessageStartOffset = 0
+									first.MessageEndSequence = 0
+									first.MessageEndOffset = 0
+								}
+								c.WriteACK(0, []DTLSRecordNumberInfo{first})
+								c.AdvanceClock(useTimeouts[0])
+								c.ReadRetransmit()
+								c.WriteFlight(next)
+							},
+							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								// The shim will process application data without an ACK.
+								msg := []byte("hello")
+								c.WriteAppData(c.OutEpoch(), msg)
+								c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+								// After a timeout, the shim will retransmit Finished.
+								c.AdvanceClock(useTimeouts[0])
+								c.ReadRetransmit()
+
+								// Application data still flows.
+								c.WriteAppData(c.OutEpoch(), msg)
+								c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+								// ACK part of the flight and check that retransmits
+								// are updated.
+								c.WriteACK(c.OutEpoch(), records[len(records)/3:2*len(records)/3])
+								c.AdvanceClock(useTimeouts[1])
+								records = c.ReadRetransmit()
+
+								// ACK the rest. Retransmits should stop.
+								c.WriteACK(c.OutEpoch(), records)
+								for _, t := range useTimeouts[2:] {
+									c.AdvanceClock(t)
+								}
+							},
+						},
+					},
+					shimCertificate: &rsaChainCertificate,
+					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
+				})
+
+				// If the client never receives an ACK for the Finished flight, it
+				// is eventually fatal.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Client-FinishedTimeout" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								for _, t := range useTimeouts[:len(useTimeouts)-1] {
+									c.AdvanceClock(t)
+									c.ReadRetransmit()
+								}
+								c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
+							},
+						},
+					},
+					flags:         flags,
+					shouldFail:    true,
+					expectedError: ":READ_TIMEOUT_EXPIRED:",
+				})
+
+				// Neither post-handshake messages nor application data implicitly
+				// ACK the Finished flight. The server may have sent either in
+				// half-RTT data. Test that the client continues to retransmit
+				// despite this.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Client-NoImplictACKFinished" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								// Merge the Finished flight into the NewSessionTicket.
+								c.MergeIntoNextFlight()
+							},
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[0].Type != typeNewSessionTicket {
+									c.WriteFlight(next)
+									return
+								}
+								if len(received) == 0 || received[0].Type != typeFinished {
+									panic("Finished should be merged with NewSessionTicket")
+								}
+								// Merge NewSessionTicket into the KeyUpdate.
+								if next[len(next)-1].Type != typeKeyUpdate {
+									c.MergeIntoNextFlight()
+									return
+								}
+
+								// Write NewSessionTicket and the KeyUpdate and
+								// read the ACK.
+								c.WriteFlight(next)
+								ackTimeout := useTimeouts[0] / 4
+								c.AdvanceClock(ackTimeout)
+								c.ReadACK(c.InEpoch())
+
+								// The retransmit timer is still running.
+								c.AdvanceClock(useTimeouts[0] - ackTimeout)
+								c.ReadRetransmit()
+
+								// Application data can flow at the old epoch.
+								msg := []byte("test")
+								c.WriteAppData(c.OutEpoch()-1, msg)
+								c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+								// The retransmit timer is still running.
+								c.AdvanceClock(useTimeouts[1])
+								c.ReadRetransmit()
+
+								// Advance the shim to the next epoch.
+								c.WriteAppData(c.OutEpoch(), msg)
+								c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+								// The retransmit timer is still running. The shim
+								// actually could implicitly ACK at this point, but
+								// RFC 9147 does not list this as an implicit ACK.
+								c.AdvanceClock(useTimeouts[2])
+								c.ReadRetransmit()
+
+								// Finally ACK the final flight. Now the shim will
+								// stop the timer.
+								c.WriteACK(c.OutEpoch(), records)
+								c.ExpectNoNextTimeout()
+							},
+						},
+					},
+					sendKeyUpdates:   1,
+					keyUpdateRequest: keyUpdateNotRequested,
+					flags:            flags,
+				})
+
+				// If the server never receives an ACK for NewSessionTicket, it
+				// is eventually fatal.
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Server-NewSessionTicketTimeout" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if received[0].Type != typeNewSessionTicket {
+									c.WriteACK(c.OutEpoch(), records)
+									return
+								}
+								// Time the peer out.
+								for _, t := range useTimeouts[:len(useTimeouts)-1] {
+									c.AdvanceClock(t)
+									c.ReadRetransmit()
+								}
+								c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
+							}),
+						},
+					},
+					flags:         flags,
+					shouldFail:    true,
+					expectedError: ":READ_TIMEOUT_EXPIRED:",
+				})
+
+				// If generating the reply to a flight takes time (generating a
+				// CertificateVerify for a client certificate), the shim should
+				// send an ACK.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-SlowReplyGeneration" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						ClientAuth: RequireAnyClientCert,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								c.WriteFlight(next)
+								if next[0].Type == typeServerHello {
+									// The shim will reply with Certificate..Finished, but
+									// take time to do so. In that time, it should schedule
+									// an ACK so the runner knows not to retransmit.
+									c.ReadACK(c.InEpoch())
+								}
+							},
+						},
+					},
+					shimCertificate: &rsaCertificate,
+					// Simulate it taking time to generate the reply.
+					flags: slices.Concat(flags, []string{"-private-key-delay-ms", strconv.Itoa(int(useTimeouts[0].Milliseconds()))}),
+				})
+
+				// BoringSSL's ACK policy may schedule both retransmit and ACK
+				// timers in parallel.
+				//
+				// TODO(crbug.com/42290594): This is only possible during the
+				// handshake because we're willing to ACK old flights without
+				// trying to distinguish these cases. However, post-handshake
+				// messages will exercise this, so that may be a better version
+				// of this test. In-handshake, it's kind of a waste to ACK this,
+				// so maybe we should stop.
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-BothTimers" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							// Arrange for there to be two server flights.
+							SendHelloRetryRequestCookie: []byte("cookie"),
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[0].Sequence == 0 || next[0].Type != typeServerHello {
+									// Send the first flight (HelloRetryRequest) as-is,
+									// as well as any post-handshake flights.
+									c.WriteFlight(next)
+									return
+								}
+
+								// The shim just send the ClientHello2 and is
+								// waiting for ServerHello..Finished. If it hears
+								// nothing, it will retransmit ClientHello2 on the
+								// assumption the packet was lost.
+								c.ExpectNextTimeout(useTimeouts[0])
+
+								// Retransmit a portion of HelloRetryRequest.
+								c.WriteFragments([]DTLSFragment{prev[0].Fragment(0, 1)})
+
+								// The shim does not actually need to ACK this,
+								// but BoringSSL does. Now both timers are active.
+								// Fire the first...
+								c.ExpectNextTimeout(useTimeouts[0] / 4)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(0)
+
+								// ...followed by the second.
+								c.ExpectNextTimeout(3 * useTimeouts[0] / 4)
+								c.AdvanceClock(3 * useTimeouts[0] / 4)
+								c.ReadRetransmit()
+
+								// The shim is now set for the next retransmit.
+								c.ExpectNextTimeout(useTimeouts[1])
+
+								// Start the ACK timer again.
+								c.WriteFragments([]DTLSFragment{prev[0].Fragment(0, 1)})
+								c.ExpectNextTimeout(useTimeouts[1] / 4)
+
+								// Expire both timers at once.
+								c.AdvanceClock(useTimeouts[1])
+								c.ReadACK(0)
+								c.ReadRetransmit()
+
+								c.WriteFlight(next)
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Client-ACKPostHandshake" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[0].Type != typeNewSessionTicket {
+									c.WriteFlight(next)
+									return
+								}
+
+								// The test should try to send two NewSessionTickets in a row.
+								if len(next) != 2 {
+									panic("unexpected message count")
+								}
+
+								// Send part of first ticket post-handshake message.
+								first0, second0 := next[0].Split(len(next[0].Data) / 2)
+								first1, second1 := next[1].Split(len(next[1].Data) / 2)
+								c.WriteFragments([]DTLSFragment{first0})
+
+								// The shim should ACK on a timer.
+								c.ExpectNextTimeout(useTimeouts[0] / 4)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+
+								// The shim is just waiting for us to retransmit.
+								c.ExpectNoNextTimeout()
+
+								// Send some more fragments.
+								c.WriteFragments([]DTLSFragment{first0, second1})
+
+								// The shim should ACK, again on a timer.
+								c.ExpectNextTimeout(useTimeouts[0] / 4)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+								c.ExpectNoNextTimeout()
+
+								// Finish up both messages. We implicitly test if shim
+								// processed these messages by checking that it returned a new
+								// session.
+								c.WriteFragments([]DTLSFragment{first1, second0})
+
+								// The shim should ACK again, once the timer expires.
+								//
+								// TODO(crbug.com/42290594): Should the shim ACK immediately?
+								// Otherwise KeyUpdates are delayed, which will complicated
+								// downstream testing.
+								c.ExpectNextTimeout(useTimeouts[0] / 4)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+								c.ExpectNoNextTimeout()
+							},
+						},
+					},
+					flags: flags,
+				})
+
+				testCases = append(testCases, testCase{
+					protocol: dtls,
+					name:     "DTLS-Retransmit-Client-ACKPostHandshakeTwice" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+								if next[0].Type != typeNewSessionTicket {
+									c.WriteFlight(next)
+									return
+								}
+
+								// The test should try to send two NewSessionTickets in a row.
+								if len(next) != 2 {
+									panic("unexpected message count")
+								}
+
+								// Send the flight. The shim should ACK it.
+								c.WriteFlight(next)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+								c.ExpectNoNextTimeout()
+
+								// Retransmit the flight, as if we lost the ACK. The shim should
+								// ACK again.
+								c.WriteFlight(next)
+								c.AdvanceClock(useTimeouts[0] / 4)
+								c.ReadACK(c.InEpoch())
+								c.ExpectNoNextTimeout()
+							},
+						},
+					},
+					flags: flags,
+				})
+			}
+		}
+	}
+
+	// Test that the final Finished retransmitting isn't
+	// duplicated if the peer badly fragments everything.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "DTLS-RetransmitFinished-Fragmented",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				MaxHandshakeRecordLength: 2,
+				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+					c.WriteFlight(prev)
+					c.ReadRetransmit()
+				},
+			},
+		},
+		flags: []string{"-async"},
+	})
+
+	// If the shim sends the last Finished (server full or client resume
+	// handshakes), it must retransmit that Finished when it sees a
+	// post-handshake penultimate Finished from the runner. The above tests
+	// cover this. Conversely, if the shim sends the penultimate Finished
+	// (client full or server resume), test that it does not retransmit.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: clientTest,
+		name:     "DTLS-StrayRetransmitFinished-ClientFull",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					c.WriteFlight(next)
+					for _, msg := range next {
+						if msg.Type == typeFinished {
+							c.WriteFlight([]DTLSMessage{msg})
+						}
+					}
+				},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "DTLS-StrayRetransmitFinished-ServerResume",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					c.WriteFlight(next)
+					for _, msg := range next {
+						if msg.Type == typeFinished {
+							c.WriteFlight([]DTLSMessage{msg})
+						}
+					}
+				},
+			},
+		},
+		resumeSession: true,
+	})
+}
+
+func addDTLSReorderTests() {
+	for _, vers := range allVersions(dtls) {
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "ReorderHandshakeFragments-Small-DTLS-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Bugs: ProtocolBugs{
+					ReorderHandshakeFragments: true,
+					// Small enough that every handshake message is
+					// fragmented.
+					MaxHandshakeRecordLength: 2,
+				},
+			},
+		})
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "ReorderHandshakeFragments-Large-DTLS-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Bugs: ProtocolBugs{
+					ReorderHandshakeFragments: true,
+					// Large enough that no handshake message is
+					// fragmented.
+					MaxHandshakeRecordLength: 2048,
+				},
+			},
+		})
+		testCases = append(testCases, testCase{
+			protocol: dtls,
+			name:     "MixCompleteMessageWithFragments-DTLS-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Bugs: ProtocolBugs{
+					ReorderHandshakeFragments:       true,
+					MixCompleteMessageWithFragments: true,
+					MaxHandshakeRecordLength:        2,
+				},
+			},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/ech_tests.go b/src/ssl/test/runner/ech_tests.go
new file mode 100644
index 0000000..0b7eb64
--- /dev/null
+++ b/src/ssl/test/runner/ech_tests.go
@@ -0,0 +1,2436 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"math/big"
+	"strconv"
+	"strings"
+	"time"
+
+	"boringssl.googlesource.com/boringssl.git/ssl/test/runner/hpke"
+)
+
+type echCipher struct {
+	name   string
+	cipher HPKECipherSuite
+}
+
+var echCiphers = []echCipher{
+	{
+		name:   "HKDF-SHA256-AES-128-GCM",
+		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
+	},
+	{
+		name:   "HKDF-SHA256-AES-256-GCM",
+		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
+	},
+	{
+		name:   "HKDF-SHA256-ChaCha20-Poly1305",
+		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
+	},
+}
+
+// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
+// keypair and using |template| as a template for the ECHConfig. If fields are
+// omitted, defaults are used.
+func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
+	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
+	if err != nil {
+		panic(err)
+	}
+	templateCopy := *template
+	if templateCopy.KEM == 0 {
+		templateCopy.KEM = hpke.X25519WithHKDFSHA256
+	}
+	if len(templateCopy.PublicKey) == 0 {
+		templateCopy.PublicKey = publicKey
+	}
+	if len(templateCopy.CipherSuites) == 0 {
+		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
+		for i, cipher := range echCiphers {
+			templateCopy.CipherSuites[i] = cipher.cipher
+		}
+	}
+	if len(templateCopy.PublicName) == 0 {
+		templateCopy.PublicName = "public.example"
+	}
+	if templateCopy.MaxNameLen == 0 {
+		templateCopy.MaxNameLen = 64
+	}
+	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
+}
+
+func addEncryptedClientHelloTests() {
+	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
+	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
+	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
+	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
+	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
+	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
+
+	echSecretCertificate := generateSingleCertChain(&x509.Certificate{
+		SerialNumber: big.NewInt(57005),
+		Subject: pkix.Name{
+			CommonName: "test cert",
+		},
+		NotBefore:             time.Now().Add(-time.Hour),
+		NotAfter:              time.Now().Add(time.Hour),
+		DNSNames:              []string{"secret.example"},
+		IsCA:                  true,
+		BasicConstraintsValid: true,
+	}, &rsa2048Key)
+	echPublicCertificate := generateSingleCertChain(&x509.Certificate{
+		SerialNumber: big.NewInt(57005),
+		Subject: pkix.Name{
+			CommonName: "test cert",
+		},
+		NotBefore:             time.Now().Add(-time.Hour),
+		NotAfter:              time.Now().Add(time.Hour),
+		DNSNames:              []string{"public.example"},
+		IsCA:                  true,
+		BasicConstraintsValid: true,
+	}, &rsa2048Key)
+	echLongNameCertificate := generateSingleCertChain(&x509.Certificate{
+		SerialNumber: big.NewInt(57005),
+		Subject: pkix.Name{
+			CommonName: "test cert",
+		},
+		NotBefore:             time.Now().Add(-time.Hour),
+		NotAfter:              time.Now().Add(time.Hour),
+		DNSNames:              []string{"test0123456789.example"},
+		IsCA:                  true,
+		BasicConstraintsValid: true,
+	}, &ecdsaP256Key)
+
+	for _, protocol := range []protocol{tls, quic, dtls} {
+		prefix := protocol.String() + "-"
+
+		// There are two ClientHellos, so many of our tests have
+		// HelloRetryRequest variations.
+		for _, hrr := range []bool{false, true} {
+			var suffix string
+			var defaultCurves []CurveID
+			if hrr {
+				suffix = "-HelloRetryRequest"
+				// Require a HelloRetryRequest for every curve.
+				defaultCurves = []CurveID{}
+			}
+
+			// Test the server can accept ECH.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					DefaultCurves:   defaultCurves,
+				},
+				resumeSession: true,
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test the server can accept ECH with a minimal ClientHelloOuter.
+			// This confirms that the server does not unexpectedly pick up
+			// fields from the wrong ClientHello.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					DefaultCurves:   defaultCurves,
+					Bugs: ProtocolBugs{
+						MinimalClientHelloOuter: true,
+					},
+				},
+				resumeSession: true,
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test that the server can decline ECH. In particular, it must send
+			// retry configs.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-Decline" + suffix,
+				config: Config{
+					ServerName:    "secret.example",
+					DefaultCurves: defaultCurves,
+					// The client uses an ECHConfig that the server does not understand
+					// so we can observe which retry configs the server sends back.
+					ClientECHConfig: echConfig.ECHConfig,
+					Bugs: ProtocolBugs{
+						OfferSessionInClientHelloOuter: true,
+						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
+					},
+				},
+				resumeSession: true,
+				flags: []string{
+					// Configure three ECHConfigs on the shim, only two of which
+					// should be sent in retry configs.
+					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig1.Key),
+					"-ech-is-retry-config", "0",
+					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig2.Key),
+					"-ech-is-retry-config", "1",
+					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig3.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "public.example",
+				},
+			})
+
+			// Test that the server considers a ClientHelloInner indicating TLS
+			// 1.2 to be a fatal error.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					Bugs: ProtocolBugs{
+						AllowTLS12InClientHelloInner: true,
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
+			})
+
+			// When inner ECH extension is absent from the ClientHelloInner, the
+			// server should fail the connection.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					Bugs: ProtocolBugs{
+						OmitECHInner:       !hrr,
+						OmitSecondECHInner: hrr,
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
+			})
+
+			// Test that the server can decode ech_outer_extensions.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionKeyShare,
+						extensionSupportedCurves,
+						// Include a custom extension, to test that unrecognized
+						// extensions are also decoded.
+						extensionCustom,
+					},
+					Bugs: ProtocolBugs{
+						CustomExtension:                    "test",
+						OnlyCompressSecondClientHelloInner: hrr,
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test that the server allows referenced ClientHelloOuter
+			// extensions to be interleaved with other extensions. Only the
+			// relative order must match.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionKeyShare,
+						extensionSupportedCurves,
+						extensionCustom,
+					},
+					Bugs: ProtocolBugs{
+						CustomExtension:                    "test",
+						OnlyCompressSecondClientHelloInner: hrr,
+						ECHOuterExtensionOrder: []uint16{
+							extensionServerName,
+							extensionKeyShare,
+							extensionSupportedVersions,
+							extensionPSKKeyExchangeModes,
+							extensionSupportedCurves,
+							extensionSignatureAlgorithms,
+							extensionCustom,
+						},
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test that the server rejects references to extensions in the
+			// wrong order.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionKeyShare,
+						extensionSupportedCurves,
+					},
+					Bugs: ProtocolBugs{
+						CustomExtension:                    "test",
+						OnlyCompressSecondClientHelloInner: hrr,
+						ECHOuterExtensionOrder: []uint16{
+							extensionSupportedCurves,
+							extensionKeyShare,
+						},
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_OUTER_EXTENSION:",
+			})
+
+			// Test that the server rejects duplicated values in ech_outer_extensions.
+			// Besides causing the server to reconstruct an invalid ClientHelloInner
+			// with duplicated extensions, this behavior would be vulnerable to DoS
+			// attacks.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionSupportedCurves,
+						extensionSupportedCurves,
+					},
+					Bugs: ProtocolBugs{
+						OnlyCompressSecondClientHelloInner: hrr,
+						// Don't duplicate the extension in ClientHelloOuter.
+						ECHOuterExtensionOrder: []uint16{
+							extensionSupportedCurves,
+						},
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_OUTER_EXTENSION:",
+			})
+
+			// Test that the server rejects references to missing extensions in
+			// ech_outer_extensions.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionCustom,
+					},
+					Bugs: ProtocolBugs{
+						OnlyCompressSecondClientHelloInner: hrr,
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_OUTER_EXTENSION:",
+			})
+
+			// Test that the server rejects a references to the ECH extension in
+			// ech_outer_extensions. The ECH extension is not authenticated in the
+			// AAD and would result in an invalid ClientHelloInner.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					DefaultCurves:   defaultCurves,
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHOuterExtensions: []uint16{
+						extensionEncryptedClientHello,
+					},
+					Bugs: ProtocolBugs{
+						OnlyCompressSecondClientHelloInner: hrr,
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: illegal parameter",
+				expectedError:      ":INVALID_OUTER_EXTENSION:",
+			})
+
+			// Test the message callback is correctly reported with ECH.
+			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
+			expectMsgCallback := clientAndServerHello
+			if protocol == tls {
+				expectMsgCallback += "write ccs\n"
+			}
+			if hrr {
+				expectMsgCallback += clientAndServerHello
+			}
+			// EncryptedExtensions onwards.
+			expectMsgCallback += `write hs 8
+write hs 11
+write hs 15
+write hs 20
+read hs 20
+write ack
+write hs 4
+write hs 4
+read ack
+read ack
+`
+			if protocol != dtls {
+				expectMsgCallback = strings.ReplaceAll(expectMsgCallback, "write ack\n", "")
+				expectMsgCallback = strings.ReplaceAll(expectMsgCallback, "read ack\n", "")
+			}
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-MessageCallback" + suffix,
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					DefaultCurves:   defaultCurves,
+					Bugs: ProtocolBugs{
+						NoCloseNotify: true, // Align QUIC and TCP traces.
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-ech-accept",
+					"-expect-msg-callback", expectMsgCallback,
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+		}
+
+		// Test that ECH, which runs before an async early callback, interacts
+		// correctly in the state machine.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-AsyncEarlyCallback",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+			},
+			flags: []string{
+				"-async",
+				"-use-early-callback",
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-server-name", "secret.example",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+
+		// Test that we successfully rewind the TLS state machine and disable ECH in the
+		// case that the select_cert_cb signals that ECH is not possible for the SNI in
+		// ClientHelloInner.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-FailCallbackNeedRewind",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+			},
+			flags: []string{
+				"-async",
+				"-fail-early-callback-ech-rewind",
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-server-name", "public.example",
+			},
+			expectations: connectionExpectations{
+				echAccepted: false,
+			},
+		})
+
+		// Test that we correctly handle falling back to a ClientHelloOuter with
+		// no SNI (public name).
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-RewindWithNoPublicName",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					OmitPublicName: true,
+				},
+			},
+			flags: []string{
+				"-async",
+				"-fail-early-callback-ech-rewind",
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-no-server-name",
+			},
+			expectations: connectionExpectations{
+				echAccepted: false,
+			},
+		})
+
+		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
+		// it uses the second ECHConfig.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-SecondECHConfig",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig1.ECHConfig,
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig1.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-server-name", "secret.example",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+
+		// Test ECH-enabled server with two ECHConfigs that have the same config
+		// ID can decrypt client's ECH when it uses the second ECHConfig.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-RepeatedConfigID",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfigRepeatID.ECHConfig,
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-server-name", "secret.example",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+
+		// Test all supported ECH cipher suites.
+		for i, cipher := range echCiphers {
+			otherCipher := echCiphers[(i+1)%len(echCiphers)]
+
+			// Test the ECH server can handle the specified cipher.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test that client can offer the specified cipher and skip over
+			// unrecognized ones.
+			cipherConfig := generateServerECHConfig(&ECHConfig{
+				ConfigID: 42,
+				CipherSuites: []HPKECipherSuite{
+					{KDF: 0x1111, AEAD: 0x2222},
+					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
+					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
+					cipher.cipher,
+				},
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{cipherConfig},
+					Credential:       &echSecretCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
+					"-host-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+
+			// Test that the ECH server rejects the specified cipher if not
+			// listed in its ECHConfig.
+			otherCipherConfig := generateServerECHConfig(&ECHConfig{
+				ConfigID:     42,
+				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
+					Bugs: ProtocolBugs{
+						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
+					},
+				},
+				flags: []string{
+					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-server-name", "public.example",
+				},
+			})
+		}
+
+		// Test that the ECH server handles a short enc value by falling back to
+		// ClientHelloOuter.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-ShortEnc",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
+					TruncateClientECHEnc:  true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-server-name", "public.example",
+			},
+		})
+
+		// Test that the server handles decryption failure by falling back to
+		// ClientHelloOuter.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
+					CorruptEncryptedClientHello: true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+			},
+		})
+
+		// Test that the server treats decryption failure in the second
+		// ClientHello as fatal.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				// Force a HelloRetryRequest.
+				DefaultCurves: []CurveID{},
+				Bugs: ProtocolBugs{
+					CorruptSecondEncryptedClientHello: true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+			},
+			shouldFail:         true,
+			expectedError:      ":DECRYPTION_FAILED:",
+			expectedLocalError: "remote error: error decrypting message",
+		})
+
+		// Test that the server treats a missing second ECH extension as fatal.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				// Force a HelloRetryRequest.
+				DefaultCurves: []CurveID{},
+				Bugs: ProtocolBugs{
+					OmitSecondEncryptedClientHello: true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+			},
+			shouldFail:         true,
+			expectedError:      ":MISSING_EXTENSION:",
+			expectedLocalError: "remote error: missing extension",
+		})
+
+		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+				// Force a HelloRetryRequest.
+				DefaultCurves: []CurveID{},
+				Bugs: ProtocolBugs{
+					CorruptSecondEncryptedClientHelloConfigID: true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+			},
+			shouldFail:         true,
+			expectedError:      ":DECODE_ERROR:",
+			expectedLocalError: "remote error: illegal parameter",
+		})
+
+		// Test early data works with ECH, in both accept and reject cases.
+		// TODO(crbug.com/381113363): Enable these tests for DTLS once we
+		// support early data in DTLS 1.3.
+		if protocol != dtls {
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-EarlyData",
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+				},
+				resumeSession: true,
+				earlyData:     true,
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-EarlyDataRejected",
+				config: Config{
+					ServerName:      "secret.example",
+					ClientECHConfig: echConfig.ECHConfig,
+					Bugs: ProtocolBugs{
+						// Cause the server to reject 0-RTT with a bad ticket age.
+						SendTicketAge: 1 * time.Hour,
+					},
+				},
+				resumeSession:           true,
+				earlyData:               true,
+				expectEarlyDataRejected: true,
+				flags: []string{
+					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+					"-ech-server-key", base64FlagValue(echConfig.Key),
+					"-ech-is-retry-config", "1",
+					"-expect-ech-accept",
+				},
+				expectations: connectionExpectations{
+					echAccepted: true,
+				},
+			})
+		}
+
+		// Test servers with ECH disabled correctly ignore the extension and
+		// handshake with the ClientHelloOuter.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-Disabled",
+			config: Config{
+				ServerName:      "secret.example",
+				ClientECHConfig: echConfig.ECHConfig,
+			},
+			flags: []string{
+				"-expect-server-name", "public.example",
+			},
+		})
+
+		// Test that ECH can be used with client certificates. In particular,
+		// the name override logic should not interfere with the server.
+		// Test the server can accept ECH.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-ClientAuth",
+			config: Config{
+				Credential:      &rsaCertificate,
+				ClientECHConfig: echConfig.ECHConfig,
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-ech-accept",
+				"-require-any-client-certificate",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-Decline-ClientAuth",
+			config: Config{
+				Credential:      &rsaCertificate,
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig1.Key),
+				"-ech-is-retry-config", "1",
+				"-require-any-client-certificate",
+			},
+		})
+
+		// Test that the server accepts padding.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-Padding",
+			config: Config{
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					ClientECHPadding: 10,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+
+		// Test that the server rejects bad padding.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-BadPadding",
+			config: Config{
+				ClientECHConfig: echConfig.ECHConfig,
+				Bugs: ProtocolBugs{
+					ClientECHPadding:    10,
+					BadClientECHPadding: true,
+				},
+			},
+			flags: []string{
+				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
+				"-ech-server-key", base64FlagValue(echConfig.Key),
+				"-ech-is-retry-config", "1",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+			shouldFail:         true,
+			expectedError:      ":DECODE_ERROR",
+			expectedLocalError: "remote error: illegal parameter",
+		})
+
+		// Test the client's behavior when the server ignores ECH GREASE.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-GREASE-Client-TLS13",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectClientECH: true,
+				},
+			},
+			flags: []string{"-enable-ech-grease"},
+		})
+
+		// Test the client's ECH GREASE behavior when responding to server's
+		// HelloRetryRequest. This test implicitly checks that the first and second
+		// ClientHello messages have identical ECH extensions.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				// P-384 requires a HelloRetryRequest against BoringSSL's default
+				// configuration. Assert this with ExpectMissingKeyShare.
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					ExpectMissingKeyShare: true,
+					ExpectClientECH:       true,
+				},
+			},
+			flags: []string{"-enable-ech-grease", "-expect-hrr"},
+		})
+
+		unsupportedVersion := []byte{
+			// version
+			0xba, 0xdd,
+			// length
+			0x00, 0x05,
+			// contents
+			0x05, 0x04, 0x03, 0x02, 0x01,
+		}
+
+		// Test that the client accepts a well-formed encrypted_client_hello
+		// extension in response to ECH GREASE. The response includes one ECHConfig
+		// with a supported version and one with an unsupported version.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectClientECH: true,
+					// Include an additional well-formed ECHConfig with an
+					// unsupported version. This ensures the client can skip
+					// unsupported configs.
+					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
+				},
+			},
+			flags: []string{"-enable-ech-grease"},
+		})
+
+		// TLS 1.2 ServerHellos cannot contain retry configs.
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
+				config: Config{
+					MinVersion:       VersionTLS12,
+					MaxVersion:       VersionTLS12,
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectClientECH:           true,
+						AlwaysSendECHRetryConfigs: true,
+					},
+				},
+				flags:              []string{"-enable-ech-grease"},
+				shouldFail:         true,
+				expectedLocalError: "remote error: unsupported extension",
+				expectedError:      ":UNEXPECTED_EXTENSION:",
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
+				config: Config{
+					MinVersion:       VersionTLS12,
+					MaxVersion:       VersionTLS12,
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectClientECH:           true,
+						AlwaysSendECHRetryConfigs: true,
+					},
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: unsupported extension",
+				expectedError:      ":UNEXPECTED_EXTENSION:",
+			})
+		}
+
+		// Retry configs must be rejected when ECH is accepted.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectClientECH:           true,
+					AlwaysSendECHRetryConfigs: true,
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: unsupported extension",
+			expectedError:      ":UNEXPECTED_EXTENSION:",
+		})
+
+		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					AlwaysSendECHHelloRetryRequest: true,
+					ExpectMissingKeyShare:          true, // Check we triggered HRR.
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: unsupported extension",
+			expectedError:      ":UNEXPECTED_EXTENSION:",
+		})
+
+		// GREASE should ignore ECH HelloRetryRequest extensions.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
+			config: Config{
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					AlwaysSendECHHelloRetryRequest: true,
+					ExpectMissingKeyShare:          true, // Check we triggered HRR.
+				},
+			},
+			flags: []string{"-enable-ech-grease"},
+		})
+
+		// Random ECH HelloRetryRequest extensions also signal ECH reject.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
+			config: Config{
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					AlwaysSendECHHelloRetryRequest: true,
+					ExpectMissingKeyShare:          true, // Check we triggered HRR.
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: ECH required",
+			expectedError:      ":ECH_REJECTED:",
+		})
+
+		// Test that the client aborts with a decode_error alert when it receives a
+		// syntactically-invalid encrypted_client_hello extension from the server.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectClientECH:     true,
+					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
+				},
+			},
+			flags:              []string{"-enable-ech-grease"},
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decoding message",
+			expectedError:      ":ERROR_PARSING_EXTENSION:",
+		})
+
+		// Test that the server responds to an inner ECH extension with the
+		// acceptance confirmation.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-ECHInner",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AlwaysSendECHInner: true,
+				},
+			},
+			resumeSession: true,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				// Force a HelloRetryRequest.
+				DefaultCurves: []CurveID{},
+				Bugs: ProtocolBugs{
+					AlwaysSendECHInner: true,
+				},
+			},
+			resumeSession: true,
+		})
+
+		// Test that server fails the handshake when it sees a non-empty
+		// inner ECH extension.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					AlwaysSendECHInner:  true,
+					SendInvalidECHInner: []byte{42, 42, 42},
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decoding message",
+			expectedError:      ":ERROR_PARSING_EXTENSION:",
+		})
+
+		// Test that a TLS 1.3 server that receives an inner ECH extension can
+		// negotiate TLS 1.2 without clobbering the downgrade signal.
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						// Omit supported_versions extension so the server negotiates
+						// TLS 1.2.
+						OmitSupportedVersions: true,
+						AlwaysSendECHInner:    true,
+					},
+				},
+				// Check that the client sees the TLS 1.3 downgrade signal in
+				// ServerHello.random.
+				shouldFail:         true,
+				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
+			})
+		}
+
+		// Test the client can negotiate ECH, with and without HelloRetryRequest.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client",
+			config: Config{
+				MinVersion:       VersionTLS13,
+				MaxVersion:       VersionTLS13,
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectServerName:      "secret.example",
+					ExpectOuterServerName: "public.example",
+				},
+				Credential: &echSecretCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				"-expect-ech-accept",
+			},
+			resumeSession: true,
+			expectations:  connectionExpectations{echAccepted: true},
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-HelloRetryRequest",
+			config: Config{
+				MinVersion:       VersionTLS13,
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{CurveP384},
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectServerName:      "secret.example",
+					ExpectOuterServerName: "public.example",
+					ExpectMissingKeyShare: true, // Check we triggered HRR.
+				},
+				Credential: &echSecretCertificate,
+			},
+			resumeSession: true,
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				"-expect-ech-accept",
+				"-expect-hrr", // Check we triggered HRR.
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Test the client can negotiate ECH with early data.
+		// TODO(crbug.com/381113363): Enable these tests for DTLS once we
+		// support early data in DTLS 1.3.
+		if protocol != dtls {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-EarlyData",
+				config: Config{
+					MinVersion:       VersionTLS13,
+					MaxVersion:       VersionTLS13,
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectServerName: "secret.example",
+					},
+					Credential: &echSecretCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-host-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				resumeSession: true,
+				earlyData:     true,
+				expectations:  connectionExpectations{echAccepted: true},
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-EarlyDataRejected",
+				config: Config{
+					MinVersion:       VersionTLS13,
+					MaxVersion:       VersionTLS13,
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectServerName:      "secret.example",
+						AlwaysRejectEarlyData: true,
+					},
+					Credential: &echSecretCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-host-name", "secret.example",
+					"-expect-ech-accept",
+				},
+				resumeSession:           true,
+				earlyData:               true,
+				expectEarlyDataRejected: true,
+				expectations:            connectionExpectations{echAccepted: true},
+			})
+		}
+
+		if protocol != quic {
+			// Test that an ECH client does not offer a TLS 1.2 session.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-TLS12SessionID",
+				config: Config{
+					MaxVersion:             VersionTLS12,
+					SessionTicketsDisabled: true,
+				},
+				resumeConfig: &Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectNoTLS12Session: true,
+					},
+				},
+				flags: []string{
+					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-on-resume-expect-ech-accept",
+				},
+				resumeSession:        true,
+				expectResumeRejected: true,
+				resumeExpectations:   &connectionExpectations{echAccepted: true},
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-TLS12SessionTicket",
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+				resumeConfig: &Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectNoTLS12Session: true,
+					},
+				},
+				flags: []string{
+					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-on-resume-expect-ech-accept",
+				},
+				resumeSession:        true,
+				expectResumeRejected: true,
+				resumeExpectations:   &connectionExpectations{echAccepted: true},
+			})
+		}
+
+		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
+		// extensions. The Go server will enforce this, so this test only needs
+		// to configure the feature on the shim. Other application extensions
+		// are sent implicitly.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NoNPN",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				// Enable NPN.
+				"-select-next-proto", "foo",
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Test that the client iterates over configurations in the
+		// ECHConfigList and selects the first with supported parameters.
+		unsupportedKEM := generateServerECHConfig(&ECHConfig{
+			KEM:       0x6666,
+			PublicKey: []byte{1, 2, 3, 4},
+		}).ECHConfig
+		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
+			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
+		}).ECHConfig
+		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
+			UnsupportedMandatoryExtension: true,
+		}).ECHConfig
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-SelectECHConfig",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(
+					unsupportedVersion,
+					unsupportedKEM.Raw,
+					unsupportedCipherSuites.Raw,
+					unsupportedMandatoryExtension.Raw,
+					echConfig.ECHConfig.Raw,
+					// |echConfig1| is also supported, but the client should
+					// select the first one.
+					echConfig1.ECHConfig.Raw,
+				)),
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+			},
+		})
+
+		// Test that the client skips sending ECH if all ECHConfigs are
+		// unsupported.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NoSupportedConfigs",
+			config: Config{
+				Bugs: ProtocolBugs{
+					ExpectNoClientECH: true,
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(
+					unsupportedVersion,
+					unsupportedKEM.Raw,
+					unsupportedCipherSuites.Raw,
+					unsupportedMandatoryExtension.Raw,
+				)),
+			},
+		})
+
+		// If ECH GREASE is enabled, the client should send ECH GREASE when no
+		// configured ECHConfig is suitable.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
+			config: Config{
+				Bugs: ProtocolBugs{
+					ExpectClientECH: true,
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(
+					unsupportedVersion,
+					unsupportedKEM.Raw,
+					unsupportedCipherSuites.Raw,
+					unsupportedMandatoryExtension.Raw,
+				)),
+				"-enable-ech-grease",
+			},
+		})
+
+		// If both ECH GREASE and suitable ECHConfigs are available, the
+		// client should send normal ECH.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-GREASE",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+			},
+			resumeSession: true,
+			expectations:  connectionExpectations{echAccepted: true},
+		})
+
+		// Test that GREASE extensions correctly interact with ECH. Both the
+		// inner and outer ClientHellos should include GREASE extensions.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-GREASEExtensions",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				"-enable-grease",
+			},
+			resumeSession: true,
+			expectations:  connectionExpectations{echAccepted: true},
+		})
+
+		// Test that the client tolerates unsupported extensions if the
+		// mandatory bit is not set.
+		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-UnsupportedExtension",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Syntax errors in the ECHConfigList should be rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-InvalidECHConfigList",
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
+			},
+			shouldFail:    true,
+			expectedError: ":INVALID_ECH_CONFIG_LIST:",
+		})
+
+		// If the ClientHelloInner has no server_name extension, while the
+		// ClientHelloOuter has one, the client must check for unsolicited
+		// extensions based on the selected ClientHello.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					// ClientHelloOuter should have a server name.
+					ExpectOuterServerName: "public.example",
+					// The server will acknowledge the server_name extension.
+					// This option runs whether or not the client requested the
+					// extension.
+					SendServerNameAck: true,
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				// No -host-name flag.
+				"-expect-ech-accept",
+			},
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_EXTENSION:",
+			expectedLocalError: "remote error: unsupported extension",
+			expectations:       connectionExpectations{echAccepted: true},
+		})
+
+		// Most extensions are the same between ClientHelloInner and
+		// ClientHelloOuter and can be compressed.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				NextProtos:       []string{"proto"},
+				Bugs: ProtocolBugs{
+					ExpectECHOuterExtensions: []uint16{
+						extensionALPN,
+						extensionKeyShare,
+						extensionPSKKeyExchangeModes,
+						extensionSignatureAlgorithms,
+						extensionSupportedCurves,
+					},
+				},
+				Credential: &echSecretCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				"-advertise-alpn", "\x05proto",
+				"-expect-alpn", "proto",
+				"-host-name", "secret.example",
+			},
+			expectations: connectionExpectations{
+				echAccepted: true,
+				nextProto:   "proto",
+			},
+			skipQUICALPNConfig: true,
+		})
+
+		// If the server name happens to match the public name, it still should
+		// not be compressed. It is not publicly known that they match.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NeverCompressServerName",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				NextProtos:       []string{"proto"},
+				Bugs: ProtocolBugs{
+					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
+					ExpectServerName:                "public.example",
+					ExpectOuterServerName:           "public.example",
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				"-host-name", "public.example",
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
+		// should also compress supported_versions.
+		tls13Vers := VersionTLS13
+		if protocol == dtls {
+			tls13Vers = VersionDTLS13
+		}
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-CompressSupportedVersions",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectECHOuterExtensions: []uint16{
+						extensionSupportedVersions,
+					},
+				},
+				Credential: &echSecretCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				"-expect-ech-accept",
+				"-min-version", strconv.Itoa(int(tls13Vers)),
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Test that the client can still offer server names that exceed the
+		// maximum name length. It is only a padding hint.
+		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NameTooLong",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
+				Bugs: ProtocolBugs{
+					ExpectServerName: "test0123456789.example",
+				},
+				Credential: &echLongNameCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
+				"-host-name", "test0123456789.example",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Test the client can recognize when ECH is rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
+				Bugs: ProtocolBugs{
+					ExpectServerName: "public.example",
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: ECH required",
+			expectedError:      ":ECH_REJECTED:",
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					ExpectServerName:      "public.example",
+					ExpectMissingKeyShare: true, // Check we triggered HRR.
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
+				"-expect-hrr", // Check we triggered HRR.
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: ECH required",
+			expectedError:      ":ECH_REJECTED:",
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
+			config: Config{
+				Bugs: ProtocolBugs{
+					ExpectServerName: "public.example",
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-no-ech-retry-configs",
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: ECH required",
+			expectedError:      ":ECH_REJECTED:",
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-TLS12",
+				config: Config{
+					MaxVersion: VersionTLS12,
+					Bugs: ProtocolBugs{
+						ExpectServerName: "public.example",
+					},
+					Credential: &echPublicCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					// TLS 1.2 cannot provide retry configs.
+					"-expect-no-ech-retry-configs",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: ECH required",
+				expectedError:      ":ECH_REJECTED:",
+			})
+
+			// Test that the client disables False Start when ECH is rejected.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
+				config: Config{
+					MaxVersion:   VersionTLS12,
+					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+					NextProtos:   []string{"foo"},
+					Bugs: ProtocolBugs{
+						// The options below cause the server to, immediately
+						// after client Finished, send an alert and try to read
+						// application data without sending server Finished.
+						ExpectFalseStart:          true,
+						AlertBeforeFalseStartTest: alertAccessDenied,
+					},
+					Credential: &echPublicCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-false-start",
+					"-advertise-alpn", "\x03foo",
+					"-expect-alpn", "foo",
+				},
+				shimWritesFirst: true,
+				shouldFail:      true,
+				// Ensure the client does not send application data at the False
+				// Start point. EOF comes from the client closing the connection
+				// in response ot the alert.
+				expectedLocalError: "tls: peer did not false start: EOF",
+				// Ensures the client picks up the alert before reporting an
+				// authenticated |SSL_R_ECH_REJECTED|.
+				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
+			})
+		}
+
+		// Test that unsupported retry configs in a valid ECHConfigList are
+		// allowed. They will be skipped when configured in the retry.
+		retryConfigs := CreateECHConfigList(
+			unsupportedVersion,
+			unsupportedKEM.Raw,
+			unsupportedCipherSuites.Raw,
+			unsupportedMandatoryExtension.Raw,
+			echConfig2.ECHConfig.Raw)
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendECHRetryConfigs: retryConfigs,
+					ExpectServerName:    "public.example",
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: ECH required",
+			expectedError:      ":ECH_REJECTED:",
+		})
+
+		// Test that the client rejects ClientHelloOuter handshakes that attempt
+		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectServerName: "secret.example",
+				},
+				Credential: &echSecretCertificate,
+			},
+			resumeConfig: &Config{
+				MaxVersion:       VersionTLS13,
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectServerName:                    "public.example",
+					UseInnerSessionWithClientHelloOuter: true,
+				},
+				Credential: &echPublicCertificate,
+			},
+			resumeSession: true,
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				"-on-initial-expect-ech-accept",
+			},
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_EXTENSION:",
+			expectations:       connectionExpectations{echAccepted: true},
+			resumeExpectations: &connectionExpectations{echAccepted: false},
+		})
+		if protocol == tls {
+			// This is only syntactically possible with TLS. In DTLS, we don't
+			// have middlebox compatibility mode, so the session ID will only
+			// filled in if we are offering a DTLS 1.2 session. But a DTLS 1.2
+			// would never be offered in ClientHelloInner. Without a session ID,
+			// the server syntactically cannot express a resumption at DTLS 1.2.
+			// In QUIC, the above is true, and 1.2 does not exist anyway.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectServerName: "secret.example",
+					},
+					Credential: &echSecretCertificate,
+				},
+				resumeConfig: &Config{
+					MinVersion:       VersionTLS12,
+					MaxVersion:       VersionTLS12,
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectServerName:                    "public.example",
+						UseInnerSessionWithClientHelloOuter: true,
+						// The client only ever offers TLS 1.3 sessions in
+						// ClientHelloInner. AcceptAnySession allows them to be
+						// resumed at TLS 1.2.
+						AcceptAnySession: true,
+					},
+					Credential: &echPublicCertificate,
+				},
+				resumeSession: true,
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-host-name", "secret.example",
+					"-on-initial-expect-ech-accept",
+				},
+				// From the client's perspective, the server echoed a session ID to
+				// signal resumption, but the selected ClientHello had nothing to
+				// resume.
+				shouldFail:         true,
+				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
+				expectedLocalError: "remote error: illegal parameter",
+				expectations:       connectionExpectations{echAccepted: true},
+				resumeExpectations: &connectionExpectations{echAccepted: false},
+			})
+		}
+
+		// Test that the client can process ECH rejects after an early data reject.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectServerName: "secret.example",
+				},
+				Credential: &echSecretCertificate,
+			},
+			resumeConfig: &Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig2},
+				Bugs: ProtocolBugs{
+					ExpectServerName: "public.example",
+				},
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				// Although the resumption connection does not accept ECH, the
+				// API will report ECH was accepted at the 0-RTT point.
+				"-expect-ech-accept",
+				// -on-retry refers to the retried handshake after 0-RTT reject,
+				// while ech-retry-configs refers to the ECHConfigs to use in
+				// the next connection attempt.
+				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
+			},
+			resumeSession:           true,
+			expectResumeRejected:    true,
+			earlyData:               true,
+			expectEarlyDataRejected: true,
+			expectations:            connectionExpectations{echAccepted: true},
+			resumeExpectations:      &connectionExpectations{echAccepted: false},
+			shouldFail:              true,
+			expectedLocalError:      "remote error: ECH required",
+			expectedError:           ":ECH_REJECTED:",
+		})
+		// TODO(crbug.com/381113363): Enable this test for DTLS once we
+		// support early data in DTLS 1.3.
+		if protocol != quic && protocol != dtls {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Bugs: ProtocolBugs{
+						ExpectServerName: "secret.example",
+					},
+					Credential: &echSecretCertificate,
+				},
+				resumeConfig: &Config{
+					MaxVersion: VersionTLS12,
+					Bugs: ProtocolBugs{
+						ExpectServerName: "public.example",
+					},
+					Credential: &echPublicCertificate,
+				},
+				flags: []string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-host-name", "secret.example",
+					// Although the resumption connection does not accept ECH, the
+					// API will report ECH was accepted at the 0-RTT point.
+					"-expect-ech-accept",
+				},
+				resumeSession:           true,
+				expectResumeRejected:    true,
+				earlyData:               true,
+				expectEarlyDataRejected: true,
+				expectations:            connectionExpectations{echAccepted: true},
+				resumeExpectations:      &connectionExpectations{echAccepted: false},
+				// ClientHellos with early data cannot negotiate TLS 1.2, with
+				// or without ECH. The shim should first report
+				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
+				// repair the first error by retrying without early data. That
+				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
+				// and ClientHelloOuter. The caller will then trigger a third
+				// attempt, which will succeed.
+				shouldFail:    true,
+				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
+			})
+		}
+
+		// Test that the client ignores ECHConfigs with invalid public names.
+		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-SkipInvalidPublicName",
+			config: Config{
+				Bugs: ProtocolBugs{
+					// No ECHConfigs are supported, so the client should fall
+					// back to cleartext.
+					ExpectNoClientECH: true,
+					ExpectServerName:  "secret.example",
+				},
+				Credential: &echSecretCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+			},
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
+			config: Config{
+				// The client should skip |invalidPublicName| and use |echConfig|.
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectOuterServerName: "public.example",
+					ExpectServerName:      "secret.example",
+				},
+				Credential: &echSecretCertificate,
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
+				"-host-name", "secret.example",
+				"-expect-ech-accept",
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+
+		// Test both sync and async mode, to test both with and without the
+		// client certificate callback.
+		for _, async := range []bool{false, true} {
+			var flags []string
+			var suffix string
+			if async {
+				flags = []string{"-async"}
+				suffix = "-Async"
+			}
+
+			// Test that ECH and client certificates can be used together.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					ClientAuth:       RequireAnyClientCert,
+				},
+				shimCertificate: &rsaCertificate,
+				flags: append([]string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-expect-ech-accept",
+				}, flags...),
+				expectations: connectionExpectations{echAccepted: true},
+			})
+
+			// Test that, when ECH is rejected, the client does not send a client
+			// certificate.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
+				config: Config{
+					MinVersion: VersionTLS13,
+					MaxVersion: VersionTLS13,
+					ClientAuth: RequireAnyClientCert,
+					Credential: &echPublicCertificate,
+				},
+				shimCertificate: &rsaCertificate,
+				flags: append([]string{
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				}, flags...),
+				shouldFail:         true,
+				expectedLocalError: "tls: client didn't provide a certificate",
+			})
+			if protocol != quic {
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
+					config: Config{
+						MinVersion: VersionTLS12,
+						MaxVersion: VersionTLS12,
+						ClientAuth: RequireAnyClientCert,
+						Credential: &echPublicCertificate,
+					},
+					shimCertificate: &rsaCertificate,
+					flags: append([]string{
+						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					}, flags...),
+					shouldFail:         true,
+					expectedLocalError: "tls: client didn't provide a certificate",
+				})
+			}
+		}
+
+		// Test that ECH and Channel ID can be used together. Channel ID does
+		// not exist in DTLS.
+		if protocol != dtls {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-ChannelID",
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					RequestChannelID: true,
+				},
+				flags: []string{
+					"-send-channel-id", channelIDKeyPath,
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					"-expect-ech-accept",
+				},
+				resumeSession: true,
+				expectations: connectionExpectations{
+					channelID:   true,
+					echAccepted: true,
+				},
+			})
+
+			// Handshakes where ECH is rejected do not offer or accept Channel ID.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
+				config: Config{
+					MinVersion: VersionTLS13,
+					MaxVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						AlwaysNegotiateChannelID: true,
+					},
+					Credential: &echPublicCertificate,
+				},
+				flags: []string{
+					"-send-channel-id", channelIDKeyPath,
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: unsupported extension",
+				expectedError:      ":UNEXPECTED_EXTENSION:",
+			})
+			if protocol != quic {
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
+					config: Config{
+						MinVersion: VersionTLS12,
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							AlwaysNegotiateChannelID: true,
+						},
+						Credential: &echPublicCertificate,
+					},
+					flags: []string{
+						"-send-channel-id", channelIDKeyPath,
+						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					},
+					shouldFail:         true,
+					expectedLocalError: "remote error: unsupported extension",
+					expectedError:      ":UNEXPECTED_EXTENSION:",
+				})
+			}
+		}
+
+		// Test that ECH correctly overrides the host name for certificate
+		// verification.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
+			flags: []string{
+				"-verify-peer",
+				"-use-custom-verify-callback",
+				// When not offering ECH, verify the usual name in both full
+				// and resumption handshakes.
+				"-reverify-on-resume",
+				"-expect-no-ech-name-override",
+			},
+			resumeSession: true,
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
+			flags: []string{
+				"-verify-peer",
+				"-use-custom-verify-callback",
+				"-enable-ech-grease",
+				// When offering ECH GREASE, verify the usual name in both full
+				// and resumption handshakes.
+				"-reverify-on-resume",
+				"-expect-no-ech-name-override",
+			},
+			resumeSession: true,
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{
+					"-verify-peer",
+					"-use-custom-verify-callback",
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					// When ECH is rejected, verify the public name. This can
+					// only happen in full handshakes.
+					"-expect-ech-name-override", "public.example",
+				},
+				shouldFail:         true,
+				expectedError:      ":ECH_REJECTED:",
+				expectedLocalError: "remote error: ECH required",
+			})
+		}
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Credential: &echPublicCertificate,
+			},
+			flags: []string{
+				"-verify-peer",
+				"-use-custom-verify-callback",
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				// When ECH is rejected, verify the public name. This can
+				// only happen in full handshakes.
+				"-expect-ech-name-override", "public.example",
+			},
+			shouldFail:         true,
+			expectedError:      ":ECH_REJECTED:",
+			expectedLocalError: "remote error: ECH required",
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-Accept-NoOverrideName",
+			config: Config{
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+			},
+			flags: []string{
+				"-verify-peer",
+				"-use-custom-verify-callback",
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				// When ECH is accepted, verify the usual name in both full and
+				// resumption handshakes.
+				"-reverify-on-resume",
+				"-expect-no-ech-name-override",
+			},
+			resumeSession: true,
+			expectations:  connectionExpectations{echAccepted: true},
+		})
+		// TODO(crbug.com/381113363): Enable this test for DTLS once we
+		// support early data in DTLS 1.3.
+		if protocol != dtls {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: protocol,
+				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
+				config: Config{
+					ServerECHConfigs: []ServerECHConfig{echConfig},
+					Credential:       &echPublicCertificate,
+				},
+				resumeConfig: &Config{
+					Credential: &echPublicCertificate,
+				},
+				flags: []string{
+					"-verify-peer",
+					"-use-custom-verify-callback",
+					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+					// Although the resumption connection does not accept ECH, the
+					// API will report ECH was accepted at the 0-RTT point.
+					"-expect-ech-accept",
+					// The resumption connection verifies certificates twice. First,
+					// if reverification is enabled, we verify the 0-RTT certificate
+					// as if ECH as accepted. There should be no name override.
+					// Next, on the post-0-RTT-rejection retry, we verify the new
+					// server certificate. This picks up the ECH reject, so it
+					// should use public.example.
+					"-reverify-on-resume",
+					"-on-resume-expect-no-ech-name-override",
+					"-on-retry-expect-ech-name-override", "public.example",
+				},
+				resumeSession:           true,
+				expectResumeRejected:    true,
+				earlyData:               true,
+				expectEarlyDataRejected: true,
+				expectations:            connectionExpectations{echAccepted: true},
+				resumeExpectations:      &connectionExpectations{echAccepted: false},
+				shouldFail:              true,
+				expectedError:           ":ECH_REJECTED:",
+				expectedLocalError:      "remote error: ECH required",
+			})
+		}
+
+		// Test that the client checks both HelloRetryRequest and ServerHello
+		// for a confirmation signal.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
+			config: Config{
+				MinVersion:       VersionTLS13,
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{CurveP384},
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectMissingKeyShare:          true, // Check we triggered HRR.
+					OmitServerHelloECHConfirmation: true,
+				},
+			},
+			resumeSession: true,
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-hrr", // Check we triggered HRR.
+			},
+			shouldFail:    true,
+			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
+		})
+
+		// Test the message callback is correctly reported, with and without
+		// HelloRetryRequest.
+		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
+		clientAndServerHelloInitial := clientAndServerHello
+		if protocol == tls {
+			clientAndServerHelloInitial += "write ccs\n"
+		}
+		// EncryptedExtensions onwards.
+		finishHandshake := `read hs 8
+read hs 11
+read hs 15
+read hs 20
+write hs 20
+read ack
+read hs 4
+read hs 4
+`
+		if protocol != dtls {
+			finishHandshake = strings.ReplaceAll(finishHandshake, "read ack\n", "")
+		}
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-MessageCallback",
+			config: Config{
+				MinVersion:       VersionTLS13,
+				MaxVersion:       VersionTLS13,
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					NoCloseNotify: true, // Align QUIC and TCP traces.
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				"-expect-msg-callback", clientAndServerHelloInitial + finishHandshake,
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			protocol: protocol,
+			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
+			config: Config{
+				MinVersion:       VersionTLS13,
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{CurveP384},
+				ServerECHConfigs: []ServerECHConfig{echConfig},
+				Bugs: ProtocolBugs{
+					ExpectMissingKeyShare: true, // Check we triggered HRR.
+					NoCloseNotify:         true, // Align QUIC and TCP traces.
+				},
+			},
+			flags: []string{
+				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+				"-expect-ech-accept",
+				"-expect-hrr", // Check we triggered HRR.
+				"-expect-msg-callback", clientAndServerHelloInitial + clientAndServerHello + finishHandshake,
+			},
+			expectations: connectionExpectations{echAccepted: true},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/ems_tests.go b/src/ssl/test/runner/ems_tests.go
new file mode 100644
index 0000000..16ce0b6
--- /dev/null
+++ b/src/ssl/test/runner/ems_tests.go
@@ -0,0 +1,199 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//	https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addExtendedMasterSecretTests() {
+	const expectEMSFlag = "-expect-extended-master-secret"
+
+	for _, with := range []bool{false, true} {
+		prefix := "No"
+		if with {
+			prefix = ""
+		}
+
+		for _, isClient := range []bool{false, true} {
+			suffix := "-Server"
+			testType := serverTest
+			if isClient {
+				suffix = "-Client"
+				testType = clientTest
+			}
+
+			for _, ver := range tlsVersions {
+				// In TLS 1.3, the extension is irrelevant and
+				// always reports as enabled.
+				var flags []string
+				if with || ver.version >= VersionTLS13 {
+					flags = []string{expectEMSFlag}
+				}
+
+				testCases = append(testCases, testCase{
+					testType: testType,
+					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							NoExtendedMasterSecret:      !with,
+							RequireExtendedMasterSecret: with,
+						},
+					},
+					flags: flags,
+				})
+			}
+		}
+	}
+
+	for _, isClient := range []bool{false, true} {
+		for _, supportedInFirstConnection := range []bool{false, true} {
+			for _, supportedInResumeConnection := range []bool{false, true} {
+				boolToWord := func(b bool) string {
+					if b {
+						return "Yes"
+					}
+					return "No"
+				}
+				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
+				if isClient {
+					suffix += "Client"
+				} else {
+					suffix += "Server"
+				}
+
+				supportedConfig := Config{
+					MaxVersion: VersionTLS12,
+					Bugs: ProtocolBugs{
+						RequireExtendedMasterSecret: true,
+					},
+				}
+
+				noSupportConfig := Config{
+					MaxVersion: VersionTLS12,
+					Bugs: ProtocolBugs{
+						NoExtendedMasterSecret: true,
+					},
+				}
+
+				test := testCase{
+					name:          "ExtendedMasterSecret-" + suffix,
+					resumeSession: true,
+				}
+
+				if !isClient {
+					test.testType = serverTest
+				}
+
+				if supportedInFirstConnection {
+					test.config = supportedConfig
+				} else {
+					test.config = noSupportConfig
+				}
+
+				if supportedInResumeConnection {
+					test.resumeConfig = &supportedConfig
+				} else {
+					test.resumeConfig = &noSupportConfig
+				}
+
+				switch suffix {
+				case "YesToYes-Client", "YesToYes-Server":
+					// When a session is resumed, it should
+					// still be aware that its master
+					// secret was generated via EMS and
+					// thus it's safe to use tls-unique.
+					test.flags = []string{expectEMSFlag}
+				case "NoToYes-Server":
+					// If an original connection did not
+					// contain EMS, but a resumption
+					// handshake does, then a server should
+					// not resume the session.
+					test.expectResumeRejected = true
+				case "YesToNo-Server":
+					// Resuming an EMS session without the
+					// EMS extension should cause the
+					// server to abort the connection.
+					test.shouldFail = true
+					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
+				case "NoToYes-Client":
+					// A client should abort a connection
+					// where the server resumed a non-EMS
+					// session but echoed the EMS
+					// extension.
+					test.shouldFail = true
+					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
+				case "YesToNo-Client":
+					// A client should abort a connection
+					// where the server didn't echo EMS
+					// when the session used it.
+					test.shouldFail = true
+					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
+				}
+
+				testCases = append(testCases, test)
+			}
+		}
+	}
+
+	// Switching EMS on renegotiation is forbidden.
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-NoEMS",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecret:                true,
+				NoExtendedMasterSecretOnRenegotiation: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-Upgrade",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecret: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-Downgrade",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecretOnRenegotiation: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
+	})
+}
diff --git a/src/ssl/test/runner/end_of_flight_tests.go b/src/ssl/test/runner/end_of_flight_tests.go
new file mode 100644
index 0000000..f563b1f
--- /dev/null
+++ b/src/ssl/test/runner/end_of_flight_tests.go
@@ -0,0 +1,138 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+// addEndOfFlightTests adds tests where the runner adds extra data in the final
+// record of each handshake flight. Depending on the implementation strategy,
+// this data may be carried over to the next flight (assuming no key change) or
+// may be rejected. To avoid differences with split handshakes and generally
+// reject misbehavior, BoringSSL treats this as an error. When possible, these
+// tests pull the extra data from the subsequent flight to distinguish the data
+// being carried over from a general syntax error.
+//
+// These tests are similar to tests in |addChangeCipherSpecTests| that send
+// extra data at key changes. Not all key changes are at the end of a flight and
+// not all flights end at a key change.
+func addEndOfFlightTests() {
+	// TLS 1.3 client handshakes.
+	//
+	// Data following the second TLS 1.3 ClientHello is covered by
+	// PartialClientFinishedWithClientHello,
+	// PartialClientFinishedWithSecondClientHello, and
+	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialSecondClientHelloAfterFirst",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Trigger a curve-based HelloRetryRequest.
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				PartialSecondClientHelloAfterFirst: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// TLS 1.3 server handshakes.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "PartialServerHelloWithHelloRetryRequest",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				PartialServerHelloWithHelloRetryRequest: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// TLS 1.2 client handshakes.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialClientKeyExchangeWithClientHello",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PartialClientKeyExchangeWithClientHello: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// TLS 1.2 server handshakes.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "PartialNewSessionTicketWithServerHelloDone",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PartialNewSessionTicketWithServerHelloDone: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	for _, vers := range tlsVersions {
+		for _, testType := range []testType{clientTest, serverTest} {
+			suffix := "-Client"
+			if testType == serverTest {
+				suffix = "-Server"
+			}
+			suffix += "-" + vers.name
+
+			testCases = append(testCases, testCase{
+				testType: testType,
+				name:     "TrailingDataWithFinished" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						TrailingDataWithFinished: true,
+					},
+				},
+				shouldFail:         true,
+				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+				expectedLocalError: "remote error: unexpected message",
+			})
+			testCases = append(testCases, testCase{
+				testType: testType,
+				name:     "TrailingDataWithFinished-Resume" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+				},
+				resumeConfig: &Config{
+					MaxVersion: vers.version,
+					Bugs: ProtocolBugs{
+						TrailingDataWithFinished: true,
+					},
+				},
+				resumeSession:      true,
+				shouldFail:         true,
+				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+				expectedLocalError: "remote error: unexpected message",
+			})
+		}
+	}
+}
diff --git a/src/ssl/test/runner/export_tests.go b/src/ssl/test/runner/export_tests.go
new file mode 100644
index 0000000..14a0c95
--- /dev/null
+++ b/src/ssl/test/runner/export_tests.go
@@ -0,0 +1,226 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "fmt"
+
+func addExportKeyingMaterialTests() {
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, vers := range allVersions(protocol) {
+			suffix := fmt.Sprintf("%s-%s", protocol, vers)
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "ExportKeyingMaterial-" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+				},
+				// Test the exporter in both initial and resumption
+				// handshakes.
+				resumeSession:        true,
+				exportKeyingMaterial: 1024,
+				exportLabel:          "label",
+				exportContext:        "context",
+				useExportContext:     true,
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "ExportKeyingMaterial-NoContext-" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+				},
+				exportKeyingMaterial: 1024,
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "ExportKeyingMaterial-EmptyContext-" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+				},
+				exportKeyingMaterial: 1024,
+				useExportContext:     true,
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "ExportKeyingMaterial-Small-" + suffix,
+				config: Config{
+					MaxVersion: vers.version,
+				},
+				exportKeyingMaterial: 1,
+				exportLabel:          "label",
+				exportContext:        "context",
+				useExportContext:     true,
+			})
+
+			// TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3.
+			if vers.version >= VersionTLS13 && protocol != dtls {
+				// Test the exporters do not work while the client is
+				// sending 0-RTT data.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "NoEarlyKeyingMaterial-Client-InEarlyData-" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+					},
+					resumeSession: true,
+					earlyData:     true,
+					flags: []string{
+						"-on-resume-export-keying-material", "1024",
+						"-on-resume-export-label", "label",
+						"-on-resume-export-context", "context",
+					},
+					shouldFail:    true,
+					expectedError: ":HANDSHAKE_NOT_COMPLETE:",
+				})
+
+				// Test the normal exporter on the server in half-RTT.
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "ExportKeyingMaterial-Server-HalfRTT-" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Bugs: ProtocolBugs{
+							// The shim writes exported data immediately after
+							// the handshake returns, so disable the built-in
+							// early data test.
+							SendEarlyData:     [][]byte{},
+							ExpectHalfRTTData: [][]byte{},
+						},
+					},
+					resumeSession:        true,
+					earlyData:            true,
+					exportKeyingMaterial: 1024,
+					exportLabel:          "label",
+					exportContext:        "context",
+					useExportContext:     true,
+				})
+			}
+		}
+	}
+
+	// Exporters work during a False Start.
+	testCases = append(testCases, testCase{
+		name: "ExportKeyingMaterial-FalseStart",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			NextProtos:   []string{"foo"},
+			Bugs: ProtocolBugs{
+				ExpectFalseStart: true,
+			},
+		},
+		flags: []string{
+			"-false-start",
+			"-advertise-alpn", "\x03foo",
+			"-expect-alpn", "foo",
+		},
+		shimWritesFirst:      true,
+		exportKeyingMaterial: 1024,
+		exportLabel:          "label",
+		exportContext:        "context",
+		useExportContext:     true,
+	})
+
+	// Exporters do not work in the middle of a renegotiation. Test this by
+	// triggering the exporter after every SSL_read call and configuring the
+	// shim to run asynchronously.
+	testCases = append(testCases, testCase{
+		name: "ExportKeyingMaterial-Renegotiate",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-async",
+			"-use-exporter-between-reads",
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: "failed to export keying material",
+	})
+}
+
+func addExportTrafficSecretsTests() {
+	for _, cipherSuite := range []testCipherSuite{
+		// Test a SHA-256 and SHA-384 based cipher suite.
+		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
+		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
+	} {
+		testCases = append(testCases, testCase{
+			name: "ExportTrafficSecrets-" + cipherSuite.name,
+			config: Config{
+				MinVersion:   VersionTLS13,
+				CipherSuites: []uint16{cipherSuite.id},
+			},
+			exportTrafficSecrets: true,
+		})
+	}
+}
+
+func addTLSUniqueTests() {
+	for _, isClient := range []bool{false, true} {
+		for _, isResumption := range []bool{false, true} {
+			for _, hasEMS := range []bool{false, true} {
+				var suffix string
+				if isResumption {
+					suffix = "Resume-"
+				} else {
+					suffix = "Full-"
+				}
+
+				if hasEMS {
+					suffix += "EMS-"
+				} else {
+					suffix += "NoEMS-"
+				}
+
+				if isClient {
+					suffix += "Client"
+				} else {
+					suffix += "Server"
+				}
+
+				test := testCase{
+					name:          "TLSUnique-" + suffix,
+					testTLSUnique: true,
+					config: Config{
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							NoExtendedMasterSecret: !hasEMS,
+						},
+					},
+				}
+
+				if isResumption {
+					test.resumeSession = true
+					test.resumeConfig = &Config{
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							NoExtendedMasterSecret: !hasEMS,
+						},
+					}
+				}
+
+				if isResumption && !hasEMS {
+					test.shouldFail = true
+					test.expectedError = "failed to get tls-unique"
+				}
+
+				testCases = append(testCases, test)
+			}
+		}
+	}
+}
diff --git a/src/ssl/test/runner/extension_tests.go b/src/ssl/test/runner/extension_tests.go
new file mode 100644
index 0000000..4286528
--- /dev/null
+++ b/src/ssl/test/runner/extension_tests.go
@@ -0,0 +1,2348 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"fmt"
+	"math/big"
+	"time"
+)
+
+func addExtensionTests() {
+	exampleCertificate := generateSingleCertChain(&x509.Certificate{
+		SerialNumber: big.NewInt(57005),
+		Subject: pkix.Name{
+			CommonName: "test cert",
+		},
+		NotBefore:             time.Now().Add(-time.Hour),
+		NotAfter:              time.Now().Add(time.Hour),
+		DNSNames:              []string{"example.com"},
+		IsCA:                  true,
+		BasicConstraintsValid: true,
+	}, &ecdsaP256Key)
+
+	// Repeat extensions tests at all versions.
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, ver := range allVersions(protocol) {
+			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
+
+			// Test that duplicate extensions are rejected.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "DuplicateExtensionClient-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						DuplicateExtension: true,
+					},
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: error decoding message",
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "DuplicateExtensionServer-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						DuplicateExtension: true,
+					},
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: error decoding message",
+			})
+
+			// Test SNI.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "ServerNameExtensionClient-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectServerName: "example.com",
+					},
+					Credential: &exampleCertificate,
+				},
+				flags: []string{"-host-name", "example.com"},
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "ServerNameExtensionClientMismatch-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectServerName: "mismatch.com",
+					},
+				},
+				flags:              []string{"-host-name", "example.com"},
+				shouldFail:         true,
+				expectedLocalError: "tls: unexpected server name",
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "ServerNameExtensionClientMissing-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectServerName: "missing.com",
+					},
+				},
+				shouldFail:         true,
+				expectedLocalError: "tls: unexpected server name",
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "TolerateServerNameAck-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendServerNameAck: true,
+					},
+					Credential: &exampleCertificate,
+				},
+				flags:         []string{"-host-name", "example.com"},
+				resumeSession: true,
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: clientTest,
+				name:     "UnsolicitedServerNameAck-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendServerNameAck: true,
+					},
+				},
+				shouldFail:         true,
+				expectedError:      ":UNEXPECTED_EXTENSION:",
+				expectedLocalError: "remote error: unsupported extension",
+			})
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "ServerNameExtensionServer-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					ServerName: "example.com",
+				},
+				flags:         []string{"-expect-server-name", "example.com"},
+				resumeSession: true,
+			})
+
+			// Test ALPN.
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           clientTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNClient-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo"},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo\x03bar\x03baz",
+					"-expect-alpn", "foo",
+				},
+				expectations: connectionExpectations{
+					nextProto:     "foo",
+					nextProtoType: alpn,
+				},
+				resumeSession: true,
+			})
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           clientTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNClient-RejectUnknown-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendALPN: "baz",
+					},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo\x03bar",
+				},
+				shouldFail:         true,
+				expectedError:      ":INVALID_ALPN_PROTOCOL:",
+				expectedLocalError: "remote error: illegal parameter",
+			})
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           clientTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNClient-AllowUnknown-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendALPN: "baz",
+					},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo\x03bar",
+					"-allow-unknown-alpn-protos",
+					"-expect-alpn", "baz",
+				},
+			})
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+				},
+				flags: []string{
+					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+					"-select-alpn", "foo",
+				},
+				expectations: connectionExpectations{
+					nextProto:     "foo",
+					nextProtoType: alpn,
+				},
+				resumeSession: true,
+			})
+
+			var shouldDeclineALPNFail bool
+			var declineALPNError, declineALPNLocalError string
+			if protocol == quic {
+				// ALPN is mandatory in QUIC.
+				shouldDeclineALPNFail = true
+				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
+				declineALPNLocalError = "remote error: no application protocol"
+			}
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-Decline-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+				},
+				flags: []string{"-decline-alpn"},
+				expectations: connectionExpectations{
+					noNextProto: true,
+				},
+				resumeSession:      true,
+				shouldFail:         shouldDeclineALPNFail,
+				expectedError:      declineALPNError,
+				expectedLocalError: declineALPNLocalError,
+			})
+
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-Reject-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+				},
+				flags:              []string{"-reject-alpn"},
+				shouldFail:         true,
+				expectedError:      ":NO_APPLICATION_PROTOCOL:",
+				expectedLocalError: "remote error: no application protocol",
+			})
+
+			// Test that the server implementation catches itself if the
+			// callback tries to return an invalid empty ALPN protocol.
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-SelectEmpty-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+				},
+				flags: []string{
+					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+					"-select-empty-alpn",
+				},
+				shouldFail:         true,
+				expectedLocalError: "remote error: internal error",
+				expectedError:      ":INVALID_ALPN_PROTOCOL:",
+			})
+
+			// Test ALPN in async mode as well to ensure that extensions callbacks are only
+			// called once.
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-Async-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+					// Prior to TLS 1.3, exercise the asynchronous session callback.
+					SessionTicketsDisabled: ver.version < VersionTLS13,
+				},
+				flags: []string{
+					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+					"-select-alpn", "foo",
+					"-async",
+				},
+				expectations: connectionExpectations{
+					nextProto:     "foo",
+					nextProtoType: alpn,
+				},
+				resumeSession: true,
+			})
+
+			var emptyString string
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           clientTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNClient-EmptyProtocolName-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{""},
+					Bugs: ProtocolBugs{
+						// A server returning an empty ALPN protocol
+						// should be rejected.
+						ALPNProtocol: &emptyString,
+					},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo",
+				},
+				shouldFail:    true,
+				expectedError: ":PARSE_TLSEXT:",
+			})
+			testCases = append(testCases, testCase{
+				protocol:           protocol,
+				testType:           serverTest,
+				skipQUICALPNConfig: true,
+				name:               "ALPNServer-EmptyProtocolName-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					// A ClientHello containing an empty ALPN protocol
+					// should be rejected.
+					NextProtos: []string{"foo", "", "baz"},
+				},
+				flags: []string{
+					"-select-alpn", "foo",
+				},
+				shouldFail:    true,
+				expectedError: ":PARSE_TLSEXT:",
+			})
+
+			// Test NPN and the interaction with ALPN.
+			if ver.version < VersionTLS13 && protocol == tls {
+				// Test that the server prefers ALPN over NPN.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "ALPNServer-Preferred-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						NextProtos: []string{"foo", "bar", "baz"},
+					},
+					flags: []string{
+						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+						"-select-alpn", "foo",
+						"-advertise-npn", "\x03foo\x03bar\x03baz",
+					},
+					expectations: connectionExpectations{
+						nextProto:     "foo",
+						nextProtoType: alpn,
+					},
+					resumeSession: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "ALPNServer-Preferred-Swapped-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						NextProtos: []string{"foo", "bar", "baz"},
+						Bugs: ProtocolBugs{
+							SwapNPNAndALPN: true,
+						},
+					},
+					flags: []string{
+						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+						"-select-alpn", "foo",
+						"-advertise-npn", "\x03foo\x03bar\x03baz",
+					},
+					expectations: connectionExpectations{
+						nextProto:     "foo",
+						nextProtoType: alpn,
+					},
+					resumeSession: true,
+				})
+
+				// Test that negotiating both NPN and ALPN is forbidden.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "NegotiateALPNAndNPN-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						NextProtos: []string{"foo", "bar", "baz"},
+						Bugs: ProtocolBugs{
+							NegotiateALPNAndNPN: true,
+						},
+					},
+					flags: []string{
+						"-advertise-alpn", "\x03foo",
+						"-select-next-proto", "foo",
+					},
+					shouldFail:    true,
+					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						NextProtos: []string{"foo", "bar", "baz"},
+						Bugs: ProtocolBugs{
+							NegotiateALPNAndNPN: true,
+							SwapNPNAndALPN:      true,
+						},
+					},
+					flags: []string{
+						"-advertise-alpn", "\x03foo",
+						"-select-next-proto", "foo",
+					},
+					shouldFail:    true,
+					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
+				})
+			}
+
+			// Test missing ALPN in QUIC
+			if protocol == quic {
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     "Client-ALPNMissingFromConfig-" + suffix,
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+					},
+					skipQUICALPNConfig: true,
+					shouldFail:         true,
+					expectedError:      ":NO_APPLICATION_PROTOCOL:",
+				})
+				testCases = append(testCases, testCase{
+					testType: clientTest,
+					protocol: protocol,
+					name:     "Client-ALPNMissing-" + suffix,
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+					},
+					flags: []string{
+						"-advertise-alpn", "\x03foo",
+					},
+					skipQUICALPNConfig: true,
+					shouldFail:         true,
+					expectedError:      ":NO_APPLICATION_PROTOCOL:",
+					expectedLocalError: "remote error: no application protocol",
+				})
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "Server-ALPNMissing-" + suffix,
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+					},
+					skipQUICALPNConfig: true,
+					shouldFail:         true,
+					expectedError:      ":NO_APPLICATION_PROTOCOL:",
+					expectedLocalError: "remote error: no application protocol",
+				})
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "Server-ALPNMismatch-" + suffix,
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+						NextProtos: []string{"foo"},
+					},
+					flags: []string{
+						"-decline-alpn",
+					},
+					skipQUICALPNConfig: true,
+					shouldFail:         true,
+					expectedError:      ":NO_APPLICATION_PROTOCOL:",
+					expectedLocalError: "remote error: no application protocol",
+				})
+			}
+
+			// Test ALPS.
+			if ver.version >= VersionTLS13 {
+				// Test basic client with different ALPS codepoint.
+				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
+					useAlpsCodepointFlag := "0"
+					if alpsCodePoint == ALPSUseCodepointNew {
+						useAlpsCodepointFlag = "1"
+					}
+
+					flags := []string{"-alps-use-new-codepoint", useAlpsCodepointFlag}
+					expectations := connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim1"),
+					}
+					resumeExpectations := &connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim2"),
+					}
+
+					if alpsCodePoint == ALPSUseCodepointNew {
+						expectations = connectionExpectations{
+							peerApplicationSettings: []byte("shim1"),
+						}
+						resumeExpectations = &connectionExpectations{
+							peerApplicationSettings: []byte("shim2"),
+						}
+					}
+
+					flags = append(flags,
+						"-advertise-alpn", "\x05proto",
+						"-expect-alpn", "proto",
+						"-on-initial-application-settings", "proto,shim1",
+						"-on-initial-expect-peer-application-settings", "runner1",
+						"-on-resume-application-settings", "proto,shim2",
+						"-on-resume-expect-peer-application-settings", "runner2")
+
+					// Test that server can negotiate ALPS, including different values
+					// on resumption.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           clientTest,
+						name:               fmt.Sprintf("ALPS-Basic-Client-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeConfig: &Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession:      true,
+						expectations:       expectations,
+						resumeExpectations: resumeExpectations,
+						flags:              flags,
+					})
+
+					// Test basic server with different ALPS codepoint.
+					flags = []string{"-alps-use-new-codepoint", useAlpsCodepointFlag}
+					expectations = connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim1"),
+					}
+					resumeExpectations = &connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim2"),
+					}
+
+					if alpsCodePoint == ALPSUseCodepointNew {
+						expectations = connectionExpectations{
+							peerApplicationSettings: []byte("shim1"),
+						}
+						resumeExpectations = &connectionExpectations{
+							peerApplicationSettings: []byte("shim2"),
+						}
+					}
+
+					flags = append(flags,
+						"-select-alpn", "proto",
+						"-on-initial-application-settings", "proto,shim1",
+						"-on-initial-expect-peer-application-settings", "runner1",
+						"-on-resume-application-settings", "proto,shim2",
+						"-on-resume-expect-peer-application-settings", "runner2")
+
+					// Test that server can negotiate ALPS, including different values
+					// on resumption.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-Basic-Server-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeConfig: &Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession:      true,
+						expectations:       expectations,
+						resumeExpectations: resumeExpectations,
+						flags:              flags,
+					})
+
+					// Try different ALPS codepoint for all the existing tests.
+					alpsFlags := []string{"-alps-use-new-codepoint", useAlpsCodepointFlag}
+					expectations = connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim1"),
+					}
+					resumeExpectations = &connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim2"),
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						expectations = connectionExpectations{
+							peerApplicationSettings: []byte("shim1"),
+						}
+						resumeExpectations = &connectionExpectations{
+							peerApplicationSettings: []byte("shim2"),
+						}
+					}
+
+					// Test that the server can defer its ALPS configuration to the ALPN
+					// selection callback.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-Basic-Server-Defer-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeConfig: &Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession:      true,
+						expectations:       expectations,
+						resumeExpectations: resumeExpectations,
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-defer-alps",
+							"-on-initial-application-settings", "proto,shim1",
+							"-on-initial-expect-peer-application-settings", "runner1",
+							"-on-resume-application-settings", "proto,shim2",
+							"-on-resume-expect-peer-application-settings", "runner2",
+						}, alpsFlags...),
+					})
+
+					expectations = connectionExpectations{
+						peerApplicationSettingsOld: []byte{},
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						expectations = connectionExpectations{
+							peerApplicationSettings: []byte{},
+						}
+					}
+					// Test the client and server correctly handle empty settings.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           clientTest,
+						name:               fmt.Sprintf("ALPS-Empty-Client-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": {}},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession: true,
+						expectations:  expectations,
+						flags: append([]string{
+							"-advertise-alpn", "\x05proto",
+							"-expect-alpn", "proto",
+							"-application-settings", "proto,",
+							"-expect-peer-application-settings", "",
+						}, alpsFlags...),
+					})
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-Empty-Server-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": {}},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession: true,
+						expectations:  expectations,
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-application-settings", "proto,",
+							"-expect-peer-application-settings", "",
+						}, alpsFlags...),
+					})
+
+					bugs := ProtocolBugs{
+						AlwaysNegotiateApplicationSettingsOld: true,
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						bugs = ProtocolBugs{
+							AlwaysNegotiateApplicationSettingsNew: true,
+						}
+					}
+					// Test the client rejects application settings from the server on
+					// protocols it doesn't have them.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           clientTest,
+						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto1"},
+							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
+							Bugs:                bugs,
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						// The client supports ALPS with "proto2", but not "proto1".
+						flags: append([]string{
+							"-advertise-alpn", "\x06proto1\x06proto2",
+							"-application-settings", "proto2,shim",
+							"-expect-alpn", "proto1",
+						}, alpsFlags...),
+						// The server sends ALPS with "proto1", which is invalid.
+						shouldFail:         true,
+						expectedError:      ":INVALID_ALPN_PROTOCOL:",
+						expectedLocalError: "remote error: illegal parameter",
+					})
+
+					// Test client rejects application settings from the server when
+					// server sends the wrong ALPS codepoint.
+					bugs = ProtocolBugs{
+						AlwaysNegotiateApplicationSettingsOld: true,
+					}
+					if alpsCodePoint == ALPSUseCodepointOld {
+						bugs = ProtocolBugs{
+							AlwaysNegotiateApplicationSettingsNew: true,
+						}
+					}
+
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           clientTest,
+						name:               fmt.Sprintf("ALPS-WrongServerCodepoint-Client-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": {}},
+							Bugs:                bugs,
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags: append([]string{
+							"-advertise-alpn", "\x05proto",
+							"-expect-alpn", "proto",
+							"-application-settings", "proto,",
+							"-expect-peer-application-settings", "",
+						}, alpsFlags...),
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_EXTENSION:",
+						expectedLocalError: "remote error: unsupported extension",
+					})
+
+					// Test server ignore wrong codepoint from client.
+					clientSends := ALPSUseCodepointNew
+					if alpsCodePoint == ALPSUseCodepointNew {
+						clientSends = ALPSUseCodepointOld
+					}
+
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-IgnoreClientWrongCodepoint-Server-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+							ALPSUseNewCodepoint: clientSends,
+						},
+						resumeConfig: &Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+							ALPSUseNewCodepoint: clientSends,
+						},
+						resumeSession: true,
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-on-initial-application-settings", "proto,shim1",
+							"-on-resume-application-settings", "proto,shim2",
+						}, alpsFlags...),
+					})
+
+					// Test the server declines ALPS if it doesn't support it for the
+					// specified protocol.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Server-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto1"},
+							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						// The server supports ALPS with "proto2", but not "proto1".
+						flags: append([]string{
+							"-select-alpn", "proto1",
+							"-application-settings", "proto2,shim",
+						}, alpsFlags...),
+					})
+
+					// Test the client rejects application settings from the server when
+					// it always negotiate both codepoint.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           clientTest,
+						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-ServerBoth-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto1"},
+							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
+							Bugs: ProtocolBugs{
+								AlwaysNegotiateApplicationSettingsBoth: true,
+							},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags: append([]string{
+							"-advertise-alpn", "\x06proto1\x06proto2",
+							"-application-settings", "proto1,shim",
+							"-expect-alpn", "proto1",
+						}, alpsFlags...),
+						// The server sends ALPS with both application settings, which is invalid.
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_EXTENSION:",
+						expectedLocalError: "remote error: unsupported extension",
+					})
+
+					expectations = connectionExpectations{
+						peerApplicationSettingsOld: []byte("shim"),
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						expectations = connectionExpectations{
+							peerApplicationSettings: []byte("shim"),
+						}
+					}
+
+					// Test that the server rejects a missing application_settings extension.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-OmitClientApplicationSettings-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
+							Bugs: ProtocolBugs{
+								OmitClientApplicationSettings: true,
+							},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-application-settings", "proto,shim",
+						}, alpsFlags...),
+						// The runner is a client, so it only processes the shim's alert
+						// after checking connection state.
+						expectations:       expectations,
+						shouldFail:         true,
+						expectedError:      ":MISSING_EXTENSION:",
+						expectedLocalError: "remote error: missing extension",
+					})
+
+					// Test that the server rejects a missing EncryptedExtensions message.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ALPS-OmitClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
+							Bugs: ProtocolBugs{
+								OmitClientEncryptedExtensions: true,
+							},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-application-settings", "proto,shim",
+						}, alpsFlags...),
+						// The runner is a client, so it only processes the shim's alert
+						// after checking connection state.
+						expectations:       expectations,
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_MESSAGE:",
+						expectedLocalError: "remote error: unexpected message",
+					})
+
+					// Test that the server rejects an unexpected EncryptedExtensions message.
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: serverTest,
+						name:     fmt.Sprintf("UnexpectedClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
+						config: Config{
+							MaxVersion: ver.version,
+							Bugs: ProtocolBugs{
+								AlwaysSendClientEncryptedExtensions: true,
+							},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_MESSAGE:",
+						expectedLocalError: "remote error: unexpected message",
+					})
+
+					// Test that the server rejects an unexpected extension in an
+					// expected EncryptedExtensions message.
+					testCases = append(testCases, testCase{
+						protocol:           protocol,
+						testType:           serverTest,
+						name:               fmt.Sprintf("ExtraClientEncryptedExtension-%s-%s", alpsCodePoint, suffix),
+						skipQUICALPNConfig: true,
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"proto"},
+							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
+							Bugs: ProtocolBugs{
+								SendExtraClientEncryptedExtension: true,
+							},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags: append([]string{
+							"-select-alpn", "proto",
+							"-application-settings", "proto,shim",
+						}, alpsFlags...),
+						// The runner is a client, so it only processes the shim's alert
+						// after checking connection state.
+						expectations:       expectations,
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_EXTENSION:",
+						expectedLocalError: "remote error: unsupported extension",
+					})
+
+					// Test that ALPS is carried over on 0-RTT.
+					// TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3.
+					if protocol != dtls {
+						for _, empty := range []bool{false, true} {
+							maybeEmpty := ""
+							runnerSettings := "runner"
+							shimSettings := "shim"
+							if empty {
+								maybeEmpty = "Empty-"
+								runnerSettings = ""
+								shimSettings = ""
+							}
+
+							expectations = connectionExpectations{
+								peerApplicationSettingsOld: []byte(shimSettings),
+							}
+							if alpsCodePoint == ALPSUseCodepointNew {
+								expectations = connectionExpectations{
+									peerApplicationSettings: []byte(shimSettings),
+								}
+							}
+							testCases = append(testCases, testCase{
+								protocol:           protocol,
+								testType:           clientTest,
+								name:               fmt.Sprintf("ALPS-EarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
+								skipQUICALPNConfig: true,
+								config: Config{
+									MaxVersion:          ver.version,
+									NextProtos:          []string{"proto"},
+									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
+									ALPSUseNewCodepoint: alpsCodePoint,
+								},
+								resumeSession: true,
+								earlyData:     true,
+								flags: append([]string{
+									"-advertise-alpn", "\x05proto",
+									"-expect-alpn", "proto",
+									"-application-settings", "proto," + shimSettings,
+									"-expect-peer-application-settings", runnerSettings,
+								}, alpsFlags...),
+								expectations: expectations,
+							})
+							testCases = append(testCases, testCase{
+								protocol:           protocol,
+								testType:           serverTest,
+								name:               fmt.Sprintf("ALPS-EarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
+								skipQUICALPNConfig: true,
+								config: Config{
+									MaxVersion:          ver.version,
+									NextProtos:          []string{"proto"},
+									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
+									ALPSUseNewCodepoint: alpsCodePoint,
+								},
+								resumeSession: true,
+								earlyData:     true,
+								flags: append([]string{
+									"-select-alpn", "proto",
+									"-application-settings", "proto," + shimSettings,
+									"-expect-peer-application-settings", runnerSettings,
+								}, alpsFlags...),
+								expectations: expectations,
+							})
+
+							// Sending application settings in 0-RTT handshakes is forbidden.
+							testCases = append(testCases, testCase{
+								protocol:           protocol,
+								testType:           clientTest,
+								name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
+								skipQUICALPNConfig: true,
+								config: Config{
+									MaxVersion:          ver.version,
+									NextProtos:          []string{"proto"},
+									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
+									Bugs: ProtocolBugs{
+										SendApplicationSettingsWithEarlyData: true,
+									},
+									ALPSUseNewCodepoint: alpsCodePoint,
+								},
+								resumeSession: true,
+								earlyData:     true,
+								flags: append([]string{
+									"-advertise-alpn", "\x05proto",
+									"-expect-alpn", "proto",
+									"-application-settings", "proto," + shimSettings,
+									"-expect-peer-application-settings", runnerSettings,
+								}, alpsFlags...),
+								expectations:       expectations,
+								shouldFail:         true,
+								expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
+								expectedLocalError: "remote error: illegal parameter",
+							})
+							testCases = append(testCases, testCase{
+								protocol:           protocol,
+								testType:           serverTest,
+								name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
+								skipQUICALPNConfig: true,
+								config: Config{
+									MaxVersion:          ver.version,
+									NextProtos:          []string{"proto"},
+									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
+									Bugs: ProtocolBugs{
+										SendApplicationSettingsWithEarlyData: true,
+									},
+									ALPSUseNewCodepoint: alpsCodePoint,
+								},
+								resumeSession: true,
+								earlyData:     true,
+								flags: append([]string{
+									"-select-alpn", "proto",
+									"-application-settings", "proto," + shimSettings,
+									"-expect-peer-application-settings", runnerSettings,
+								}, alpsFlags...),
+								expectations:       expectations,
+								shouldFail:         true,
+								expectedError:      ":UNEXPECTED_MESSAGE:",
+								expectedLocalError: "remote error: unexpected message",
+							})
+						}
+
+						// Test that the client and server each decline early data if local
+						// ALPS preferences has changed for the current connection.
+						alpsMismatchTests := []struct {
+							name                            string
+							initialSettings, resumeSettings []byte
+						}{
+							{"DifferentValues", []byte("settings1"), []byte("settings2")},
+							{"OnOff", []byte("settings"), nil},
+							{"OffOn", nil, []byte("settings")},
+							// The empty settings value should not be mistaken for ALPS not
+							// being negotiated.
+							{"OnEmpty", []byte("settings"), []byte{}},
+							{"EmptyOn", []byte{}, []byte("settings")},
+							{"EmptyOff", []byte{}, nil},
+							{"OffEmpty", nil, []byte{}},
+						}
+						for _, test := range alpsMismatchTests {
+							flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
+							flags = append(flags, alpsFlags...)
+							if test.initialSettings != nil {
+								flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
+								flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
+							}
+							if test.resumeSettings != nil {
+								flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
+								flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
+							}
+
+							expectations = connectionExpectations{
+								peerApplicationSettingsOld: test.initialSettings,
+							}
+							resumeExpectations = &connectionExpectations{
+								peerApplicationSettingsOld: test.resumeSettings,
+							}
+							if alpsCodePoint == ALPSUseCodepointNew {
+								expectations = connectionExpectations{
+									peerApplicationSettings: test.initialSettings,
+								}
+								resumeExpectations = &connectionExpectations{
+									peerApplicationSettings: test.resumeSettings,
+								}
+							}
+							// The client should not offer early data if the session is
+							// inconsistent with the new configuration. Note that if
+							// the session did not negotiate ALPS (test.initialSettings
+							// is nil), the client always offers early data.
+							if test.initialSettings != nil {
+								testCases = append(testCases, testCase{
+									protocol:           protocol,
+									testType:           clientTest,
+									name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s-%s", test.name, alpsCodePoint, suffix),
+									skipQUICALPNConfig: true,
+									config: Config{
+										MaxVersion:          ver.version,
+										MaxEarlyDataSize:    16384,
+										NextProtos:          []string{"proto"},
+										ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
+										ALPSUseNewCodepoint: alpsCodePoint,
+									},
+									resumeSession: true,
+									flags: append([]string{
+										"-enable-early-data",
+										"-expect-ticket-supports-early-data",
+										"-expect-no-offer-early-data",
+										"-advertise-alpn", "\x05proto",
+										"-expect-alpn", "proto",
+									}, flags...),
+									expectations:       expectations,
+									resumeExpectations: resumeExpectations,
+								})
+							}
+
+							// The server should reject early data if the session is
+							// inconsistent with the new selection.
+							testCases = append(testCases, testCase{
+								protocol:           protocol,
+								testType:           serverTest,
+								name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s-%s", test.name, alpsCodePoint, suffix),
+								skipQUICALPNConfig: true,
+								config: Config{
+									MaxVersion:          ver.version,
+									NextProtos:          []string{"proto"},
+									ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
+									ALPSUseNewCodepoint: alpsCodePoint,
+								},
+								resumeSession:           true,
+								earlyData:               true,
+								expectEarlyDataRejected: true,
+								flags: append([]string{
+									"-select-alpn", "proto",
+								}, flags...),
+								expectations:       expectations,
+								resumeExpectations: resumeExpectations,
+							})
+						}
+
+						// Test that 0-RTT continues working when the shim configures
+						// ALPS but the peer does not.
+						testCases = append(testCases, testCase{
+							protocol:           protocol,
+							testType:           clientTest,
+							name:               fmt.Sprintf("ALPS-EarlyData-Client-ServerDecline-%s-%s", alpsCodePoint, suffix),
+							skipQUICALPNConfig: true,
+							config: Config{
+								MaxVersion:          ver.version,
+								NextProtos:          []string{"proto"},
+								ALPSUseNewCodepoint: alpsCodePoint,
+							},
+							resumeSession: true,
+							earlyData:     true,
+							flags: append([]string{
+								"-advertise-alpn", "\x05proto",
+								"-expect-alpn", "proto",
+								"-application-settings", "proto,shim",
+							}, alpsFlags...),
+						})
+						testCases = append(testCases, testCase{
+							protocol:           protocol,
+							testType:           serverTest,
+							name:               fmt.Sprintf("ALPS-EarlyData-Server-ClientNoOffe-%s-%s", alpsCodePoint, suffix),
+							skipQUICALPNConfig: true,
+							config: Config{
+								MaxVersion:          ver.version,
+								NextProtos:          []string{"proto"},
+								ALPSUseNewCodepoint: alpsCodePoint,
+							},
+							resumeSession: true,
+							earlyData:     true,
+							flags: append([]string{
+								"-select-alpn", "proto",
+								"-application-settings", "proto,shim",
+							}, alpsFlags...),
+						})
+					}
+				}
+			} else {
+				// Test the client rejects the ALPS extension if the server
+				// negotiated TLS 1.2 or below.
+				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
+					useAlpsCodepointFlag := "0"
+					if alpsCodePoint == ALPSUseCodepointNew {
+						useAlpsCodepointFlag = "1"
+					}
+
+					flags := []string{
+						"-advertise-alpn", "\x03foo",
+						"-expect-alpn", "foo",
+						"-application-settings", "foo,shim",
+						"-alps-use-new-codepoint", useAlpsCodepointFlag,
+					}
+					bugs := ProtocolBugs{
+						AlwaysNegotiateApplicationSettingsOld: true,
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						bugs = ProtocolBugs{
+							AlwaysNegotiateApplicationSettingsNew: true,
+						}
+					}
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: clientTest,
+						name:     fmt.Sprintf("ALPS-Reject-Client-%s-%s", alpsCodePoint, suffix),
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"foo"},
+							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
+							Bugs:                bugs,
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						flags:              flags,
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_EXTENSION:",
+						expectedLocalError: "remote error: unsupported extension",
+					})
+
+					flags = []string{
+						"-on-resume-advertise-alpn", "\x03foo",
+						"-on-resume-expect-alpn", "foo",
+						"-on-resume-application-settings", "foo,shim",
+						"-alps-use-new-codepoint", useAlpsCodepointFlag,
+					}
+					bugs = ProtocolBugs{
+						AlwaysNegotiateApplicationSettingsOld: true,
+					}
+					if alpsCodePoint == ALPSUseCodepointNew {
+						bugs = ProtocolBugs{
+							AlwaysNegotiateApplicationSettingsNew: true,
+						}
+					}
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: clientTest,
+						name:     fmt.Sprintf("ALPS-Reject-Client-Resume-%s-%s", alpsCodePoint, suffix),
+						config: Config{
+							MaxVersion: ver.version,
+						},
+						resumeConfig: &Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"foo"},
+							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
+							Bugs:                bugs,
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						resumeSession:      true,
+						flags:              flags,
+						shouldFail:         true,
+						expectedError:      ":UNEXPECTED_EXTENSION:",
+						expectedLocalError: "remote error: unsupported extension",
+					})
+
+					// Test the server declines ALPS if it negotiates TLS 1.2 or below.
+					flags = []string{
+						"-select-alpn", "foo",
+						"-application-settings", "foo,shim",
+						"-alps-use-new-codepoint", useAlpsCodepointFlag,
+					}
+
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: serverTest,
+						name:     fmt.Sprintf("ALPS-Decline-Server-%s-%s", alpsCodePoint, suffix),
+						config: Config{
+							MaxVersion:          ver.version,
+							NextProtos:          []string{"foo"},
+							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
+							ALPSUseNewCodepoint: alpsCodePoint,
+						},
+						// Test both TLS 1.2 full and resumption handshakes.
+						resumeSession: true,
+						flags:         flags,
+						// If not specified, runner and shim both implicitly expect ALPS
+						// is not negotiated.
+					})
+				}
+			}
+
+			// Test QUIC transport params
+			if protocol == quic {
+				// Client sends params
+				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
+					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
+						useCodepointFlag := "0"
+						if clientConfig == QUICUseCodepointLegacy {
+							useCodepointFlag = "1"
+						}
+						flags := []string{
+							"-quic-transport-params",
+							base64FlagValue([]byte{1, 2}),
+							"-quic-use-legacy-codepoint", useCodepointFlag,
+						}
+						expectations := connectionExpectations{
+							quicTransportParams: []byte{1, 2},
+						}
+						shouldFail := false
+						expectedError := ""
+						expectedLocalError := ""
+						if clientConfig == QUICUseCodepointLegacy {
+							expectations = connectionExpectations{
+								quicTransportParamsLegacy: []byte{1, 2},
+							}
+						}
+						if serverSends != clientConfig {
+							expectations = connectionExpectations{}
+							shouldFail = true
+							if serverSends == QUICUseCodepointNeither {
+								expectedError = ":MISSING_EXTENSION:"
+							} else {
+								expectedLocalError = "remote error: unsupported extension"
+							}
+						} else {
+							flags = append(flags,
+								"-expect-quic-transport-params",
+								base64FlagValue([]byte{3, 4}))
+						}
+						testCases = append(testCases, testCase{
+							testType: clientTest,
+							protocol: protocol,
+							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
+							config: Config{
+								MinVersion:                            ver.version,
+								MaxVersion:                            ver.version,
+								QUICTransportParams:                   []byte{3, 4},
+								QUICTransportParamsUseLegacyCodepoint: serverSends,
+							},
+							flags:                     flags,
+							expectations:              expectations,
+							shouldFail:                shouldFail,
+							expectedError:             expectedError,
+							expectedLocalError:        expectedLocalError,
+							skipTransportParamsConfig: true,
+						})
+					}
+				}
+				// Server sends params
+				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
+					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
+						expectations := connectionExpectations{
+							quicTransportParams: []byte{3, 4},
+						}
+						shouldFail := false
+						expectedError := ""
+						useCodepointFlag := "0"
+						if serverConfig == QUICUseCodepointLegacy {
+							useCodepointFlag = "1"
+							expectations = connectionExpectations{
+								quicTransportParamsLegacy: []byte{3, 4},
+							}
+						}
+						flags := []string{
+							"-quic-transport-params",
+							base64FlagValue([]byte{3, 4}),
+							"-quic-use-legacy-codepoint", useCodepointFlag,
+						}
+						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
+							expectations = connectionExpectations{}
+							shouldFail = true
+							expectedError = ":MISSING_EXTENSION:"
+						} else {
+							flags = append(flags,
+								"-expect-quic-transport-params",
+								base64FlagValue([]byte{1, 2}),
+							)
+						}
+						testCases = append(testCases, testCase{
+							testType: serverTest,
+							protocol: protocol,
+							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
+							config: Config{
+								MinVersion:                            ver.version,
+								MaxVersion:                            ver.version,
+								QUICTransportParams:                   []byte{1, 2},
+								QUICTransportParamsUseLegacyCodepoint: clientSends,
+							},
+							flags:                     flags,
+							expectations:              expectations,
+							shouldFail:                shouldFail,
+							expectedError:             expectedError,
+							skipTransportParamsConfig: true,
+						})
+					}
+				}
+			} else {
+				// Ensure non-QUIC client doesn't send QUIC transport parameters.
+				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
+					useCodepointFlag := "0"
+					if clientConfig == QUICUseCodepointLegacy {
+						useCodepointFlag = "1"
+					}
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: clientTest,
+						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
+						config: Config{
+							MinVersion:                            ver.version,
+							MaxVersion:                            ver.version,
+							QUICTransportParamsUseLegacyCodepoint: clientConfig,
+						},
+						flags: []string{
+							"-max-version",
+							ver.shimFlag(protocol),
+							"-quic-transport-params",
+							base64FlagValue([]byte{3, 4}),
+							"-quic-use-legacy-codepoint", useCodepointFlag,
+						},
+						shouldFail:                true,
+						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
+						skipTransportParamsConfig: true,
+					})
+				}
+				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
+				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
+					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
+						shouldFail := false
+						expectedLocalError := ""
+						useCodepointFlag := "0"
+						if serverConfig == QUICUseCodepointLegacy {
+							useCodepointFlag = "1"
+						}
+						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
+							shouldFail = true
+							expectedLocalError = "remote error: unsupported extension"
+						}
+						testCases = append(testCases, testCase{
+							protocol: protocol,
+							testType: serverTest,
+							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
+							config: Config{
+								MinVersion:                            ver.version,
+								MaxVersion:                            ver.version,
+								QUICTransportParams:                   []byte{1, 2},
+								QUICTransportParamsUseLegacyCodepoint: clientSends,
+							},
+							flags: []string{
+								"-quic-use-legacy-codepoint", useCodepointFlag,
+							},
+							shouldFail:                shouldFail,
+							expectedLocalError:        expectedLocalError,
+							skipTransportParamsConfig: true,
+						})
+					}
+				}
+
+			}
+
+			// Test ticket behavior.
+
+			// Resume with a corrupt ticket.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "CorruptTicket-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						FilterTicket: func(in []byte) ([]byte, error) {
+							in[len(in)-1] ^= 1
+							return in, nil
+						},
+					},
+				},
+				resumeSession:        true,
+				expectResumeRejected: true,
+			})
+			// Test the ticket callbacks.
+			for _, aeadCallback := range []bool{false, true} {
+				flag := "-use-ticket-callback"
+				callbackSuffix := suffix
+				if aeadCallback {
+					flag = "-use-ticket-aead-callback"
+					callbackSuffix += "-AEAD"
+				}
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketCallback-" + callbackSuffix,
+					config: Config{
+						MaxVersion: ver.version,
+					},
+					resumeSession: true,
+					flags:         []string{flag},
+				})
+				// Only the old callback supports renewal.
+				if !aeadCallback {
+					testCases = append(testCases, testCase{
+						protocol: protocol,
+						testType: serverTest,
+						name:     "TicketCallback-Renew-" + callbackSuffix,
+						config: Config{
+							MaxVersion: ver.version,
+							Bugs: ProtocolBugs{
+								ExpectNewTicket: true,
+							},
+						},
+						flags:         []string{flag, "-renew-ticket"},
+						resumeSession: true,
+					})
+				}
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketCallback-Skip-" + callbackSuffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							ExpectNoNonEmptyNewSessionTicket: true,
+						},
+					},
+					flags: []string{flag, "-skip-ticket"},
+				})
+
+				// Test that the ticket callback is only called once when everything before
+				// it in the ClientHello is asynchronous. This corrupts the ticket so
+				// certificate selection callbacks run.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketCallback-SingleCall-" + callbackSuffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							FilterTicket: func(in []byte) ([]byte, error) {
+								in[len(in)-1] ^= 1
+								return in, nil
+							},
+						},
+					},
+					resumeSession:        true,
+					expectResumeRejected: true,
+					flags: []string{
+						flag,
+						"-async",
+					},
+				})
+			}
+
+			// Resume with various lengths of ticket session id.
+			if ver.version < VersionTLS13 {
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketSessionIDLength-0-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							EmptyTicketSessionID: true,
+						},
+					},
+					resumeSession: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketSessionIDLength-16-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							TicketSessionIDLength: 16,
+						},
+					},
+					resumeSession: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketSessionIDLength-32-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							TicketSessionIDLength: 32,
+						},
+					},
+					resumeSession: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "TicketSessionIDLength-33-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							TicketSessionIDLength: 33,
+						},
+					},
+					resumeSession: true,
+					shouldFail:    true,
+					// The maximum session ID length is 32.
+					expectedError: ":CLIENTHELLO_PARSE_FAILED:",
+				})
+			}
+
+			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
+			// are ignored.
+			if protocol == dtls {
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "SRTP-Client-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+					},
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "SRTP-Server-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+					},
+				})
+				// Test that the MKI is ignored.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "SRTP-Server-IgnoreMKI-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
+						Bugs: ProtocolBugs{
+							SRTPMasterKeyIdentifier: "bogus",
+						},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+					},
+				})
+				// Test that SRTP isn't negotiated on the server if there were
+				// no matching profiles.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "SRTP-Server-NoMatch-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{100, 101, 102},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: 0,
+					},
+				})
+				// Test that the server returning an invalid SRTP profile is
+				// flagged as an error by the client.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "SRTP-Client-NoMatch-" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
+						},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80",
+					},
+					shouldFail:    true,
+					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
+				})
+			} else {
+				// DTLS-SRTP is not defined for other protocols. Configuring it
+				// on the client and server should ignore the extension.
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					name:     "SRTP-Client-Ignore-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: 0,
+					},
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "SRTP-Server-Ignore-" + suffix,
+					config: Config{
+						MaxVersion:             ver.version,
+						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+					},
+					flags: []string{
+						"-srtp-profiles",
+						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+					},
+					expectations: connectionExpectations{
+						srtpProtectionProfile: 0,
+					},
+				})
+			}
+
+			// Test SCT list.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "SignedCertificateTimestampList-Client-" + suffix,
+				testType: clientTest,
+				config: Config{
+					MaxVersion: ver.version,
+					Credential: rsaCertificate.WithSCTList(testSCTList),
+				},
+				flags: []string{
+					"-enable-signed-cert-timestamps",
+					"-expect-signed-cert-timestamps",
+					base64FlagValue(testSCTList),
+				},
+				resumeSession: true,
+			})
+
+			var differentSCTList []byte
+			differentSCTList = append(differentSCTList, testSCTList...)
+			differentSCTList[len(differentSCTList)-1] ^= 1
+
+			// The SCT extension did not specify that it must only be sent on the inital handshake as it
+			// should have, so test that we tolerate but ignore it. This is only an issue pre-1.3, since
+			// SCTs are sent in the CertificateEntry message in 1.3, whereas they were previously sent
+			// in an extension in the ServerHello pre-1.3.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "SendSCTListOnResume-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Credential: rsaCertificate.WithSCTList(testSCTList),
+					Bugs: ProtocolBugs{
+						SendSCTListOnResume: differentSCTList,
+					},
+				},
+				flags: []string{
+					"-enable-signed-cert-timestamps",
+					"-expect-signed-cert-timestamps",
+					base64FlagValue(testSCTList),
+				},
+				resumeSession: true,
+			})
+
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "SignedCertificateTimestampList-Server-" + suffix,
+				testType: serverTest,
+				config: Config{
+					MaxVersion: ver.version,
+				},
+				shimCertificate: rsaCertificate.WithSCTList(testSCTList),
+				expectations: connectionExpectations{
+					peerCertificate: rsaCertificate.WithSCTList(testSCTList),
+				},
+				resumeSession: true,
+			})
+
+			// Test empty SCT list.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
+				testType: clientTest,
+				config: Config{
+					MaxVersion: ver.version,
+					Credential: rsaCertificate.WithSCTList([]byte{0, 0}),
+				},
+				flags: []string{
+					"-enable-signed-cert-timestamps",
+				},
+				shouldFail:    true,
+				expectedError: ":ERROR_PARSING_EXTENSION:",
+			})
+
+			// Test empty SCT in non-empty list.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
+				testType: clientTest,
+				config: Config{
+					MaxVersion: ver.version,
+					Credential: rsaCertificate.WithSCTList([]byte{0, 6, 0, 2, 1, 2, 0, 0}),
+				},
+				flags: []string{
+					"-enable-signed-cert-timestamps",
+				},
+				shouldFail:    true,
+				expectedError: ":ERROR_PARSING_EXTENSION:",
+			})
+
+			// Test that certificate-related extensions are not sent unsolicited.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "UnsolicitedCertificateExtensions-" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						NoOCSPStapling:                true,
+						NoSignedCertificateTimestamps: true,
+					},
+				},
+				shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+			})
+
+			// Extension permutation should interact correctly with other extensions,
+			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
+			// in ssl_test.cc tests that the extensions are actually permuted. This
+			// tests the handshake still works.
+			//
+			// This test also tests that all our extensions interact with each other.
+			for _, ech := range []bool{false, true} {
+				if ech && ver.version < VersionTLS13 {
+					continue
+				}
+
+				test := testCase{
+					protocol:           protocol,
+					name:               "AllExtensions-Client-Permute",
+					skipQUICALPNConfig: true,
+					config: Config{
+						MinVersion:          ver.version,
+						MaxVersion:          ver.version,
+						Credential:          rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+						NextProtos:          []string{"proto"},
+						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+						Bugs: ProtocolBugs{
+							SendServerNameAck: true,
+							ExpectServerName:  "example.com",
+							ExpectGREASE:      true,
+						},
+					},
+					resumeSession: true,
+					flags: []string{
+						"-permute-extensions",
+						"-enable-grease",
+						"-enable-ocsp-stapling",
+						"-enable-signed-cert-timestamps",
+						"-advertise-alpn", "\x05proto",
+						"-expect-alpn", "proto",
+						"-host-name", "example.com",
+					},
+				}
+
+				if ech {
+					test.name += "-ECH"
+					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
+					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
+					test.flags = append(test.flags,
+						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
+						"-expect-ech-accept",
+					)
+					test.expectations.echAccepted = true
+				}
+
+				if ver.version >= VersionTLS13 {
+					// Trigger a HelloRetryRequest to test both ClientHellos. Note
+					// our DTLS tests always enable HelloVerifyRequest.
+					test.name += "-HelloRetryRequest"
+
+					// ALPS is only available on TLS 1.3.
+					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
+					test.flags = append(test.flags,
+						"-application-settings", "proto,shim",
+						"-alps-use-new-codepoint", "1",
+						"-expect-peer-application-settings", "runner")
+					test.expectations.peerApplicationSettings = []byte("shim")
+				}
+
+				if protocol == dtls {
+					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
+					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
+					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
+				}
+
+				test.name += "-" + suffix
+				testCases = append(testCases, test)
+			}
+		}
+	}
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientHelloPadding",
+		config: Config{
+			Bugs: ProtocolBugs{
+				RequireClientHelloSize: 512,
+			},
+		},
+		// This hostname just needs to be long enough to push the
+		// ClientHello into F5's danger zone between 256 and 511 bytes
+		// long.
+		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
+	})
+
+	// Test that illegal extensions in TLS 1.3 are rejected by the client if
+	// in ServerHello.
+	testCases = append(testCases, testCase{
+		name: "NPN-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+			Bugs: ProtocolBugs{
+				NegotiateNPNAtAllVersions: true,
+			},
+		},
+		flags:         []string{"-select-next-proto", "foo"},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "EMS-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiateEMSAtAllVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "RenegotiationInfo-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiateRenegotiationInfoAtAllVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Ticket-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AdvertiseTicketExtension: true,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+
+	// Test that illegal extensions in TLS 1.3 are declined by the server if
+	// offered in ClientHello. The runner's server will fail if this occurs,
+	// so we exercise the offering path. (EMS and Renegotiation Info are
+	// implicit in every test.)
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NPN-Declined-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"bar"},
+		},
+		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
+	})
+
+	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
+	// tolerated.
+	testCases = append(testCases, testCase{
+		name: "SendOCSPResponseOnResume-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: rsaCertificate.WithOCSP(testOCSPResponse),
+			Bugs: ProtocolBugs{
+				SendOCSPResponseOnResume: []byte("bogus"),
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64FlagValue(testOCSPResponse),
+		},
+		resumeSession: true,
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testOCSPExtension,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnsolicitedSCTOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testSCTExtension,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// Test that extensions on client certificates are never accepted.
+	testCases = append(testCases, testCase{
+		name:     "SendExtensionOnClientCertificate-TLS13",
+		testType: serverTest,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &rsaCertificate,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testOCSPExtension,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnknownExtensionOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// Test that extensions on intermediates are allowed but ignored.
+	testCases = append(testCases, testCase{
+		name: "IgnoreExtensionsOnIntermediates-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+			Bugs: ProtocolBugs{
+				// Send different values on the intermediate. This tests
+				// the intermediate's extensions do not override the
+				// leaf's.
+				SendOCSPOnIntermediates: testOCSPResponse2,
+				SendSCTOnIntermediates:  testSCTList2,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64FlagValue(testOCSPResponse),
+			"-enable-signed-cert-timestamps",
+			"-expect-signed-cert-timestamps",
+			base64FlagValue(testSCTList),
+		},
+		resumeSession: true,
+	})
+
+	// Test that extensions are not sent on intermediates when configured
+	// only for a leaf.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendNoExtensionsOnIntermediate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectNoExtensionsOnIntermediate: true,
+			},
+		},
+		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+	})
+
+	// Test that extensions are not sent on client certificates.
+	testCases = append(testCases, testCase{
+		name: "SendNoClientCertificateExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendDuplicateExtensionsOnCerts-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+			Bugs: ProtocolBugs{
+				SendDuplicateCertExtensions: true,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-enable-signed-cert-timestamps",
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":DUPLICATE_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name:            "SignedCertificateTimestampListInvalid-Server",
+		testType:        serverTest,
+		shimCertificate: rsaCertificate.WithSCTList([]byte{0, 0}),
+		shouldFail:      true,
+		expectedError:   ":INVALID_SCT_LIST:",
+	})
+}
+
+func addUnknownExtensionTests() {
+	// Test an unknown extension from the server.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownExtension-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				CustomExtension: "custom extension",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomExtension: "custom extension",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomUnencryptedExtension: "custom extension",
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendUnencryptedALPN: "foo",
+			},
+		},
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
+
+	// Test a known but unoffered extension from the server.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnofferedExtension-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendALPN: "alpn",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnofferedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendALPN: "alpn",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+}
+
+// Test that omitted and empty extensions blocks are tolerated.
+func addOmitExtensionsTests() {
+	// Check the ExpectOmitExtensions setting works.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExpectOmitExtensions",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectOmitExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "tls: ServerHello did not omit extensions",
+	})
+
+	for _, ver := range tlsVersions {
+		if ver.version > VersionTLS12 {
+			continue
+		}
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "OmitExtensions-ClientHello-" + ver.name,
+			config: Config{
+				MinVersion:             ver.version,
+				MaxVersion:             ver.version,
+				SessionTicketsDisabled: true,
+				Bugs: ProtocolBugs{
+					OmitExtensions: true,
+					// With no client extensions, the ServerHello must not have
+					// extensions. It should then omit the extensions field.
+					ExpectOmitExtensions: true,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "EmptyExtensions-ClientHello-" + ver.name,
+			config: Config{
+				MinVersion:             ver.version,
+				MaxVersion:             ver.version,
+				SessionTicketsDisabled: true,
+				Bugs: ProtocolBugs{
+					EmptyExtensions: true,
+					// With no client extensions, the ServerHello must not have
+					// extensions. It should then omit the extensions field.
+					ExpectOmitExtensions: true,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "OmitExtensions-ServerHello-" + ver.name,
+			config: Config{
+				MinVersion:             ver.version,
+				MaxVersion:             ver.version,
+				SessionTicketsDisabled: true,
+				Bugs: ProtocolBugs{
+					OmitExtensions: true,
+					// Disable all ServerHello extensions so
+					// OmitExtensions works.
+					NoExtendedMasterSecret:        true,
+					NoRenegotiationInfo:           true,
+					NoOCSPStapling:                true,
+					NoSignedCertificateTimestamps: true,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "EmptyExtensions-ServerHello-" + ver.name,
+			config: Config{
+				MinVersion:             ver.version,
+				MaxVersion:             ver.version,
+				SessionTicketsDisabled: true,
+				Bugs: ProtocolBugs{
+					EmptyExtensions: true,
+					// Disable all ServerHello extensions so
+					// EmptyExtensions works.
+					NoExtendedMasterSecret:        true,
+					NoRenegotiationInfo:           true,
+					NoOCSPStapling:                true,
+					NoSignedCertificateTimestamps: true,
+				},
+			},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/extra_handshake_tests.go b/src/ssl/test/runner/extra_handshake_tests.go
new file mode 100644
index 0000000..911ff3e
--- /dev/null
+++ b/src/ssl/test/runner/extra_handshake_tests.go
@@ -0,0 +1,113 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addExtraHandshakeTests() {
+	// An extra SSL_do_handshake is normally a no-op. These tests use -async
+	// to ensure there is no transport I/O.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-Client-TLS12",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-TLS12",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-Client-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+
+	// An extra SSL_do_handshake is a no-op in server 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-EarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		messageCount:  2,
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+
+	// An extra SSL_do_handshake drives the handshake to completion in False
+	// Start. We test this by handshaking twice and asserting the False
+	// Start does not appear to happen. See AlertBeforeFalseStartTest for
+	// how the test works.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-FalseStart",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			NextProtos:   []string{"foo"},
+			Bugs: ProtocolBugs{
+				ExpectFalseStart:          true,
+				AlertBeforeFalseStartTest: alertAccessDenied,
+			},
+		},
+		flags: []string{
+			"-handshake-twice",
+			"-false-start",
+			"-advertise-alpn", "\x03foo",
+			"-expect-alpn", "foo",
+		},
+		shimWritesFirst:    true,
+		shouldFail:         true,
+		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+		expectedLocalError: "tls: peer did not false start: EOF",
+	})
+}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 91f0833..ed94cab 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -513,6 +513,7 @@
 		omitExtensions:            c.config.Bugs.OmitExtensions,
 		emptyExtensions:           c.config.Bugs.EmptyExtensions,
 		delegatedCredential:       c.config.DelegatedCredentialAlgorithms,
+		trustAnchors:              c.config.RequestTrustAnchors,
 	}
 
 	// Translate the bugs that modify ClientHello extension order into a
@@ -632,6 +633,10 @@
 		}
 	}
 
+	if c.config.SendRootCAs && c.config.RootCAs != nil {
+		hello.certificateAuthorities = c.config.RootCAs.Subjects()
+	}
+
 	if maxVersion >= VersionTLS13 {
 		// Use the same key shares between ClientHelloInner and ClientHelloOuter.
 		if innerHello != nil {
@@ -1257,10 +1262,6 @@
 				return errors.New("tls: non-empty certificate request context sent in handshake")
 			}
 
-			if c.config.Bugs.ExpectNoCertificateAuthoritiesExtension && certReq.hasCAExtension {
-				return errors.New("tls: expected no certificate_authorities extension")
-			}
-
 			hs.writeServerHash(certReq.marshal())
 
 			credential = c.config.Credential
@@ -1334,6 +1335,15 @@
 				return errors.New("tls: unexpected extensions in the server certificate")
 			}
 		}
+		if c.config.RequestTrustAnchors == nil && certMsg.matchedTrustAnchor {
+			return errors.New("tls: unsolicited trust_anchors extension in the server certificate")
+		}
+		if expected := c.config.Bugs.ExpectPeerMatchTrustAnchor; expected != nil && certMsg.matchedTrustAnchor != *expected {
+			if certMsg.matchedTrustAnchor {
+				return errors.New("tls: server certificate unexpectedly matched trust anchor")
+			}
+			return errors.New("tls: server certificate unexpectedly did not match trust anchor")
+		}
 
 		if err := hs.verifyCertificates(certMsg); err != nil {
 			return err
@@ -2038,6 +2048,13 @@
 		return errors.New("tls: server advertised unrequested SCTs")
 	}
 
+	if len(serverExtensions.trustAnchors) > 0 && c.config.RequestTrustAnchors == nil {
+		return errors.New("tls: server advertised unrequested trust anchor IDs")
+	}
+	if expected := c.config.Bugs.ExpectPeerAvailableTrustAnchors; expected != nil && !slices.EqualFunc(expected, serverExtensions.trustAnchors, slices.Equal) {
+		return errors.New("tls: server advertised trust anchor IDs that did not match expectations")
+	}
+
 	if serverExtensions.srtpProtectionProfile != 0 {
 		if serverExtensions.srtpMasterKeyIdentifier != "" {
 			return errors.New("tls: server selected SRTP MKI value")
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 5232581..71aa840 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -150,6 +150,53 @@
 	msg []byte
 }
 
+type flagSet struct {
+	bytes       []byte
+	mustInclude bool
+	padding     int
+}
+
+func (f *flagSet) hasFlag(bit uint) bool {
+	idx := bit / 8
+	mask := byte(1 << (bit % 8))
+	return idx < uint(len(f.bytes)) && f.bytes[idx]&mask != 0
+}
+
+func (f *flagSet) setFlag(bit uint) {
+	idx := bit / 8
+	mask := byte(1 << (bit % 8))
+	for uint(len(f.bytes)) <= idx {
+		f.bytes = append(f.bytes, 0)
+	}
+	f.bytes[idx] |= mask
+}
+
+func (f *flagSet) unmarshalExtensionValue(s cryptobyte.String) bool {
+	if !readUint8LengthPrefixedBytes(&s, &f.bytes) || !s.Empty() || len(f.bytes) == 0 {
+		return false
+	}
+	// Flags must be minimally-encoded.
+	if f.bytes[len(f.bytes)-1] == 0 {
+		return false
+	}
+	return true
+}
+
+func (f *flagSet) marshalExtension(b *cryptobyte.Builder) {
+	if len(f.bytes) == 0 && !f.mustInclude {
+		return
+	}
+	b.AddUint16(extensionTLSFlags)
+	b.AddUint16LengthPrefixed(func(value *cryptobyte.Builder) {
+		value.AddUint8LengthPrefixed(func(flags *cryptobyte.Builder) {
+			flags.AddBytes(f.bytes)
+			for range f.padding {
+				flags.AddUint8(0)
+			}
+		})
+	})
+}
+
 type clientHelloMsg struct {
 	raw                                      []byte
 	isDTLS                                   bool
@@ -205,6 +252,8 @@
 	pakeClientID                             []byte
 	pakeServerID                             []byte
 	pakeShares                               []pakeShare
+	certificateAuthorities                   [][]byte
+	trustAnchors                             [][]byte
 	outerExtensions                          []uint16
 	reorderOuterExtensionsWithoutCompressing bool
 	prefixExtensions                         []uint16
@@ -560,6 +609,31 @@
 			body: body.BytesOrPanic(),
 		})
 	}
+	if len(m.certificateAuthorities) > 0 {
+		body := cryptobyte.NewBuilder(nil)
+		body.AddUint16LengthPrefixed(func(certificateAuthorities *cryptobyte.Builder) {
+			for _, ca := range m.certificateAuthorities {
+				addUint16LengthPrefixedBytes(certificateAuthorities, ca)
+			}
+		})
+		extensions = append(extensions, extension{
+			id:   extensionCertificateAuthorities,
+			body: body.BytesOrPanic(),
+		})
+	}
+	// Check against nil to distinguish missing and empty.
+	if m.trustAnchors != nil {
+		body := cryptobyte.NewBuilder(nil)
+		body.AddUint16LengthPrefixed(func(trustAnchorList *cryptobyte.Builder) {
+			for _, id := range m.trustAnchors {
+				addUint8LengthPrefixedBytes(trustAnchorList, id)
+			}
+		})
+		extensions = append(extensions, extension{
+			id:   extensionTrustAnchors,
+			body: body.BytesOrPanic(),
+		})
+	}
 	// The PSK extension must be last. See https://tools.ietf.org/html/rfc8446#section-4.2.11
 	if len(m.pskIdentities) > 0 {
 		pskExtension := cryptobyte.NewBuilder(nil)
@@ -1101,6 +1175,17 @@
 				m.pakeServerID = []byte(serverId)
 				m.pakeShares = append(m.pakeShares, pakeShare{id: id, msg: msg})
 			}
+		case extensionCertificateAuthorities:
+			if !parseCAs(&body, &m.certificateAuthorities) || len(body) != 0 ||
+				// If present, the CA extension may not be empty.
+				len(m.certificateAuthorities) == 0 {
+				return false
+			}
+		case extensionTrustAnchors:
+			// An empty list is allowed here.
+			if !parseTrustAnchors(&body, &m.trustAnchors) {
+				return false
+			}
 		}
 
 		if isGREASEValue(extension) {
@@ -1511,6 +1596,7 @@
 	applicationSettingsOld    []byte
 	hasApplicationSettingsOld bool
 	echRetryConfigs           []byte
+	trustAnchors              [][]byte
 }
 
 func (m *serverExtensions) marshal(extensions *cryptobyte.Builder) {
@@ -1645,6 +1731,16 @@
 		extensions.AddUint16(extensionEncryptedClientHello)
 		addUint16LengthPrefixedBytes(extensions, m.echRetryConfigs)
 	}
+	if len(m.trustAnchors) > 0 {
+		extensions.AddUint16(extensionTrustAnchors)
+		extensions.AddUint16LengthPrefixed(func(extension *cryptobyte.Builder) {
+			extension.AddUint16LengthPrefixed(func(trustAnchorList *cryptobyte.Builder) {
+				for _, id := range m.trustAnchors {
+					addUint8LengthPrefixedBytes(trustAnchorList, id)
+				}
+			})
+		})
+	}
 }
 
 func (m *serverExtensions) unmarshal(data cryptobyte.String, version uint16) bool {
@@ -1776,6 +1872,13 @@
 			if len(body) > 0 {
 				return false
 			}
+		case extensionTrustAnchors:
+			if version < VersionTLS13 {
+				return false
+			}
+			if !parseTrustAnchors(&body, &m.trustAnchors) || len(body) != 0 {
+				return false
+			}
 		default:
 			// Unknown extensions are illegal from the server.
 			return false
@@ -1940,6 +2043,11 @@
 }
 
 func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
+	expectedLegacyVers := uint16(VersionTLS12)
+	if m.isDTLS {
+		expectedLegacyVers = VersionDTLS12
+	}
+
 	m.raw = data
 	reader := cryptobyte.String(data[4:])
 	var legacyVers uint16
@@ -1947,7 +2055,7 @@
 	var compressionMethod byte
 	var extensions cryptobyte.String
 	if !reader.ReadUint16(&legacyVers) ||
-		legacyVers != VersionTLS12 ||
+		legacyVers != expectedLegacyVers ||
 		!reader.ReadBytes(&random, 32) ||
 		!readUint8LengthPrefixedBytes(&reader, &m.sessionID) ||
 		!reader.ReadUint16(&m.cipherSuite) ||
@@ -2018,10 +2126,13 @@
 }
 
 type certificateMsg struct {
-	raw               []byte
-	hasRequestContext bool
-	requestContext    []byte
-	certificates      []certificateEntry
+	raw                             []byte
+	hasRequestContext               bool
+	requestContext                  []byte
+	certificates                    []certificateEntry
+	matchedTrustAnchor              bool
+	sendTrustAnchorWrongCertificate bool
+	sendNonEmptyTrustAnchorMatch    bool
 }
 
 func (m *certificateMsg) marshal() (x []byte) {
@@ -2036,10 +2147,18 @@
 			addUint8LengthPrefixedBytes(certificate, m.requestContext)
 		}
 		certificate.AddUint24LengthPrefixed(func(certificateList *cryptobyte.Builder) {
-			for _, cert := range m.certificates {
+			for i, cert := range m.certificates {
 				addUint24LengthPrefixedBytes(certificateList, cert.data)
 				if m.hasRequestContext {
 					certificateList.AddUint16LengthPrefixed(func(extensions *cryptobyte.Builder) {
+						if (i == 0 && m.matchedTrustAnchor) || (i == 1 && m.sendTrustAnchorWrongCertificate) {
+							extensions.AddUint16(extensionTrustAnchors)
+							if m.sendNonEmptyTrustAnchorMatch {
+								addUint16LengthPrefixedBytes(extensions, []byte{0x03, 0xba, 0xdb, 0x0b})
+							} else {
+								extensions.AddUint16(0) // Empty extension
+							}
+						}
 						count := 1
 						if cert.duplicateExtensions {
 							count = 2
@@ -2137,6 +2256,14 @@
 					dc.raw = origBody
 					dc.signedBytes = []byte(origBody)[:4+2+3+len(dc.pkixPublicKey)]
 					cert.delegatedCredential = dc
+				case extensionTrustAnchors:
+					if len(m.certificates) != 0 {
+						return false // Only allowed in first certificate.
+					}
+					if len(body) != 0 {
+						return false
+					}
+					m.matchedTrustAnchor = true
 				default:
 					return false
 				}
@@ -2386,7 +2513,6 @@
 	signatureAlgorithms     []signatureAlgorithm
 	signatureAlgorithmsCert []signatureAlgorithm
 	certificateAuthorities  [][]byte
-	hasCAExtension          bool
 	customExtension         uint16
 }
 
@@ -2432,7 +2558,6 @@
 						})
 					})
 				}
-
 				if m.customExtension > 0 {
 					extensions.AddUint16(m.customExtension)
 					extensions.AddUint16(0) // Empty extension
@@ -2468,7 +2593,7 @@
 	}
 	for len(cas) > 0 {
 		var ca []byte
-		if !readUint16LengthPrefixedBytes(&cas, &ca) {
+		if !readUint16LengthPrefixedBytes(&cas, &ca) || len(ca) == 0 {
 			return false
 		}
 		*out = append(*out, ca)
@@ -2476,6 +2601,23 @@
 	return true
 }
 
+func parseTrustAnchors(reader *cryptobyte.String, out *[][]byte) bool {
+	var ids cryptobyte.String
+	if !reader.ReadUint16LengthPrefixed(&ids) {
+		return false
+	}
+	// Distinguish nil and empty.
+	*out = [][]byte{}
+	for len(ids) > 0 {
+		var id []byte
+		if !readUint8LengthPrefixedBytes(&ids, &id) {
+			return false
+		}
+		*out = append(*out, id)
+	}
+	return true
+}
+
 func (m *certificateRequestMsg) unmarshal(data []byte) bool {
 	m.raw = data
 	reader := cryptobyte.String(data[4:])
@@ -2505,10 +2647,11 @@
 					return false
 				}
 			case extensionCertificateAuthorities:
-				if !parseCAs(&body, &m.certificateAuthorities) || len(body) != 0 {
+				if !parseCAs(&body, &m.certificateAuthorities) || len(body) != 0 ||
+					// If present, the CA extension may not be empty.
+					len(m.certificateAuthorities) == 0 {
 					return false
 				}
-				m.hasCAExtension = true
 			}
 		}
 	} else {
@@ -2584,6 +2727,7 @@
 	customExtension             string
 	duplicateEarlyDataExtension bool
 	hasGREASEExtension          bool
+	flags                       flagSet
 }
 
 func (m *newSessionTicketMsg) marshal() []byte {
@@ -2626,6 +2770,7 @@
 					extensions.AddUint16(extensionCustom)
 					addUint16LengthPrefixedBytes(extensions, []byte(m.customExtension))
 				}
+				m.flags.marshalExtension(extensions)
 			})
 		}
 	})
@@ -2678,6 +2823,10 @@
 				if !body.ReadUint32(&m.maxEarlyDataSize) || !body.Empty() {
 					return false
 				}
+			case extensionTLSFlags:
+				if !m.flags.unmarshalExtensionValue(body) {
+					return false
+				}
 			default:
 				if isGREASEValue(extension) {
 					m.hasGREASEExtension = true
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 8dc6348..d9a710b 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -452,6 +452,15 @@
 		return errors.New("tls: expected non-empty session ID from client")
 	}
 
+	if expected := c.config.Bugs.ExpectPeerRequestedTrustAnchors; expected != nil {
+		if hs.clientHello.trustAnchors == nil {
+			return errors.New("tls: client did not send trust anchors")
+		}
+		if !slices.EqualFunc(expected, hs.clientHello.trustAnchors, slices.Equal) {
+			return fmt.Errorf("tls: client offered trust anchors %v, but expected %v", hs.clientHello.trustAnchors, expected)
+		}
+	}
+
 	applyBugsToClientHello(hs.clientHello, config)
 
 	return nil
@@ -1160,6 +1169,19 @@
 		certMsg := &certificateMsg{
 			hasRequestContext: true,
 		}
+		certMsg.sendTrustAnchorWrongCertificate = config.Bugs.SendTrustAnchorWrongCertificate
+		certMsg.sendNonEmptyTrustAnchorMatch = config.Bugs.SendNonEmptyTrustAnchorMatch
+		if config.Bugs.AlwaysMatchTrustAnchorID {
+			certMsg.matchedTrustAnchor = true
+		} else {
+			if hs.clientHello.trustAnchors != nil && useCert.TrustAnchorID != nil {
+				for _, id := range hs.clientHello.trustAnchors {
+					if bytes.Equal(useCert.TrustAnchorID, id) {
+						certMsg.matchedTrustAnchor = true
+					}
+				}
+			}
+		}
 		if !config.Bugs.EmptyCertificateList {
 			for i, certData := range useCert.Certificate {
 				cert := certificateEntry{
@@ -1751,6 +1773,9 @@
 		return errors.New("tls: no GREASE extension found")
 	}
 
+	if hs.clientHello.trustAnchors != nil || config.Bugs.AlwaysSendAvailableTrustAnchors {
+		serverExtensions.trustAnchors = c.config.AvailableTrustAnchors
+	}
 	serverExtensions.serverNameAck = c.config.Bugs.SendServerNameAck
 
 	if (c.vers >= VersionTLS13 && hs.clientHello.echOuter != nil) || c.config.Bugs.AlwaysSendECHRetryConfigs {
diff --git a/src/ssl/test/runner/hint_mismatch_tests.go b/src/ssl/test/runner/hint_mismatch_tests.go
new file mode 100644
index 0000000..db96716
--- /dev/null
+++ b/src/ssl/test/runner/hint_mismatch_tests.go
@@ -0,0 +1,491 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "strconv"
+
+func addHintMismatchTests() {
+	// Each of these tests skips split handshakes because split handshakes does
+	// not handle a mismatch between shim and handshaker. Handshake hints,
+	// however, are designed to tolerate the mismatch.
+	//
+	// Note also these tests do not specify -handshake-hints directly. Instead,
+	// we define normal tests, that run even without a handshaker, and rely on
+	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
+	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
+	// (While not useful, the tests will still pass without a handshaker.)
+	for _, protocol := range []protocol{tls, quic} {
+		// If the signing payload is different, the handshake still completes
+		// successfully. Different ALPN preferences will trigger a mismatch.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-SignatureInput",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				NextProtos: []string{"foo", "bar"},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-select-alpn", "foo",
+				"-on-handshaker-select-alpn", "bar",
+			},
+			expectations: connectionExpectations{
+				nextProto:     "foo",
+				nextProtoType: alpn,
+			},
+		})
+
+		// The shim and handshaker may have different curve preferences.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-KeyShare",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				// Send both curves in the key share list, to avoid getting
+				// mixed up with HelloRetryRequest.
+				DefaultCurves: []CurveID{CurveX25519, CurveP256},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
+				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
+			},
+			expectations: connectionExpectations{
+				curveID: CurveX25519,
+			},
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-ECDHE-Group",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion:    VersionTLS12,
+					MaxVersion:    VersionTLS12,
+					DefaultCurves: []CurveID{CurveX25519, CurveP256},
+				},
+				flags: []string{
+					"-allow-hint-mismatch",
+					"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
+					"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
+				},
+				expectations: connectionExpectations{
+					curveID: CurveX25519,
+				},
+			})
+		}
+
+		// If the handshaker does HelloRetryRequest, it will omit most hints.
+		// The shim should still work.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion:    VersionTLS13,
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: []CurveID{CurveX25519},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
+				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
+			},
+			expectations: connectionExpectations{
+				curveID: CurveX25519,
+			},
+		})
+
+		// If the shim does HelloRetryRequest, the hints from the handshaker
+		// will be ignored. This is not reported as a mismatch because hints
+		// would not have helped the shim anyway.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion:    VersionTLS13,
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: []CurveID{CurveX25519},
+			},
+			flags: []string{
+				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
+				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
+			},
+			expectations: connectionExpectations{
+				curveID: CurveP256,
+			},
+		})
+
+		// The shim and handshaker may have different signature algorithm
+		// preferences.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS13",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				VerifySignatureAlgorithms: []signatureAlgorithm{
+					signatureRSAPSSWithSHA256,
+					signatureRSAPSSWithSHA384,
+				},
+			},
+			shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
+			flags:                 []string{"-allow-hint-mismatch"},
+			expectations: connectionExpectations{
+				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
+			},
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS12",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+					VerifySignatureAlgorithms: []signatureAlgorithm{
+						signatureRSAPSSWithSHA256,
+						signatureRSAPSSWithSHA384,
+					},
+				},
+				shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+				handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
+				flags:                 []string{"-allow-hint-mismatch"},
+				expectations: connectionExpectations{
+					peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
+				},
+			})
+		}
+
+		// The shim and handshaker may use different certificates. In TLS 1.3,
+		// the signature input includes the certificate, so we do not need to
+		// explicitly check for a public key match. In TLS 1.2, it does not.
+		ecdsaP256Certificate2 := generateSingleCertChain(nil, &channelIDKey)
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-Certificate-TLS13",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+			},
+			shimCertificate:       &ecdsaP256Certificate,
+			handshakerCertificate: &ecdsaP256Certificate2,
+			flags:                 []string{"-allow-hint-mismatch"},
+			expectations: connectionExpectations{
+				peerCertificate: &ecdsaP256Certificate,
+			},
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-Certificate-TLS12",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				shimCertificate:       &ecdsaP256Certificate,
+				handshakerCertificate: &ecdsaP256Certificate2,
+				flags:                 []string{"-allow-hint-mismatch"},
+				expectations: connectionExpectations{
+					peerCertificate: &ecdsaP256Certificate,
+				},
+			})
+		}
+
+		// The shim and handshaker may disagree on whether resumption is allowed.
+		// We run the first connection with tickets enabled, so the client is
+		// issued a ticket, then disable tickets on the second connection.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-NoTickets1-TLS13",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+			},
+			flags: []string{
+				"-on-resume-allow-hint-mismatch",
+				"-on-shim-on-resume-no-ticket",
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-NoTickets2-TLS13",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+			},
+			flags: []string{
+				"-on-resume-allow-hint-mismatch",
+				"-on-handshaker-on-resume-no-ticket",
+			},
+			resumeSession: true,
+		})
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-NoTickets1-TLS12",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{
+					"-on-resume-allow-hint-mismatch",
+					"-on-shim-on-resume-no-ticket",
+				},
+				resumeSession:        true,
+				expectResumeRejected: true,
+			})
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-NoTickets2-TLS12",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{
+					"-on-resume-allow-hint-mismatch",
+					"-on-handshaker-on-resume-no-ticket",
+				},
+				resumeSession: true,
+			})
+		}
+
+		// The shim and handshaker may disagree on whether to request a client
+		// certificate.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-CertificateRequest",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-require-any-client-certificate",
+			},
+		})
+
+		// The shim and handshaker may negotiate different versions altogether.
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-Version1",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS13,
+				},
+				flags: []string{
+					"-allow-hint-mismatch",
+					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
+					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
+				},
+				expectations: connectionExpectations{
+					version: VersionTLS12,
+				},
+			})
+			testCases = append(testCases, testCase{
+				name:               protocol.String() + "-HintMismatch-Version2",
+				testType:           serverTest,
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS13,
+				},
+				flags: []string{
+					"-allow-hint-mismatch",
+					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
+					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
+				},
+				expectations: connectionExpectations{
+					version: VersionTLS13,
+				},
+			})
+		}
+
+		// The shim and handshaker may disagree on the certificate compression
+		// algorithm, whether to enable certificate compression, or certificate
+		// compression inputs.
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: shrinkingCompressionAlgID,
+				},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-install-cert-compression-algs",
+			},
+		})
+		testCases = append(testCases, testCase{
+			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
+			testType:           serverTest,
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectUncompressedCert: true,
+				},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-handshaker-install-cert-compression-algs",
+			},
+		})
+		testCases = append(testCases, testCase{
+			testType:           serverTest,
+			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+					expandingCompressionAlgID: expandingCompression,
+				},
+				Bugs: ProtocolBugs{
+					// The shim's preferences should take effect.
+					ExpectedCompressedCert: shrinkingCompressionAlgID,
+				},
+			},
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
+				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
+			},
+		})
+		testCases = append(testCases, testCase{
+			testType:           serverTest,
+			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
+			protocol:           protocol,
+			skipSplitHandshake: true,
+			config: Config{
+				MinVersion: VersionTLS13,
+				MaxVersion: VersionTLS13,
+				CertCompressionAlgs: map[uint16]CertCompressionAlg{
+					shrinkingCompressionAlgID: shrinkingCompression,
+				},
+				Bugs: ProtocolBugs{
+					ExpectedCompressedCert: shrinkingCompressionAlgID,
+				},
+			},
+			// Configure the shim and handshaker with different OCSP responses,
+			// so the compression inputs do not match.
+			shimCertificate:       rsaCertificate.WithOCSP(testOCSPResponse),
+			handshakerCertificate: rsaCertificate.WithOCSP(testOCSPResponse2),
+			flags: []string{
+				"-allow-hint-mismatch",
+				"-install-cert-compression-algs",
+			},
+			expectations: connectionExpectations{
+				// The shim's configuration should take precendence.
+				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+		})
+
+		// The shim and handshaker may disagree on cipher suite, to the point
+		// that one selects RSA key exchange (no applicable hint) and the other
+		// selects ECDHE_RSA (hints are useful).
+		if protocol != quic {
+			testCases = append(testCases, testCase{
+				testType:           serverTest,
+				name:               protocol.String() + "-HintMismatch-CipherMismatch1",
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{
+					"-allow-hint-mismatch",
+					"-on-shim-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+					"-on-handshaker-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
+				},
+				expectations: connectionExpectations{
+					cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				},
+			})
+			testCases = append(testCases, testCase{
+				testType:           serverTest,
+				name:               protocol.String() + "-HintMismatch-CipherMismatch2",
+				protocol:           protocol,
+				skipSplitHandshake: true,
+				config: Config{
+					MinVersion: VersionTLS12,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{
+					// There is no need to pass -allow-hint-mismatch. The
+					// handshaker will unnecessarily generate a signature hints.
+					// This is not reported as a mismatch because hints would
+					// not have helped the shim anyway.
+					"-on-shim-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
+					"-on-handshaker-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+				},
+				expectations: connectionExpectations{
+					cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
+				},
+			})
+		}
+	}
+}
diff --git a/src/ssl/test/runner/jdk11_workaround_tests.go b/src/ssl/test/runner/jdk11_workaround_tests.go
new file mode 100644
index 0000000..b43baf3
--- /dev/null
+++ b/src/ssl/test/runner/jdk11_workaround_tests.go
@@ -0,0 +1,182 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"strconv"
+)
+
+func addJDK11WorkaroundTests() {
+	// Test the client treats the JDK 11 downgrade random like the usual one.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Client-RejectJDK11DowngradeRandom",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendJDK11DowngradeRandom: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":TLS13_DOWNGRADE:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Client-AcceptJDK11DowngradeRandom",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendJDK11DowngradeRandom: true,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	clientHelloTests := []struct {
+		clientHello []byte
+		isJDK11     bool
+	}{
+		{
+			// A default JDK 11 ClientHello.
+			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
+			true,
+		},
+		{
+			// The above with supported_versions and
+			// psk_key_exchange_modes in the wrong order.
+			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
+			false,
+		},
+		{
+			// The above with a padding extension added at the end.
+			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
+			false,
+		},
+		{
+			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
+			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
+			true,
+		},
+		{
+			// A JDK 11 ClientHello offering a TLS 1.2 session.
+			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
+			true,
+		},
+		{
+			// A JDK 11 ClientHello with EMS disabled.
+			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
+			true,
+		},
+		{
+			// A JDK 11 ClientHello with OCSP stapling disabled.
+			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
+			true,
+		},
+		{
+			// A JDK 11 ClientHello configured with a smaller set of
+			// ciphers.
+			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
+			true,
+		},
+		{
+			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
+			// which JDK 11 does not support.
+			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
+			false,
+		},
+		{
+			// The above with X25519 added, which JDK 11 does not
+			// support.
+			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
+			false,
+		},
+		{
+			// A JDK 11 ClientHello with ALPN protocols configured.
+			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
+			true,
+		},
+	}
+	for i, t := range clientHelloTests {
+		expectedVersion := uint16(VersionTLS13)
+		if t.isJDK11 {
+			expectedVersion = VersionTLS12
+		}
+
+		// In each of these tests, we set DefaultCurves to P-256 to
+		// match the test inputs. SendClientHelloWithFixes requires the
+		// key_shares extension to match in type.
+
+		// With the workaround enabled, we should negotiate TLS 1.2 on
+		// JDK 11 ClientHellos.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     fmt.Sprintf("Server-JDK11-%d", i),
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: []CurveID{CurveP256},
+				Bugs: ProtocolBugs{
+					SendClientHelloWithFixes:   t.clientHello,
+					ExpectJDK11DowngradeRandom: t.isJDK11,
+				},
+			},
+			expectations: connectionExpectations{
+				version: expectedVersion,
+			},
+			flags: []string{"-jdk11-workaround"},
+		})
+
+		// With the workaround disabled, we always negotiate TLS 1.3.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: []CurveID{CurveP256},
+				Bugs: ProtocolBugs{
+					SendClientHelloWithFixes:   t.clientHello,
+					ExpectJDK11DowngradeRandom: false,
+				},
+			},
+			expectations: connectionExpectations{
+				version: VersionTLS13,
+			},
+		})
+
+		// If the server does not support TLS 1.3, the workaround should
+		// be a no-op. In particular, it should not send the downgrade
+		// signal.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: []CurveID{CurveP256},
+				Bugs: ProtocolBugs{
+					SendClientHelloWithFixes:   t.clientHello,
+					ExpectJDK11DowngradeRandom: false,
+				},
+			},
+			expectations: connectionExpectations{
+				version: VersionTLS12,
+			},
+			flags: []string{
+				"-jdk11-workaround",
+				"-max-version", strconv.Itoa(VersionTLS12),
+			},
+		})
+	}
+}
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index a65e771..144a693 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -588,7 +588,7 @@
 		// draft-tls-westerbaan-xyber768d00-03
 		kem = &concatKEM{kem1: &ecdhKEM{curve: ecdh.X25519()}, kem2: &kyberKEM{}}
 	case CurveX25519MLKEM768:
-		// draft-kwiatkowski-tls-ecdhe-mlkem-01
+		// draft-ietf-tls-ecdhe-mlkem-00
 		kem = &concatKEM{kem1: &mlkem768KEM{}, kem2: &ecdhKEM{curve: ecdh.X25519()}}
 	default:
 		return nil, false
diff --git a/src/ssl/test/runner/key_update_tests.go b/src/ssl/test/runner/key_update_tests.go
new file mode 100644
index 0000000..0a90530
--- /dev/null
+++ b/src/ssl/test/runner/key_update_tests.go
@@ -0,0 +1,597 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "slices"
+
+func addKeyUpdateTests() {
+	// TLS tests.
+	testCases = append(testCases, testCase{
+		name: "KeyUpdate-ToClient",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   10,
+		keyUpdateRequest: keyUpdateNotRequested,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "KeyUpdate-ToServer",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   10,
+		keyUpdateRequest: keyUpdateNotRequested,
+	})
+	testCases = append(testCases, testCase{
+		name: "KeyUpdate-FromClient",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		expectUnsolicitedKeyUpdate: true,
+		flags:                      []string{"-key-update"},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "KeyUpdate-FromServer",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		expectUnsolicitedKeyUpdate: true,
+		flags:                      []string{"-key-update"},
+	})
+	testCases = append(testCases, testCase{
+		name: "KeyUpdate-InvalidRequestMode",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   1,
+		keyUpdateRequest: 42,
+		shouldFail:       true,
+		expectedError:    ":DECODE_ERROR:",
+	})
+	testCases = append(testCases, testCase{
+		// Test that shim responds to KeyUpdate requests.
+		name: "KeyUpdate-Requested",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				RejectUnsolicitedKeyUpdate: true,
+			},
+		},
+		// Test the shim receiving many KeyUpdates in a row.
+		sendKeyUpdates:   5,
+		messageCount:     5,
+		keyUpdateRequest: keyUpdateRequested,
+	})
+	testCases = append(testCases, testCase{
+		// Test that shim responds to KeyUpdate requests if peer's KeyUpdate is
+		// discovered while a write is pending.
+		name: "KeyUpdate-Requested-UnfinishedWrite",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				RejectUnsolicitedKeyUpdate: true,
+			},
+		},
+		// Test the shim receiving many KeyUpdates in a row.
+		sendKeyUpdates:          5,
+		messageCount:            5,
+		keyUpdateRequest:        keyUpdateRequested,
+		readWithUnfinishedWrite: true,
+		flags:                   []string{"-async"},
+	})
+
+	// DTLS tests.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ToClient-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		// Send many KeyUpdates to make sure record reassembly can handle it.
+		sendKeyUpdates:   10,
+		keyUpdateRequest: keyUpdateNotRequested,
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "KeyUpdate-ToServer-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   10,
+		keyUpdateRequest: keyUpdateNotRequested,
+	})
+
+	// Test that the shim accounts for packet loss when processing KeyUpdate.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ToClient-PacketLoss-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					if next[0].Type != typeKeyUpdate {
+						c.WriteFlight(next)
+						return
+					}
+
+					// Send the KeyUpdate. The shim should ACK it.
+					c.WriteFlight(next)
+					ackTimeout := timeouts[0] / 4
+					c.AdvanceClock(ackTimeout)
+					c.ReadACK(c.InEpoch())
+
+					// The shim should continue reading data at the old epoch.
+					// The ACK may not have come through.
+					msg := []byte("test")
+					c.WriteAppData(c.OutEpoch()-1, msg)
+					c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+					// Re-send KeyUpdate. The shim should ACK it again. The ACK
+					// may not have come through.
+					c.WriteFlight(next)
+					c.AdvanceClock(ackTimeout)
+					c.ReadACK(c.InEpoch())
+
+					// The shim should be able to read data at the new epoch.
+					c.WriteAppData(c.OutEpoch(), msg)
+					c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+					// The shim continues to accept application data at the old
+					// epoch, for a period of time.
+					c.WriteAppData(c.OutEpoch()-1, msg)
+					c.ReadAppData(c.InEpoch(), expectedReply(msg))
+
+					// It will even ACK the retransmission, though it knows the
+					// shim has seen the ACK.
+					c.WriteFlight(next)
+					c.AdvanceClock(ackTimeout)
+					c.ReadACK(c.InEpoch())
+
+					// After some time has passed, the shim will discard the old
+					// epoch. The following writes should be ignored.
+					c.AdvanceClock(dtlsPrevEpochExpiration)
+					f := next[0].Fragment(0, len(next[0].Data))
+					f.ShouldDiscard = true
+					c.WriteFragments([]DTLSFragment{f})
+					c.WriteAppData(c.OutEpoch()-1, msg)
+				},
+			},
+		},
+		sendKeyUpdates:   10,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-async"},
+	})
+
+	// In DTLS, we KeyUpdate before read, rather than write, because the
+	// KeyUpdate will not be applied before the shim reads the ACK.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-FromClient-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		// Perform several message exchanges to update keys several times.
+		messageCount: 10,
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "KeyUpdate-FromServer-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		// Perform several message exchanges to update keys several times.
+		messageCount: 10,
+		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
+		flags: []string{"-no-ticket"},
+	})
+
+	// If the shim has a pending unACKed flight, it defers sending KeyUpdate.
+	// BoringSSL does not support multiple outgoing flights at once.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-DeferredSend-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Request a client certificate, so the shim has more to send.
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				MaxPacketLength: 512,
+				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+					if received[len(received)-1].Type != typeFinished {
+						c.WriteACK(c.OutEpoch(), records)
+						return
+					}
+
+					// This test relies on the Finished flight being multiple
+					// records.
+					if len(records) <= 1 {
+						panic("shim sent Finished flight in one record")
+					}
+
+					// Before ACKing Finished, do some rounds of exchanging
+					// application data. Although the shim has already scheduled
+					// KeyUpdate, it should not send the KeyUpdate until it gets
+					// an ACK. (If it sent KeyUpdate, ReadAppData would report
+					// an unexpected record.)
+					msg := []byte("test")
+					for i := 0; i < 10; i++ {
+						c.WriteAppData(c.OutEpoch(), msg)
+						c.ReadAppData(c.InEpoch(), expectedReply(msg))
+					}
+
+					// ACK some of the Finished flight, but not all of it.
+					c.WriteACK(c.OutEpoch(), records[:1])
+
+					// The shim continues to defer KeyUpdate.
+					for i := 0; i < 10; i++ {
+						c.WriteAppData(c.OutEpoch(), msg)
+						c.ReadAppData(c.InEpoch(), expectedReply(msg))
+					}
+
+					// ACK the remainder.
+					c.WriteACK(c.OutEpoch(), records[1:])
+
+					// The shim should now send KeyUpdate. Return to the test
+					// harness, which will look for it.
+				},
+			},
+		},
+		shimCertificate:              &rsaChainCertificate,
+		shimSendsKeyUpdateBeforeRead: true,
+		flags:                        []string{"-mtu", "512"},
+	})
+
+	// The shim should not switch keys until it receives an ACK.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-WaitForACK-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				MaxPacketLength: 512,
+				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+					if received[0].Type != typeKeyUpdate {
+						c.WriteACK(c.OutEpoch(), records)
+						return
+					}
+
+					// Make the shim send application data. We have not yet
+					// ACKed KeyUpdate, so the shim should send at the previous
+					// epoch. Through each of these rounds, the shim will also
+					// try to KeyUpdate again. These calls will be suppressed
+					// because there is still an outstanding KeyUpdate.
+					msg := []byte("test")
+					for i := 0; i < 10; i++ {
+						c.WriteAppData(c.OutEpoch(), msg)
+						c.ReadAppData(c.InEpoch()-1, expectedReply(msg))
+					}
+
+					// ACK the KeyUpdate. Ideally we'd test a partial ACK, but
+					// BoringSSL's minimum MTU is such that KeyUpdate always
+					// fits in one record.
+					c.WriteACK(c.OutEpoch(), records)
+
+					// The shim should now send at the new epoch. Return to the
+					// test harness, which will enforce this.
+				},
+			},
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+	})
+
+	// Test that shim responds to KeyUpdate requests.
+	fixKeyUpdateReply := func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
+		c.WriteACK(c.OutEpoch(), records)
+		if received[0].Type != typeKeyUpdate {
+			return
+		}
+		// This works around an awkward testing mismatch. The test
+		// harness expects the shim to immediately change keys, but
+		// the shim writes app data before seeing the ACK. The app
+		// data will be sent at the previous epoch. Consume this and
+		// prime the shim to resend its reply at the new epoch.
+		msg := makeTestMessage(int(received[0].Sequence)-2, 32)
+		c.ReadAppData(c.InEpoch()-1, expectedReply(msg))
+		c.WriteAppData(c.OutEpoch(), msg)
+	}
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-Requested-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				RejectUnsolicitedKeyUpdate: true,
+				ACKFlightDTLS:              fixKeyUpdateReply,
+			},
+		},
+		// Test the shim receiving many KeyUpdates in a row. They will be
+		// combined into one reply KeyUpdate.
+		sendKeyUpdates:   5,
+		messageLen:       32,
+		messageCount:     5,
+		keyUpdateRequest: keyUpdateRequested,
+	})
+
+	mergeNewSessionTicketAndKeyUpdate := func(f WriteFlightFunc) WriteFlightFunc {
+		return func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+			// Send NewSessionTicket and the first KeyUpdate all together.
+			if next[0].Type == typeKeyUpdate {
+				panic("key update should have been merged into NewSessionTicket")
+			}
+			if next[0].Type != typeNewSessionTicket {
+				c.WriteFlight(next)
+				return
+			}
+			if next[0].Type == typeNewSessionTicket && next[len(next)-1].Type != typeKeyUpdate {
+				c.MergeIntoNextFlight()
+				return
+			}
+
+			f(c, prev, received, next, records)
+		}
+	}
+
+	// Test that the shim does not process KeyUpdate until it has processed all
+	// preceding messages.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ProcessInOrder-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					// Write the KeyUpdate. The shim should buffer and ACK it.
+					keyUpdate := next[len(next)-1]
+					c.WriteFlight([]DTLSMessage{keyUpdate})
+					ackTimeout := timeouts[0] / 4
+					c.AdvanceClock(ackTimeout)
+					c.ReadACK(c.InEpoch())
+
+					// The shim should not process KeyUpdate yet. It should not
+					// read from the new epoch.
+					msg1, msg2 := []byte("aaaa"), []byte("bbbb")
+					c.WriteAppData(c.OutEpoch(), msg1)
+					c.AdvanceClock(0) // Check there are no messages.
+
+					// It can read from the old epoch, however.
+					c.WriteAppData(c.OutEpoch()-1, msg2)
+					c.ReadAppData(c.InEpoch(), expectedReply(msg2))
+
+					// Write the rest of the flight.
+					c.WriteFlight(next[:len(next)-1])
+					c.AdvanceClock(ackTimeout)
+					c.ReadACK(c.InEpoch())
+
+					// Now the new epoch is functional.
+					c.WriteAppData(c.OutEpoch(), msg1)
+					c.ReadAppData(c.InEpoch(), expectedReply(msg1))
+				}),
+			},
+		},
+		sendKeyUpdates:   1,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-async"},
+	})
+
+	// Messages after a KeyUpdate are not allowed.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ExtraMessage-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					extra := next[0]
+					extra.Sequence = next[len(next)-1].Sequence + 1
+					next = append(slices.Clip(next), extra)
+					c.WriteFlight(next)
+				}),
+			},
+		},
+		sendKeyUpdates:     1,
+		keyUpdateRequest:   keyUpdateNotRequested,
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ExtraMessageBuffered-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					// Send the extra message first. The shim should accept and
+					// buffer it.
+					extra := next[0]
+					extra.Sequence = next[len(next)-1].Sequence + 1
+					c.WriteFlight([]DTLSMessage{extra})
+
+					// Now send the flight, including a KeyUpdate. The shim
+					// should now notice the extra message and reject.
+					c.WriteFlight(next)
+				}),
+			},
+		},
+		sendKeyUpdates:     1,
+		keyUpdateRequest:   keyUpdateNotRequested,
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// Test KeyUpdate overflow conditions. Both the epoch number and the message
+	// number may overflow, in either the read or write direction.
+
+	// When the sender is the client, the first KeyUpdate is message 2 at epoch
+	// 3, so the epoch number overflows first.
+	const maxClientKeyUpdates = 0xffff - 3
+
+	// Test that the shim, as a server, rejects KeyUpdates at epoch 0xffff. RFC
+	// 9147 does not prescribe this limit, but we enforce it. See
+	// https://mailarchive.ietf.org/arch/msg/tls/6y8wTv8Q_IPM-PCcbCAmDOYg6bM/
+	// and https://www.rfc-editor.org/errata/eid8050
+	writeFlightKeyUpdate := func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+		if next[0].Type == typeKeyUpdate {
+			// Exchange some data to avoid tripping KeyUpdate DoS limits.
+			msg := []byte("test")
+			c.WriteAppData(c.OutEpoch()-1, msg)
+			c.ReadAppData(c.InEpoch(), expectedReply(msg))
+		}
+		c.WriteFlight(next)
+	}
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "KeyUpdate-MaxReadEpoch-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AllowEpochOverflow: true,
+				WriteFlightDTLS:    writeFlightKeyUpdate,
+			},
+		},
+		// Avoid the NewSessionTicket messages interfering with the callback.
+		flags:            []string{"-no-ticket"},
+		sendKeyUpdates:   maxClientKeyUpdates,
+		keyUpdateRequest: keyUpdateNotRequested,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: dtls,
+		name:     "KeyUpdate-ReadEpochOverflow-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AllowEpochOverflow: true,
+				WriteFlightDTLS:    writeFlightKeyUpdate,
+			},
+		},
+		// Avoid the NewSessionTicket messages interfering with the callback.
+		flags:              []string{"-no-ticket"},
+		sendKeyUpdates:     maxClientKeyUpdates + 1,
+		keyUpdateRequest:   keyUpdateNotRequested,
+		shouldFail:         true,
+		expectedError:      ":TOO_MANY_KEY_UPDATES:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// Test that the shim, as a client, notices its epoch overflow condition
+	// when asked to send too many KeyUpdates. The shim sends KeyUpdate before
+	// every read, including reading connection close, so the number of
+	// KeyUpdates is one more than the message count.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-MaxWriteEpoch-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		messageCount:                 maxClientKeyUpdates - 1,
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-WriteEpochOverflow-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// The shim does not notice the overflow until immediately after
+				// sending KeyUpdate, so tolerate the overflow on the runner.
+				AllowEpochOverflow: true,
+			},
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		messageCount:                 maxClientKeyUpdates,
+		shouldFail:                   true,
+		expectedError:                ":TOO_MANY_KEY_UPDATES:",
+	})
+
+	// When the sender is a server that doesn't send tickets, the first
+	// KeyUpdate is message 5 (SH, EE, C, CV, Fin) at epoch 3, so the message
+	// number overflows first.
+	const maxServerKeyUpdates = 0xffff - 5
+
+	// Test that the shim, as a client, does not allow the value to wraparound.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "KeyUpdate-ReadMessageOverflow-DTLS",
+		config: Config{
+			MaxVersion:             VersionTLS13,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				AllowEpochOverflow: true,
+				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
+					writeFlightKeyUpdate(c, prev, received, next, records)
+					if next[0].Type == typeKeyUpdate && next[0].Sequence == 0xffff {
+						// At this point, the shim has accepted message 0xffff.
+						// Check the shim does not now accept message 0 as the
+						// current message. Test this by sending a garbage
+						// message 0. A shim that overflows and processes the
+						// message will notice the syntax error. A shim that
+						// correctly interprets this as an old message will drop
+						// the record and simply ACK it.
+						//
+						// We do this rather than send a valid KeyUpdate because
+						// the shim will keep the old epoch active and drop
+						// decryption failures. Looking for the lack of an error
+						// is more straightforward.
+						c.WriteFlight([]DTLSMessage{{Epoch: c.OutEpoch(), Sequence: 0, Type: typeKeyUpdate, Data: []byte("INVALID")}})
+						c.ExpectNextTimeout(timeouts[0] / 4)
+						c.AdvanceClock(timeouts[0] / 4)
+						c.ReadACK(c.InEpoch())
+					}
+				},
+			},
+		},
+		sendKeyUpdates:   maxServerKeyUpdates + 1,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-async", "-expect-no-session"},
+	})
+
+	// Test that the shim, as a server, notices its message overflow condition,
+	// when asked to send too many KeyUpdates.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "KeyUpdate-MaxWriteMessage-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		messageCount:                 maxServerKeyUpdates,
+		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
+		flags: []string{"-no-ticket"},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "KeyUpdate-WriteMessageOverflow-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		shimSendsKeyUpdateBeforeRead: true,
+		messageCount:                 maxServerKeyUpdates + 1,
+		shouldFail:                   true,
+		expectedError:                ":overflow:",
+		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
+		flags: []string{"-no-ticket"},
+	})
+}
diff --git a/src/ssl/test/runner/key_usage_tests.go b/src/ssl/test/runner/key_usage_tests.go
new file mode 100644
index 0000000..8c1df84
--- /dev/null
+++ b/src/ssl/test/runner/key_usage_tests.go
@@ -0,0 +1,249 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"math/big"
+	"time"
+)
+
+func addECDSAKeyUsageTests() {
+	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+	if err != nil {
+		panic(err)
+	}
+
+	template := &x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
+		},
+		NotBefore: time.Now(),
+		NotAfter:  time.Now(),
+
+		// An ECC certificate with only the keyAgreement key usgae may
+		// be used with ECDH, but not ECDSA.
+		KeyUsage:              x509.KeyUsageKeyAgreement,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	cert := generateSingleCertChain(template, &ecdsaP256Key)
+
+	for _, ver := range tlsVersions {
+		if ver.version < VersionTLS12 {
+			continue
+		}
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ECDSAKeyUsage-Client-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &cert,
+			},
+			shouldFail:    true,
+			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ECDSAKeyUsage-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &cert,
+			},
+			flags:         []string{"-require-any-client-certificate"},
+			shouldFail:    true,
+			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+		})
+	}
+}
+
+func addRSAKeyUsageTests() {
+	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
+
+	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+	if err != nil {
+		panic(err)
+	}
+
+	dsTemplate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
+		},
+		NotBefore: time.Now(),
+		NotAfter:  time.Now(),
+
+		KeyUsage:              x509.KeyUsageDigitalSignature,
+		BasicConstraintsValid: true,
+	}
+
+	encTemplate := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
+		},
+		NotBefore: time.Now(),
+		NotAfter:  time.Now(),
+
+		KeyUsage:              x509.KeyUsageKeyEncipherment,
+		BasicConstraintsValid: true,
+	}
+
+	dsCert := generateSingleCertChain(&dsTemplate, priv)
+
+	encCert := generateSingleCertChain(&encTemplate, priv)
+
+	dsSuites := []uint16{
+		TLS_AES_128_GCM_SHA256,
+		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	}
+	encSuites := []uint16{
+		TLS_RSA_WITH_AES_128_GCM_SHA256,
+		TLS_RSA_WITH_AES_128_CBC_SHA,
+	}
+
+	for _, ver := range tlsVersions {
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Credential:   &encCert,
+				CipherSuites: dsSuites,
+			},
+			shouldFail:    true,
+			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Credential:   &dsCert,
+				CipherSuites: dsSuites,
+			},
+		})
+
+		// TLS 1.3 removes the encipherment suites.
+		if ver.version < VersionTLS13 {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
+				config: Config{
+					MinVersion:   ver.version,
+					MaxVersion:   ver.version,
+					Credential:   &encCert,
+					CipherSuites: encSuites,
+				},
+			})
+
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
+				config: Config{
+					MinVersion:   ver.version,
+					MaxVersion:   ver.version,
+					Credential:   &dsCert,
+					CipherSuites: encSuites,
+				},
+				shouldFail:    true,
+				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+			})
+
+			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
+				config: Config{
+					MinVersion:   ver.version,
+					MaxVersion:   ver.version,
+					Credential:   &dsCert,
+					CipherSuites: encSuites,
+				},
+				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
+			})
+
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
+				config: Config{
+					MinVersion:   ver.version,
+					MaxVersion:   ver.version,
+					Credential:   &encCert,
+					CipherSuites: dsSuites,
+				},
+				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
+			})
+		}
+
+		if ver.version >= VersionTLS13 {
+			// In 1.3 and above, we enforce keyUsage even when disabled.
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
+				config: Config{
+					MinVersion:   ver.version,
+					MaxVersion:   ver.version,
+					Credential:   &encCert,
+					CipherSuites: dsSuites,
+				},
+				flags:         []string{"-ignore-rsa-key-usage"},
+				shouldFail:    true,
+				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+			})
+		}
+
+		// The server only uses signatures and always enforces it.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &encCert,
+			},
+			shouldFail:    true,
+			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+			flags:         []string{"-require-any-client-certificate"},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Credential: &dsCert,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+
+	}
+}
diff --git a/src/ssl/test/runner/pake_tests.go b/src/ssl/test/runner/pake_tests.go
new file mode 100644
index 0000000..ddd2eb3
--- /dev/null
+++ b/src/ssl/test/runner/pake_tests.go
@@ -0,0 +1,513 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "errors"
+
+func addPAKETests() {
+	spakeCredential := Credential{
+		Type:         CredentialTypeSPAKE2PlusV1,
+		PAKEContext:  []byte("context"),
+		PAKEClientID: []byte("client"),
+		PAKEServerID: []byte("server"),
+		PAKEPassword: []byte("password"),
+	}
+
+	spakeWrongClientID := spakeCredential
+	spakeWrongClientID.PAKEClientID = []byte("wrong")
+
+	spakeWrongServerID := spakeCredential
+	spakeWrongServerID.PAKEServerID = []byte("wrong")
+
+	spakeWrongPassword := spakeCredential
+	spakeWrongPassword.PAKEPassword = []byte("wrong")
+
+	spakeWrongRole := spakeCredential
+	spakeWrongRole.WrongPAKERole = true
+
+	spakeWrongCodepoint := spakeCredential
+	spakeWrongCodepoint.OverridePAKECodepoint = 1234
+
+	testCases = append(testCases, testCase{
+		name:     "PAKE-No-Server-Support",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+	testCases = append(testCases, testCase{
+		name:     "PAKE-Server",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				// We do not currently support resumption with PAKE, so PAKE
+				// servers should not issue session tickets.
+				ExpectNoNewSessionTicket: true,
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+	})
+	testCases = append(testCases, testCase{
+		// Send a ClientHello with the wrong PAKE client ID.
+		name:     "PAKE-Server-WrongClientID",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeWrongClientID,
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":PEER_PAKE_MISMATCH:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// Send a ClientHello with the wrong PAKE server ID.
+		name:     "PAKE-Server-WrongServerID",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeWrongServerID,
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":PEER_PAKE_MISMATCH:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// Send a ClientHello with the wrong PAKE codepoint.
+		name:     "PAKE-Server-WrongCodepoint",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeWrongCodepoint,
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":PEER_PAKE_MISMATCH:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// A server configured with a mix of PAKE and non-PAKE
+		// credentials will select the first that matches what the
+		// client offered. In doing so, it should skip unsupported
+		// PAKE algorithms.
+		name:     "PAKE-Server-MultiplePAKEs",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				OfferExtraPAKEs: []uint16{1, 2, 3, 4, 5},
+			},
+		},
+		shimCredentials: []*Credential{&spakeWrongClientID, &spakeWrongServerID, &spakeWrongRole, &spakeCredential, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "3"},
+	})
+	testCases = append(testCases, testCase{
+		// A server configured with a certificate credential before a
+		// PAKE credential will consider the certificate credential first.
+		name:     "PAKE-Server-CertificateBeforePAKE",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Pretend to offer a matching PAKE share, but expect the
+				// shim to select the credential first and negotiate a
+				// normal handshake.
+				OfferExtraPAKEClientID: spakeCredential.PAKEClientID,
+				OfferExtraPAKEServerID: spakeCredential.PAKEServerID,
+				OfferExtraPAKEs:        []uint16{spakeID},
+			},
+		},
+		shimCredentials: []*Credential{&rsaCertificate, &spakeCredential},
+		flags:           []string{"-expect-selected-credential", "0"},
+	})
+	testCases = append(testCases, testCase{
+		// A server configured with just a PAKE credential should reject normal
+		// clients.
+		name:     "PAKE-Server-NormalClient",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":PEER_PAKE_MISMATCH:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// ... and TLS 1.2 clients.
+		name:     "PAKE-Server-NormalTLS12Client",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":NO_SHARED_CIPHER:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// ... but you can configure a server with both PAKE and certificate-based
+		// SSL_CREDENTIALs and that works.
+		name:     "PAKE-ServerWithCertsToo-NormalClient",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+		},
+		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+	})
+	testCases = append(testCases, testCase{
+		// ... and for older clients.
+		name:     "PAKE-ServerWithCertsToo-NormalTLS12Client",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
+		flags:           []string{"-expect-selected-credential", "1"},
+	})
+	testCases = append(testCases, testCase{
+		name:     "PAKE-Client",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				CheckClientHello: func(c *clientHelloMsg) error {
+					// PAKE connections don't use the key_share / supported_groups mechanism.
+					if c.hasKeyShares {
+						return errors.New("unexpected key_share extension")
+					}
+					if len(c.supportedCurves) != 0 {
+						return errors.New("unexpected supported_groups extension")
+					}
+					// PAKE connections don't use signature algorithms.
+					if len(c.signatureAlgorithms) != 0 {
+						return errors.New("unexpected signature_algorithms extension")
+					}
+					// We don't support resumption with PAKEs.
+					if len(c.pskKEModes) != 0 {
+						return errors.New("unexpected psk_key_exchange_modes extension")
+					}
+					return nil
+				},
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+	})
+	testCases = append(testCases, testCase{
+		// Although there is no reason to request new key shares, the PAKE
+		// client should handle cookie requests.
+		name:     "PAKE-Client-HRRCookie",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+	})
+	testCases = append(testCases, testCase{
+		// A PAKE client will not offer key shares, so the client should
+		// reject a HelloRetryRequest requesting a different key share.
+		name:     "PAKE-Client-HRRKeyShare",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCurve: CurveX25519,
+			},
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		// A server cannot reply with an HRR asking for a PAKE if the client didn't
+		// offer a PAKE in the ClientHello.
+		name:     "PAKE-NormalClient-PAKEInHRR",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				AlwaysSendHelloRetryRequest: true,
+				SendPAKEInHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		// A PAKE client should not accept an empty ServerHello.
+		name:     "PAKE-Client-EmptyServerHello",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Trigger an empty ServerHello by making a normal server skip
+				// the key_share extension.
+				MissingKeyShare: true,
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":MISSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		// A PAKE client should not accept a key_share ServerHello.
+		name:     "PAKE-Client-KeyShareServerHello",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Trigger a key_share ServerHello by making a normal server
+				// skip the HelloRetryRequest it would otherwise send in
+				// response to the shim's key_share-less ClientHello.
+				SkipHelloRetryRequest: true,
+				// Ignore the client's lack of supported_groups.
+				IgnorePeerCurvePreferences: true,
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":UNEXPECTED_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		// A PAKE client should not accept a TLS 1.2 ServerHello.
+		name:     "PAKE-Client-TLS12ServerHello",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":UNSUPPORTED_PROTOCOL:",
+	})
+	testCases = append(testCases, testCase{
+		// A server cannot send the PAKE extension to a non-PAKE client.
+		name:     "PAKE-NormalClient-UnsolicitedPAKEInServerHello",
+		testType: clientTest,
+		config: Config{
+			Bugs: ProtocolBugs{
+				UnsolicitedPAKE: spakeID,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		// A server cannot reply with a PAKE that the client did not offer.
+		name:     "PAKE-Client-WrongPAKEInServerHello",
+		testType: clientTest,
+		config: Config{
+			Bugs: ProtocolBugs{
+				UnsolicitedPAKE: 1234,
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":DECODE_ERROR:",
+	})
+	testCases = append(testCases, testCase{
+		name:     "PAKE-Extension-Duplicate",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				OfferExtraPAKEClientID: []byte("client"),
+				OfferExtraPAKEServerID: []byte("server"),
+				OfferExtraPAKEs:        []uint16{1234, 1234},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		// If the client sees a server with a wrong password, it should
+		// reject the confirmV value in the ServerHello.
+		name:     "PAKE-Client-WrongPassword",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeWrongPassword,
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":DECODE_ERROR:",
+	})
+	testCases = append(testCases, testCase{
+		name:     "PAKE-Client-Truncate",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				TruncatePAKEMessage: true,
+			},
+		},
+		shimCredentials: []*Credential{&spakeCredential},
+		shouldFail:      true,
+		expectedError:   ":DECODE_ERROR:",
+	})
+	testCases = append(testCases, testCase{
+		name:     "PAKE-Server-Truncate",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				TruncatePAKEMessage: true,
+			},
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+	testCases = append(testCases, testCase{
+		// Servers may not send CertificateRequest in a PAKE handshake.
+		name:     "PAKE-Client-UnexpectedCertificateRequest",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				AlwaysSendCertificateRequest: true,
+			},
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+	testCases = append(testCases, testCase{
+		// Servers may not send Certificate in a PAKE handshake.
+		name:     "PAKE-Client-UnexpectedCertificate",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				AlwaysSendCertificate:    true,
+				UseCertificateCredential: &rsaCertificate,
+				// Ignore the client's lack of signature_algorithms.
+				IgnorePeerSignatureAlgorithmPreferences: true,
+			},
+		},
+		shimCredentials:    []*Credential{&spakeCredential},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+	testCases = append(testCases, testCase{
+		// If a server is configured to request client certificates, it should
+		// still not do so when negotiating a PAKE.
+		name:     "PAKE-Server-DoNotRequestClientCertificate",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+		},
+		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
+		flags:           []string{"-require-any-client-certificate"},
+	})
+	testCases = append(testCases, testCase{
+		// Clients should ignore server PAKE credentials.
+		name:     "PAKE-Client-WrongRole",
+		testType: clientTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+		},
+		shimCredentials: []*Credential{&spakeWrongRole},
+		shouldFail:      true,
+		// The shim will send a non-PAKE ClientHello.
+		expectedLocalError: "tls: client not configured with PAKE",
+	})
+	testCases = append(testCases, testCase{
+		// Servers should ignore client PAKE credentials.
+		name:     "PAKE-Server-WrongRole",
+		testType: serverTest,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Credential: &spakeCredential,
+		},
+		shimCredentials: []*Credential{&spakeWrongRole},
+		shouldFail:      true,
+		// The shim will fail the handshake because it has no usable credentials
+		// available.
+		expectedError:      ":UNKNOWN_CERTIFICATE_TYPE:",
+		expectedLocalError: "remote error: handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		// On the client, we only support a single PAKE credential.
+		name:            "PAKE-Client-MultiplePAKEs",
+		testType:        clientTest,
+		shimCredentials: []*Credential{&spakeCredential, &spakeWrongPassword},
+		shouldFail:      true,
+		expectedError:   ":UNSUPPORTED_CREDENTIAL_LIST:",
+	})
+	testCases = append(testCases, testCase{
+		// On the client, we only support a single PAKE credential.
+		name:            "PAKE-Client-PAKEAndCertificate",
+		testType:        clientTest,
+		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
+		shouldFail:      true,
+		expectedError:   ":UNSUPPORTED_CREDENTIAL_LIST:",
+	})
+	testCases = append(testCases, testCase{
+		// We currently do not support resumption with PAKE. Even if configured
+		// with a session, the client should not offer the session with PAKEs.
+		name:     "PAKE-Client-NoResume",
+		testType: clientTest,
+		// Make two connections. For the first connection, just establish a
+		// session without PAKE, to pick up a session.
+		config: Config{
+			Credential: &rsaCertificate,
+		},
+		// For the second connection, use SPAKE.
+		resumeSession: true,
+		resumeConfig: &Config{
+			Credential: &spakeCredential,
+			Bugs: ProtocolBugs{
+				// Check that the ClientHello does not offer a session, even
+				// though one was configured.
+				ExpectNoTLS13PSK: true,
+				// Respond with an unsolicted PSK extension in ServerHello, to
+				// check that the client rejects it.
+				AlwaysSelectPSKIdentity: true,
+			},
+		},
+		resumeShimCredentials: []*Credential{&spakeCredential},
+		shouldFail:            true,
+		expectedError:         ":UNEXPECTED_EXTENSION:",
+	})
+}
diff --git a/src/ssl/test/runner/peek_tests.go b/src/ssl/test/runner/peek_tests.go
new file mode 100644
index 0000000..368903a
--- /dev/null
+++ b/src/ssl/test/runner/peek_tests.go
@@ -0,0 +1,85 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addPeekTests() {
+	// Test SSL_peek works, including on empty records.
+	testCases = append(testCases, testCase{
+		name:             "Peek-Basic",
+		sendEmptyRecords: 1,
+		flags:            []string{"-peek-then-read"},
+	})
+
+	// Test SSL_peek can drive the initial handshake.
+	testCases = append(testCases, testCase{
+		name: "Peek-ImplicitHandshake",
+		flags: []string{
+			"-peek-then-read",
+			"-implicit-handshake",
+		},
+	})
+
+	// Test SSL_peek can discover and drive a renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Peek-Renegotiate",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-peek-then-read",
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	// Test SSL_peek can discover a close_notify.
+	testCases = append(testCases, testCase{
+		name: "Peek-Shutdown",
+		config: Config{
+			Bugs: ProtocolBugs{
+				ExpectCloseNotify: true,
+			},
+		},
+		flags: []string{
+			"-peek-then-read",
+			"-check-close-notify",
+		},
+	})
+
+	// Test SSL_peek can discover an alert.
+	testCases = append(testCases, testCase{
+		name: "Peek-Alert",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSpuriousAlert: alertRecordOverflow,
+			},
+		},
+		flags:         []string{"-peek-then-read"},
+		shouldFail:    true,
+		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+	})
+
+	// Test SSL_peek can handle KeyUpdate.
+	testCases = append(testCases, testCase{
+		name: "Peek-KeyUpdate",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   1,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-peek-then-read"},
+	})
+}
diff --git a/src/ssl/test/runner/per_message_tests.go b/src/ssl/test/runner/per_message_tests.go
new file mode 100644
index 0000000..5ef58d5
--- /dev/null
+++ b/src/ssl/test/runner/per_message_tests.go
@@ -0,0 +1,437 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+type perMessageTest struct {
+	messageType uint8
+	test        testCase
+}
+
+// makePerMessageTests returns a series of test templates which cover each
+// message in the TLS handshake. These may be used with bugs like
+// WrongMessageType to fully test a per-message bug.
+func makePerMessageTests() []perMessageTest {
+	var ret []perMessageTest
+	// The following tests are limited to TLS 1.2, so QUIC is not tested.
+	for _, protocol := range []protocol{tls, dtls} {
+		suffix := "-" + protocol.String()
+
+		ret = append(ret, perMessageTest{
+			messageType: typeClientHello,
+			test: testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "ClientHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		if protocol == dtls {
+			ret = append(ret, perMessageTest{
+				messageType: typeHelloVerifyRequest,
+				test: testCase{
+					protocol: protocol,
+					name:     "HelloVerifyRequest" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+					},
+				},
+			})
+		}
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHello,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerCertificate" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateStatus,
+			test: testCase{
+				protocol: protocol,
+				name:     "CertificateStatus" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+					Credential: rsaCertificate.WithOCSP(testOCSPResponse),
+				},
+				flags: []string{"-enable-ocsp-stapling"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerKeyExchange,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerKeyExchange" + suffix,
+				config: Config{
+					MaxVersion:   VersionTLS12,
+					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateRequest,
+			test: testCase{
+				protocol: protocol,
+				name:     "CertificateRequest" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+					ClientAuth: RequireAnyClientCert,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHelloDone,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerHelloDone" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientCertificate" + suffix,
+				config: Config{
+					Credential: &rsaCertificate,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "CertificateVerify" + suffix,
+				config: Config{
+					Credential: &rsaCertificate,
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeClientKeyExchange,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientKeyExchange" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		if protocol != dtls {
+			ret = append(ret, perMessageTest{
+				messageType: typeNextProtocol,
+				test: testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "NextProtocol" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+						NextProtos: []string{"bar"},
+					},
+					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
+				},
+			})
+
+			ret = append(ret, perMessageTest{
+				messageType: typeChannelID,
+				test: testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "ChannelID" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+						ChannelID:  &channelIDKey,
+					},
+					flags: []string{
+						"-expect-channel-id",
+						base64FlagValue(channelIDBytes),
+					},
+				},
+			})
+		}
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeNewSessionTicket,
+			test: testCase{
+				protocol: protocol,
+				name:     "NewSessionTicket" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+	}
+
+	for _, protocol := range []protocol{tls, quic, dtls} {
+		suffix := "-" + protocol.String()
+		ret = append(ret, perMessageTest{
+			messageType: typeClientHello,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "TLS13-ClientHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHello,
+			test: testCase{
+				name:     "TLS13-ServerHello" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeEncryptedExtensions,
+			test: testCase{
+				name:     "TLS13-EncryptedExtensions" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateRequest,
+			test: testCase{
+				name:     "TLS13-CertificateRequest" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+					ClientAuth: RequireAnyClientCert,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				name:     "TLS13-ServerCertificate" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				name:     "TLS13-ServerCertificateVerify" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				name:     "TLS13-ServerFinished" + suffix,
+				protocol: protocol,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "TLS13-ClientCertificate" + suffix,
+				config: Config{
+					Credential: &rsaCertificate,
+					MaxVersion: VersionTLS13,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "TLS13-ClientCertificateVerify" + suffix,
+				config: Config{
+					Credential: &rsaCertificate,
+					MaxVersion: VersionTLS13,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "TLS13-ClientFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		// Only TLS uses EndOfEarlyData.
+		if protocol == tls {
+			ret = append(ret, perMessageTest{
+				messageType: typeEndOfEarlyData,
+				test: testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "TLS13-EndOfEarlyData" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS13,
+					},
+					resumeSession: true,
+					earlyData:     true,
+				},
+			})
+		}
+	}
+
+	return ret
+}
+
+func addWrongMessageTypeTests() {
+	for _, t := range makePerMessageTests() {
+		t.test.name = "WrongMessageType-" + t.test.name
+		if t.test.resumeConfig != nil {
+			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
+		} else {
+			t.test.config.Bugs.SendWrongMessageType = t.messageType
+		}
+		t.test.shouldFail = true
+		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
+		t.test.expectedLocalError = "remote error: unexpected message"
+
+		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
+			// In TLS 1.3, if the server believes it has sent ServerHello,
+			// but the client cannot process it, the client will send an
+			// unencrypted alert while the server expects encryption. This
+			// decryption failure is reported differently for each protocol, so
+			// leave it unchecked.
+			t.test.expectedLocalError = ""
+		}
+
+		testCases = append(testCases, t.test)
+	}
+}
+
+func addTrailingMessageDataTests() {
+	for _, t := range makePerMessageTests() {
+		t.test.name = "TrailingMessageData-" + t.test.name
+		if t.test.resumeConfig != nil {
+			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
+		} else {
+			t.test.config.Bugs.SendTrailingMessageData = t.messageType
+		}
+		t.test.shouldFail = true
+		t.test.expectedError = ":DECODE_ERROR:"
+		t.test.expectedLocalError = "remote error: error decoding message"
+
+		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
+			// In TLS 1.3, if the server believes it has sent ServerHello,
+			// but the client cannot process it, the client will send an
+			// unencrypted alert while the server expects encryption. This
+			// decryption failure is reported differently for each protocol, so
+			// leave it unchecked.
+			t.test.expectedLocalError = ""
+		}
+
+		if t.messageType == typeClientHello {
+			// We have a different error for ClientHello parsing.
+			t.test.expectedError = ":CLIENTHELLO_PARSE_FAILED:"
+		}
+
+		if t.messageType == typeFinished {
+			// Bad Finished messages read as the verify data having
+			// the wrong length.
+			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
+			t.test.expectedLocalError = "remote error: error decrypting message"
+		}
+
+		testCases = append(testCases, t.test)
+	}
+}
diff --git a/src/ssl/test/runner/renegotiation_tests.go b/src/ssl/test/runner/renegotiation_tests.go
new file mode 100644
index 0000000..02dbc19
--- /dev/null
+++ b/src/ssl/test/runner/renegotiation_tests.go
@@ -0,0 +1,546 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addRenegotiationTests() {
+	// Servers cannot renegotiate.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Renegotiate-Server-Forbidden",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate:        1,
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+	// The server shouldn't echo the renegotiation extension unless
+	// requested by the client.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Renegotiate-Server-NoExt",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfo:      true,
+				RequireRenegotiationInfo: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "renegotiation extension missing",
+	})
+	// The renegotiation SCSV should be sufficient for the server to echo
+	// the extension.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Renegotiate-Server-NoExt-SCSV",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfo:      true,
+				SendRenegotiationSCSV:    true,
+				RequireRenegotiationInfo: true,
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				FailIfResumeOnRenego: true,
+			},
+		},
+		renegotiate: 1,
+		// Test renegotiation after both an initial and resumption
+		// handshake.
+		resumeSession: true,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+			"-expect-secure-renegotiation",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				FailIfResumeOnRenego: true,
+			},
+		},
+		renegotiate: 1,
+		// Test renegotiation after both an initial and resumption
+		// handshake.
+		resumeSession: true,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+			"-expect-secure-renegotiation",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-EmptyExt",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EmptyRenegotiationInfo: true,
+			},
+		},
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":RENEGOTIATION_MISMATCH:",
+		expectedLocalError: "handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-BadExt",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadRenegotiationInfo: true,
+			},
+		},
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":RENEGOTIATION_MISMATCH:",
+		expectedLocalError: "handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-BadExt2",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadRenegotiationInfoEnd: true,
+			},
+		},
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":RENEGOTIATION_MISMATCH:",
+		expectedLocalError: "handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-Downgrade",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfoAfterInitial: true,
+			},
+		},
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":RENEGOTIATION_MISMATCH:",
+		expectedLocalError: "handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-Upgrade",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfoInInitial: true,
+			},
+		},
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":RENEGOTIATION_MISMATCH:",
+		expectedLocalError: "handshake failure",
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-NoExt-Allowed",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfo: true,
+			},
+		},
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+			"-expect-no-secure-renegotiation",
+		},
+	})
+
+	// Test that the server may switch ciphers on renegotiation without
+	// problems.
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-SwitchCiphers",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+		},
+		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-Client-SwitchCiphers2",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		renegotiateCiphers: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	// Test that the server may not switch versions on renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-SwitchVersion",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			// Pick a cipher which exists at both versions.
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				NegotiateVersionOnRenego: VersionTLS11,
+				// Avoid failing early at the record layer.
+				SendRecordVersion: VersionTLS12,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SSL_VERSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-SameClientVersion",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion: VersionTLS10,
+			Bugs: ProtocolBugs{
+				RequireSameRenegoClientVersion: true,
+			},
+		},
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name:        "Renegotiate-FalseStart",
+		renegotiate: 1,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			NextProtos:   []string{"foo"},
+		},
+		flags: []string{
+			"-false-start",
+			"-select-next-proto", "foo",
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shimWritesFirst: true,
+	})
+
+	// Client-side renegotiation controls.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Forbidden-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate:        1,
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Once-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-once",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Freely-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Once-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate:        2,
+		flags:              []string{"-renegotiate-once"},
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Freely-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 2,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "2",
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-NoIgnore",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryAppDataRecord: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_RENEGOTIATION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Ignore",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryAppDataRecord: true,
+			},
+		},
+		flags: []string{
+			"-renegotiate-ignore",
+			"-expect-total-renegotiations", "0",
+		},
+	})
+
+	// Renegotiation may be enabled and then disabled immediately after the
+	// handshake.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-ForbidAfterHandshake",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate:        1,
+		flags:              []string{"-forbid-renegotiation-after-handshake"},
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+
+	// Renegotiation is not allowed when there is an unfinished write.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-UnfinishedWrite",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate:             1,
+		readWithUnfinishedWrite: true,
+		flags: []string{
+			"-async",
+			"-renegotiate-freely",
+		},
+		shouldFail:    true,
+		expectedError: ":NO_RENEGOTIATION:",
+		// We do not successfully send the no_renegotiation alert in
+		// this case. https://crbug.com/boringssl/130
+	})
+
+	// We reject stray HelloRequests during the handshake in TLS 1.2.
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest-Packed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PackHandshakeFlight:                         true,
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Test that HelloRequest is rejected if it comes in the same record as the
+	// server Finished.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Packed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PackHandshakeFlight:          true,
+				PackHelloRequestWithFinished: true,
+			},
+		},
+		renegotiate:        1,
+		flags:              []string{"-renegotiate-freely"},
+		shouldFail:         true,
+		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// Renegotiation is forbidden in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryAppDataRecord: true,
+			},
+		},
+		flags: []string{
+			"-renegotiate-freely",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
+	// always reads as supporting it, regardless of whether it was
+	// negotiated.
+	testCases = append(testCases, testCase{
+		name: "AlwaysReportRenegotiationInfo-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfo: true,
+			},
+		},
+		flags: []string{
+			"-expect-secure-renegotiation",
+		},
+	})
+
+	// Certificates may not change on renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Renegotiation-CertificateChange",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: &rsaCertificate,
+			Bugs: ProtocolBugs{
+				RenegotiationCertificate: &rsaChainCertificate,
+			},
+		},
+		renegotiate:   1,
+		flags:         []string{"-renegotiate-freely"},
+		shouldFail:    true,
+		expectedError: ":SERVER_CERT_CHANGED:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiation-CertificateChange-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: &rsaCertificate,
+			Bugs: ProtocolBugs{
+				RenegotiationCertificate: &rsa1024Certificate,
+			},
+		},
+		renegotiate:   1,
+		flags:         []string{"-renegotiate-freely"},
+		shouldFail:    true,
+		expectedError: ":SERVER_CERT_CHANGED:",
+	})
+
+	// We do not negotiate ALPN after the initial handshake. This is
+	// error-prone and only risks bugs in consumers.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Renegotiation-ForbidALPN",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				// Forcibly negotiate ALPN on both initial and
+				// renegotiation handshakes. The test stack will
+				// internally check the client does not offer
+				// it.
+				SendALPN: "foo",
+			},
+		},
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar\x03baz",
+			"-expect-alpn", "foo",
+			"-renegotiate-freely",
+		},
+		renegotiate:   1,
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// The server may send different stapled OCSP responses or SCT lists on
+	// renegotiation, but BoringSSL ignores this and reports the old values.
+	// Also test that non-fatal verify results are preserved.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Renegotiation-ChangeAuthProperties",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
+			Bugs: ProtocolBugs{
+				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
+				SendSCTListOnRenegotiation:      testSCTList2,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64FlagValue(testOCSPResponse),
+			"-enable-signed-cert-timestamps",
+			"-expect-signed-cert-timestamps",
+			base64FlagValue(testSCTList),
+			"-verify-fail",
+			"-expect-verify-result",
+		},
+	})
+}
diff --git a/src/ssl/test/runner/resumption_tests.go b/src/ssl/test/runner/resumption_tests.go
new file mode 100644
index 0000000..63e609c
--- /dev/null
+++ b/src/ssl/test/runner/resumption_tests.go
@@ -0,0 +1,1082 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"time"
+)
+
+func addResumptionVersionTests() {
+	for _, sessionVers := range tlsVersions {
+		for _, resumeVers := range tlsVersions {
+			protocols := []protocol{tls}
+			if sessionVers.hasDTLS && resumeVers.hasDTLS {
+				protocols = append(protocols, dtls)
+			}
+			if sessionVers.hasQUIC && resumeVers.hasQUIC {
+				protocols = append(protocols, quic)
+			}
+			for _, protocol := range protocols {
+				suffix := "-" + sessionVers.name + "-" + resumeVers.name
+				suffix += "-" + protocol.String()
+
+				if sessionVers.version == resumeVers.version {
+					testCases = append(testCases, testCase{
+						protocol:      protocol,
+						name:          "Resume-Client" + suffix,
+						resumeSession: true,
+						config: Config{
+							MaxVersion: sessionVers.version,
+							Bugs: ProtocolBugs{
+								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
+							},
+						},
+						expectations: connectionExpectations{
+							version: sessionVers.version,
+						},
+						resumeExpectations: &connectionExpectations{
+							version: resumeVers.version,
+						},
+					})
+				} else if protocol != tls && sessionVers.version >= VersionTLS13 && resumeVers.version < VersionTLS13 {
+					// In TLS 1.2 and below, the server indicates resumption by echoing
+					// the client's session ID, which is impossible if the client did
+					// not send a session ID. If the client offers a TLS 1.3 session, it
+					// only fills in session ID in TLS (not DTLS or QUIC) for middlebox
+					// compatibility mode. So, instead, test that the session ID was
+					// empty and it was indeed impossible to hit this path
+					testCases = append(testCases, testCase{
+						protocol:      protocol,
+						name:          "Resume-Client-Impossible" + suffix,
+						resumeSession: true,
+						config: Config{
+							MaxVersion: sessionVers.version,
+						},
+						expectations: connectionExpectations{
+							version: sessionVers.version,
+						},
+						resumeConfig: &Config{
+							MaxVersion: resumeVers.version,
+							Bugs: ProtocolBugs{
+								ExpectNoSessionID: true,
+							},
+						},
+						resumeExpectations: &connectionExpectations{
+							version: resumeVers.version,
+						},
+						expectResumeRejected: true,
+					})
+				} else {
+					// Test that the client rejects ServerHellos which resume
+					// sessions at inconsistent versions.
+					expectedError := ":OLD_SESSION_VERSION_NOT_RETURNED:"
+					if sessionVers.version < VersionTLS13 && resumeVers.version >= VersionTLS13 {
+						// The server will "resume" the session by sending pre_shared_key,
+						// but the shim will not have sent pre_shared_key at all. The shim
+						// should reject this because the extension was not allowed at all.
+						expectedError = ":UNEXPECTED_EXTENSION:"
+					}
+
+					testCases = append(testCases, testCase{
+						protocol:      protocol,
+						name:          "Resume-Client-Mismatch" + suffix,
+						resumeSession: true,
+						config: Config{
+							MaxVersion: sessionVers.version,
+						},
+						expectations: connectionExpectations{
+							version: sessionVers.version,
+						},
+						resumeConfig: &Config{
+							MaxVersion: resumeVers.version,
+							Bugs: ProtocolBugs{
+								AcceptAnySession: true,
+							},
+						},
+						resumeExpectations: &connectionExpectations{
+							version: resumeVers.version,
+						},
+						shouldFail:    true,
+						expectedError: expectedError,
+					})
+				}
+
+				testCases = append(testCases, testCase{
+					protocol:      protocol,
+					name:          "Resume-Client-NoResume" + suffix,
+					resumeSession: true,
+					config: Config{
+						MaxVersion: sessionVers.version,
+					},
+					expectations: connectionExpectations{
+						version: sessionVers.version,
+					},
+					resumeConfig: &Config{
+						MaxVersion: resumeVers.version,
+					},
+					newSessionsOnResume:  true,
+					expectResumeRejected: true,
+					resumeExpectations: &connectionExpectations{
+						version: resumeVers.version,
+					},
+				})
+
+				testCases = append(testCases, testCase{
+					protocol:      protocol,
+					testType:      serverTest,
+					name:          "Resume-Server" + suffix,
+					resumeSession: true,
+					config: Config{
+						MaxVersion: sessionVers.version,
+					},
+					expectations: connectionExpectations{
+						version: sessionVers.version,
+					},
+					expectResumeRejected: sessionVers != resumeVers,
+					resumeConfig: &Config{
+						MaxVersion: resumeVers.version,
+						Bugs: ProtocolBugs{
+							SendBothTickets: true,
+						},
+					},
+					resumeExpectations: &connectionExpectations{
+						version: resumeVers.version,
+					},
+				})
+
+				// Repeat the test using session IDs, rather than tickets.
+				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
+					testCases = append(testCases, testCase{
+						protocol:      protocol,
+						testType:      serverTest,
+						name:          "Resume-Server-NoTickets" + suffix,
+						resumeSession: true,
+						config: Config{
+							MaxVersion:             sessionVers.version,
+							SessionTicketsDisabled: true,
+						},
+						expectations: connectionExpectations{
+							version: sessionVers.version,
+						},
+						expectResumeRejected: sessionVers != resumeVers,
+						resumeConfig: &Config{
+							MaxVersion:             resumeVers.version,
+							SessionTicketsDisabled: true,
+						},
+						resumeExpectations: &connectionExpectations{
+							version: resumeVers.version,
+						},
+					})
+				}
+			}
+		}
+	}
+
+	// Make sure shim ticket mutations are functional.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "ShimTicketRewritable",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					in, err := SetShimTicketVersion(in, VersionTLS12)
+					if err != nil {
+						return nil, err
+					}
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+	})
+
+	// Resumptions are declined if the version does not match.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineCrossVersion",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketVersion(in, VersionTLS13)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineCrossVersion-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketVersion(in, VersionTLS12)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// Resumptions are declined if the cipher is invalid or disabled.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher-2",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
+				},
+			},
+		},
+		flags: []string{
+			"-cipher", "AES128",
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// Sessions are not resumed if they do not use the preferred cipher.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-CipherNotPreferred",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		shouldFail:           false,
+		expectResumeRejected: true,
+	})
+
+	// TLS 1.3 allows sessions to be resumed at a different cipher if their
+	// PRF hashes match, but BoringSSL will always decline such resumptions.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-CipherNotPreferred-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					// If the client (runner) offers ChaCha20-Poly1305 first, the
+					// server (shim) always prefers it. Switch it to AES-GCM.
+					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		shouldFail:           false,
+		expectResumeRejected: true,
+	})
+
+	// Sessions may not be resumed if they contain another version's cipher.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64FlagValue(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// If the client does not offer the cipher from the session, decline to
+	// resume. Clients are forbidden from doing this, but BoringSSL selects
+	// the cipher first, so we only decline.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			},
+		},
+		expectResumeRejected: true,
+	})
+
+	// In TLS 1.3, clients may advertise a cipher list which does not
+	// include the selected cipher. Test that we tolerate this. Servers may
+	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
+	// BoringSSL will always decline.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+			},
+		},
+		expectResumeRejected: true,
+	})
+
+	// Sessions may not be resumed at a different cipher.
+	testCases = append(testCases, testCase{
+		name:          "Resume-Client-CipherMismatch",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
+	})
+
+	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
+	// matches.
+	testCases = append(testCases, testCase{
+		name:          "Resume-Client-CipherMismatch-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+		},
+	})
+
+	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
+	testCases = append(testCases, testCase{
+		name:          "Resume-Client-PRFMismatch-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_AES_256_GCM_SHA384,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
+	})
+
+	for _, secondBinder := range []bool{false, true} {
+		var suffix string
+		var defaultCurves []CurveID
+		if secondBinder {
+			suffix = "-SecondBinder"
+			// Force a HelloRetryRequest by predicting an empty curve list.
+			defaultCurves = []CurveID{}
+		}
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-BinderWrongLength" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					SendShortPSKBinder:         true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decrypting message",
+			expectedError:      ":DIGEST_CHECK_FAILED:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-NoPSKBinder" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					SendNoPSKBinder:            true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decoding message",
+			expectedError:      ":DECODE_ERROR:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-ExtraPSKBinder" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					SendExtraPSKBinder:         true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: illegal parameter",
+			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					ExtraPSKIdentity:           true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: illegal parameter",
+			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-InvalidPSKBinder" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					SendInvalidPSKBinder:       true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decrypting message",
+			expectedError:      ":DIGEST_CHECK_FAILED:",
+		})
+
+		testCases = append(testCases, testCase{
+			testType:      serverTest,
+			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
+			resumeSession: true,
+			config: Config{
+				MaxVersion:    VersionTLS13,
+				DefaultCurves: defaultCurves,
+				Bugs: ProtocolBugs{
+					PSKBinderFirst:             true,
+					OnlyCorruptSecondPSKBinder: secondBinder,
+				},
+			},
+			shouldFail:         true,
+			expectedLocalError: "remote error: illegal parameter",
+			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
+		})
+	}
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				OmitPSKsOnSecondClientHello: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
+	})
+}
+
+func addSessionTicketTests() {
+	testCases = append(testCases, testCase{
+		// In TLS 1.2 and below, empty NewSessionTicket messages
+		// mean the server changed its mind on sending a ticket.
+		name: "SendEmptySessionTicket-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendEmptySessionTicket: true,
+			},
+		},
+		flags: []string{"-expect-no-session"},
+	})
+
+	testCases = append(testCases, testCase{
+		// In TLS 1.3, empty NewSessionTicket messages are not
+		// allowed.
+		name: "SendEmptySessionTicket-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEmptySessionTicket: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	// Test that the server ignores unknown PSK modes.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-SendUnknownModeSessionTicket-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
+			},
+		},
+		resumeSession: true,
+		expectations: connectionExpectations{
+			version: VersionTLS13,
+		},
+	})
+
+	// Test that the server does not send session tickets with no matching key exchange mode.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes:  []byte{0x1a},
+				ExpectNoNewSessionTicket: true,
+			},
+		},
+	})
+
+	// Test that the server does not accept a session with no matching key exchange mode.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-SendBadKEModeSessionTicket-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes: []byte{0x1a},
+			},
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+
+	// Test that the server rejects ClientHellos with pre_shared_key but without
+	// psk_key_exchange_modes.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-SendNoKEMModesWithPSK-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes: []byte{},
+			},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedLocalError: "remote error: missing extension",
+		expectedError:      ":MISSING_EXTENSION:",
+	})
+
+	// Test that the client ticket age is sent correctly.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-TestValidTicketAge-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketAge: 10 * time.Second,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+		},
+	})
+
+	// Test that the client ticket age is enforced.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-TestBadTicketAge-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketAge: 1000 * time.Second,
+			},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedLocalError: "tls: invalid ticket age",
+	})
+
+	// Test that the server's ticket age skew reporting works.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Forward",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 15 * time.Second,
+			},
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "5",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Backward",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 5 * time.Second,
+			},
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "-5",
+		},
+	})
+
+	// Test that ticket age skew up to 60 seconds in either direction is accepted.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 70 * time.Second,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "60",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 10 * time.Second,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-resumption-delay", "70",
+			"-expect-ticket-age-skew", "-60",
+		},
+	})
+
+	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 71 * time.Second,
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "61",
+			"-on-resume-expect-early-data-reason", "ticket_age_skew",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 10 * time.Second,
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-resumption-delay", "71",
+			"-expect-ticket-age-skew", "-61",
+			"-on-resume-expect-early-data-reason", "ticket_age_skew",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-SendTicketEarlyDataSupport",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		flags: []string{
+			"-enable-early-data",
+			"-expect-ticket-supports-early-data",
+		},
+	})
+
+	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		flags: []string{
+			"-expect-ticket-supports-early-data",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DuplicateTicketEarlyDataSupport",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				DuplicateTicketEarlyData: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-ExpectTicketEarlyDataSupport",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketEarlyData: true,
+			},
+		},
+		flags: []string{
+			"-enable-early-data",
+		},
+	})
+
+	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
+	// is honored.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-HonorServerSessionTicketLifetime",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketLifetime: 20 * time.Second,
+			},
+		},
+		flags: []string{
+			"-resumption-delay", "19",
+		},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-HonorServerSessionTicketLifetime-2",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketLifetime: 20 * time.Second,
+				// The client should not offer the expired session.
+				ExpectNoTLS13PSK: true,
+			},
+		},
+		flags: []string{
+			"-resumption-delay", "21",
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+
+	for _, ver := range tlsVersions {
+		// Prior to TLS 1.3, disabling session tickets enables session IDs.
+		useStatefulResumption := ver.version < VersionTLS13
+
+		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-NoTicket-NoMint",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					ExpectNoNewSessionTicket: true,
+					RequireSessionIDs:        useStatefulResumption,
+				},
+			},
+			resumeSession: useStatefulResumption,
+			flags:         []string{"-no-ticket"},
+		})
+
+		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-NoTicket-NoAccept",
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+			// Set SSL_OP_NO_TICKET on the second connection, after the first
+			// has established tickets.
+			flags: []string{"-on-resume-no-ticket"},
+		})
+
+		// SSL_OP_NO_TICKET implies the client must not offer ticket-based
+		// sessions. The client not only should not send the session ticket
+		// extension, but if the server echos the session ID, the client should
+		// reject this.
+		if ver.version < VersionTLS13 {
+			testCases = append(testCases, testCase{
+				name: ver.name + "-NoTicket-NoOffer",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				resumeConfig: &Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectNoTLS12TicketSupport: true,
+						// Pretend to accept the session, even though the client
+						// did not offer it. The client should reject this as
+						// invalid. A buggy client will still fail because it
+						// expects resumption, but with a different error.
+						// Ideally, we would test this by actually resuming the
+						// previous session, even though the client did not
+						// provide a ticket.
+						EchoSessionIDInFullHandshake: true,
+					},
+				},
+				resumeSession:        true,
+				expectResumeRejected: true,
+				// Set SSL_OP_NO_TICKET on the second connection, after the first
+				// has established tickets.
+				flags:              []string{"-on-resume-no-ticket"},
+				shouldFail:         true,
+				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
+				expectedLocalError: "remote error: illegal parameter",
+			})
+		}
+
+		// Test ticket flags.
+		if ver.version >= VersionTLS13 {
+			// The client should parse and ignore unknown ticket flags. 2039
+			// is the highest possible flag number (8*255 flags total).
+			for i, flags := range [][]uint{{1}, {31}, {100}, {2039}, {1, 31, 100, 2039}} {
+				testCases = append(testCases, testCase{
+					name: fmt.Sprintf("%s-Client-UnknownTicketFlags-%d", ver.name, i),
+					config: Config{
+						MinVersion: ver.version,
+						MaxVersion: ver.version,
+						Bugs: ProtocolBugs{
+							SendTicketFlags: flags,
+						},
+					},
+				})
+				testCases = append(testCases, testCase{
+					name: fmt.Sprintf("%s-Client-KnownAndUnknownTicketFlags-%d", ver.name, i),
+					config: Config{
+						MinVersion:            ver.version,
+						MaxVersion:            ver.version,
+						ResumptionAcrossNames: true,
+						Bugs: ProtocolBugs{
+							SendTicketFlags: flags,
+						},
+					},
+					flags: []string{"-expect-resumable-across-names"},
+				})
+			}
+
+			// The client should reject invalid ticket flag extensions.
+			testCases = append(testCases, testCase{
+				name: ver.name + "-Client-NonminimalTicketFlags",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendTicketFlags:   []uint{1},
+						TicketFlagPadding: 1,
+					},
+				},
+				shouldFail:         true,
+				expectedError:      ":DECODE_ERROR:",
+				expectedLocalError: "remote error: illegal parameter",
+			})
+			testCases = append(testCases, testCase{
+				name: ver.name + "-Client-EmptyTicketFlags",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						AlwaysSendTicketFlags: true,
+					},
+				},
+				shouldFail:         true,
+				expectedError:      ":DECODE_ERROR:",
+				expectedLocalError: "remote error: error decoding message",
+			})
+
+			// The client should parse the resumption_across_names flag.
+			testCases = append(testCases, testCase{
+				name: ver.name + "-Client-NoResumptionAcrossNames",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				flags: []string{"-expect-not-resumable-across-names"},
+			})
+			testCases = append(testCases, testCase{
+				name: ver.name + "-Client-ResumptionAcrossNames",
+				config: Config{
+					MinVersion:            ver.version,
+					MaxVersion:            ver.version,
+					ResumptionAcrossNames: true,
+				},
+				flags: []string{"-expect-resumable-across-names"},
+			})
+
+			// The server should offer resumption_across_names as configured.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     ver.name + "-Server-NoResumptionAcrossNames",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectResumptionAcrossNames: ptrTo(false),
+					},
+				},
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     ver.name + "-Server-ResumptionAcrossNames",
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						ExpectResumptionAcrossNames: ptrTo(true),
+					},
+				},
+				flags: []string{"-resumption-across-names-enabled"},
+			})
+		}
+	}
+}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 2a52dfd..968b9bc 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -19,11 +19,8 @@
 	"crypto"
 	"crypto/ecdsa"
 	"crypto/ed25519"
-	"crypto/elliptic"
-	"crypto/rand"
 	"crypto/rsa"
 	"crypto/x509"
-	"crypto/x509/pkix"
 	_ "embed"
 	"encoding/base64"
 	"encoding/binary"
@@ -34,7 +31,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"math/big"
 	"net"
 	"os"
 	"os/exec"
@@ -47,7 +43,6 @@
 	"syscall"
 	"time"
 
-	"boringssl.googlesource.com/boringssl.git/ssl/test/runner/hpke"
 	"boringssl.googlesource.com/boringssl.git/util/testresult"
 	"golang.org/x/crypto/cryptobyte"
 )
@@ -94,7 +89,7 @@
 	// string for the shim in question. For example, it might map
 	// “:NO_SHARED_CIPHER:” (a BoringSSL error string) to something
 	// like “SSL_ERROR_NO_CYPHER_OVERLAP”.
-	ErrorMap map[string]string
+	ErrorMap map[string][]string
 
 	// HalfRTTTickets is the number of half-RTT tickets the client should
 	// expect before half-RTT data when testing 0-RTT.
@@ -231,18 +226,21 @@
 
 func initCertificates() {
 	for _, def := range []struct {
-		key crypto.Signer
-		out *Credential
+		name string
+		key  crypto.Signer
+		out  *Credential
 	}{
-		{&rsa1024Key, &rsa1024Certificate},
-		{&rsa2048Key, &rsaCertificate},
-		{&ecdsaP224Key, &ecdsaP224Certificate},
-		{&ecdsaP256Key, &ecdsaP256Certificate},
-		{&ecdsaP384Key, &ecdsaP384Certificate},
-		{&ecdsaP521Key, &ecdsaP521Certificate},
-		{ed25519Key, &ed25519Certificate},
+		{"Test RSA-1024 Cert", &rsa1024Key, &rsa1024Certificate},
+		{"Test RSA-2048 Cert", &rsa2048Key, &rsaCertificate},
+		{"Test ECDSA P-224 Cert", &ecdsaP224Key, &ecdsaP224Certificate},
+		{"Test ECDSA P-256 Cert", &ecdsaP256Key, &ecdsaP256Certificate},
+		{"Test ECDSA P-384 Cert", &ecdsaP384Key, &ecdsaP384Certificate},
+		{"Test ECDSA P-521 Cert", &ecdsaP521Key, &ecdsaP521Certificate},
+		{"Test Ed25519 Cert", ed25519Key, &ed25519Certificate},
 	} {
-		*def.out = generateSingleCertChain(nil, def.key)
+		template := *baseCertTemplate
+		template.Subject.CommonName = def.name
+		*def.out = generateSingleCertChain(&template, def.key)
 	}
 
 	channelIDBytes = make([]byte, 64)
@@ -267,12 +265,13 @@
 	rootCertPath, chainPath := writeTempCertFile([]*x509.Certificate{rootCert}), writeTempCertFile([]*x509.Certificate{leafCert, intermediateCert})
 
 	rsaChainCertificate = Credential{
-		Certificate: [][]byte{leafCert.Raw, intermediateCert.Raw},
-		PrivateKey:  &rsa2048Key,
-		Leaf:        leafCert,
-		ChainPath:   chainPath,
-		KeyPath:     keyPath,
-		RootPath:    rootCertPath,
+		Certificate:     [][]byte{leafCert.Raw, intermediateCert.Raw},
+		RootCertificate: rootCert.Raw,
+		PrivateKey:      &rsa2048Key,
+		Leaf:            leafCert,
+		ChainPath:       chainPath,
+		KeyPath:         keyPath,
+		RootPath:        rootCertPath,
 	}
 }
 
@@ -292,21 +291,6 @@
 	return *useGDB || *useLLDB || *useRR || *waitForDebugger
 }
 
-// delegatedCredentialConfig specifies the shape of a delegated credential, not
-// including the keys themselves.
-type delegatedCredentialConfig struct {
-	// lifetime is the amount of time, from the notBefore of the parent
-	// certificate, that the delegated credential is valid for. If zero, then 24
-	// hours is assumed.
-	lifetime time.Duration
-	// dcAlgo is the signature scheme that should be used with this delegated
-	// credential. If zero, ECDSA with P-256 is assumed.
-	dcAlgo signatureAlgorithm
-	// algo is the signature algorithm that the delegated credential itself is
-	// signed with. Cannot be zero.
-	algo signatureAlgorithm
-}
-
 func loadPEMKey(pemBytes []byte) (crypto.PrivateKey, error) {
 	block, _ := pem.Decode(pemBytes)
 	if block == nil {
@@ -325,81 +309,6 @@
 	return k, nil
 }
 
-func createDelegatedCredential(parent *Credential, config delegatedCredentialConfig) *Credential {
-	if parent.Type != CredentialTypeX509 {
-		panic("delegated credentials must be issued by X.509 credentials")
-	}
-
-	dcAlgo := config.dcAlgo
-	if dcAlgo == 0 {
-		dcAlgo = signatureECDSAWithP256AndSHA256
-	}
-
-	var dcPriv crypto.Signer
-	switch dcAlgo {
-	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
-		dcPriv = &rsa2048Key
-
-	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
-		var curve elliptic.Curve
-		switch dcAlgo {
-		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
-			curve = elliptic.P256()
-		case signatureECDSAWithP384AndSHA384:
-			curve = elliptic.P384()
-		case signatureECDSAWithP521AndSHA512:
-			curve = elliptic.P521()
-		default:
-			panic("internal error")
-		}
-
-		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
-		if err != nil {
-			panic(err)
-		}
-		dcPriv = priv
-
-	default:
-		panic(fmt.Errorf("unsupported DC signature algorithm: %x", dcAlgo))
-	}
-
-	lifetime := config.lifetime
-	if lifetime == 0 {
-		lifetime = 24 * time.Hour
-	}
-	lifetimeSecs := int64(lifetime.Seconds())
-	if lifetimeSecs < 0 || lifetimeSecs > 1<<32 {
-		panic(fmt.Errorf("lifetime %s is too long to be expressed", lifetime))
-	}
-
-	// https://www.rfc-editor.org/rfc/rfc9345.html#section-4
-	dc := cryptobyte.NewBuilder(nil)
-	dc.AddUint32(uint32(lifetimeSecs))
-	dc.AddUint16(uint16(dcAlgo))
-
-	pubBytes, err := x509.MarshalPKIXPublicKey(dcPriv.Public())
-	if err != nil {
-		panic(err)
-	}
-	addUint24LengthPrefixedBytes(dc, pubBytes)
-
-	var dummyConfig Config
-	parentSignature, err := signMessage(false /* server */, VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
-	if err != nil {
-		panic(err)
-	}
-
-	dc.AddUint16(uint16(config.algo))
-	addUint16LengthPrefixedBytes(dc, parentSignature)
-
-	dcCred := *parent
-	dcCred.Type = CredentialTypeDelegated
-	dcCred.DelegatedCredential = dc.BytesOrPanic()
-	dcCred.PrivateKey = dcPriv
-	dcCred.KeyPath = writeTempKeyFile(dcPriv)
-	return &dcCred
-}
-
 // recordVersionToWire maps a record-layer protocol version to its wire
 // representation.
 func recordVersionToWire(vers uint16, protocol protocol) uint16 {
@@ -1446,16 +1355,42 @@
 	return nil
 }
 
-func translateExpectedError(errorStr string) string {
-	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
+// translateExpectedError uses a canonical BoringSSL error to produce
+// a slice of expected canonical errors in bogo_shim_config.json.
+func translateExpectedError(canonical string) []string {
+	if translated, found := shimConfig.ErrorMap[canonical]; found {
 		return translated
 	}
 
-	if *looseErrors {
-		return ""
-	}
+	// not specifying a canonical error will have the same effect as -loose-errors being true
+	// since the emptry string with match all error substrings.
+	return []string{canonical}
+}
 
-	return errorStr
+// formatErrors takes the semantic mapping from translateExpectedError
+// and outputs human-readable digest of BoGo error state.
+func formatErrors(expectedErrors []string, stderr, local, child, stdout, expectedLocal, expectedCanonical string) (string, string) {
+	got := fmt.Sprintf("\tstderr:\n\t\t%s\n\tlocal: %q\n\tchild: %q\n\tstdout: %s", stderr, local, child, stdout)
+	want := fmt.Sprintf("\tlocal: %q\n\tremote: %q", expectedLocal, expectedCanonical)
+	if slices.Equal(expectedErrors, []string{expectedCanonical}) {
+		return got, want
+	}
+	if len(expectedErrors) == 0 || expectedErrors == nil {
+		return got, want + " (no specified mapping)"
+	}
+	return got, want + " mapped to one of:\n\t\t" + strings.Join(expectedErrors, "\n\t\t")
+}
+
+// matchError plucks the relevant canonical error from the provided
+// slice if found; if the slice is empty/nil, strict error checking
+// is presumed to be disabled.
+func matchError(expectedErrors []string, stderr string) bool {
+	for _, expectedError := range expectedErrors {
+		if strings.Contains(stderr, expectedError) {
+			return true
+		}
+	}
+	return false
 }
 
 // shimInitialWrite is the data we expect from the shim when the
@@ -1496,6 +1431,9 @@
 		flags = append(flags, prefix+"-signing-prefs", strconv.Itoa(int(sigAlg)))
 	}
 	handleBase64Field("delegated-credential", cred.DelegatedCredential)
+	if cred.MustMatchIssuer {
+		flags = append(flags, prefix+"-must-match-issuer")
+	}
 	handleBase64Field("pake-context", cred.PAKEContext)
 	handleBase64Field("pake-client-id", cred.PAKEClientID)
 	handleBase64Field("pake-server-id", cred.PAKEServerID)
@@ -1503,6 +1441,7 @@
 	if cred.WrongPAKERole {
 		flags = append(flags, prefix+"-wrong-pake-role")
 	}
+	handleBase64Field("trust-anchor-id", cred.TrustAnchorID)
 	return flags
 }
 
@@ -1519,6 +1458,9 @@
 	if len(*shimExtraFlags) > 0 {
 		flags = strings.Split(*shimExtraFlags, ";")
 	}
+	if *fuzzer {
+		flags = append(flags, "-fuzzer-mode")
+	}
 	if test.testType == serverTest {
 		flags = append(flags, "-server")
 	}
@@ -1800,8 +1742,8 @@
 	}
 
 	failed := localErr != nil || childErr != nil
-	expectedError := translateExpectedError(test.expectedError)
-	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
+	expectedErrors := translateExpectedError(test.expectedError)
+	correctFailure := *looseErrors || matchError(expectedErrors, stderr)
 
 	localErrString := "none"
 	if localErr != nil {
@@ -1817,21 +1759,25 @@
 			childErrString = childErr.Error()
 		}
 
+		got, want := formatErrors(expectedErrors,
+			stderr, localErrString, childErrString, stdout,
+			test.expectedLocalError, test.expectedError)
+
 		var msg string
 		switch {
 		case failed && !test.shouldFail:
-			msg = "unexpected failure"
+			msg = fmt.Sprintf("unexpected failure\ngot:\n%s\n", got)
 		case !failed && test.shouldFail:
-			msg = fmt.Sprintf("unexpected success (wanted failure with %q / %q)", expectedError, test.expectedLocalError)
+			msg = fmt.Sprintf("unexpected success\nwant:\n%s\n", want)
 		case failed && !correctFailure:
-			msg = fmt.Sprintf("bad error (wanted %q / %q)", expectedError, test.expectedLocalError)
+			msg = fmt.Sprintf("unexpected error\ngot:\n%s\n\nwant:\n%s\n", got, want)
 		case mustFail:
 			msg = "test failure"
 		default:
 			panic("internal error")
 		}
 
-		return fmt.Errorf("%s: local error %q, child error %q, stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
+		return fmt.Errorf("%s\nextra stderr:\n%s", msg, extraStderr)
 	}
 
 	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
@@ -1939,61 +1885,6 @@
 	return ret
 }
 
-type testCipherSuite struct {
-	name string
-	id   uint16
-}
-
-var testCipherSuites = []testCipherSuite{
-	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
-	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
-	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
-	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
-	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
-	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
-	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
-	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
-	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
-	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-	{"ECDHE_RSA_WITH_AES_128_CBC_SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
-	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
-	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
-	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
-	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
-	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
-	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
-	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
-	{"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},
-}
-
-func hasComponent(suiteName, component string) bool {
-	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
-}
-
-func isTLS12Only(suiteName string) bool {
-	return hasComponent(suiteName, "GCM") ||
-		hasComponent(suiteName, "SHA256") ||
-		hasComponent(suiteName, "SHA384") ||
-		hasComponent(suiteName, "POLY1305")
-}
-
-func isTLS13Suite(suiteName string) bool {
-	return !hasComponent(suiteName, "WITH")
-}
-
-func bigFromHex(hex string) *big.Int {
-	ret, ok := new(big.Int).SetString(hex, 16)
-	if !ok {
-		panic("failed to parse hex number 0x" + hex)
-	}
-	return ret
-}
-
 func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
 	var stdout bytes.Buffer
 	var flags []string
@@ -2077,21312 +1968,6 @@
 	return splitHandshakeTests, nil
 }
 
-func addBasicTests() {
-	basicTests := []testCase{
-		{
-			name: "NoFallbackSCSV",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FailIfNotFallbackSCSV: true,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "no fallback SCSV found",
-		},
-		{
-			name: "SendFallbackSCSV",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FailIfNotFallbackSCSV: true,
-				},
-			},
-			flags: []string{"-fallback-scsv"},
-		},
-		{
-			name: "ClientCertificateTypes",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequestClientCert,
-				ClientCertificateTypes: []byte{
-					CertTypeDSSSign,
-					CertTypeRSASign,
-					CertTypeECDSASign,
-				},
-			},
-			flags: []string{
-				"-expect-certificate-types",
-				base64FlagValue([]byte{
-					CertTypeDSSSign,
-					CertTypeRSASign,
-					CertTypeECDSASign,
-				}),
-			},
-		},
-		{
-			name: "CheckClientCertificateTypes",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				ClientAuth:             RequestClientCert,
-				ClientCertificateTypes: []byte{CertTypeECDSASign},
-			},
-			shimCertificate: &rsaCertificate,
-			shouldFail:      true,
-			expectedError:   ":UNKNOWN_CERTIFICATE_TYPE:",
-		},
-		{
-			name: "UnauthenticatedECDH",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					UnauthenticatedECDH: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_MESSAGE:",
-		},
-		{
-			name: "SkipCertificateStatus",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					SkipCertificateStatus: true,
-				},
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				// This test involves an optional message. Test the message callback
-				// trace to ensure we do not miss or double-report any.
-				"-expect-msg-callback",
-				`write hs 1
-read hs 2
-read hs 11
-read hs 12
-read hs 14
-write hs 16
-write ccs
-write hs 20
-read hs 4
-read ccs
-read hs 20
-read alert 1 0
-`,
-			},
-		},
-		{
-			protocol: dtls,
-			name:     "SkipCertificateStatus-DTLS",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					SkipCertificateStatus: true,
-				},
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				// This test involves an optional message. Test the message callback
-				// trace to ensure we do not miss or double-report any.
-				"-expect-msg-callback",
-				`write hs 1
-read hs 3
-write hs 1
-read hs 2
-read hs 11
-read hs 12
-read hs 14
-write hs 16
-write ccs
-write hs 20
-read hs 4
-read ccs
-read hs 20
-read alert 1 0
-`,
-			},
-		},
-		{
-			name: "SkipServerKeyExchange",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					SkipServerKeyExchange: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_MESSAGE:",
-		},
-		{
-			testType: serverTest,
-			name:     "ServerSkipCertificateVerify",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Credential: &rsaCertificate,
-				Bugs: ProtocolBugs{
-					SkipCertificateVerify: true,
-				},
-			},
-			expectations: connectionExpectations{
-				peerCertificate: &rsaCertificate,
-			},
-			flags: []string{
-				"-require-any-client-certificate",
-			},
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_RECORD:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			testType: serverTest,
-			name:     "Alert",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "Alert-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
-		},
-		{
-			testType: serverTest,
-			name:     "FragmentAlert",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FragmentAlert:     true,
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_ALERT:",
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "FragmentAlert-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FragmentAlert:     true,
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_ALERT:",
-		},
-		{
-			testType: serverTest,
-			name:     "DoubleAlert",
-			config: Config{
-				Bugs: ProtocolBugs{
-					DoubleAlert:       true,
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_ALERT:",
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "DoubleAlert-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					DoubleAlert:       true,
-					SendSpuriousAlert: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_ALERT:",
-		},
-		{
-			name: "SkipNewSessionTicket",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SkipNewSessionTicket: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType: serverTest,
-			name:     "FallbackSCSV",
-			config: Config{
-				MaxVersion: VersionTLS11,
-				Bugs: ProtocolBugs{
-					SendFallbackSCSV: true,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":INAPPROPRIATE_FALLBACK:",
-			expectedLocalError: "remote error: inappropriate fallback",
-		},
-		{
-			testType: serverTest,
-			name:     "FallbackSCSV-VersionMatch-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendFallbackSCSV: true,
-				},
-			},
-		},
-		{
-			testType: serverTest,
-			name:     "FallbackSCSV-VersionMatch-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendFallbackSCSV: true,
-				},
-			},
-			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-		},
-		// Regression test for CVE-2014-3511. Even when the ClientHello is
-		// maximally fragmented, version negotiation works correctly.
-		{
-			testType: serverTest,
-			name:     "FragmentedClientVersion",
-			config: Config{
-				Bugs: ProtocolBugs{
-					MaxHandshakeRecordLength: 1,
-				},
-			},
-			expectations: connectionExpectations{
-				version: VersionTLS13,
-			},
-		},
-		{
-			testType:      serverTest,
-			name:          "HttpGET",
-			sendPrefix:    "GET / HTTP/1.0\n",
-			shouldFail:    true,
-			expectedError: ":HTTP_REQUEST:",
-		},
-		{
-			testType:      serverTest,
-			name:          "HttpPOST",
-			sendPrefix:    "POST / HTTP/1.0\n",
-			shouldFail:    true,
-			expectedError: ":HTTP_REQUEST:",
-		},
-		{
-			testType:      serverTest,
-			name:          "HttpHEAD",
-			sendPrefix:    "HEAD / HTTP/1.0\n",
-			shouldFail:    true,
-			expectedError: ":HTTP_REQUEST:",
-		},
-		{
-			testType:      serverTest,
-			name:          "HttpPUT",
-			sendPrefix:    "PUT / HTTP/1.0\n",
-			shouldFail:    true,
-			expectedError: ":HTTP_REQUEST:",
-		},
-		{
-			testType:      serverTest,
-			name:          "HttpCONNECT",
-			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
-			shouldFail:    true,
-			expectedError: ":HTTPS_PROXY_REQUEST:",
-		},
-		{
-			testType:      serverTest,
-			name:          "Garbage",
-			sendPrefix:    "blah",
-			shouldFail:    true,
-			expectedError: ":WRONG_VERSION_NUMBER:",
-		},
-		{
-			name: "RSAEphemeralKey",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-				Bugs: ProtocolBugs{
-					RSAEphemeralKey: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_MESSAGE:",
-		},
-		{
-			name:          "DisableEverything",
-			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
-			shouldFail:    true,
-			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
-		},
-		{
-			protocol:      dtls,
-			name:          "DisableEverything-DTLS",
-			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls1"},
-			shouldFail:    true,
-			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "MTU-DTLS12-AEAD",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					MaxPacketLength: 256,
-				},
-			},
-			flags: []string{"-mtu", "256"},
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "MTU-DTLS12-AES-CBC",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
-				Bugs: ProtocolBugs{
-					MaxPacketLength: 256,
-				},
-			},
-			flags: []string{"-mtu", "256"},
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "MTU-DTLS12-3DES-CBC",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
-				Bugs: ProtocolBugs{
-					MaxPacketLength: 256,
-				},
-			},
-			flags: []string{"-mtu", "256", "-cipher", "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "MTU-DTLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					MaxPacketLength: 256,
-				},
-			},
-			flags: []string{"-mtu", "256"},
-		},
-		{
-			name: "EmptyCertificateList",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					EmptyCertificateList: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECODE_ERROR:",
-		},
-		{
-			name: "EmptyCertificateList-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					EmptyCertificateList: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
-		},
-		{
-			name:             "TLSFatalBadPackets",
-			damageFirstWrite: true,
-			shouldFail:       true,
-			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-		},
-		{
-			protocol:         dtls,
-			name:             "DTLSIgnoreBadPackets",
-			damageFirstWrite: true,
-		},
-		{
-			protocol:         dtls,
-			name:             "DTLSIgnoreBadPackets-Async",
-			damageFirstWrite: true,
-			flags:            []string{"-async"},
-		},
-		{
-			name: "AppDataBeforeHandshake",
-			config: Config{
-				Bugs: ProtocolBugs{
-					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "AppDataBeforeHandshake-Empty",
-			config: Config{
-				Bugs: ProtocolBugs{
-					AppDataBeforeHandshake: []byte{},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataBeforeHandshake-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataBeforeHandshake-DTLS-Empty",
-			config: Config{
-				Bugs: ProtocolBugs{
-					AppDataBeforeHandshake: []byte{},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "AppDataBeforeTLS13KeyChange",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"),
-				},
-			},
-			// The shim should fail to decrypt this record.
-			shouldFail:         true,
-			expectedError:      ":BAD_DECRYPT:",
-			expectedLocalError: "remote error: bad record MAC",
-		},
-		{
-			name: "AppDataBeforeTLS13KeyChange-Empty",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AppDataBeforeTLS13KeyChange: []byte{},
-				},
-			},
-			// The shim should fail to decrypt this record.
-			shouldFail:         true,
-			expectedError:      ":BAD_DECRYPT:",
-			expectedLocalError: "remote error: bad record MAC",
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataBeforeTLS13KeyChange-DTLS",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"),
-				},
-			},
-			// The shim will decrypt the record, because it has not
-			// yet applied the key change, but it should know to
-			// reject the record.
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_RECORD:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataBeforeTLS13KeyChange-DTLS-Empty",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AppDataBeforeTLS13KeyChange: []byte{},
-				},
-			},
-			// The shim will decrypt the record, because it has not
-			// yet applied the key change, but it should know to
-			// reject the record.
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_RECORD:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			name: "UnencryptedEncryptedExtensions",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					UnencryptedEncryptedExtensions: true,
-				},
-			},
-			// The shim should fail to decrypt this record.
-			shouldFail:         true,
-			expectedError:      ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-			expectedLocalError: "remote error: bad record MAC",
-		},
-		{
-			protocol: dtls,
-			name:     "UnencryptedEncryptedExtensions-DTLS",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					UnencryptedEncryptedExtensions: true,
-				},
-			},
-			// The shim will decrypt the record, because it has not
-			// yet applied the key change, but it should know to
-			// reject new handshake data on the previous epoch.
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			name: "AppDataAfterChangeCipherSpec",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "AppDataAfterChangeCipherSpec-Empty",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AppDataAfterChangeCipherSpec: []byte{},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataAfterChangeCipherSpec-DTLS",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
-				},
-			},
-			// BoringSSL's DTLS implementation will drop the out-of-order
-			// application data.
-		},
-		{
-			protocol: dtls,
-			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AppDataAfterChangeCipherSpec: []byte{},
-				},
-			},
-			// BoringSSL's DTLS implementation will drop the out-of-order
-			// application data.
-		},
-		{
-			name: "AlertAfterChangeCipherSpec",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AlertAfterChangeCipherSpec: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
-		},
-		{
-			protocol: dtls,
-			name:     "AlertAfterChangeCipherSpec-DTLS",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					AlertAfterChangeCipherSpec: alertRecordOverflow,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
-		},
-		{
-			name: "SendInvalidRecordType",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendInvalidRecordType: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "SendInvalidRecordType-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendInvalidRecordType: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "FalseStart-SkipServerSecondLeg",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					SkipNewSessionTicket: true,
-					SkipChangeCipherSpec: true,
-					SkipFinished:         true,
-					ExpectFalseStart:     true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-handshake-never-done",
-				"-advertise-alpn", "\x03foo",
-				"-expect-alpn", "foo",
-			},
-			shimWritesFirst: true,
-			shouldFail:      true,
-			expectedError:   ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "FalseStart-SkipServerSecondLeg-Implicit",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					SkipNewSessionTicket: true,
-					SkipChangeCipherSpec: true,
-					SkipFinished:         true,
-				},
-			},
-			flags: []string{
-				"-implicit-handshake",
-				"-false-start",
-				"-handshake-never-done",
-				"-advertise-alpn", "\x03foo",
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType:           serverTest,
-			name:               "FailEarlyCallback",
-			flags:              []string{"-fail-early-callback"},
-			shouldFail:         true,
-			expectedError:      ":CONNECTION_REJECTED:",
-			expectedLocalError: "remote error: handshake failure",
-		},
-		{
-			name: "FailCertCallback-Client-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequestClientCert,
-			},
-			flags:              []string{"-fail-cert-callback"},
-			shouldFail:         true,
-			expectedError:      ":CERT_CB_ERROR:",
-			expectedLocalError: "remote error: internal error",
-		},
-		{
-			testType: serverTest,
-			name:     "FailCertCallback-Server-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			flags:              []string{"-fail-cert-callback"},
-			shouldFail:         true,
-			expectedError:      ":CERT_CB_ERROR:",
-			expectedLocalError: "remote error: internal error",
-		},
-		{
-			name: "FailCertCallback-Client-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				ClientAuth: RequestClientCert,
-			},
-			flags:              []string{"-fail-cert-callback"},
-			shouldFail:         true,
-			expectedError:      ":CERT_CB_ERROR:",
-			expectedLocalError: "remote error: internal error",
-		},
-		{
-			testType: serverTest,
-			name:     "FailCertCallback-Server-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			flags:              []string{"-fail-cert-callback"},
-			shouldFail:         true,
-			expectedError:      ":CERT_CB_ERROR:",
-			expectedLocalError: "remote error: internal error",
-		},
-		{
-			protocol: dtls,
-			name:     "FragmentMessageTypeMismatch-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-						f1 := next[0].Fragment(0, 1)
-						f2 := next[0].Fragment(1, 1)
-						f2.Type++
-						c.WriteFragments([]DTLSFragment{f1, f2})
-					},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":FRAGMENT_MISMATCH:",
-		},
-		{
-			protocol: dtls,
-			name:     "FragmentMessageLengthMismatch-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-						f1 := next[0].Fragment(0, 1)
-						f2 := next[0].Fragment(1, 1)
-						f2.TotalLength++
-						c.WriteFragments([]DTLSFragment{f1, f2})
-					},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":FRAGMENT_MISMATCH:",
-		},
-		{
-			protocol: dtls,
-			name:     "SplitFragments-Header-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SplitFragments: 2,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_HANDSHAKE_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "SplitFragments-Boundary-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SplitFragments: dtlsMaxRecordHeaderLen,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_HANDSHAKE_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "SplitFragments-Body-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SplitFragments: dtlsMaxRecordHeaderLen + 1,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_HANDSHAKE_RECORD:",
-		},
-		{
-			protocol: dtls,
-			name:     "SendEmptyFragments-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendEmptyFragments: true,
-				},
-			},
-		},
-		{
-			testType: serverTest,
-			protocol: dtls,
-			name:     "SendEmptyFragments-Padded-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					// Test empty fragments for a message with a
-					// nice power-of-two length.
-					PadClientHello:     64,
-					SendEmptyFragments: true,
-				},
-			},
-		},
-		{
-			name: "BadFinished-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					BadFinished: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DIGEST_CHECK_FAILED:",
-		},
-		{
-			name: "BadFinished-Client-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					BadFinished: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DIGEST_CHECK_FAILED:",
-		},
-		{
-			testType: serverTest,
-			name:     "BadFinished-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					BadFinished: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DIGEST_CHECK_FAILED:",
-		},
-		{
-			testType: serverTest,
-			name:     "BadFinished-Server-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					BadFinished: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DIGEST_CHECK_FAILED:",
-		},
-		{
-			name: "FalseStart-BadFinished",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					BadFinished:      true,
-					ExpectFalseStart: true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-handshake-never-done",
-				"-advertise-alpn", "\x03foo",
-				"-expect-alpn", "foo",
-			},
-			shimWritesFirst: true,
-			shouldFail:      true,
-			expectedError:   ":DIGEST_CHECK_FAILED:",
-		},
-		{
-			name: "NoFalseStart-NoALPN",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart:          true,
-					AlertBeforeFalseStartTest: alertAccessDenied,
-				},
-			},
-			flags: []string{
-				"-false-start",
-			},
-			shimWritesFirst:    true,
-			shouldFail:         true,
-			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
-			expectedLocalError: "tls: peer did not false start: EOF",
-		},
-		{
-			name: "FalseStart-NoALPNAllowed",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart: true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-allow-false-start-without-alpn",
-			},
-			shimWritesFirst: true,
-		},
-		{
-			name: "NoFalseStart-NoAEAD",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart:          true,
-					AlertBeforeFalseStartTest: alertAccessDenied,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-advertise-alpn", "\x03foo",
-			},
-			shimWritesFirst:    true,
-			shouldFail:         true,
-			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
-			expectedLocalError: "tls: peer did not false start: EOF",
-		},
-		{
-			name: "NoFalseStart-RSA",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart:          true,
-					AlertBeforeFalseStartTest: alertAccessDenied,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-advertise-alpn", "\x03foo",
-			},
-			shimWritesFirst:    true,
-			shouldFail:         true,
-			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
-			expectedLocalError: "tls: peer did not false start: EOF",
-		},
-		{
-			protocol: dtls,
-			name:     "SendSplitAlert-Sync",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendSplitAlert: true,
-				},
-			},
-		},
-		{
-			protocol: dtls,
-			name:     "SendSplitAlert-Async",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendSplitAlert: true,
-				},
-			},
-			flags: []string{"-async"},
-		},
-		{
-			name:             "SendEmptyRecords-Pass",
-			sendEmptyRecords: 32,
-		},
-		{
-			name:             "SendEmptyRecords",
-			sendEmptyRecords: 33,
-			shouldFail:       true,
-			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
-		},
-		{
-			name:             "SendEmptyRecords-Async",
-			sendEmptyRecords: 33,
-			flags:            []string{"-async"},
-			shouldFail:       true,
-			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
-		},
-		{
-			name: "SendWarningAlerts-Pass",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			sendWarningAlerts: 4,
-		},
-		{
-			protocol: dtls,
-			name:     "SendWarningAlerts-DTLS-Pass",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			sendWarningAlerts: 4,
-		},
-		{
-			name: "SendWarningAlerts-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			sendWarningAlerts:  4,
-			shouldFail:         true,
-			expectedError:      ":BAD_ALERT:",
-			expectedLocalError: "remote error: error decoding message",
-		},
-		// Although TLS 1.3 intended to remove warning alerts, it left in
-		// user_canceled. JDK11 misuses this alert as a post-handshake
-		// full-duplex signal. As a workaround, skip user_canceled as in
-		// TLS 1.2, which is consistent with NSS and OpenSSL.
-		{
-			name: "SendUserCanceledAlerts-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			sendUserCanceledAlerts: 4,
-		},
-		{
-			name: "SendUserCanceledAlerts-TooMany-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			sendUserCanceledAlerts: 5,
-			shouldFail:             true,
-			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
-		},
-		{
-			name: "SendWarningAlerts-TooMany",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			sendWarningAlerts: 5,
-			shouldFail:        true,
-			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
-		},
-		{
-			name: "SendWarningAlerts-TooMany-Async",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			sendWarningAlerts: 5,
-			flags:             []string{"-async"},
-			shouldFail:        true,
-			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
-		},
-		{
-			name:               "SendBogusAlertType",
-			sendBogusAlertType: true,
-			shouldFail:         true,
-			expectedError:      ":UNKNOWN_ALERT_TYPE:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		{
-			protocol:           dtls,
-			name:               "SendBogusAlertType-DTLS",
-			sendBogusAlertType: true,
-			shouldFail:         true,
-			expectedError:      ":UNKNOWN_ALERT_TYPE:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		{
-			name: "TooManyKeyUpdates",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			sendKeyUpdates:   33,
-			keyUpdateRequest: keyUpdateNotRequested,
-			shouldFail:       true,
-			expectedError:    ":TOO_MANY_KEY_UPDATES:",
-		},
-		{
-			name: "EmptySessionID",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-			noSessionCache: true,
-			flags:          []string{"-expect-no-session"},
-		},
-		{
-			name: "Unclean-Shutdown",
-			config: Config{
-				Bugs: ProtocolBugs{
-					NoCloseNotify:     true,
-					ExpectCloseNotify: true,
-				},
-			},
-			shimShutsDown: true,
-			flags:         []string{"-check-close-notify"},
-			shouldFail:    true,
-			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
-		},
-		{
-			name: "Unclean-Shutdown-Ignored",
-			config: Config{
-				Bugs: ProtocolBugs{
-					NoCloseNotify: true,
-				},
-			},
-			shimShutsDown: true,
-		},
-		{
-			name: "Unclean-Shutdown-Alert",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendAlertOnShutdown: alertDecompressionFailure,
-					ExpectCloseNotify:   true,
-				},
-			},
-			shimShutsDown: true,
-			flags:         []string{"-check-close-notify"},
-			shouldFail:    true,
-			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
-		},
-		{
-			name: "LargePlaintext",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendLargeRecords: true,
-				},
-			},
-			messageLen:         maxPlaintext + 1,
-			shouldFail:         true,
-			expectedError:      ":DATA_LENGTH_TOO_LONG:",
-			expectedLocalError: "remote error: record overflow",
-		},
-		{
-			protocol: dtls,
-			name:     "LargePlaintext-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendLargeRecords: true,
-				},
-			},
-			messageLen:         maxPlaintext + 1,
-			shouldFail:         true,
-			expectedError:      ":DATA_LENGTH_TOO_LONG:",
-			expectedLocalError: "remote error: record overflow",
-		},
-		{
-			name: "LargePlaintext-TLS13-Padded-8192-8192",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					RecordPadding:    8192,
-					SendLargeRecords: true,
-				},
-			},
-			messageLen: 8192,
-		},
-		{
-			name: "LargePlaintext-TLS13-Padded-8193-8192",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					RecordPadding:    8193,
-					SendLargeRecords: true,
-				},
-			},
-			messageLen:         8192,
-			shouldFail:         true,
-			expectedError:      ":DATA_LENGTH_TOO_LONG:",
-			expectedLocalError: "remote error: record overflow",
-		},
-		{
-			name: "LargePlaintext-TLS13-Padded-16383-1",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					RecordPadding:    1,
-					SendLargeRecords: true,
-				},
-			},
-			messageLen: 16383,
-		},
-		{
-			name: "LargePlaintext-TLS13-Padded-16384-1",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					RecordPadding:    1,
-					SendLargeRecords: true,
-				},
-			},
-			messageLen:         16384,
-			shouldFail:         true,
-			expectedError:      ":DATA_LENGTH_TOO_LONG:",
-			expectedLocalError: "remote error: record overflow",
-		},
-		{
-			name: "LargeCiphertext",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendLargeRecords: true,
-				},
-			},
-			messageLen:    maxPlaintext * 2,
-			shouldFail:    true,
-			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
-		},
-		{
-			protocol: dtls,
-			name:     "LargeCiphertext-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendLargeRecords: true,
-				},
-			},
-			messageLen: maxPlaintext * 2,
-			// Unlike the other four cases, DTLS drops records which
-			// are invalid before authentication, so the connection
-			// does not fail.
-			expectMessageDropped: true,
-		},
-		{
-			name:        "BadHelloRequest-1",
-			renegotiate: 1,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
-				},
-			},
-			flags: []string{
-				"-renegotiate-freely",
-				"-expect-total-renegotiations", "1",
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_HELLO_REQUEST:",
-		},
-		{
-			name:        "BadHelloRequest-2",
-			renegotiate: 1,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
-				},
-			},
-			flags: []string{
-				"-renegotiate-freely",
-				"-expect-total-renegotiations", "1",
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_HELLO_REQUEST:",
-		},
-		{
-			testType: serverTest,
-			name:     "SupportTicketsWithSessionID",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-			resumeConfig: &Config{
-				MaxVersion: VersionTLS12,
-			},
-			resumeSession: true,
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS12-SendExtraFinished",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendExtraFinished: true,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_RECORD:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS12-SendExtraFinished-Reordered",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					MaxHandshakeRecordLength:  2,
-					ReorderHandshakeFragments: true,
-					SendExtraFinished:         true,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS12-SendExtraFinished-Packed",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendExtraFinished:      true,
-					PackHandshakeFragments: 1000,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS13-SendExtraFinished",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendExtraFinished: true,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS13-SendExtraFinished-Reordered",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					MaxHandshakeRecordLength:  2,
-					ReorderHandshakeFragments: true,
-					SendExtraFinished:         true,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			name:     "DTLS13-SendExtraFinished-Packed",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendExtraFinished:      true,
-					PackHandshakeFragments: 1000,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-		},
-		{
-			protocol: dtls,
-			testType: serverTest,
-			name:     "DTLS13-SendExtraFinished-AfterAppData",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SkipImplicitACKRead: true,
-					WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-						if next[len(next)-1].Type != typeFinished {
-							c.WriteFlight(next)
-							return
-						}
-
-						// Complete the handshake.
-						c.WriteFlight(next)
-						c.ReadACK(c.InEpoch())
-
-						// Send some application data. The shim is now on epoch 3.
-						msg := []byte("hello")
-						c.WriteAppData(c.OutEpoch(), msg)
-						c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-						// The shim is still accepting data from epoch 2, so it can
-						// ACK a retransmit if needed, but it should not accept new
-						// messages at epoch three.
-						extraFinished := next[len(next)-1]
-						extraFinished.Sequence++
-						c.WriteFlight([]DTLSMessage{extraFinished})
-					},
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-			expectedLocalError: "remote error: unexpected message",
-			// Disable tickets on the shim to avoid NewSessionTicket
-			// interfering with the test callback.
-			flags: []string{"-no-ticket"},
-		},
-		{
-			testType: serverTest,
-			name:     "V2ClientHello-EmptyRecordPrefix",
-			config: Config{
-				// Choose a cipher suite that does not involve
-				// elliptic curves, so no extensions are
-				// involved.
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-				Bugs: ProtocolBugs{
-					SendV2ClientHello: true,
-				},
-			},
-			sendPrefix: string([]byte{
-				byte(recordTypeHandshake),
-				3, 1, // version
-				0, 0, // length
-			}),
-			// A no-op empty record may not be sent before V2ClientHello.
-			shouldFail:    true,
-			expectedError: ":WRONG_VERSION_NUMBER:",
-		},
-		{
-			testType: serverTest,
-			name:     "V2ClientHello-WarningAlertPrefix",
-			config: Config{
-				// Choose a cipher suite that does not involve
-				// elliptic curves, so no extensions are
-				// involved.
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-				Bugs: ProtocolBugs{
-					SendV2ClientHello: true,
-				},
-			},
-			sendPrefix: string([]byte{
-				byte(recordTypeAlert),
-				3, 1, // version
-				0, 2, // length
-				alertLevelWarning, byte(alertDecompressionFailure),
-			}),
-			// A no-op warning alert may not be sent before V2ClientHello.
-			shouldFail:    true,
-			expectedError: ":WRONG_VERSION_NUMBER:",
-		},
-		{
-			name: "SendSNIWarningAlert",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendSNIWarningAlert: true,
-				},
-			},
-		},
-		{
-			testType: serverTest,
-			name:     "ExtraCompressionMethods-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
-				},
-			},
-		},
-		{
-			testType: serverTest,
-			name:     "ExtraCompressionMethods-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":INVALID_COMPRESSION_LIST:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		{
-			testType: serverTest,
-			name:     "NoNullCompression-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":INVALID_COMPRESSION_LIST:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		{
-			testType: serverTest,
-			name:     "NoNullCompression-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":INVALID_COMPRESSION_LIST:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		// Test that the client rejects invalid compression methods
-		// from the server.
-		{
-			testType: clientTest,
-			name:     "InvalidCompressionMethod",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendCompressionMethod: 1,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
-			expectedLocalError: "remote error: illegal parameter",
-		},
-		{
-			testType: clientTest,
-			name:     "TLS13-InvalidCompressionMethod",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendCompressionMethod: 1,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECODE_ERROR:",
-		},
-		{
-			testType: clientTest,
-			name:     "TLS13-HRR-InvalidCompressionMethod",
-			config: Config{
-				MaxVersion:       VersionTLS13,
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					SendCompressionMethod: 1,
-				},
-			},
-			shouldFail:         true,
-			expectedError:      ":DECODE_ERROR:",
-			expectedLocalError: "remote error: error decoding message",
-		},
-		{
-			name: "GREASE-Client-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					ExpectGREASE: true,
-				},
-			},
-			flags: []string{"-enable-grease"},
-		},
-		{
-			name: "GREASE-Client-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ExpectGREASE: true,
-				},
-			},
-			flags: []string{"-enable-grease"},
-		},
-		{
-			testType: serverTest,
-			name:     "GREASE-Server-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					// TLS 1.3 servers are expected to
-					// always enable GREASE. TLS 1.3 is new,
-					// so there is no existing ecosystem to
-					// worry about.
-					ExpectGREASE: true,
-				},
-			},
-		},
-		{
-			// Test the TLS 1.2 server so there is a large
-			// unencrypted certificate as well as application data.
-			testType: serverTest,
-			name:     "MaxSendFragment-TLS12",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					MaxReceivePlaintext: 512,
-				},
-			},
-			messageLen: 1024,
-			flags: []string{
-				"-max-send-fragment", "512",
-				"-read-size", "1024",
-			},
-		},
-		{
-			// Test the TLS 1.2 server so there is a large
-			// unencrypted certificate as well as application data.
-			testType: serverTest,
-			name:     "MaxSendFragment-TLS12-TooLarge",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					// Ensure that some of the records are
-					// 512.
-					MaxReceivePlaintext: 511,
-				},
-			},
-			messageLen: 1024,
-			flags: []string{
-				"-max-send-fragment", "512",
-				"-read-size", "1024",
-			},
-			shouldFail:         true,
-			expectedLocalError: "local error: record overflow",
-		},
-		{
-			// Test the TLS 1.3 server so there is a large encrypted
-			// certificate as well as application data.
-			testType: serverTest,
-			name:     "MaxSendFragment-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					MaxReceivePlaintext:            512,
-					ExpectPackedEncryptedHandshake: 512,
-				},
-			},
-			messageLen: 1024,
-			flags: []string{
-				"-max-send-fragment", "512",
-				"-read-size", "1024",
-			},
-		},
-		{
-			// Test the TLS 1.3 server so there is a large encrypted
-			// certificate as well as application data.
-			testType: serverTest,
-			name:     "MaxSendFragment-TLS13-TooLarge",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					// Ensure that some of the records are
-					// 512.
-					MaxReceivePlaintext: 511,
-				},
-			},
-			messageLen: 1024,
-			flags: []string{
-				"-max-send-fragment", "512",
-				"-read-size", "1024",
-			},
-			shouldFail:         true,
-			expectedLocalError: "local error: record overflow",
-		},
-		{
-			// Test that handshake data is tightly packed in TLS 1.3.
-			testType: serverTest,
-			name:     "PackedEncryptedHandshake-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ExpectPackedEncryptedHandshake: 16384,
-				},
-			},
-		},
-		{
-			// Test that DTLS can handle multiple application data
-			// records in a single packet.
-			protocol: dtls,
-			name:     "SplitAndPackAppData-DTLS",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SplitAndPackAppData: true,
-				},
-			},
-		},
-		{
-			protocol: dtls,
-			name:     "SplitAndPackAppData-DTLS-Async",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SplitAndPackAppData: true,
-				},
-			},
-			flags: []string{"-async"},
-		},
-		{
-			// DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which
-			// is the largest encodable value.
-			protocol: dtls,
-			name:     "DTLS-HelloVerifyRequest-255",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					HelloVerifyRequestCookieLength: 255,
-				},
-			},
-		},
-		{
-			// DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which
-			// was probably a mistake in the spec but test that it works
-			// nonetheless.
-			protocol: dtls,
-			name:     "DTLS-HelloVerifyRequest-0",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					EmptyHelloVerifyRequestCookie: true,
-				},
-			},
-		},
-	}
-	testCases = append(testCases, basicTests...)
-
-	// Test that very large messages can be received.
-	cert := rsaCertificate
-	for i := 0; i < 50; i++ {
-		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
-	}
-	testCases = append(testCases, testCase{
-		name: "LargeMessage",
-		config: Config{
-			Credential: &cert,
-		},
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "LargeMessage-DTLS",
-		config: Config{
-			Credential: &cert,
-		},
-	})
-
-	// They are rejected if the maximum certificate chain length is capped.
-	testCases = append(testCases, testCase{
-		name: "LargeMessage-Reject",
-		config: Config{
-			Credential: &cert,
-		},
-		flags:         []string{"-max-cert-list", "16384"},
-		shouldFail:    true,
-		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "LargeMessage-Reject-DTLS",
-		config: Config{
-			Credential: &cert,
-		},
-		flags:         []string{"-max-cert-list", "16384"},
-		shouldFail:    true,
-		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
-	})
-
-	// Servers echoing the TLS 1.3 compatibility mode session ID should be
-	// rejected.
-	testCases = append(testCases, testCase{
-		name: "EchoTLS13CompatibilitySessionID",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				EchoSessionIDInFullHandshake: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	// Servers should reject QUIC client hellos that have a legacy
-	// session ID.
-	testCases = append(testCases, testCase{
-		name:     "QUICCompatibilityMode",
-		testType: serverTest,
-		protocol: quic,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				CompatModeWithQUIC: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
-	})
-
-	// Clients should reject DTLS 1.3 ServerHellos that echo the legacy
-	// session ID.
-	testCases = append(testCases, testCase{
-		protocol:      dtls,
-		name:          "DTLS13CompatibilityMode-EchoSessionID",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		resumeConfig: &Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				DTLS13EchoSessionID: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-
-	// DTLS 1.3 should work with record headers that don't set the
-	// length bit or that use the short sequence number format.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-NoLength-Client",
-		config: Config{
-			MinVersion:                 VersionTLS13,
-			DTLSRecordHeaderOmitLength: true,
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-NoLength-Server",
-		config: Config{
-			MinVersion:                 VersionTLS13,
-			DTLSRecordHeaderOmitLength: true,
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-ShortSeqNums-Client",
-		config: Config{
-			MinVersion:          VersionTLS13,
-			DTLSUseShortSeqNums: true,
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-ShortSeqNums-Server",
-		config: Config{
-			MinVersion:          VersionTLS13,
-			DTLSUseShortSeqNums: true,
-		},
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-OldHeader",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				DTLSUsePlaintextRecordHeader: true,
-			},
-		},
-		expectMessageDropped: true,
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "DTLS13RecordHeader-CIDBit",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				DTLS13RecordHeaderSetCIDBit: true,
-			},
-		},
-		expectMessageDropped: true,
-	})
-
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "DTLS13-MessageCallback-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		flags: []string{
-			"-expect-msg-callback",
-			`write hs 1
-read hs 2
-read hs 8
-read hs 11
-read hs 15
-read hs 20
-write hs 20
-read ack
-read hs 4
-read hs 4
-read alert 1 0
-`,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "DTLS13-MessageCallback-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		flags: []string{
-			"-expect-msg-callback",
-			`read hs 1
-write hs 2
-write hs 8
-write hs 11
-write hs 15
-write hs 20
-read hs 20
-write ack
-write hs 4
-write hs 4
-read ack
-read ack
-read alert 1 0
-`,
-		},
-	})
-}
-
-func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
-	const psk = "12345"
-	const pskIdentity = "luggage combo"
-
-	if !ver.supportsProtocol(protocol) {
-		return
-	}
-	prefix := protocol.String() + "-"
-
-	var cert *Credential
-	if isTLS13Suite(suite.name) {
-		cert = &rsaCertificate
-	} else if hasComponent(suite.name, "ECDSA") {
-		cert = &ecdsaP256Certificate
-	} else if hasComponent(suite.name, "RSA") {
-		cert = &rsaCertificate
-	}
-
-	var flags []string
-	if hasComponent(suite.name, "PSK") {
-		flags = append(flags,
-			"-psk", psk,
-			"-psk-identity", pskIdentity)
-	}
-
-	if hasComponent(suite.name, "3DES") {
-		// BoringSSL disables 3DES ciphers by default.
-		flags = append(flags, "-cipher", "3DES")
-	}
-
-	var shouldFail bool
-	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
-		shouldFail = true
-	}
-	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
-		shouldFail = true
-	}
-	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
-		shouldFail = true
-	}
-
-	var sendCipherSuite uint16
-	var expectedServerError, expectedClientError string
-	serverCipherSuites := []uint16{suite.id}
-	if shouldFail {
-		expectedServerError = ":NO_SHARED_CIPHER:"
-		if ver.version >= VersionTLS13 && cert == nil {
-			// TLS 1.2 PSK ciphers won't configure a server certificate, but we
-			// require one in TLS 1.3.
-			expectedServerError = ":NO_CERTIFICATE_SET:"
-		}
-		expectedClientError = ":WRONG_CIPHER_RETURNED:"
-		// Configure the server to select ciphers as normal but
-		// select an incompatible cipher in ServerHello.
-		serverCipherSuites = nil
-		sendCipherSuite = suite.id
-	}
-
-	// Verify exporters interoperate.
-	exportKeyingMaterial := 1024
-
-	if ver.version != VersionTLS13 || !ver.hasDTLS {
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + ver.name + "-" + suite.name + "-server",
-			config: Config{
-				MinVersion:           ver.version,
-				MaxVersion:           ver.version,
-				CipherSuites:         []uint16{suite.id},
-				Credential:           cert,
-				PreSharedKey:         []byte(psk),
-				PreSharedKeyIdentity: pskIdentity,
-				Bugs: ProtocolBugs{
-					AdvertiseAllConfiguredCiphers: true,
-				},
-			},
-			shimCertificate:      cert,
-			flags:                flags,
-			resumeSession:        true,
-			shouldFail:           shouldFail,
-			expectedError:        expectedServerError,
-			exportKeyingMaterial: exportKeyingMaterial,
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + ver.name + "-" + suite.name + "-client",
-			config: Config{
-				MinVersion:           ver.version,
-				MaxVersion:           ver.version,
-				CipherSuites:         serverCipherSuites,
-				Credential:           cert,
-				PreSharedKey:         []byte(psk),
-				PreSharedKeyIdentity: pskIdentity,
-				Bugs: ProtocolBugs{
-					IgnorePeerCipherPreferences: shouldFail,
-					SendCipherSuite:             sendCipherSuite,
-				},
-			},
-			flags:                flags,
-			resumeSession:        true,
-			shouldFail:           shouldFail,
-			expectedError:        expectedClientError,
-			exportKeyingMaterial: exportKeyingMaterial,
-		})
-	}
-
-	if shouldFail {
-		return
-	}
-
-	// Ensure the maximum record size is accepted.
-	testCases = append(testCases, testCase{
-		protocol: protocol,
-		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
-		config: Config{
-			MinVersion:           ver.version,
-			MaxVersion:           ver.version,
-			CipherSuites:         []uint16{suite.id},
-			Credential:           cert,
-			PreSharedKey:         []byte(psk),
-			PreSharedKeyIdentity: pskIdentity,
-		},
-		flags:      flags,
-		messageLen: maxPlaintext,
-	})
-
-	// Test bad records for all ciphers. Bad records are fatal in TLS
-	// and ignored in DTLS.
-	shouldFail = protocol == tls
-	var expectedError string
-	if shouldFail {
-		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
-	}
-
-	// When QUIC is used, the QUIC stack handles record encryption/decryption.
-	// Thus it is not possible for the TLS stack in QUIC mode to receive a
-	// bad record (i.e. one that fails to decrypt).
-	if protocol != quic {
-		testCases = append(testCases, testCase{
-			protocol: protocol,
-			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
-			config: Config{
-				MinVersion:           ver.version,
-				MaxVersion:           ver.version,
-				CipherSuites:         []uint16{suite.id},
-				Credential:           cert,
-				PreSharedKey:         []byte(psk),
-				PreSharedKeyIdentity: pskIdentity,
-			},
-			flags:            flags,
-			damageFirstWrite: true,
-			messageLen:       maxPlaintext,
-			shouldFail:       shouldFail,
-			expectedError:    expectedError,
-		})
-	}
-}
-
-func addCipherSuiteTests() {
-	const bogusCipher = 0xfe00
-
-	for _, suite := range testCipherSuites {
-		for _, ver := range tlsVersions {
-			for _, protocol := range []protocol{tls, dtls, quic} {
-				addTestForCipherSuite(suite, ver, protocol)
-			}
-		}
-	}
-
-	testCases = append(testCases, testCase{
-		name: "NoSharedCipher",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{},
-		},
-		shouldFail:    true,
-		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "NoSharedCipher-TLS13",
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{},
-		},
-		shouldFail:    true,
-		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "UnsupportedCipherSuite",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-			Bugs: ProtocolBugs{
-				IgnorePeerCipherPreferences: true,
-			},
-		},
-		flags:         []string{"-cipher", "DEFAULT:!AES"},
-		shouldFail:    true,
-		expectedError: ":WRONG_CIPHER_RETURNED:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ServerHelloBogusCipher",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendCipherSuite: bogusCipher,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CIPHER_RETURNED:",
-	})
-	testCases = append(testCases, testCase{
-		name: "ServerHelloBogusCipher-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendCipherSuite: bogusCipher,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CIPHER_RETURNED:",
-	})
-
-	// The server must be tolerant to bogus ciphers.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "UnknownCipher",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				AdvertiseAllConfiguredCiphers: true,
-			},
-		},
-	})
-
-	// The server must be tolerant to bogus ciphers.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "UnknownCipher-TLS13",
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				AdvertiseAllConfiguredCiphers: true,
-			},
-		},
-	})
-
-	// Test empty ECDHE_PSK identity hints work as expected.
-	testCases = append(testCases, testCase{
-		name: "EmptyECDHEPSKHint",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
-			PreSharedKey: []byte("secret"),
-		},
-		flags: []string{"-psk", "secret"},
-	})
-
-	// Test empty PSK identity hints work as expected, even if an explicit
-	// ServerKeyExchange is sent.
-	testCases = append(testCases, testCase{
-		name: "ExplicitEmptyPSKHint",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
-			PreSharedKey: []byte("secret"),
-			Bugs: ProtocolBugs{
-				AlwaysSendPreSharedKeyIdentityHint: true,
-			},
-		},
-		flags: []string{"-psk", "secret"},
-	})
-
-	// Test that clients enforce that the server-sent certificate and cipher
-	// suite match in TLS 1.2.
-	testCases = append(testCases, testCase{
-		name: "CertificateCipherMismatch-RSA",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Credential:   &rsaCertificate,
-			Bugs: ProtocolBugs{
-				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CERTIFICATE_TYPE:",
-	})
-	testCases = append(testCases, testCase{
-		name: "CertificateCipherMismatch-ECDSA",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Credential:   &ecdsaP256Certificate,
-			Bugs: ProtocolBugs{
-				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CERTIFICATE_TYPE:",
-	})
-	testCases = append(testCases, testCase{
-		name: "CertificateCipherMismatch-Ed25519",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Credential:   &ed25519Certificate,
-			Bugs: ProtocolBugs{
-				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CERTIFICATE_TYPE:",
-	})
-
-	// Test that servers decline to select a cipher suite which is
-	// inconsistent with their configured certificate.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerCipherFilter-RSA",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-		},
-		shimCertificate: &rsaCertificate,
-		shouldFail:      true,
-		expectedError:   ":NO_SHARED_CIPHER:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerCipherFilter-ECDSA",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		shimCertificate: &ecdsaP256Certificate,
-		shouldFail:      true,
-		expectedError:   ":NO_SHARED_CIPHER:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerCipherFilter-Ed25519",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		shimCertificate: &ed25519Certificate,
-		shouldFail:      true,
-		expectedError:   ":NO_SHARED_CIPHER:",
-	})
-
-	// Test cipher suite negotiation works as expected. Configure a
-	// complicated cipher suite configuration.
-	const negotiationTestCiphers = "" +
-		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
-		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
-		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
-		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
-		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
-	negotiationTests := []struct {
-		ciphers  []uint16
-		expected uint16
-	}{
-		// Server preferences are honored, including when
-		// equipreference groups are involved.
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_128_CBC_SHA,
-				TLS_RSA_WITH_AES_128_GCM_SHA256,
-				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-			},
-			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-		},
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_128_CBC_SHA,
-				TLS_RSA_WITH_AES_128_GCM_SHA256,
-				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-			},
-			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-		},
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_128_CBC_SHA,
-				TLS_RSA_WITH_AES_128_GCM_SHA256,
-			},
-			TLS_RSA_WITH_AES_128_GCM_SHA256,
-		},
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_128_CBC_SHA,
-			},
-			TLS_RSA_WITH_AES_128_CBC_SHA,
-		},
-		// Equipreference groups use the client preference.
-		{
-			[]uint16{
-				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-			},
-			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-		},
-		{
-			[]uint16{
-				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-			},
-			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-		},
-		{
-			[]uint16{
-				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-			},
-			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-		},
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_256_CBC_SHA,
-			},
-			TLS_RSA_WITH_AES_256_GCM_SHA384,
-		},
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_CBC_SHA,
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-			},
-			TLS_RSA_WITH_AES_256_CBC_SHA,
-		},
-		// If there are two equipreference groups, the preferred one
-		// takes precedence.
-		{
-			[]uint16{
-				TLS_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_RSA_WITH_AES_256_CBC_SHA,
-				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-			},
-			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-		},
-	}
-	for i, t := range negotiationTests {
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CipherNegotiation-" + strconv.Itoa(i),
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: t.ciphers,
-			},
-			flags: []string{"-cipher", negotiationTestCiphers},
-			expectations: connectionExpectations{
-				cipher: t.expected,
-			},
-		})
-	}
-}
-
-func addBadECDSASignatureTests() {
-	for badR := BadValue(1); badR < NumBadValues; badR++ {
-		for badS := BadValue(1); badS < NumBadValues; badS++ {
-			testCases = append(testCases, testCase{
-				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
-				config: Config{
-					MaxVersion:   VersionTLS12,
-					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-					Credential:   &ecdsaP256Certificate,
-					Bugs: ProtocolBugs{
-						BadECDSAR: badR,
-						BadECDSAS: badS,
-					},
-				},
-				shouldFail:    true,
-				expectedError: ":BAD_SIGNATURE:",
-			})
-			testCases = append(testCases, testCase{
-				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Credential: &ecdsaP256Certificate,
-					Bugs: ProtocolBugs{
-						BadECDSAR: badR,
-						BadECDSAS: badS,
-					},
-				},
-				shouldFail:    true,
-				expectedError: ":BAD_SIGNATURE:",
-			})
-		}
-	}
-}
-
-func addCBCPaddingTests() {
-	testCases = append(testCases, testCase{
-		name: "MaxCBCPadding",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-			Bugs: ProtocolBugs{
-				MaxPadding: true,
-			},
-		},
-		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
-	})
-	testCases = append(testCases, testCase{
-		name: "BadCBCPadding",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-			Bugs: ProtocolBugs{
-				PaddingFirstByteBad: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-	})
-	// OpenSSL previously had an issue where the first byte of padding in
-	// 255 bytes of padding wasn't checked.
-	testCases = append(testCases, testCase{
-		name: "BadCBCPadding255",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-			Bugs: ProtocolBugs{
-				MaxPadding:               true,
-				PaddingFirstByteBadIf255: true,
-			},
-		},
-		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
-		shouldFail:    true,
-		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-	})
-}
-
-func addCBCSplittingTests() {
-	cbcCiphers := []struct {
-		name   string
-		cipher uint16
-	}{
-		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
-		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
-	}
-	for _, t := range cbcCiphers {
-		testCases = append(testCases, testCase{
-			name: "CBCRecordSplitting-" + t.name,
-			config: Config{
-				MaxVersion:   VersionTLS10,
-				MinVersion:   VersionTLS10,
-				CipherSuites: []uint16{t.cipher},
-				Bugs: ProtocolBugs{
-					ExpectRecordSplitting: true,
-				},
-			},
-			messageLen:    -1, // read until EOF
-			resumeSession: true,
-			flags: []string{
-				"-async",
-				"-write-different-record-sizes",
-				"-cbc-record-splitting",
-				// BoringSSL disables 3DES by default.
-				"-cipher", "ALL:3DES",
-			},
-		})
-		testCases = append(testCases, testCase{
-			name: "CBCRecordSplittingPartialWrite-" + t.name,
-			config: Config{
-				MaxVersion:   VersionTLS10,
-				MinVersion:   VersionTLS10,
-				CipherSuites: []uint16{t.cipher},
-				Bugs: ProtocolBugs{
-					ExpectRecordSplitting: true,
-				},
-			},
-			messageLen: -1, // read until EOF
-			flags: []string{
-				"-async",
-				"-write-different-record-sizes",
-				"-cbc-record-splitting",
-				"-partial-write",
-				// BoringSSL disables 3DES by default.
-				"-cipher", "ALL:3DES",
-			},
-		})
-	}
-}
-
-func addClientAuthTests() {
-	// Add a dummy cert pool to stress certificate authority parsing.
-	certPool := x509.NewCertPool()
-	for _, cert := range []Credential{rsaCertificate, rsa1024Certificate} {
-		cert, err := x509.ParseCertificate(cert.Certificate[0])
-		if err != nil {
-			panic(err)
-		}
-		certPool.AddCert(cert)
-	}
-	caNames := certPool.Subjects()
-
-	for _, ver := range tlsVersions {
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     ver.name + "-Client-ClientAuth-RSA",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				ClientAuth: RequireAnyClientCert,
-				ClientCAs:  certPool,
-			},
-			shimCertificate: &rsaCertificate,
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     ver.name + "-Server-ClientAuth-RSA",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     ver.name + "-Server-ClientAuth-ECDSA",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &ecdsaP256Certificate,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     ver.name + "-Client-ClientAuth-ECDSA",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				ClientAuth: RequireAnyClientCert,
-				ClientCAs:  certPool,
-			},
-			shimCertificate: &ecdsaP256Certificate,
-		})
-
-		testCases = append(testCases, testCase{
-			name: "NoClientCertificate-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				ClientAuth: RequireAnyClientCert,
-			},
-			shouldFail:         true,
-			expectedLocalError: "client didn't provide a certificate",
-		})
-
-		testCases = append(testCases, testCase{
-			// Even if not configured to expect a certificate, OpenSSL will
-			// return X509_V_OK as the verify_result.
-			testType: serverTest,
-			name:     "NoClientCertificateRequested-Server-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			flags: []string{
-				"-expect-verify-result",
-			},
-			resumeSession: true,
-		})
-
-		testCases = append(testCases, testCase{
-			// If a client certificate is not provided, OpenSSL will still
-			// return X509_V_OK as the verify_result.
-			testType: serverTest,
-			name:     "NoClientCertificate-Server-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			flags: []string{
-				"-expect-verify-result",
-				"-verify-peer",
-			},
-			resumeSession: true,
-		})
-
-		certificateRequired := "remote error: certificate required"
-		if ver.version < VersionTLS13 {
-			// Prior to TLS 1.3, the generic handshake_failure alert
-			// was used.
-			certificateRequired = "remote error: handshake failure"
-		}
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RequireAnyClientCertificate-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			flags:              []string{"-require-any-client-certificate"},
-			shouldFail:         true,
-			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
-			expectedLocalError: certificateRequired,
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "SkipClientCertificate-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					SkipClientCertificate: true,
-				},
-			},
-			// Setting SSL_VERIFY_PEER allows anonymous clients.
-			flags:         []string{"-verify-peer"},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_MESSAGE:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "VerifyPeerIfNoOBC-NoChannelID-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			flags: []string{
-				"-enable-channel-id",
-				"-verify-peer-if-no-obc",
-			},
-			shouldFail:         true,
-			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
-			expectedLocalError: certificateRequired,
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "VerifyPeerIfNoOBC-ChannelID-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				ChannelID:  &channelIDKey,
-			},
-			expectations: connectionExpectations{
-				channelID: true,
-			},
-			flags: []string{
-				"-enable-channel-id",
-				"-verify-peer-if-no-obc",
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     ver.name + "-Server-CertReq-CA-List",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-				Bugs: ProtocolBugs{
-					ExpectCertificateReqNames: caNames,
-				},
-			},
-			flags: []string{
-				"-require-any-client-certificate",
-				"-use-client-ca-list", encodeDERValues(caNames),
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     ver.name + "-Client-CertReq-CA-List",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-				ClientAuth: RequireAnyClientCert,
-				ClientCAs:  certPool,
-			},
-			shimCertificate: &rsaCertificate,
-			flags: []string{
-				"-expect-client-ca-list", encodeDERValues(caNames),
-			},
-		})
-	}
-
-	// Client auth is only legal in certificate-based ciphers.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-PSK",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
-			PreSharedKey: []byte("secret"),
-			ClientAuth:   RequireAnyClientCert,
-		},
-		shimCertificate: &rsaCertificate,
-		flags: []string{
-			"-psk", "secret",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-ECDHE_PSK",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
-			PreSharedKey: []byte("secret"),
-			ClientAuth:   RequireAnyClientCert,
-		},
-		shimCertificate: &rsaCertificate,
-		flags: []string{
-			"-psk", "secret",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-
-	// Regression test for a bug where the client CA list, if explicitly
-	// set to NULL, was mis-encoded.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Null-Client-CA-List",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: &rsaCertificate,
-			Bugs: ProtocolBugs{
-				ExpectCertificateReqNames: [][]byte{},
-			},
-		},
-		flags: []string{
-			"-require-any-client-certificate",
-			"-use-client-ca-list", "<NULL>",
-		},
-	})
-
-	// Test that an empty client CA list doesn't send a CA extension.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-Empty-Client-CA-List",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &rsaCertificate,
-			Bugs: ProtocolBugs{
-				ExpectNoCertificateAuthoritiesExtension: true,
-			},
-		},
-		flags: []string{
-			"-require-any-client-certificate",
-			"-use-client-ca-list", "<EMPTY>",
-		},
-	})
-}
-
-func addExtendedMasterSecretTests() {
-	const expectEMSFlag = "-expect-extended-master-secret"
-
-	for _, with := range []bool{false, true} {
-		prefix := "No"
-		if with {
-			prefix = ""
-		}
-
-		for _, isClient := range []bool{false, true} {
-			suffix := "-Server"
-			testType := serverTest
-			if isClient {
-				suffix = "-Client"
-				testType = clientTest
-			}
-
-			for _, ver := range tlsVersions {
-				// In TLS 1.3, the extension is irrelevant and
-				// always reports as enabled.
-				var flags []string
-				if with || ver.version >= VersionTLS13 {
-					flags = []string{expectEMSFlag}
-				}
-
-				testCases = append(testCases, testCase{
-					testType: testType,
-					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
-					config: Config{
-						MinVersion: ver.version,
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							NoExtendedMasterSecret:      !with,
-							RequireExtendedMasterSecret: with,
-						},
-					},
-					flags: flags,
-				})
-			}
-		}
-	}
-
-	for _, isClient := range []bool{false, true} {
-		for _, supportedInFirstConnection := range []bool{false, true} {
-			for _, supportedInResumeConnection := range []bool{false, true} {
-				boolToWord := func(b bool) string {
-					if b {
-						return "Yes"
-					}
-					return "No"
-				}
-				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
-				if isClient {
-					suffix += "Client"
-				} else {
-					suffix += "Server"
-				}
-
-				supportedConfig := Config{
-					MaxVersion: VersionTLS12,
-					Bugs: ProtocolBugs{
-						RequireExtendedMasterSecret: true,
-					},
-				}
-
-				noSupportConfig := Config{
-					MaxVersion: VersionTLS12,
-					Bugs: ProtocolBugs{
-						NoExtendedMasterSecret: true,
-					},
-				}
-
-				test := testCase{
-					name:          "ExtendedMasterSecret-" + suffix,
-					resumeSession: true,
-				}
-
-				if !isClient {
-					test.testType = serverTest
-				}
-
-				if supportedInFirstConnection {
-					test.config = supportedConfig
-				} else {
-					test.config = noSupportConfig
-				}
-
-				if supportedInResumeConnection {
-					test.resumeConfig = &supportedConfig
-				} else {
-					test.resumeConfig = &noSupportConfig
-				}
-
-				switch suffix {
-				case "YesToYes-Client", "YesToYes-Server":
-					// When a session is resumed, it should
-					// still be aware that its master
-					// secret was generated via EMS and
-					// thus it's safe to use tls-unique.
-					test.flags = []string{expectEMSFlag}
-				case "NoToYes-Server":
-					// If an original connection did not
-					// contain EMS, but a resumption
-					// handshake does, then a server should
-					// not resume the session.
-					test.expectResumeRejected = true
-				case "YesToNo-Server":
-					// Resuming an EMS session without the
-					// EMS extension should cause the
-					// server to abort the connection.
-					test.shouldFail = true
-					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
-				case "NoToYes-Client":
-					// A client should abort a connection
-					// where the server resumed a non-EMS
-					// session but echoed the EMS
-					// extension.
-					test.shouldFail = true
-					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
-				case "YesToNo-Client":
-					// A client should abort a connection
-					// where the server didn't echo EMS
-					// when the session used it.
-					test.shouldFail = true
-					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
-				}
-
-				testCases = append(testCases, test)
-			}
-		}
-	}
-
-	// Switching EMS on renegotiation is forbidden.
-	testCases = append(testCases, testCase{
-		name: "ExtendedMasterSecret-Renego-NoEMS",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoExtendedMasterSecret:                true,
-				NoExtendedMasterSecretOnRenegotiation: true,
-			},
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ExtendedMasterSecret-Renego-Upgrade",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoExtendedMasterSecret: true,
-			},
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-		shouldFail:    true,
-		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ExtendedMasterSecret-Renego-Downgrade",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoExtendedMasterSecretOnRenegotiation: true,
-			},
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-		shouldFail:    true,
-		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
-	})
-}
-
-type stateMachineTestConfig struct {
-	protocol          protocol
-	async             bool
-	splitHandshake    bool
-	packHandshake     bool
-	implicitHandshake bool
-}
-
-// Adds tests that try to cover the range of the handshake state machine, under
-// various conditions. Some of these are redundant with other tests, but they
-// only cover the synchronous case.
-func addAllStateMachineCoverageTests() {
-	for _, async := range []bool{false, true} {
-		for _, protocol := range []protocol{tls, dtls, quic} {
-			addStateMachineCoverageTests(stateMachineTestConfig{
-				protocol: protocol,
-				async:    async,
-			})
-			// QUIC doesn't work with the implicit handshake API. Additionally,
-			// splitting or packing handshake records is meaningless in QUIC.
-			if protocol != quic {
-				addStateMachineCoverageTests(stateMachineTestConfig{
-					protocol:          protocol,
-					async:             async,
-					implicitHandshake: true,
-				})
-				addStateMachineCoverageTests(stateMachineTestConfig{
-					protocol:       protocol,
-					async:          async,
-					splitHandshake: true,
-				})
-				addStateMachineCoverageTests(stateMachineTestConfig{
-					protocol:      protocol,
-					async:         async,
-					packHandshake: true,
-				})
-			}
-		}
-	}
-}
-
-func addStateMachineCoverageTests(config stateMachineTestConfig) {
-	var tests []testCase
-
-	// Basic handshake, with resumption. Client and server,
-	// session ID and session ticket.
-	// The following tests have a max version of 1.2, so they are not suitable
-	// for use with QUIC.
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			name: "Basic-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			resumeSession: true,
-			// Ensure session tickets are used, not session IDs.
-			noSessionCache: true,
-			flags:          []string{"-expect-no-hrr"},
-		})
-		tests = append(tests, testCase{
-			name: "Basic-Client-RenewTicket",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					RenewTicketOnResume: true,
-				},
-			},
-			flags:                []string{"-expect-ticket-renewal"},
-			resumeSession:        true,
-			resumeRenewedSession: true,
-		})
-		tests = append(tests, testCase{
-			name: "Basic-Client-NoTicket",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-			resumeSession: true,
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					RequireSessionTickets: true,
-				},
-			},
-			resumeSession: true,
-			flags: []string{
-				"-expect-no-session-id",
-				"-expect-no-hrr",
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-NoTickets",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-			resumeSession: true,
-			flags:         []string{"-expect-session-id"},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-EarlyCallback",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			flags:         []string{"-use-early-callback"},
-			resumeSession: true,
-		})
-	}
-
-	// TLS 1.3 basic handshake shapes.
-	tests = append(tests, testCase{
-		name: "TLS13-1RTT-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		resumeSession:        true,
-		resumeRenewedSession: true,
-		// 0-RTT being disabled overrides all other 0-RTT reasons.
-		flags: []string{"-expect-early-data-reason", "disabled"},
-	})
-
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "TLS13-1RTT-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		resumeSession:        true,
-		resumeRenewedSession: true,
-		flags: []string{
-			// TLS 1.3 uses tickets, so the session should not be
-			// cached statefully.
-			"-expect-no-session-id",
-			// 0-RTT being disabled overrides all other 0-RTT reasons.
-			"-expect-early-data-reason", "disabled",
-		},
-	})
-
-	tests = append(tests, testCase{
-		name: "TLS13-HelloRetryRequest-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			// P-384 requires a HelloRetryRequest against BoringSSL's default
-			// configuration. Assert this with ExpectMissingKeyShare.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				ExpectMissingKeyShare: true,
-			},
-		},
-		// Cover HelloRetryRequest during an ECDHE-PSK resumption.
-		resumeSession: true,
-		flags:         []string{"-expect-hrr"},
-	})
-
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "TLS13-HelloRetryRequest-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			// Require a HelloRetryRequest for every curve.
-			DefaultCurves: []CurveID{},
-		},
-		// Cover HelloRetryRequest during an ECDHE-PSK resumption.
-		resumeSession: true,
-		flags:         []string{"-expect-hrr"},
-	})
-
-	// TLS 1.3 early data tests. DTLS 1.3 doesn't support early data yet.
-	// These tests are disabled for QUIC as well because they test features
-	// that do not apply to QUIC's use of TLS 1.3.
-	//
-	// TODO(crbug.com/381113363): Enable these tests for DTLS once we
-	// support early data in DTLS 1.3.
-	if config.protocol != dtls && config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "TLS13-EarlyData-TooMuchData-Client",
-			config: Config{
-				MaxVersion:       VersionTLS13,
-				MinVersion:       VersionTLS13,
-				MaxEarlyDataSize: 2,
-			},
-			resumeConfig: &Config{
-				MaxVersion:       VersionTLS13,
-				MinVersion:       VersionTLS13,
-				MaxEarlyDataSize: 2,
-				Bugs: ProtocolBugs{
-					ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
-				},
-			},
-			resumeShimPrefix: shimInitialWrite[2:],
-			resumeSession:    true,
-			earlyData:        true,
-		})
-
-		// Unfinished writes can only be tested when operations are async. EarlyData
-		// can't be tested as part of an ImplicitHandshake in this case since
-		// otherwise the early data will be sent as normal data.
-		if config.async && !config.implicitHandshake {
-			tests = append(tests, testCase{
-				testType: clientTest,
-				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
-				config: Config{
-					MaxVersion: VersionTLS13,
-					MinVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						// Write the server response before expecting early data.
-						ExpectEarlyData:     [][]byte{},
-						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
-					},
-				},
-				resumeSession: true,
-				earlyData:     true,
-				flags:         []string{"-on-resume-read-with-unfinished-write"},
-			})
-
-			// Rejected unfinished writes are discarded (from the
-			// perspective of the calling application) on 0-RTT
-			// reject.
-			tests = append(tests, testCase{
-				testType: clientTest,
-				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
-				config: Config{
-					MaxVersion: VersionTLS13,
-					MinVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						AlwaysRejectEarlyData: true,
-					},
-				},
-				resumeSession:           true,
-				earlyData:               true,
-				expectEarlyDataRejected: true,
-				flags:                   []string{"-on-resume-read-with-unfinished-write"},
-			})
-		}
-
-		// Early data has no size limit in QUIC.
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "TLS13-MaxEarlyData-Server",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
-					ExpectEarlyDataAccepted: true,
-				},
-			},
-			messageCount:  2,
-			resumeSession: true,
-			earlyData:     true,
-			shouldFail:    true,
-			expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
-		})
-	}
-
-	// Test that early data is disabled for DTLS 1.3.
-	if config.protocol == dtls {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			protocol: dtls,
-			name:     "DTLS13-EarlyData",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-			},
-			resumeSession: true,
-			earlyData:     true,
-		})
-	}
-
-	// TLS client auth.
-	// The following tests have a max version of 1.2, so they are not suitable
-	// for use with QUIC.
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-NoCertificate-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequestClientCert,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ClientAuth-NoCertificate-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			// Setting SSL_VERIFY_PEER allows anonymous clients.
-			flags: []string{"-verify-peer"},
-		})
-	}
-	if config.protocol != dtls {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-NoCertificate-Client-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				ClientAuth: RequestClientCert,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ClientAuth-NoCertificate-Server-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			// Setting SSL_VERIFY_PEER allows anonymous clients.
-			flags: []string{"-verify-peer"},
-		})
-	}
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-RSA-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequireAnyClientCert,
-			},
-			shimCertificate: &rsaCertificate,
-		})
-	}
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-RSA-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-		},
-		shimCertificate: &rsaCertificate,
-	})
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-ECDSA-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequireAnyClientCert,
-			},
-			shimCertificate: &ecdsaP256Certificate,
-		})
-	}
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-ECDSA-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-		},
-		shimCertificate: &ecdsaP256Certificate,
-	})
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-NoCertificate-OldCallback",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequestClientCert,
-			},
-			flags: []string{"-use-old-client-cert-callback"},
-		})
-	}
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequestClientCert,
-		},
-		flags: []string{"-use-old-client-cert-callback"},
-	})
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientAuth-OldCallback",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ClientAuth: RequireAnyClientCert,
-			},
-			shimCertificate: &rsaCertificate,
-			flags: []string{
-				"-use-old-client-cert-callback",
-			},
-		})
-	}
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-OldCallback-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-		},
-		shimCertificate: &rsaCertificate,
-		flags: []string{
-			"-use-old-client-cert-callback",
-		},
-	})
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ClientAuth-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		})
-	}
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "ClientAuth-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &rsaCertificate,
-		},
-		flags: []string{"-require-any-client-certificate"},
-	})
-
-	// Test each key exchange on the server side for async keys.
-	if config.protocol != quic {
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-RSA",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-			},
-			shimCertificate: &rsaCertificate,
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-ECDHE-RSA",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			},
-			shimCertificate: &rsaCertificate,
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-ECDHE-ECDSA",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			},
-			shimCertificate: &ecdsaP256Certificate,
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-Ed25519",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			},
-			shimCertificate: &ed25519Certificate,
-			flags: []string{
-				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
-			},
-		})
-
-		// No session ticket support; server doesn't send NewSessionTicket.
-		tests = append(tests, testCase{
-			name: "SessionTicketsDisabled-Client",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "SessionTicketsDisabled-Server",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				SessionTicketsDisabled: true,
-			},
-		})
-
-		// Skip ServerKeyExchange in PSK key exchange if there's no
-		// identity hint.
-		tests = append(tests, testCase{
-			name: "EmptyPSKHint-Client",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
-				PreSharedKey: []byte("secret"),
-			},
-			flags: []string{"-psk", "secret"},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "EmptyPSKHint-Server",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
-				PreSharedKey: []byte("secret"),
-			},
-			flags: []string{"-psk", "secret"},
-		})
-	}
-
-	// OCSP stapling tests.
-	for _, vers := range allVersions(config.protocol) {
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "OCSPStapling-Client-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				"-expect-ocsp-response",
-				base64FlagValue(testOCSPResponse),
-				"-verify-peer",
-			},
-			resumeSession: true,
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "OCSPStapling-Server-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			expectations: connectionExpectations{
-				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			resumeSession:   true,
-		})
-
-		// The client OCSP callback is an alternate certificate
-		// verification callback.
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientOCSPCallback-Pass-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				"-use-ocsp-callback",
-			},
-		})
-		var expectedLocalError string
-		if !config.async {
-			// TODO(davidben): Asynchronous fatal alerts are never
-			// sent. https://crbug.com/boringssl/130.
-			expectedLocalError = "remote error: bad certificate status response"
-		}
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientOCSPCallback-Fail-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				"-use-ocsp-callback",
-				"-fail-ocsp-callback",
-			},
-			shouldFail:         true,
-			expectedLocalError: expectedLocalError,
-			expectedError:      ":OCSP_CB_ERROR:",
-		})
-		// The callback still runs if the server does not send an OCSP
-		// response.
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-enable-ocsp-stapling",
-				"-use-ocsp-callback",
-				"-fail-ocsp-callback",
-			},
-			shouldFail:         true,
-			expectedLocalError: expectedLocalError,
-			expectedError:      ":OCSP_CB_ERROR:",
-		})
-
-		// The server OCSP callback is a legacy mechanism for
-		// configuring OCSP, used by unreliable server software.
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			expectations: connectionExpectations{
-				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-			flags: []string{
-				"-use-ocsp-callback",
-				"-set-ocsp-in-callback",
-			},
-			resumeSession: true,
-		})
-
-		// The callback may decline OCSP, in which case  we act as if
-		// the client did not support it, even if a response was
-		// configured.
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ServerOCSPCallback-Decline-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			expectations: connectionExpectations{
-				// There should be no OCSP response from the peer.
-				peerCertificate: &rsaCertificate,
-			},
-			flags: []string{
-				"-use-ocsp-callback",
-				"-decline-ocsp-callback",
-			},
-			resumeSession: true,
-		})
-
-		// The callback may also signal an internal error.
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ServerOCSPCallback-Fail-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			flags: []string{
-				"-use-ocsp-callback",
-				"-fail-ocsp-callback",
-			},
-			shouldFail:    true,
-			expectedError: ":OCSP_CB_ERROR:",
-		})
-	}
-
-	// Certificate verification tests.
-	for _, vers := range allVersions(config.protocol) {
-		for _, useCustomCallback := range []bool{false, true} {
-			for _, testType := range []testType{clientTest, serverTest} {
-				suffix := "-Client"
-				if testType == serverTest {
-					suffix = "-Server"
-				}
-				suffix += "-" + vers.name
-				if useCustomCallback {
-					suffix += "-CustomCallback"
-				}
-
-				// The custom callback and legacy callback have different default
-				// alerts.
-				verifyFailLocalError := "remote error: handshake failure"
-				if useCustomCallback {
-					verifyFailLocalError = "remote error: unknown certificate"
-				}
-
-				// We do not reliably send asynchronous fatal alerts. See
-				// https://crbug.com/boringssl/130.
-				if config.async {
-					verifyFailLocalError = ""
-				}
-
-				flags := []string{"-verify-peer"}
-				if testType == serverTest {
-					flags = append(flags, "-require-any-client-certificate")
-				}
-				if useCustomCallback {
-					flags = append(flags, "-use-custom-verify-callback")
-				}
-
-				tests = append(tests, testCase{
-					testType: testType,
-					name:     "CertificateVerificationSucceed" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Credential: &rsaCertificate,
-					},
-					flags:         append([]string{"-expect-verify-result"}, flags...),
-					resumeSession: true,
-				})
-				tests = append(tests, testCase{
-					testType: testType,
-					name:     "CertificateVerificationFail" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Credential: &rsaCertificate,
-					},
-					flags:              append([]string{"-verify-fail"}, flags...),
-					shouldFail:         true,
-					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
-					expectedLocalError: verifyFailLocalError,
-				})
-				// Tests that although the verify callback fails on resumption, by default we don't call it.
-				tests = append(tests, testCase{
-					testType: testType,
-					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Credential: &rsaCertificate,
-					},
-					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
-					resumeSession: true,
-				})
-				if testType == clientTest && useCustomCallback {
-					tests = append(tests, testCase{
-						testType: testType,
-						name:     "CertificateVerificationFailsOnResume" + suffix,
-						config: Config{
-							MaxVersion: vers.version,
-							Credential: &rsaCertificate,
-						},
-						flags: append([]string{
-							"-on-resume-verify-fail",
-							"-reverify-on-resume",
-						}, flags...),
-						resumeSession:      true,
-						shouldFail:         true,
-						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
-						expectedLocalError: verifyFailLocalError,
-					})
-					tests = append(tests, testCase{
-						testType: testType,
-						name:     "CertificateVerificationPassesOnResume" + suffix,
-						config: Config{
-							MaxVersion: vers.version,
-							Credential: &rsaCertificate,
-						},
-						flags: append([]string{
-							"-reverify-on-resume",
-						}, flags...),
-						resumeSession: true,
-					})
-					// TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3.
-					if vers.version >= VersionTLS13 && config.protocol != dtls {
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-							},
-							resumeConfig: &Config{
-								MaxVersion:             vers.version,
-								SessionTicketsDisabled: true,
-							},
-							resumeSession:           true,
-							expectResumeRejected:    true,
-							earlyData:               true,
-							expectEarlyDataRejected: true,
-							flags: append([]string{
-								"-reverify-on-resume",
-								// Session tickets are disabled, so the runner will not send a ticket.
-								"-on-retry-expect-no-session",
-							}, flags...),
-						})
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-								Bugs: ProtocolBugs{
-									AlwaysRejectEarlyData: true,
-								},
-							},
-							resumeSession:           true,
-							expectResumeRejected:    false,
-							earlyData:               true,
-							expectEarlyDataRejected: true,
-							flags: append([]string{
-								"-reverify-on-resume",
-							}, flags...),
-						})
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-							},
-							resumeConfig: &Config{
-								MaxVersion:             vers.version,
-								SessionTicketsDisabled: true,
-							},
-							resumeSession:           true,
-							expectResumeRejected:    true,
-							earlyData:               true,
-							expectEarlyDataRejected: true,
-							shouldFail:              true,
-							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
-							flags: append([]string{
-								"-reverify-on-resume",
-								// Session tickets are disabled, so the runner will not send a ticket.
-								"-on-retry-expect-no-session",
-								"-on-retry-verify-fail",
-							}, flags...),
-						})
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-								Bugs: ProtocolBugs{
-									AlwaysRejectEarlyData: true,
-								},
-							},
-							resumeSession:           true,
-							expectResumeRejected:    false,
-							earlyData:               true,
-							expectEarlyDataRejected: true,
-							shouldFail:              true,
-							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
-							expectedLocalError:      verifyFailLocalError,
-							flags: append([]string{
-								"-reverify-on-resume",
-								"-on-retry-verify-fail",
-							}, flags...),
-						})
-						// This tests that we only call the verify callback once.
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-							},
-							resumeSession: true,
-							earlyData:     true,
-							flags: append([]string{
-								"-reverify-on-resume",
-							}, flags...),
-						})
-						tests = append(tests, testCase{
-							testType: testType,
-							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
-							config: Config{
-								MaxVersion: vers.version,
-							},
-							resumeSession: true,
-							earlyData:     true,
-							shouldFail:    true,
-							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
-							// We do not set expectedLocalError here because the shim rejects
-							// the connection without an alert.
-							flags: append([]string{
-								"-reverify-on-resume",
-								"-on-resume-verify-fail",
-							}, flags...),
-						})
-					}
-				}
-			}
-		}
-
-		// By default, the client is in a soft fail mode where the peer
-		// certificate is verified but failures are non-fatal.
-		tests = append(tests, testCase{
-			testType: clientTest,
-			name:     "CertificateVerificationSoftFail-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-verify-fail",
-				"-expect-verify-result",
-			},
-			resumeSession: true,
-		})
-	}
-
-	tests = append(tests, testCase{
-		name:               "ShimSendAlert",
-		flags:              []string{"-send-alert"},
-		shimWritesFirst:    true,
-		shouldFail:         true,
-		expectedLocalError: "remote error: decompression failure",
-	})
-
-	if config.protocol == tls {
-		tests = append(tests, testCase{
-			name: "Renegotiate-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			renegotiate: 1,
-			flags: []string{
-				"-renegotiate-freely",
-				"-expect-total-renegotiations", "1",
-			},
-		})
-
-		tests = append(tests, testCase{
-			name: "Renegotiate-Client-Explicit",
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			renegotiate: 1,
-			flags: []string{
-				"-renegotiate-explicit",
-				"-expect-total-renegotiations", "1",
-			},
-		})
-
-		halfHelloRequestError := ":UNEXPECTED_RECORD:"
-		if config.packHandshake {
-			// If the HelloRequest is sent in the same record as the server Finished,
-			// BoringSSL rejects it before the handshake completes.
-			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
-		}
-		tests = append(tests, testCase{
-			name: "SendHalfHelloRequest",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					PackHelloRequestWithFinished: config.packHandshake,
-				},
-			},
-			sendHalfHelloRequest: true,
-			flags:                []string{"-renegotiate-ignore"},
-			shouldFail:           true,
-			expectedError:        halfHelloRequestError,
-		})
-
-		// NPN on client and server; results in post-ChangeCipherSpec message.
-		tests = append(tests, testCase{
-			name: "NPN-Client",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				NextProtos: []string{"foo"},
-			},
-			flags:         []string{"-select-next-proto", "foo"},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				nextProto:     "foo",
-				nextProtoType: npn,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "NPN-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				NextProtos: []string{"bar"},
-			},
-			flags: []string{
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-				"-expect-next-proto", "bar",
-			},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				nextProto:     "bar",
-				nextProtoType: npn,
-			},
-		})
-
-		// The client may select no protocol after seeing the server list.
-		tests = append(tests, testCase{
-			name: "NPN-Client-ClientSelectEmpty",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				NextProtos: []string{"foo"},
-			},
-			flags:         []string{"-select-empty-next-proto"},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				noNextProto:   true,
-				nextProtoType: npn,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "NPN-Server-ClientSelectEmpty",
-			config: Config{
-				MaxVersion:          VersionTLS12,
-				NextProtos:          []string{"no-match"},
-				NoFallbackNextProto: true,
-			},
-			flags: []string{
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-				"-expect-no-next-proto",
-			},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				noNextProto:   true,
-				nextProtoType: npn,
-			},
-		})
-
-		// The server may negotiate NPN, despite offering no protocols. In this
-		// case, the server must still be prepared for the client to select a
-		// fallback protocol.
-		tests = append(tests, testCase{
-			name: "NPN-Client-ServerAdvertiseEmpty",
-			config: Config{
-				MaxVersion:               VersionTLS12,
-				NegotiateNPNWithNoProtos: true,
-			},
-			flags:         []string{"-select-next-proto", "foo"},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				nextProto:     "foo",
-				nextProtoType: npn,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "NPN-Server-ServerAdvertiseEmpty",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				NextProtos: []string{"foo"},
-			},
-			flags: []string{
-				"-advertise-empty-npn",
-				"-expect-next-proto", "foo",
-			},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				nextProto:     "foo",
-				nextProtoType: npn,
-			},
-		})
-
-		// Client does False Start and negotiates NPN.
-		tests = append(tests, testCase{
-			name: "FalseStart",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart: true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-select-next-proto", "foo",
-			},
-			shimWritesFirst: true,
-			resumeSession:   true,
-		})
-
-		// Client does False Start and negotiates ALPN.
-		tests = append(tests, testCase{
-			name: "FalseStart-ALPN",
-			config: Config{
-				MaxVersion:   VersionTLS12,
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart: true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-advertise-alpn", "\x03foo",
-				"-expect-alpn", "foo",
-			},
-			shimWritesFirst: true,
-			resumeSession:   true,
-		})
-
-		// False Start without session tickets.
-		tests = append(tests, testCase{
-			name: "FalseStart-SessionTicketsDisabled",
-			config: Config{
-				MaxVersion:             VersionTLS12,
-				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:             []string{"foo"},
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					ExpectFalseStart: true,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-select-next-proto", "foo",
-			},
-			shimWritesFirst: true,
-		})
-
-		// Server parses a V2ClientHello. Test different lengths for the
-		// challenge field.
-		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
-			tests = append(tests, testCase{
-				testType: serverTest,
-				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
-				config: Config{
-					// Choose a cipher suite that does not involve
-					// elliptic curves, so no extensions are
-					// involved.
-					MaxVersion:   VersionTLS12,
-					CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-					Bugs: ProtocolBugs{
-						SendV2ClientHello:            true,
-						V2ClientHelloChallengeLength: challengeLength,
-					},
-				},
-				flags: []string{
-					"-expect-msg-callback",
-					`read v2clienthello
-write hs 2
-write hs 11
-write hs 14
-read hs 16
-read ccs
-read hs 20
-write ccs
-write hs 20
-read alert 1 0
-`,
-				},
-			})
-		}
-
-		// Channel ID and NPN at the same time, to ensure their relative
-		// ordering is correct.
-		tests = append(tests, testCase{
-			name: "ChannelID-NPN-Client",
-			config: Config{
-				MaxVersion:       VersionTLS12,
-				RequestChannelID: true,
-				NextProtos:       []string{"foo"},
-			},
-			flags: []string{
-				"-send-channel-id", channelIDKeyPath,
-				"-select-next-proto", "foo",
-			},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				channelID:     true,
-				nextProto:     "foo",
-				nextProtoType: npn,
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "ChannelID-NPN-Server",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				ChannelID:  &channelIDKey,
-				NextProtos: []string{"bar"},
-			},
-			flags: []string{
-				"-expect-channel-id",
-				base64FlagValue(channelIDBytes),
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-				"-expect-next-proto", "bar",
-			},
-			resumeSession: true,
-			expectations: connectionExpectations{
-				channelID:     true,
-				nextProto:     "bar",
-				nextProtoType: npn,
-			},
-		})
-
-		// Bidirectional shutdown with the runner initiating.
-		tests = append(tests, testCase{
-			name: "Shutdown-Runner",
-			config: Config{
-				Bugs: ProtocolBugs{
-					ExpectCloseNotify: true,
-				},
-			},
-			flags: []string{"-check-close-notify"},
-		})
-	}
-	if config.protocol != dtls {
-		// Test Channel ID
-		for _, ver := range allVersions(config.protocol) {
-			if ver.version < VersionTLS10 {
-				continue
-			}
-			// Client sends a Channel ID.
-			tests = append(tests, testCase{
-				name: "ChannelID-Client-" + ver.name,
-				config: Config{
-					MaxVersion:       ver.version,
-					RequestChannelID: true,
-				},
-				flags:         []string{"-send-channel-id", channelIDKeyPath},
-				resumeSession: true,
-				expectations: connectionExpectations{
-					channelID: true,
-				},
-			})
-
-			// Server accepts a Channel ID.
-			tests = append(tests, testCase{
-				testType: serverTest,
-				name:     "ChannelID-Server-" + ver.name,
-				config: Config{
-					MaxVersion: ver.version,
-					ChannelID:  &channelIDKey,
-				},
-				flags: []string{
-					"-expect-channel-id",
-					base64FlagValue(channelIDBytes),
-				},
-				resumeSession: true,
-				expectations: connectionExpectations{
-					channelID: true,
-				},
-			})
-
-			tests = append(tests, testCase{
-				testType: serverTest,
-				name:     "InvalidChannelIDSignature-" + ver.name,
-				config: Config{
-					MaxVersion: ver.version,
-					ChannelID:  &channelIDKey,
-					Bugs: ProtocolBugs{
-						InvalidChannelIDSignature: true,
-					},
-				},
-				flags:         []string{"-enable-channel-id"},
-				shouldFail:    true,
-				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
-			})
-
-			if ver.version < VersionTLS13 {
-				// Channel ID requires ECDHE ciphers.
-				tests = append(tests, testCase{
-					testType: serverTest,
-					name:     "ChannelID-NoECDHE-" + ver.name,
-					config: Config{
-						MaxVersion:   ver.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-						ChannelID:    &channelIDKey,
-					},
-					expectations: connectionExpectations{
-						channelID: false,
-					},
-					flags: []string{"-enable-channel-id"},
-				})
-
-				// Sanity-check setting expectations.channelID false works.
-				tests = append(tests, testCase{
-					testType: serverTest,
-					name:     "ChannelID-ECDHE-" + ver.name,
-					config: Config{
-						MaxVersion:   ver.version,
-						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
-						ChannelID:    &channelIDKey,
-					},
-					expectations: connectionExpectations{
-						channelID: false,
-					},
-					flags:              []string{"-enable-channel-id"},
-					shouldFail:         true,
-					expectedLocalError: "channel ID unexpectedly negotiated",
-				})
-			}
-		}
-
-		if !config.implicitHandshake {
-			// Bidirectional shutdown with the shim initiating. The runner,
-			// in the meantime, sends garbage before the close_notify which
-			// the shim must ignore. This test is disabled under implicit
-			// handshake tests because the shim never reads or writes.
-
-			// Tests that require checking for a close notify alert don't work with
-			// QUIC because alerts are handled outside of the TLS stack in QUIC.
-			if config.protocol != quic {
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim",
-					config: Config{
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown:     true,
-					sendEmptyRecords:  1,
-					sendWarningAlerts: 1,
-					flags:             []string{"-check-close-notify"},
-				})
-
-				// The shim should reject unexpected application data
-				// when shutting down.
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim-ApplicationData",
-					config: Config{
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown:     true,
-					messageCount:      1,
-					sendEmptyRecords:  1,
-					sendWarningAlerts: 1,
-					flags:             []string{"-check-close-notify"},
-					shouldFail:        true,
-					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
-				})
-
-				// Test that SSL_shutdown still processes KeyUpdate.
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim-KeyUpdate",
-					config: Config{
-						MinVersion: VersionTLS13,
-						MaxVersion: VersionTLS13,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown:    true,
-					sendKeyUpdates:   1,
-					keyUpdateRequest: keyUpdateRequested,
-					flags:            []string{"-check-close-notify"},
-				})
-
-				// Test that SSL_shutdown processes HelloRequest
-				// correctly.
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim-HelloRequest-Ignore",
-					config: Config{
-						MinVersion: VersionTLS12,
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							SendHelloRequestBeforeEveryAppDataRecord: true,
-							ExpectCloseNotify:                        true,
-						},
-					},
-					shimShutsDown: true,
-					flags: []string{
-						"-renegotiate-ignore",
-						"-check-close-notify",
-					},
-				})
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim-HelloRequest-Reject",
-					config: Config{
-						MinVersion: VersionTLS12,
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown: true,
-					renegotiate:   1,
-					shouldFail:    true,
-					expectedError: ":NO_RENEGOTIATION:",
-					flags:         []string{"-check-close-notify"},
-				})
-				tests = append(tests, testCase{
-					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
-					config: Config{
-						MinVersion: VersionTLS12,
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown: true,
-					renegotiate:   1,
-					shouldFail:    true,
-					expectedError: ":NO_RENEGOTIATION:",
-					flags: []string{
-						"-check-close-notify",
-						"-renegotiate-freely",
-					},
-				})
-
-				tests = append(tests, testCase{
-					testType: serverTest,
-					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
-					config: Config{
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							ExpectCloseNotify: true,
-						},
-					},
-					shimShutsDown: true,
-					renegotiate:   1,
-					shouldFail:    true,
-					expectedError: ":NO_RENEGOTIATION:",
-					flags: []string{
-						"-check-close-notify",
-					},
-				})
-			}
-		}
-	}
-	if config.protocol == dtls {
-		tests = append(tests, testCase{
-			name: "SkipHelloVerifyRequest",
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SkipHelloVerifyRequest: true,
-				},
-			},
-		})
-		tests = append(tests, testCase{
-			name: "DTLS13-HelloVerifyRequest",
-			config: Config{
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ForceHelloVerifyRequest: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":INVALID_MESSAGE:",
-		})
-		tests = append(tests, testCase{
-			name: "DTLS13-HelloVerifyRequestEmptyCookie",
-			config: Config{
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ForceHelloVerifyRequest:       true,
-					EmptyHelloVerifyRequestCookie: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":INVALID_MESSAGE:",
-		})
-	}
-
-	for _, test := range tests {
-		test.protocol = config.protocol
-		test.name += "-" + config.protocol.String()
-		if config.async {
-			test.name += "-Async"
-			test.flags = append(test.flags, "-async")
-		} else {
-			test.name += "-Sync"
-		}
-		if config.splitHandshake {
-			test.name += "-SplitHandshakeRecords"
-			test.config.Bugs.MaxHandshakeRecordLength = 1
-			if config.protocol == dtls {
-				test.config.Bugs.MaxPacketLength = 256
-				test.flags = append(test.flags, "-mtu", "256")
-			}
-		}
-		if config.packHandshake {
-			test.name += "-PackHandshake"
-			if config.protocol == dtls {
-				test.config.Bugs.MaxHandshakeRecordLength = 2
-				test.config.Bugs.PackHandshakeFragments = 20
-				test.config.Bugs.PackHandshakeRecords = 1500
-				test.config.Bugs.PackAppDataWithHandshake = true
-			} else {
-				test.config.Bugs.PackHandshakeFlight = true
-			}
-		}
-		if config.implicitHandshake {
-			test.name += "-ImplicitHandshake"
-			test.flags = append(test.flags, "-implicit-handshake")
-		}
-		testCases = append(testCases, test)
-	}
-}
-
-func addDDoSCallbackTests() {
-	// DDoS callback.
-	for _, resume := range []bool{false, true} {
-		suffix := "Resume"
-		if resume {
-			suffix = "No" + suffix
-		}
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "Server-DDoS-OK-" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			flags:         []string{"-install-ddos-callback"},
-			resumeSession: resume,
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			flags:         []string{"-install-ddos-callback"},
-			resumeSession: resume,
-		})
-
-		failFlag := "-fail-ddos-callback"
-		if resume {
-			failFlag = "-on-resume-fail-ddos-callback"
-		}
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "Server-DDoS-Reject-" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			flags:              []string{"-install-ddos-callback", failFlag},
-			resumeSession:      resume,
-			shouldFail:         true,
-			expectedError:      ":CONNECTION_REJECTED:",
-			expectedLocalError: "remote error: internal error",
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			flags:              []string{"-install-ddos-callback", failFlag},
-			resumeSession:      resume,
-			shouldFail:         true,
-			expectedError:      ":CONNECTION_REJECTED:",
-			expectedLocalError: "remote error: internal error",
-		})
-	}
-}
-
-func addVersionNegotiationTests() {
-	for _, protocol := range []protocol{tls, dtls, quic} {
-		for _, shimVers := range allVersions(protocol) {
-			// Assemble flags to disable all newer versions on the shim.
-			var flags []string
-			for _, vers := range allVersions(protocol) {
-				if vers.version > shimVers.version {
-					flags = append(flags, vers.excludeFlag)
-				}
-			}
-
-			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
-
-			// Test configuring the runner's maximum version.
-			for _, runnerVers := range allVersions(protocol) {
-				expectedVersion := shimVers.version
-				if runnerVers.version < shimVers.version {
-					expectedVersion = runnerVers.version
-				}
-
-				suffix := shimVers.name + "-" + runnerVers.name
-				suffix += "-" + protocol.String()
-
-				// Determine the expected initial record-layer versions.
-				clientVers := shimVers.version
-				if clientVers > VersionTLS10 {
-					clientVers = VersionTLS10
-				}
-				clientVers = recordVersionToWire(clientVers, protocol)
-				serverVers := expectedVersion
-				if expectedVersion >= VersionTLS13 {
-					serverVers = VersionTLS12
-				}
-				serverVers = recordVersionToWire(serverVers, protocol)
-
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "VersionNegotiation-Client-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: clientVers,
-						},
-					},
-					flags: flags,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					// The version name check does not recognize the
-					// |excludeFlag| construction in |flags|.
-					skipVersionNameCheck: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "VersionNegotiation-Client2-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: clientVers,
-						},
-					},
-					flags: flags2,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-				})
-
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "VersionNegotiation-Server-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: serverVers,
-						},
-					},
-					flags: flags,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					// The version name check does not recognize the
-					// |excludeFlag| construction in |flags|.
-					skipVersionNameCheck: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "VersionNegotiation-Server2-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: serverVers,
-						},
-					},
-					flags: flags2,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-				})
-			}
-		}
-	}
-
-	// Test the version extension at all versions.
-	for _, protocol := range []protocol{tls, dtls, quic} {
-		for _, vers := range allVersions(protocol) {
-			suffix := vers.name + "-" + protocol.String()
-
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "VersionNegotiationExtension-" + suffix,
-				config: Config{
-					Bugs: ProtocolBugs{
-						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
-						IgnoreTLS13DowngradeRandom: true,
-					},
-				},
-				expectations: connectionExpectations{
-					version: vers.version,
-				},
-			})
-		}
-	}
-
-	// If all versions are unknown, negotiation fails.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoSupportedVersions",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendSupportedVersions: []uint16{0x1111},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNSUPPORTED_PROTOCOL:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "NoSupportedVersions-DTLS",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendSupportedVersions: []uint16{0x1111},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNSUPPORTED_PROTOCOL:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ClientHelloVersionTooHigh",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendClientVersion:          0x0304,
-				OmitSupportedVersions:      true,
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ConflictingVersionNegotiation",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          VersionTLS12,
-				SendSupportedVersions:      []uint16{VersionTLS11},
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		// The extension takes precedence over the ClientHello version.
-		expectations: connectionExpectations{
-			version: VersionTLS11,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ConflictingVersionNegotiation-2",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          VersionTLS11,
-				SendSupportedVersions:      []uint16{VersionTLS12},
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		// The extension takes precedence over the ClientHello version.
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-
-	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
-	// the ServerHello.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "SupportedVersionSelection-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendServerSupportedVersionExtension: VersionTLS12,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	// Test that the maximum version is selected regardless of the
-	// client-sent order.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "IgnoreClientVersionOrder",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS13,
-		},
-	})
-
-	// Test for version tolerance.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "MinorVersionTolerance",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          0x03ff,
-				OmitSupportedVersions:      true,
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "MajorVersionTolerance",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          0x0400,
-				OmitSupportedVersions:      true,
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		// TLS 1.3 must be negotiated with the supported_versions
-		// extension, not ClientHello.version.
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "VersionTolerance-TLS13",
-		config: Config{
-			Bugs: ProtocolBugs{
-				// Although TLS 1.3 does not use
-				// ClientHello.version, it still tolerates high
-				// values there.
-				SendClientVersion: 0x0400,
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS13,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "MinorVersionTolerance-DTLS",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          0xfe00,
-				OmitSupportedVersions:      true,
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "MajorVersionTolerance-DTLS",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:          0xfdff,
-				OmitSupportedVersions:      true,
-				IgnoreTLS13DowngradeRandom: true,
-			},
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-	})
-
-	// Test that versions below 3.0 are rejected.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "VersionTooLow",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:     0x0200,
-				OmitSupportedVersions: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNSUPPORTED_PROTOCOL:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "VersionTooLow-DTLS",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendClientVersion:     0xffff,
-				OmitSupportedVersions: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNSUPPORTED_PROTOCOL:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ServerBogusVersion",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendServerHelloVersion: 0x1234,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNSUPPORTED_PROTOCOL:",
-	})
-
-	// Test TLS 1.3's downgrade signal.
-	for _, protocol := range []protocol{tls, dtls} {
-		for _, vers := range allVersions(protocol) {
-			if vers.version >= VersionTLS13 {
-				continue
-			}
-			clientShimError := "tls: downgrade from TLS 1.3 detected"
-			if vers.version < VersionTLS12 {
-				clientShimError = "tls: downgrade from TLS 1.2 detected"
-			}
-			// for _, test := range downgradeTests {
-			// The client should enforce the downgrade sentinel.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "Downgrade-" + vers.name + "-Client-" + protocol.String(),
-				config: Config{
-					Bugs: ProtocolBugs{
-						NegotiateVersion: vers.wire(protocol),
-					},
-				},
-				expectations: connectionExpectations{
-					version: vers.version,
-				},
-				shouldFail:         true,
-				expectedError:      ":TLS13_DOWNGRADE:",
-				expectedLocalError: "remote error: illegal parameter",
-			})
-
-			// The server should emit the downgrade signal.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "Downgrade-" + vers.name + "-Server-" + protocol.String(),
-				config: Config{
-					Bugs: ProtocolBugs{
-						SendSupportedVersions: []uint16{vers.wire(protocol)},
-					},
-				},
-				expectations: connectionExpectations{
-					version: vers.version,
-				},
-				shouldFail:         true,
-				expectedLocalError: clientShimError,
-			})
-		}
-	}
-
-	// SSL 3.0 support has been removed. Test that the shim does not
-	// support it.
-	testCases = append(testCases, testCase{
-		name: "NoSSL3-Client",
-		config: Config{
-			MinVersion: VersionSSL30,
-			MaxVersion: VersionSSL30,
-		},
-		shouldFail:         true,
-		expectedLocalError: "tls: client did not offer any supported protocol versions",
-	})
-	testCases = append(testCases, testCase{
-		name: "NoSSL3-Client-Unsolicited",
-		config: Config{
-			MinVersion: VersionSSL30,
-			MaxVersion: VersionSSL30,
-			Bugs: ProtocolBugs{
-				// The above test asserts the client does not
-				// offer SSL 3.0 in the supported_versions
-				// list. Additionally assert that it rejects an
-				// unsolicited SSL 3.0 ServerHello.
-				NegotiateVersion: VersionSSL30,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNSUPPORTED_PROTOCOL:",
-		expectedLocalError: "remote error: protocol version not supported",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoSSL3-Server",
-		config: Config{
-			MinVersion: VersionSSL30,
-			MaxVersion: VersionSSL30,
-		},
-		shouldFail:         true,
-		expectedError:      ":UNSUPPORTED_PROTOCOL:",
-		expectedLocalError: "remote error: protocol version not supported",
-	})
-}
-
-func addMinimumVersionTests() {
-	for _, protocol := range []protocol{tls, dtls, quic} {
-		for _, shimVers := range allVersions(protocol) {
-			// Assemble flags to disable all older versions on the shim.
-			var flags []string
-			for _, vers := range allVersions(protocol) {
-				if vers.version < shimVers.version {
-					flags = append(flags, vers.excludeFlag)
-				}
-			}
-
-			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
-
-			for _, runnerVers := range allVersions(protocol) {
-				suffix := shimVers.name + "-" + runnerVers.name
-				suffix += "-" + protocol.String()
-
-				var expectedVersion uint16
-				var shouldFail bool
-				var expectedError, expectedLocalError string
-				if runnerVers.version >= shimVers.version {
-					expectedVersion = runnerVers.version
-				} else {
-					shouldFail = true
-					expectedError = ":UNSUPPORTED_PROTOCOL:"
-					expectedLocalError = "remote error: protocol version not supported"
-				}
-
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "MinimumVersion-Client-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							// Ensure the server does not decline to
-							// select a version (versions extension) or
-							// cipher (some ciphers depend on versions).
-							NegotiateVersion:            runnerVers.wire(protocol),
-							IgnorePeerCipherPreferences: shouldFail,
-						},
-					},
-					flags: flags,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					shouldFail:         shouldFail,
-					expectedError:      expectedError,
-					expectedLocalError: expectedLocalError,
-					// The version name check does not recognize the
-					// |excludeFlag| construction in |flags|.
-					skipVersionNameCheck: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "MinimumVersion-Client2-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-						Bugs: ProtocolBugs{
-							// Ensure the server does not decline to
-							// select a version (versions extension) or
-							// cipher (some ciphers depend on versions).
-							NegotiateVersion:            runnerVers.wire(protocol),
-							IgnorePeerCipherPreferences: shouldFail,
-						},
-					},
-					flags: flags2,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					shouldFail:         shouldFail,
-					expectedError:      expectedError,
-					expectedLocalError: expectedLocalError,
-				})
-
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "MinimumVersion-Server-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-					},
-					flags: flags,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					shouldFail:         shouldFail,
-					expectedError:      expectedError,
-					expectedLocalError: expectedLocalError,
-					// The version name check does not recognize the
-					// |excludeFlag| construction in |flags|.
-					skipVersionNameCheck: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "MinimumVersion-Server2-" + suffix,
-					config: Config{
-						MaxVersion: runnerVers.version,
-					},
-					flags: flags2,
-					expectations: connectionExpectations{
-						version: expectedVersion,
-					},
-					shouldFail:         shouldFail,
-					expectedError:      expectedError,
-					expectedLocalError: expectedLocalError,
-				})
-			}
-		}
-	}
-}
-
-func addExtensionTests() {
-	exampleCertificate := generateSingleCertChain(&x509.Certificate{
-		SerialNumber: big.NewInt(57005),
-		Subject: pkix.Name{
-			CommonName: "test cert",
-		},
-		NotBefore:             time.Now().Add(-time.Hour),
-		NotAfter:              time.Now().Add(time.Hour),
-		DNSNames:              []string{"example.com"},
-		IsCA:                  true,
-		BasicConstraintsValid: true,
-	}, &ecdsaP256Key)
-
-	// Repeat extensions tests at all versions.
-	for _, protocol := range []protocol{tls, dtls, quic} {
-		for _, ver := range allVersions(protocol) {
-			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
-
-			// Test that duplicate extensions are rejected.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "DuplicateExtensionClient-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						DuplicateExtension: true,
-					},
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: error decoding message",
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "DuplicateExtensionServer-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						DuplicateExtension: true,
-					},
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: error decoding message",
-			})
-
-			// Test SNI.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "ServerNameExtensionClient-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						ExpectServerName: "example.com",
-					},
-					Credential: &exampleCertificate,
-				},
-				flags: []string{"-host-name", "example.com"},
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "ServerNameExtensionClientMismatch-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						ExpectServerName: "mismatch.com",
-					},
-				},
-				flags:              []string{"-host-name", "example.com"},
-				shouldFail:         true,
-				expectedLocalError: "tls: unexpected server name",
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "ServerNameExtensionClientMissing-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						ExpectServerName: "missing.com",
-					},
-				},
-				shouldFail:         true,
-				expectedLocalError: "tls: unexpected server name",
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "TolerateServerNameAck-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						SendServerNameAck: true,
-					},
-					Credential: &exampleCertificate,
-				},
-				flags:         []string{"-host-name", "example.com"},
-				resumeSession: true,
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: clientTest,
-				name:     "UnsolicitedServerNameAck-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						SendServerNameAck: true,
-					},
-				},
-				shouldFail:         true,
-				expectedError:      ":UNEXPECTED_EXTENSION:",
-				expectedLocalError: "remote error: unsupported extension",
-			})
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "ServerNameExtensionServer-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					ServerName: "example.com",
-				},
-				flags:         []string{"-expect-server-name", "example.com"},
-				resumeSession: true,
-			})
-
-			// Test ALPN.
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           clientTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNClient-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo"},
-				},
-				flags: []string{
-					"-advertise-alpn", "\x03foo\x03bar\x03baz",
-					"-expect-alpn", "foo",
-				},
-				expectations: connectionExpectations{
-					nextProto:     "foo",
-					nextProtoType: alpn,
-				},
-				resumeSession: true,
-			})
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           clientTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNClient-RejectUnknown-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						SendALPN: "baz",
-					},
-				},
-				flags: []string{
-					"-advertise-alpn", "\x03foo\x03bar",
-				},
-				shouldFail:         true,
-				expectedError:      ":INVALID_ALPN_PROTOCOL:",
-				expectedLocalError: "remote error: illegal parameter",
-			})
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           clientTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNClient-AllowUnknown-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						SendALPN: "baz",
-					},
-				},
-				flags: []string{
-					"-advertise-alpn", "\x03foo\x03bar",
-					"-allow-unknown-alpn-protos",
-					"-expect-alpn", "baz",
-				},
-			})
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo", "bar", "baz"},
-				},
-				flags: []string{
-					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-					"-select-alpn", "foo",
-				},
-				expectations: connectionExpectations{
-					nextProto:     "foo",
-					nextProtoType: alpn,
-				},
-				resumeSession: true,
-			})
-
-			var shouldDeclineALPNFail bool
-			var declineALPNError, declineALPNLocalError string
-			if protocol == quic {
-				// ALPN is mandatory in QUIC.
-				shouldDeclineALPNFail = true
-				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
-				declineALPNLocalError = "remote error: no application protocol"
-			}
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-Decline-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo", "bar", "baz"},
-				},
-				flags: []string{"-decline-alpn"},
-				expectations: connectionExpectations{
-					noNextProto: true,
-				},
-				resumeSession:      true,
-				shouldFail:         shouldDeclineALPNFail,
-				expectedError:      declineALPNError,
-				expectedLocalError: declineALPNLocalError,
-			})
-
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-Reject-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo", "bar", "baz"},
-				},
-				flags:              []string{"-reject-alpn"},
-				shouldFail:         true,
-				expectedError:      ":NO_APPLICATION_PROTOCOL:",
-				expectedLocalError: "remote error: no application protocol",
-			})
-
-			// Test that the server implementation catches itself if the
-			// callback tries to return an invalid empty ALPN protocol.
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-SelectEmpty-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo", "bar", "baz"},
-				},
-				flags: []string{
-					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-					"-select-empty-alpn",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: internal error",
-				expectedError:      ":INVALID_ALPN_PROTOCOL:",
-			})
-
-			// Test ALPN in async mode as well to ensure that extensions callbacks are only
-			// called once.
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-Async-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{"foo", "bar", "baz"},
-					// Prior to TLS 1.3, exercise the asynchronous session callback.
-					SessionTicketsDisabled: ver.version < VersionTLS13,
-				},
-				flags: []string{
-					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-					"-select-alpn", "foo",
-					"-async",
-				},
-				expectations: connectionExpectations{
-					nextProto:     "foo",
-					nextProtoType: alpn,
-				},
-				resumeSession: true,
-			})
-
-			var emptyString string
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           clientTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNClient-EmptyProtocolName-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					NextProtos: []string{""},
-					Bugs: ProtocolBugs{
-						// A server returning an empty ALPN protocol
-						// should be rejected.
-						ALPNProtocol: &emptyString,
-					},
-				},
-				flags: []string{
-					"-advertise-alpn", "\x03foo",
-				},
-				shouldFail:    true,
-				expectedError: ":PARSE_TLSEXT:",
-			})
-			testCases = append(testCases, testCase{
-				protocol:           protocol,
-				testType:           serverTest,
-				skipQUICALPNConfig: true,
-				name:               "ALPNServer-EmptyProtocolName-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					// A ClientHello containing an empty ALPN protocol
-					// should be rejected.
-					NextProtos: []string{"foo", "", "baz"},
-				},
-				flags: []string{
-					"-select-alpn", "foo",
-				},
-				shouldFail:    true,
-				expectedError: ":PARSE_TLSEXT:",
-			})
-
-			// Test NPN and the interaction with ALPN.
-			if ver.version < VersionTLS13 && protocol == tls {
-				// Test that the server prefers ALPN over NPN.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "ALPNServer-Preferred-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						NextProtos: []string{"foo", "bar", "baz"},
-					},
-					flags: []string{
-						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-						"-select-alpn", "foo",
-						"-advertise-npn", "\x03foo\x03bar\x03baz",
-					},
-					expectations: connectionExpectations{
-						nextProto:     "foo",
-						nextProtoType: alpn,
-					},
-					resumeSession: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "ALPNServer-Preferred-Swapped-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						NextProtos: []string{"foo", "bar", "baz"},
-						Bugs: ProtocolBugs{
-							SwapNPNAndALPN: true,
-						},
-					},
-					flags: []string{
-						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-						"-select-alpn", "foo",
-						"-advertise-npn", "\x03foo\x03bar\x03baz",
-					},
-					expectations: connectionExpectations{
-						nextProto:     "foo",
-						nextProtoType: alpn,
-					},
-					resumeSession: true,
-				})
-
-				// Test that negotiating both NPN and ALPN is forbidden.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					name:     "NegotiateALPNAndNPN-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						NextProtos: []string{"foo", "bar", "baz"},
-						Bugs: ProtocolBugs{
-							NegotiateALPNAndNPN: true,
-						},
-					},
-					flags: []string{
-						"-advertise-alpn", "\x03foo",
-						"-select-next-proto", "foo",
-					},
-					shouldFail:    true,
-					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						NextProtos: []string{"foo", "bar", "baz"},
-						Bugs: ProtocolBugs{
-							NegotiateALPNAndNPN: true,
-							SwapNPNAndALPN:      true,
-						},
-					},
-					flags: []string{
-						"-advertise-alpn", "\x03foo",
-						"-select-next-proto", "foo",
-					},
-					shouldFail:    true,
-					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
-				})
-			}
-
-			// Test missing ALPN in QUIC
-			if protocol == quic {
-				testCases = append(testCases, testCase{
-					testType: clientTest,
-					protocol: protocol,
-					name:     "Client-ALPNMissingFromConfig-" + suffix,
-					config: Config{
-						MinVersion: ver.version,
-						MaxVersion: ver.version,
-					},
-					skipQUICALPNConfig: true,
-					shouldFail:         true,
-					expectedError:      ":NO_APPLICATION_PROTOCOL:",
-				})
-				testCases = append(testCases, testCase{
-					testType: clientTest,
-					protocol: protocol,
-					name:     "Client-ALPNMissing-" + suffix,
-					config: Config{
-						MinVersion: ver.version,
-						MaxVersion: ver.version,
-					},
-					flags: []string{
-						"-advertise-alpn", "\x03foo",
-					},
-					skipQUICALPNConfig: true,
-					shouldFail:         true,
-					expectedError:      ":NO_APPLICATION_PROTOCOL:",
-					expectedLocalError: "remote error: no application protocol",
-				})
-				testCases = append(testCases, testCase{
-					testType: serverTest,
-					protocol: protocol,
-					name:     "Server-ALPNMissing-" + suffix,
-					config: Config{
-						MinVersion: ver.version,
-						MaxVersion: ver.version,
-					},
-					skipQUICALPNConfig: true,
-					shouldFail:         true,
-					expectedError:      ":NO_APPLICATION_PROTOCOL:",
-					expectedLocalError: "remote error: no application protocol",
-				})
-				testCases = append(testCases, testCase{
-					testType: serverTest,
-					protocol: protocol,
-					name:     "Server-ALPNMismatch-" + suffix,
-					config: Config{
-						MinVersion: ver.version,
-						MaxVersion: ver.version,
-						NextProtos: []string{"foo"},
-					},
-					flags: []string{
-						"-decline-alpn",
-					},
-					skipQUICALPNConfig: true,
-					shouldFail:         true,
-					expectedError:      ":NO_APPLICATION_PROTOCOL:",
-					expectedLocalError: "remote error: no application protocol",
-				})
-			}
-
-			// Test ALPS.
-			if ver.version >= VersionTLS13 {
-				// Test basic client with different ALPS codepoint.
-				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
-					flags := []string{}
-					expectations := connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim1"),
-					}
-					resumeExpectations := &connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim2"),
-					}
-
-					if alpsCodePoint == ALPSUseCodepointNew {
-						flags = append(flags, "-alps-use-new-codepoint")
-						expectations = connectionExpectations{
-							peerApplicationSettings: []byte("shim1"),
-						}
-						resumeExpectations = &connectionExpectations{
-							peerApplicationSettings: []byte("shim2"),
-						}
-					}
-
-					flags = append(flags,
-						"-advertise-alpn", "\x05proto",
-						"-expect-alpn", "proto",
-						"-on-initial-application-settings", "proto,shim1",
-						"-on-initial-expect-peer-application-settings", "runner1",
-						"-on-resume-application-settings", "proto,shim2",
-						"-on-resume-expect-peer-application-settings", "runner2")
-
-					// Test that server can negotiate ALPS, including different values
-					// on resumption.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           clientTest,
-						name:               fmt.Sprintf("ALPS-Basic-Client-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeConfig: &Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession:      true,
-						expectations:       expectations,
-						resumeExpectations: resumeExpectations,
-						flags:              flags,
-					})
-
-					// Test basic server with different ALPS codepoint.
-					flags = []string{}
-					expectations = connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim1"),
-					}
-					resumeExpectations = &connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim2"),
-					}
-
-					if alpsCodePoint == ALPSUseCodepointNew {
-						flags = append(flags, "-alps-use-new-codepoint")
-						expectations = connectionExpectations{
-							peerApplicationSettings: []byte("shim1"),
-						}
-						resumeExpectations = &connectionExpectations{
-							peerApplicationSettings: []byte("shim2"),
-						}
-					}
-
-					flags = append(flags,
-						"-select-alpn", "proto",
-						"-on-initial-application-settings", "proto,shim1",
-						"-on-initial-expect-peer-application-settings", "runner1",
-						"-on-resume-application-settings", "proto,shim2",
-						"-on-resume-expect-peer-application-settings", "runner2")
-
-					// Test that server can negotiate ALPS, including different values
-					// on resumption.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-Basic-Server-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeConfig: &Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession:      true,
-						expectations:       expectations,
-						resumeExpectations: resumeExpectations,
-						flags:              flags,
-					})
-
-					// Try different ALPS codepoint for all the existing tests.
-					alpsFlags := []string{}
-					expectations = connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim1"),
-					}
-					resumeExpectations = &connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim2"),
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						alpsFlags = append(alpsFlags, "-alps-use-new-codepoint")
-						expectations = connectionExpectations{
-							peerApplicationSettings: []byte("shim1"),
-						}
-						resumeExpectations = &connectionExpectations{
-							peerApplicationSettings: []byte("shim2"),
-						}
-					}
-
-					// Test that the server can defer its ALPS configuration to the ALPN
-					// selection callback.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-Basic-Server-Defer-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeConfig: &Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession:      true,
-						expectations:       expectations,
-						resumeExpectations: resumeExpectations,
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-defer-alps",
-							"-on-initial-application-settings", "proto,shim1",
-							"-on-initial-expect-peer-application-settings", "runner1",
-							"-on-resume-application-settings", "proto,shim2",
-							"-on-resume-expect-peer-application-settings", "runner2",
-						}, alpsFlags...),
-					})
-
-					expectations = connectionExpectations{
-						peerApplicationSettingsOld: []byte{},
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						expectations = connectionExpectations{
-							peerApplicationSettings: []byte{},
-						}
-					}
-					// Test the client and server correctly handle empty settings.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           clientTest,
-						name:               fmt.Sprintf("ALPS-Empty-Client-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": {}},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession: true,
-						expectations:  expectations,
-						flags: append([]string{
-							"-advertise-alpn", "\x05proto",
-							"-expect-alpn", "proto",
-							"-application-settings", "proto,",
-							"-expect-peer-application-settings", "",
-						}, alpsFlags...),
-					})
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-Empty-Server-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": {}},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession: true,
-						expectations:  expectations,
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-application-settings", "proto,",
-							"-expect-peer-application-settings", "",
-						}, alpsFlags...),
-					})
-
-					bugs := ProtocolBugs{
-						AlwaysNegotiateApplicationSettingsOld: true,
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						bugs = ProtocolBugs{
-							AlwaysNegotiateApplicationSettingsNew: true,
-						}
-					}
-					// Test the client rejects application settings from the server on
-					// protocols it doesn't have them.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           clientTest,
-						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto1"},
-							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
-							Bugs:                bugs,
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						// The client supports ALPS with "proto2", but not "proto1".
-						flags: append([]string{
-							"-advertise-alpn", "\x06proto1\x06proto2",
-							"-application-settings", "proto2,shim",
-							"-expect-alpn", "proto1",
-						}, alpsFlags...),
-						// The server sends ALPS with "proto1", which is invalid.
-						shouldFail:         true,
-						expectedError:      ":INVALID_ALPN_PROTOCOL:",
-						expectedLocalError: "remote error: illegal parameter",
-					})
-
-					// Test client rejects application settings from the server when
-					// server sends the wrong ALPS codepoint.
-					bugs = ProtocolBugs{
-						AlwaysNegotiateApplicationSettingsOld: true,
-					}
-					if alpsCodePoint == ALPSUseCodepointOld {
-						bugs = ProtocolBugs{
-							AlwaysNegotiateApplicationSettingsNew: true,
-						}
-					}
-
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           clientTest,
-						name:               fmt.Sprintf("ALPS-WrongServerCodepoint-Client-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": {}},
-							Bugs:                bugs,
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags: append([]string{
-							"-advertise-alpn", "\x05proto",
-							"-expect-alpn", "proto",
-							"-application-settings", "proto,",
-							"-expect-peer-application-settings", "",
-						}, alpsFlags...),
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_EXTENSION:",
-						expectedLocalError: "remote error: unsupported extension",
-					})
-
-					// Test server ignore wrong codepoint from client.
-					clientSends := ALPSUseCodepointNew
-					if alpsCodePoint == ALPSUseCodepointNew {
-						clientSends = ALPSUseCodepointOld
-					}
-
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-IgnoreClientWrongCodepoint-Server-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
-							ALPSUseNewCodepoint: clientSends,
-						},
-						resumeConfig: &Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
-							ALPSUseNewCodepoint: clientSends,
-						},
-						resumeSession: true,
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-on-initial-application-settings", "proto,shim1",
-							"-on-resume-application-settings", "proto,shim2",
-						}, alpsFlags...),
-					})
-
-					// Test the server declines ALPS if it doesn't support it for the
-					// specified protocol.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Server-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto1"},
-							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						// The server supports ALPS with "proto2", but not "proto1".
-						flags: append([]string{
-							"-select-alpn", "proto1",
-							"-application-settings", "proto2,shim",
-						}, alpsFlags...),
-					})
-
-					// Test the client rejects application settings from the server when
-					// it always negotiate both codepoint.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           clientTest,
-						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-ServerBoth-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto1"},
-							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
-							Bugs: ProtocolBugs{
-								AlwaysNegotiateApplicationSettingsBoth: true,
-							},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags: append([]string{
-							"-advertise-alpn", "\x06proto1\x06proto2",
-							"-application-settings", "proto1,shim",
-							"-expect-alpn", "proto1",
-						}, alpsFlags...),
-						// The server sends ALPS with both application settings, which is invalid.
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_EXTENSION:",
-						expectedLocalError: "remote error: unsupported extension",
-					})
-
-					expectations = connectionExpectations{
-						peerApplicationSettingsOld: []byte("shim"),
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						expectations = connectionExpectations{
-							peerApplicationSettings: []byte("shim"),
-						}
-					}
-
-					// Test that the server rejects a missing application_settings extension.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-OmitClientApplicationSettings-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
-							Bugs: ProtocolBugs{
-								OmitClientApplicationSettings: true,
-							},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-application-settings", "proto,shim",
-						}, alpsFlags...),
-						// The runner is a client, so it only processes the shim's alert
-						// after checking connection state.
-						expectations:       expectations,
-						shouldFail:         true,
-						expectedError:      ":MISSING_EXTENSION:",
-						expectedLocalError: "remote error: missing extension",
-					})
-
-					// Test that the server rejects a missing EncryptedExtensions message.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ALPS-OmitClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
-							Bugs: ProtocolBugs{
-								OmitClientEncryptedExtensions: true,
-							},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-application-settings", "proto,shim",
-						}, alpsFlags...),
-						// The runner is a client, so it only processes the shim's alert
-						// after checking connection state.
-						expectations:       expectations,
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_MESSAGE:",
-						expectedLocalError: "remote error: unexpected message",
-					})
-
-					// Test that the server rejects an unexpected EncryptedExtensions message.
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     fmt.Sprintf("UnexpectedClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
-						config: Config{
-							MaxVersion: ver.version,
-							Bugs: ProtocolBugs{
-								AlwaysSendClientEncryptedExtensions: true,
-							},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_MESSAGE:",
-						expectedLocalError: "remote error: unexpected message",
-					})
-
-					// Test that the server rejects an unexpected extension in an
-					// expected EncryptedExtensions message.
-					testCases = append(testCases, testCase{
-						protocol:           protocol,
-						testType:           serverTest,
-						name:               fmt.Sprintf("ExtraClientEncryptedExtension-%s-%s", alpsCodePoint, suffix),
-						skipQUICALPNConfig: true,
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"proto"},
-							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
-							Bugs: ProtocolBugs{
-								SendExtraClientEncryptedExtension: true,
-							},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags: append([]string{
-							"-select-alpn", "proto",
-							"-application-settings", "proto,shim",
-						}, alpsFlags...),
-						// The runner is a client, so it only processes the shim's alert
-						// after checking connection state.
-						expectations:       expectations,
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_EXTENSION:",
-						expectedLocalError: "remote error: unsupported extension",
-					})
-
-					// Test that ALPS is carried over on 0-RTT.
-					// TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3.
-					if protocol != dtls {
-						for _, empty := range []bool{false, true} {
-							maybeEmpty := ""
-							runnerSettings := "runner"
-							shimSettings := "shim"
-							if empty {
-								maybeEmpty = "Empty-"
-								runnerSettings = ""
-								shimSettings = ""
-							}
-
-							expectations = connectionExpectations{
-								peerApplicationSettingsOld: []byte(shimSettings),
-							}
-							if alpsCodePoint == ALPSUseCodepointNew {
-								expectations = connectionExpectations{
-									peerApplicationSettings: []byte(shimSettings),
-								}
-							}
-							testCases = append(testCases, testCase{
-								protocol:           protocol,
-								testType:           clientTest,
-								name:               fmt.Sprintf("ALPS-EarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
-								skipQUICALPNConfig: true,
-								config: Config{
-									MaxVersion:          ver.version,
-									NextProtos:          []string{"proto"},
-									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
-									ALPSUseNewCodepoint: alpsCodePoint,
-								},
-								resumeSession: true,
-								earlyData:     true,
-								flags: append([]string{
-									"-advertise-alpn", "\x05proto",
-									"-expect-alpn", "proto",
-									"-application-settings", "proto," + shimSettings,
-									"-expect-peer-application-settings", runnerSettings,
-								}, alpsFlags...),
-								expectations: expectations,
-							})
-							testCases = append(testCases, testCase{
-								protocol:           protocol,
-								testType:           serverTest,
-								name:               fmt.Sprintf("ALPS-EarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
-								skipQUICALPNConfig: true,
-								config: Config{
-									MaxVersion:          ver.version,
-									NextProtos:          []string{"proto"},
-									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
-									ALPSUseNewCodepoint: alpsCodePoint,
-								},
-								resumeSession: true,
-								earlyData:     true,
-								flags: append([]string{
-									"-select-alpn", "proto",
-									"-application-settings", "proto," + shimSettings,
-									"-expect-peer-application-settings", runnerSettings,
-								}, alpsFlags...),
-								expectations: expectations,
-							})
-
-							// Sending application settings in 0-RTT handshakes is forbidden.
-							testCases = append(testCases, testCase{
-								protocol:           protocol,
-								testType:           clientTest,
-								name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
-								skipQUICALPNConfig: true,
-								config: Config{
-									MaxVersion:          ver.version,
-									NextProtos:          []string{"proto"},
-									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
-									Bugs: ProtocolBugs{
-										SendApplicationSettingsWithEarlyData: true,
-									},
-									ALPSUseNewCodepoint: alpsCodePoint,
-								},
-								resumeSession: true,
-								earlyData:     true,
-								flags: append([]string{
-									"-advertise-alpn", "\x05proto",
-									"-expect-alpn", "proto",
-									"-application-settings", "proto," + shimSettings,
-									"-expect-peer-application-settings", runnerSettings,
-								}, alpsFlags...),
-								expectations:       expectations,
-								shouldFail:         true,
-								expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
-								expectedLocalError: "remote error: illegal parameter",
-							})
-							testCases = append(testCases, testCase{
-								protocol:           protocol,
-								testType:           serverTest,
-								name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
-								skipQUICALPNConfig: true,
-								config: Config{
-									MaxVersion:          ver.version,
-									NextProtos:          []string{"proto"},
-									ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
-									Bugs: ProtocolBugs{
-										SendApplicationSettingsWithEarlyData: true,
-									},
-									ALPSUseNewCodepoint: alpsCodePoint,
-								},
-								resumeSession: true,
-								earlyData:     true,
-								flags: append([]string{
-									"-select-alpn", "proto",
-									"-application-settings", "proto," + shimSettings,
-									"-expect-peer-application-settings", runnerSettings,
-								}, alpsFlags...),
-								expectations:       expectations,
-								shouldFail:         true,
-								expectedError:      ":UNEXPECTED_MESSAGE:",
-								expectedLocalError: "remote error: unexpected message",
-							})
-						}
-
-						// Test that the client and server each decline early data if local
-						// ALPS preferences has changed for the current connection.
-						alpsMismatchTests := []struct {
-							name                            string
-							initialSettings, resumeSettings []byte
-						}{
-							{"DifferentValues", []byte("settings1"), []byte("settings2")},
-							{"OnOff", []byte("settings"), nil},
-							{"OffOn", nil, []byte("settings")},
-							// The empty settings value should not be mistaken for ALPS not
-							// being negotiated.
-							{"OnEmpty", []byte("settings"), []byte{}},
-							{"EmptyOn", []byte{}, []byte("settings")},
-							{"EmptyOff", []byte{}, nil},
-							{"OffEmpty", nil, []byte{}},
-						}
-						for _, test := range alpsMismatchTests {
-							flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
-							flags = append(flags, alpsFlags...)
-							if test.initialSettings != nil {
-								flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
-								flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
-							}
-							if test.resumeSettings != nil {
-								flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
-								flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
-							}
-
-							expectations = connectionExpectations{
-								peerApplicationSettingsOld: test.initialSettings,
-							}
-							resumeExpectations = &connectionExpectations{
-								peerApplicationSettingsOld: test.resumeSettings,
-							}
-							if alpsCodePoint == ALPSUseCodepointNew {
-								expectations = connectionExpectations{
-									peerApplicationSettings: test.initialSettings,
-								}
-								resumeExpectations = &connectionExpectations{
-									peerApplicationSettings: test.resumeSettings,
-								}
-							}
-							// The client should not offer early data if the session is
-							// inconsistent with the new configuration. Note that if
-							// the session did not negotiate ALPS (test.initialSettings
-							// is nil), the client always offers early data.
-							if test.initialSettings != nil {
-								testCases = append(testCases, testCase{
-									protocol:           protocol,
-									testType:           clientTest,
-									name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s-%s", test.name, alpsCodePoint, suffix),
-									skipQUICALPNConfig: true,
-									config: Config{
-										MaxVersion:          ver.version,
-										MaxEarlyDataSize:    16384,
-										NextProtos:          []string{"proto"},
-										ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
-										ALPSUseNewCodepoint: alpsCodePoint,
-									},
-									resumeSession: true,
-									flags: append([]string{
-										"-enable-early-data",
-										"-expect-ticket-supports-early-data",
-										"-expect-no-offer-early-data",
-										"-advertise-alpn", "\x05proto",
-										"-expect-alpn", "proto",
-									}, flags...),
-									expectations:       expectations,
-									resumeExpectations: resumeExpectations,
-								})
-							}
-
-							// The server should reject early data if the session is
-							// inconsistent with the new selection.
-							testCases = append(testCases, testCase{
-								protocol:           protocol,
-								testType:           serverTest,
-								name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s-%s", test.name, alpsCodePoint, suffix),
-								skipQUICALPNConfig: true,
-								config: Config{
-									MaxVersion:          ver.version,
-									NextProtos:          []string{"proto"},
-									ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
-									ALPSUseNewCodepoint: alpsCodePoint,
-								},
-								resumeSession:           true,
-								earlyData:               true,
-								expectEarlyDataRejected: true,
-								flags: append([]string{
-									"-select-alpn", "proto",
-								}, flags...),
-								expectations:       expectations,
-								resumeExpectations: resumeExpectations,
-							})
-						}
-
-						// Test that 0-RTT continues working when the shim configures
-						// ALPS but the peer does not.
-						testCases = append(testCases, testCase{
-							protocol:           protocol,
-							testType:           clientTest,
-							name:               fmt.Sprintf("ALPS-EarlyData-Client-ServerDecline-%s-%s", alpsCodePoint, suffix),
-							skipQUICALPNConfig: true,
-							config: Config{
-								MaxVersion:          ver.version,
-								NextProtos:          []string{"proto"},
-								ALPSUseNewCodepoint: alpsCodePoint,
-							},
-							resumeSession: true,
-							earlyData:     true,
-							flags: append([]string{
-								"-advertise-alpn", "\x05proto",
-								"-expect-alpn", "proto",
-								"-application-settings", "proto,shim",
-							}, alpsFlags...),
-						})
-						testCases = append(testCases, testCase{
-							protocol:           protocol,
-							testType:           serverTest,
-							name:               fmt.Sprintf("ALPS-EarlyData-Server-ClientNoOffe-%s-%s", alpsCodePoint, suffix),
-							skipQUICALPNConfig: true,
-							config: Config{
-								MaxVersion:          ver.version,
-								NextProtos:          []string{"proto"},
-								ALPSUseNewCodepoint: alpsCodePoint,
-							},
-							resumeSession: true,
-							earlyData:     true,
-							flags: append([]string{
-								"-select-alpn", "proto",
-								"-application-settings", "proto,shim",
-							}, alpsFlags...),
-						})
-					}
-				}
-			} else {
-				// Test the client rejects the ALPS extension if the server
-				// negotiated TLS 1.2 or below.
-				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
-					flags := []string{
-						"-advertise-alpn", "\x03foo",
-						"-expect-alpn", "foo",
-						"-application-settings", "foo,shim",
-					}
-					bugs := ProtocolBugs{
-						AlwaysNegotiateApplicationSettingsOld: true,
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						flags = append(flags, "-alps-use-new-codepoint")
-						bugs = ProtocolBugs{
-							AlwaysNegotiateApplicationSettingsNew: true,
-						}
-					}
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     fmt.Sprintf("ALPS-Reject-Client-%s-%s", alpsCodePoint, suffix),
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"foo"},
-							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
-							Bugs:                bugs,
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						flags:              flags,
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_EXTENSION:",
-						expectedLocalError: "remote error: unsupported extension",
-					})
-
-					flags = []string{
-						"-on-resume-advertise-alpn", "\x03foo",
-						"-on-resume-expect-alpn", "foo",
-						"-on-resume-application-settings", "foo,shim",
-					}
-					bugs = ProtocolBugs{
-						AlwaysNegotiateApplicationSettingsOld: true,
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						flags = append(flags, "-alps-use-new-codepoint")
-						bugs = ProtocolBugs{
-							AlwaysNegotiateApplicationSettingsNew: true,
-						}
-					}
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     fmt.Sprintf("ALPS-Reject-Client-Resume-%s-%s", alpsCodePoint, suffix),
-						config: Config{
-							MaxVersion: ver.version,
-						},
-						resumeConfig: &Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"foo"},
-							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
-							Bugs:                bugs,
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						resumeSession:      true,
-						flags:              flags,
-						shouldFail:         true,
-						expectedError:      ":UNEXPECTED_EXTENSION:",
-						expectedLocalError: "remote error: unsupported extension",
-					})
-
-					// Test the server declines ALPS if it negotiates TLS 1.2 or below.
-					flags = []string{
-						"-select-alpn", "foo",
-						"-application-settings", "foo,shim",
-					}
-					if alpsCodePoint == ALPSUseCodepointNew {
-						flags = append(flags, "-alps-use-new-codepoint")
-					}
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     fmt.Sprintf("ALPS-Decline-Server-%s-%s", alpsCodePoint, suffix),
-						config: Config{
-							MaxVersion:          ver.version,
-							NextProtos:          []string{"foo"},
-							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
-							ALPSUseNewCodepoint: alpsCodePoint,
-						},
-						// Test both TLS 1.2 full and resumption handshakes.
-						resumeSession: true,
-						flags:         flags,
-						// If not specified, runner and shim both implicitly expect ALPS
-						// is not negotiated.
-					})
-				}
-			}
-
-			// Test QUIC transport params
-			if protocol == quic {
-				// Client sends params
-				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
-					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
-						useCodepointFlag := "0"
-						if clientConfig == QUICUseCodepointLegacy {
-							useCodepointFlag = "1"
-						}
-						flags := []string{
-							"-quic-transport-params",
-							base64FlagValue([]byte{1, 2}),
-							"-quic-use-legacy-codepoint", useCodepointFlag,
-						}
-						expectations := connectionExpectations{
-							quicTransportParams: []byte{1, 2},
-						}
-						shouldFail := false
-						expectedError := ""
-						expectedLocalError := ""
-						if clientConfig == QUICUseCodepointLegacy {
-							expectations = connectionExpectations{
-								quicTransportParamsLegacy: []byte{1, 2},
-							}
-						}
-						if serverSends != clientConfig {
-							expectations = connectionExpectations{}
-							shouldFail = true
-							if serverSends == QUICUseCodepointNeither {
-								expectedError = ":MISSING_EXTENSION:"
-							} else {
-								expectedLocalError = "remote error: unsupported extension"
-							}
-						} else {
-							flags = append(flags,
-								"-expect-quic-transport-params",
-								base64FlagValue([]byte{3, 4}))
-						}
-						testCases = append(testCases, testCase{
-							testType: clientTest,
-							protocol: protocol,
-							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
-							config: Config{
-								MinVersion:                            ver.version,
-								MaxVersion:                            ver.version,
-								QUICTransportParams:                   []byte{3, 4},
-								QUICTransportParamsUseLegacyCodepoint: serverSends,
-							},
-							flags:                     flags,
-							expectations:              expectations,
-							shouldFail:                shouldFail,
-							expectedError:             expectedError,
-							expectedLocalError:        expectedLocalError,
-							skipTransportParamsConfig: true,
-						})
-					}
-				}
-				// Server sends params
-				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
-					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
-						expectations := connectionExpectations{
-							quicTransportParams: []byte{3, 4},
-						}
-						shouldFail := false
-						expectedError := ""
-						useCodepointFlag := "0"
-						if serverConfig == QUICUseCodepointLegacy {
-							useCodepointFlag = "1"
-							expectations = connectionExpectations{
-								quicTransportParamsLegacy: []byte{3, 4},
-							}
-						}
-						flags := []string{
-							"-quic-transport-params",
-							base64FlagValue([]byte{3, 4}),
-							"-quic-use-legacy-codepoint", useCodepointFlag,
-						}
-						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
-							expectations = connectionExpectations{}
-							shouldFail = true
-							expectedError = ":MISSING_EXTENSION:"
-						} else {
-							flags = append(flags,
-								"-expect-quic-transport-params",
-								base64FlagValue([]byte{1, 2}),
-							)
-						}
-						testCases = append(testCases, testCase{
-							testType: serverTest,
-							protocol: protocol,
-							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
-							config: Config{
-								MinVersion:                            ver.version,
-								MaxVersion:                            ver.version,
-								QUICTransportParams:                   []byte{1, 2},
-								QUICTransportParamsUseLegacyCodepoint: clientSends,
-							},
-							flags:                     flags,
-							expectations:              expectations,
-							shouldFail:                shouldFail,
-							expectedError:             expectedError,
-							skipTransportParamsConfig: true,
-						})
-					}
-				}
-			} else {
-				// Ensure non-QUIC client doesn't send QUIC transport parameters.
-				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
-					useCodepointFlag := "0"
-					if clientConfig == QUICUseCodepointLegacy {
-						useCodepointFlag = "1"
-					}
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
-						config: Config{
-							MinVersion:                            ver.version,
-							MaxVersion:                            ver.version,
-							QUICTransportParamsUseLegacyCodepoint: clientConfig,
-						},
-						flags: []string{
-							"-max-version",
-							ver.shimFlag(protocol),
-							"-quic-transport-params",
-							base64FlagValue([]byte{3, 4}),
-							"-quic-use-legacy-codepoint", useCodepointFlag,
-						},
-						shouldFail:                true,
-						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
-						skipTransportParamsConfig: true,
-					})
-				}
-				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
-				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
-					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
-						shouldFail := false
-						expectedLocalError := ""
-						useCodepointFlag := "0"
-						if serverConfig == QUICUseCodepointLegacy {
-							useCodepointFlag = "1"
-						}
-						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
-							shouldFail = true
-							expectedLocalError = "remote error: unsupported extension"
-						}
-						testCases = append(testCases, testCase{
-							protocol: protocol,
-							testType: serverTest,
-							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
-							config: Config{
-								MinVersion:                            ver.version,
-								MaxVersion:                            ver.version,
-								QUICTransportParams:                   []byte{1, 2},
-								QUICTransportParamsUseLegacyCodepoint: clientSends,
-							},
-							flags: []string{
-								"-quic-use-legacy-codepoint", useCodepointFlag,
-							},
-							shouldFail:                shouldFail,
-							expectedLocalError:        expectedLocalError,
-							skipTransportParamsConfig: true,
-						})
-					}
-				}
-
-			}
-
-			// Test ticket behavior.
-
-			// Resume with a corrupt ticket.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "CorruptTicket-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						FilterTicket: func(in []byte) ([]byte, error) {
-							in[len(in)-1] ^= 1
-							return in, nil
-						},
-					},
-				},
-				resumeSession:        true,
-				expectResumeRejected: true,
-			})
-			// Test the ticket callbacks.
-			for _, aeadCallback := range []bool{false, true} {
-				flag := "-use-ticket-callback"
-				callbackSuffix := suffix
-				if aeadCallback {
-					flag = "-use-ticket-aead-callback"
-					callbackSuffix += "-AEAD"
-				}
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketCallback-" + callbackSuffix,
-					config: Config{
-						MaxVersion: ver.version,
-					},
-					resumeSession: true,
-					flags:         []string{flag},
-				})
-				// Only the old callback supports renewal.
-				if !aeadCallback {
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     "TicketCallback-Renew-" + callbackSuffix,
-						config: Config{
-							MaxVersion: ver.version,
-							Bugs: ProtocolBugs{
-								ExpectNewTicket: true,
-							},
-						},
-						flags:         []string{flag, "-renew-ticket"},
-						resumeSession: true,
-					})
-				}
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketCallback-Skip-" + callbackSuffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							ExpectNoNonEmptyNewSessionTicket: true,
-						},
-					},
-					flags: []string{flag, "-skip-ticket"},
-				})
-
-				// Test that the ticket callback is only called once when everything before
-				// it in the ClientHello is asynchronous. This corrupts the ticket so
-				// certificate selection callbacks run.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketCallback-SingleCall-" + callbackSuffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							FilterTicket: func(in []byte) ([]byte, error) {
-								in[len(in)-1] ^= 1
-								return in, nil
-							},
-						},
-					},
-					resumeSession:        true,
-					expectResumeRejected: true,
-					flags: []string{
-						flag,
-						"-async",
-					},
-				})
-			}
-
-			// Resume with various lengths of ticket session id.
-			if ver.version < VersionTLS13 {
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketSessionIDLength-0-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							EmptyTicketSessionID: true,
-						},
-					},
-					resumeSession: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketSessionIDLength-16-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							TicketSessionIDLength: 16,
-						},
-					},
-					resumeSession: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketSessionIDLength-32-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							TicketSessionIDLength: 32,
-						},
-					},
-					resumeSession: true,
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TicketSessionIDLength-33-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							TicketSessionIDLength: 33,
-						},
-					},
-					resumeSession: true,
-					shouldFail:    true,
-					// The maximum session ID length is 32.
-					expectedError: ":CLIENTHELLO_PARSE_FAILED:",
-				})
-			}
-
-			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
-			// are ignored.
-			if protocol == dtls {
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					name:     "SRTP-Client-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "SRTP-Server-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-					},
-				})
-				// Test that the MKI is ignored.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "SRTP-Server-IgnoreMKI-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
-						Bugs: ProtocolBugs{
-							SRTPMasterKeyIdentifier: "bogus",
-						},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-					},
-				})
-				// Test that SRTP isn't negotiated on the server if there were
-				// no matching profiles.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "SRTP-Server-NoMatch-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{100, 101, 102},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: 0,
-					},
-				})
-				// Test that the server returning an invalid SRTP profile is
-				// flagged as an error by the client.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					name:     "SRTP-Client-NoMatch-" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Bugs: ProtocolBugs{
-							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
-						},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80",
-					},
-					shouldFail:    true,
-					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
-				})
-			} else {
-				// DTLS-SRTP is not defined for other protocols. Configuring it
-				// on the client and server should ignore the extension.
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					name:     "SRTP-Client-Ignore-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: 0,
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "SRTP-Server-Ignore-" + suffix,
-					config: Config{
-						MaxVersion:             ver.version,
-						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-					},
-					flags: []string{
-						"-srtp-profiles",
-						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-					},
-					expectations: connectionExpectations{
-						srtpProtectionProfile: 0,
-					},
-				})
-			}
-
-			// Test SCT list.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "SignedCertificateTimestampList-Client-" + suffix,
-				testType: clientTest,
-				config: Config{
-					MaxVersion: ver.version,
-					Credential: rsaCertificate.WithSCTList(testSCTList),
-				},
-				flags: []string{
-					"-enable-signed-cert-timestamps",
-					"-expect-signed-cert-timestamps",
-					base64FlagValue(testSCTList),
-				},
-				resumeSession: true,
-			})
-
-			var differentSCTList []byte
-			differentSCTList = append(differentSCTList, testSCTList...)
-			differentSCTList[len(differentSCTList)-1] ^= 1
-
-			// The SCT extension did not specify that it must only be sent on the inital handshake as it
-			// should have, so test that we tolerate but ignore it. This is only an issue pre-1.3, since
-			// SCTs are sent in the CertificateEntry message in 1.3, whereas they were previously sent
-			// in an extension in the ServerHello pre-1.3.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "SendSCTListOnResume-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Credential: rsaCertificate.WithSCTList(testSCTList),
-					Bugs: ProtocolBugs{
-						SendSCTListOnResume: differentSCTList,
-					},
-				},
-				flags: []string{
-					"-enable-signed-cert-timestamps",
-					"-expect-signed-cert-timestamps",
-					base64FlagValue(testSCTList),
-				},
-				resumeSession: true,
-			})
-
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "SignedCertificateTimestampList-Server-" + suffix,
-				testType: serverTest,
-				config: Config{
-					MaxVersion: ver.version,
-				},
-				shimCertificate: rsaCertificate.WithSCTList(testSCTList),
-				expectations: connectionExpectations{
-					peerCertificate: rsaCertificate.WithSCTList(testSCTList),
-				},
-				resumeSession: true,
-			})
-
-			// Test empty SCT list.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
-				testType: clientTest,
-				config: Config{
-					MaxVersion: ver.version,
-					Credential: rsaCertificate.WithSCTList([]byte{0, 0}),
-				},
-				flags: []string{
-					"-enable-signed-cert-timestamps",
-				},
-				shouldFail:    true,
-				expectedError: ":ERROR_PARSING_EXTENSION:",
-			})
-
-			// Test empty SCT in non-empty list.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
-				testType: clientTest,
-				config: Config{
-					MaxVersion: ver.version,
-					Credential: rsaCertificate.WithSCTList([]byte{0, 6, 0, 2, 1, 2, 0, 0}),
-				},
-				flags: []string{
-					"-enable-signed-cert-timestamps",
-				},
-				shouldFail:    true,
-				expectedError: ":ERROR_PARSING_EXTENSION:",
-			})
-
-			// Test that certificate-related extensions are not sent unsolicited.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "UnsolicitedCertificateExtensions-" + suffix,
-				config: Config{
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						NoOCSPStapling:                true,
-						NoSignedCertificateTimestamps: true,
-					},
-				},
-				shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-			})
-
-			// Extension permutation should interact correctly with other extensions,
-			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
-			// in ssl_test.cc tests that the extensions are actually permuted. This
-			// tests the handshake still works.
-			//
-			// This test also tests that all our extensions interact with each other.
-			for _, ech := range []bool{false, true} {
-				if ech && ver.version < VersionTLS13 {
-					continue
-				}
-
-				test := testCase{
-					protocol:           protocol,
-					name:               "AllExtensions-Client-Permute",
-					skipQUICALPNConfig: true,
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						Credential:          rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-						NextProtos:          []string{"proto"},
-						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
-						Bugs: ProtocolBugs{
-							SendServerNameAck: true,
-							ExpectServerName:  "example.com",
-							ExpectGREASE:      true,
-						},
-					},
-					resumeSession: true,
-					flags: []string{
-						"-permute-extensions",
-						"-enable-grease",
-						"-enable-ocsp-stapling",
-						"-enable-signed-cert-timestamps",
-						"-advertise-alpn", "\x05proto",
-						"-expect-alpn", "proto",
-						"-host-name", "example.com",
-					},
-				}
-
-				if ech {
-					test.name += "-ECH"
-					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
-					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
-					test.flags = append(test.flags,
-						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-						"-expect-ech-accept",
-					)
-					test.expectations.echAccepted = true
-				}
-
-				if ver.version >= VersionTLS13 {
-					// Trigger a HelloRetryRequest to test both ClientHellos. Note
-					// our DTLS tests always enable HelloVerifyRequest.
-					test.name += "-HelloRetryRequest"
-
-					// ALPS is only available on TLS 1.3.
-					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
-					test.flags = append(test.flags,
-						"-application-settings", "proto,shim",
-						"-alps-use-new-codepoint",
-						"-expect-peer-application-settings", "runner")
-					test.expectations.peerApplicationSettings = []byte("shim")
-				}
-
-				if protocol == dtls {
-					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
-					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
-					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
-				}
-
-				test.name += "-" + suffix
-				testCases = append(testCases, test)
-			}
-		}
-	}
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ClientHelloPadding",
-		config: Config{
-			Bugs: ProtocolBugs{
-				RequireClientHelloSize: 512,
-			},
-		},
-		// This hostname just needs to be long enough to push the
-		// ClientHello into F5's danger zone between 256 and 511 bytes
-		// long.
-		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
-	})
-
-	// Test that illegal extensions in TLS 1.3 are rejected by the client if
-	// in ServerHello.
-	testCases = append(testCases, testCase{
-		name: "NPN-Forbidden-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-			Bugs: ProtocolBugs{
-				NegotiateNPNAtAllVersions: true,
-			},
-		},
-		flags:         []string{"-select-next-proto", "foo"},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		name: "EMS-Forbidden-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NegotiateEMSAtAllVersions: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		name: "RenegotiationInfo-Forbidden-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NegotiateRenegotiationInfoAtAllVersions: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		name: "Ticket-Forbidden-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AdvertiseTicketExtension: true,
-			},
-		},
-		resumeSession: true,
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-
-	// Test that illegal extensions in TLS 1.3 are declined by the server if
-	// offered in ClientHello. The runner's server will fail if this occurs,
-	// so we exercise the offering path. (EMS and Renegotiation Info are
-	// implicit in every test.)
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NPN-Declined-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"bar"},
-		},
-		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
-	})
-
-	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
-	// tolerated.
-	testCases = append(testCases, testCase{
-		name: "SendOCSPResponseOnResume-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: rsaCertificate.WithOCSP(testOCSPResponse),
-			Bugs: ProtocolBugs{
-				SendOCSPResponseOnResume: []byte("bogus"),
-			},
-		},
-		flags: []string{
-			"-enable-ocsp-stapling",
-			"-expect-ocsp-response",
-			base64FlagValue(testOCSPResponse),
-		},
-		resumeSession: true,
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendExtensionOnCertificate: testOCSPExtension,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SendUnsolicitedSCTOnCertificate-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendExtensionOnCertificate: testSCTExtension,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	// Test that extensions on client certificates are never accepted.
-	testCases = append(testCases, testCase{
-		name:     "SendExtensionOnClientCertificate-TLS13",
-		testType: serverTest,
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &rsaCertificate,
-			Bugs: ProtocolBugs{
-				SendExtensionOnCertificate: testOCSPExtension,
-			},
-		},
-		flags: []string{
-			"-enable-ocsp-stapling",
-			"-require-any-client-certificate",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SendUnknownExtensionOnCertificate-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	// Test that extensions on intermediates are allowed but ignored.
-	testCases = append(testCases, testCase{
-		name: "IgnoreExtensionsOnIntermediates-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-			Bugs: ProtocolBugs{
-				// Send different values on the intermediate. This tests
-				// the intermediate's extensions do not override the
-				// leaf's.
-				SendOCSPOnIntermediates: testOCSPResponse2,
-				SendSCTOnIntermediates:  testSCTList2,
-			},
-		},
-		flags: []string{
-			"-enable-ocsp-stapling",
-			"-expect-ocsp-response",
-			base64FlagValue(testOCSPResponse),
-			"-enable-signed-cert-timestamps",
-			"-expect-signed-cert-timestamps",
-			base64FlagValue(testSCTList),
-		},
-		resumeSession: true,
-	})
-
-	// Test that extensions are not sent on intermediates when configured
-	// only for a leaf.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SendNoExtensionsOnIntermediate-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectNoExtensionsOnIntermediate: true,
-			},
-		},
-		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-	})
-
-	// Test that extensions are not sent on client certificates.
-	testCases = append(testCases, testCase{
-		name: "SendNoClientCertificateExtensions-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-		},
-		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SendDuplicateExtensionsOnCerts-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-			Bugs: ProtocolBugs{
-				SendDuplicateCertExtensions: true,
-			},
-		},
-		flags: []string{
-			"-enable-ocsp-stapling",
-			"-enable-signed-cert-timestamps",
-		},
-		resumeSession: true,
-		shouldFail:    true,
-		expectedError: ":DUPLICATE_EXTENSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		name:            "SignedCertificateTimestampListInvalid-Server",
-		testType:        serverTest,
-		shimCertificate: rsaCertificate.WithSCTList([]byte{0, 0}),
-		shouldFail:      true,
-		expectedError:   ":INVALID_SCT_LIST:",
-	})
-}
-
-func addResumptionVersionTests() {
-	for _, sessionVers := range tlsVersions {
-		for _, resumeVers := range tlsVersions {
-			protocols := []protocol{tls}
-			if sessionVers.hasDTLS && resumeVers.hasDTLS {
-				protocols = append(protocols, dtls)
-			}
-			if sessionVers.hasQUIC && resumeVers.hasQUIC {
-				protocols = append(protocols, quic)
-			}
-			for _, protocol := range protocols {
-				suffix := "-" + sessionVers.name + "-" + resumeVers.name
-				suffix += "-" + protocol.String()
-
-				if sessionVers.version == resumeVers.version {
-					testCases = append(testCases, testCase{
-						protocol:      protocol,
-						name:          "Resume-Client" + suffix,
-						resumeSession: true,
-						config: Config{
-							MaxVersion: sessionVers.version,
-							Bugs: ProtocolBugs{
-								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
-							},
-						},
-						expectations: connectionExpectations{
-							version: sessionVers.version,
-						},
-						resumeExpectations: &connectionExpectations{
-							version: resumeVers.version,
-						},
-					})
-				} else if protocol != tls && sessionVers.version >= VersionTLS13 && resumeVers.version < VersionTLS13 {
-					// In TLS 1.2 and below, the server indicates resumption by echoing
-					// the client's session ID, which is impossible if the client did
-					// not send a session ID. If the client offers a TLS 1.3 session, it
-					// only fills in session ID in TLS (not DTLS or QUIC) for middlebox
-					// compatibility mode. So, instead, test that the session ID was
-					// empty and it was indeed impossible to hit this path
-					testCases = append(testCases, testCase{
-						protocol:      protocol,
-						name:          "Resume-Client-Impossible" + suffix,
-						resumeSession: true,
-						config: Config{
-							MaxVersion: sessionVers.version,
-						},
-						expectations: connectionExpectations{
-							version: sessionVers.version,
-						},
-						resumeConfig: &Config{
-							MaxVersion: resumeVers.version,
-							Bugs: ProtocolBugs{
-								ExpectNoSessionID: true,
-							},
-						},
-						resumeExpectations: &connectionExpectations{
-							version: resumeVers.version,
-						},
-						expectResumeRejected: true,
-					})
-				} else {
-					// Test that the client rejects ServerHellos which resume
-					// sessions at inconsistent versions.
-					expectedError := ":OLD_SESSION_VERSION_NOT_RETURNED:"
-					if sessionVers.version < VersionTLS13 && resumeVers.version >= VersionTLS13 {
-						// The server will "resume" the session by sending pre_shared_key,
-						// but the shim will not have sent pre_shared_key at all. The shim
-						// should reject this because the extension was not allowed at all.
-						expectedError = ":UNEXPECTED_EXTENSION:"
-					}
-
-					testCases = append(testCases, testCase{
-						protocol:      protocol,
-						name:          "Resume-Client-Mismatch" + suffix,
-						resumeSession: true,
-						config: Config{
-							MaxVersion: sessionVers.version,
-						},
-						expectations: connectionExpectations{
-							version: sessionVers.version,
-						},
-						resumeConfig: &Config{
-							MaxVersion: resumeVers.version,
-							Bugs: ProtocolBugs{
-								AcceptAnySession: true,
-							},
-						},
-						resumeExpectations: &connectionExpectations{
-							version: resumeVers.version,
-						},
-						shouldFail:    true,
-						expectedError: expectedError,
-					})
-				}
-
-				testCases = append(testCases, testCase{
-					protocol:      protocol,
-					name:          "Resume-Client-NoResume" + suffix,
-					resumeSession: true,
-					config: Config{
-						MaxVersion: sessionVers.version,
-					},
-					expectations: connectionExpectations{
-						version: sessionVers.version,
-					},
-					resumeConfig: &Config{
-						MaxVersion: resumeVers.version,
-					},
-					newSessionsOnResume:  true,
-					expectResumeRejected: true,
-					resumeExpectations: &connectionExpectations{
-						version: resumeVers.version,
-					},
-				})
-
-				testCases = append(testCases, testCase{
-					protocol:      protocol,
-					testType:      serverTest,
-					name:          "Resume-Server" + suffix,
-					resumeSession: true,
-					config: Config{
-						MaxVersion: sessionVers.version,
-					},
-					expectations: connectionExpectations{
-						version: sessionVers.version,
-					},
-					expectResumeRejected: sessionVers != resumeVers,
-					resumeConfig: &Config{
-						MaxVersion: resumeVers.version,
-						Bugs: ProtocolBugs{
-							SendBothTickets: true,
-						},
-					},
-					resumeExpectations: &connectionExpectations{
-						version: resumeVers.version,
-					},
-				})
-
-				// Repeat the test using session IDs, rather than tickets.
-				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
-					testCases = append(testCases, testCase{
-						protocol:      protocol,
-						testType:      serverTest,
-						name:          "Resume-Server-NoTickets" + suffix,
-						resumeSession: true,
-						config: Config{
-							MaxVersion:             sessionVers.version,
-							SessionTicketsDisabled: true,
-						},
-						expectations: connectionExpectations{
-							version: sessionVers.version,
-						},
-						expectResumeRejected: sessionVers != resumeVers,
-						resumeConfig: &Config{
-							MaxVersion:             resumeVers.version,
-							SessionTicketsDisabled: true,
-						},
-						resumeExpectations: &connectionExpectations{
-							version: resumeVers.version,
-						},
-					})
-				}
-			}
-		}
-	}
-
-	// Make sure shim ticket mutations are functional.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "ShimTicketRewritable",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				FilterTicket: func(in []byte) ([]byte, error) {
-					in, err := SetShimTicketVersion(in, VersionTLS12)
-					if err != nil {
-						return nil, err
-					}
-					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-	})
-
-	// Resumptions are declined if the version does not match.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-DeclineCrossVersion",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				ExpectNewTicket: true,
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketVersion(in, VersionTLS13)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		expectResumeRejected: true,
-	})
-
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-DeclineCrossVersion-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketVersion(in, VersionTLS12)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		expectResumeRejected: true,
-	})
-
-	// Resumptions are declined if the cipher is invalid or disabled.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-DeclineBadCipher",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				ExpectNewTicket: true,
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		expectResumeRejected: true,
-	})
-
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-DeclineBadCipher-2",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				ExpectNewTicket: true,
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
-				},
-			},
-		},
-		flags: []string{
-			"-cipher", "AES128",
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		expectResumeRejected: true,
-	})
-
-	// Sessions are not resumed if they do not use the preferred cipher.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-CipherNotPreferred",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				ExpectNewTicket: true,
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		shouldFail:           false,
-		expectResumeRejected: true,
-	})
-
-	// TLS 1.3 allows sessions to be resumed at a different cipher if their
-	// PRF hashes match, but BoringSSL will always decline such resumptions.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-CipherNotPreferred-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				FilterTicket: func(in []byte) ([]byte, error) {
-					// If the client (runner) offers ChaCha20-Poly1305 first, the
-					// server (shim) always prefers it. Switch it to AES-GCM.
-					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		shouldFail:           false,
-		expectResumeRejected: true,
-	})
-
-	// Sessions may not be resumed if they contain another version's cipher.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-DeclineBadCipher-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				FilterTicket: func(in []byte) ([]byte, error) {
-					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-				},
-			},
-		},
-		flags: []string{
-			"-ticket-key",
-			base64FlagValue(TestShimTicketKey),
-		},
-		expectResumeRejected: true,
-	})
-
-	// If the client does not offer the cipher from the session, decline to
-	// resume. Clients are forbidden from doing this, but BoringSSL selects
-	// the cipher first, so we only decline.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-UnofferedCipher",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			},
-		},
-		expectResumeRejected: true,
-	})
-
-	// In TLS 1.3, clients may advertise a cipher list which does not
-	// include the selected cipher. Test that we tolerate this. Servers may
-	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
-	// BoringSSL will always decline.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-UnofferedCipher-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-			},
-		},
-		expectResumeRejected: true,
-	})
-
-	// Sessions may not be resumed at a different cipher.
-	testCases = append(testCases, testCase{
-		name:          "Resume-Client-CipherMismatch",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
-	})
-
-	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
-	// matches.
-	testCases = append(testCases, testCase{
-		name:          "Resume-Client-CipherMismatch-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
-		},
-	})
-
-	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
-	testCases = append(testCases, testCase{
-		name:          "Resume-Client-PRFMismatch-TLS13",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				SendCipherSuite: TLS_AES_256_GCM_SHA384,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
-	})
-
-	for _, secondBinder := range []bool{false, true} {
-		var suffix string
-		var defaultCurves []CurveID
-		if secondBinder {
-			suffix = "-SecondBinder"
-			// Force a HelloRetryRequest by predicting an empty curve list.
-			defaultCurves = []CurveID{}
-		}
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-BinderWrongLength" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					SendShortPSKBinder:         true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: error decrypting message",
-			expectedError:      ":DIGEST_CHECK_FAILED:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-NoPSKBinder" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					SendNoPSKBinder:            true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: error decoding message",
-			expectedError:      ":DECODE_ERROR:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-ExtraPSKBinder" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					SendExtraPSKBinder:         true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: illegal parameter",
-			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					ExtraPSKIdentity:           true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: illegal parameter",
-			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-InvalidPSKBinder" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					SendInvalidPSKBinder:       true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: error decrypting message",
-			expectedError:      ":DIGEST_CHECK_FAILED:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
-			resumeSession: true,
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: defaultCurves,
-				Bugs: ProtocolBugs{
-					PSKBinderFirst:             true,
-					OnlyCorruptSecondPSKBinder: secondBinder,
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: illegal parameter",
-			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
-		})
-	}
-
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
-		resumeSession: true,
-		config: Config{
-			MaxVersion:    VersionTLS13,
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				OmitPSKsOnSecondClientHello: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: illegal parameter",
-		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
-	})
-}
-
-func addRenegotiationTests() {
-	// Servers cannot renegotiate.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Renegotiate-Server-Forbidden",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate:        1,
-		shouldFail:         true,
-		expectedError:      ":NO_RENEGOTIATION:",
-		expectedLocalError: "remote error: no renegotiation",
-	})
-	// The server shouldn't echo the renegotiation extension unless
-	// requested by the client.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Renegotiate-Server-NoExt",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfo:      true,
-				RequireRenegotiationInfo: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "renegotiation extension missing",
-	})
-	// The renegotiation SCSV should be sufficient for the server to echo
-	// the extension.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Renegotiate-Server-NoExt-SCSV",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfo:      true,
-				SendRenegotiationSCSV:    true,
-				RequireRenegotiationInfo: true,
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				FailIfResumeOnRenego: true,
-			},
-		},
-		renegotiate: 1,
-		// Test renegotiation after both an initial and resumption
-		// handshake.
-		resumeSession: true,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-			"-expect-secure-renegotiation",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				FailIfResumeOnRenego: true,
-			},
-		},
-		renegotiate: 1,
-		// Test renegotiation after both an initial and resumption
-		// handshake.
-		resumeSession: true,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-			"-expect-secure-renegotiation",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-EmptyExt",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				EmptyRenegotiationInfo: true,
-			},
-		},
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":RENEGOTIATION_MISMATCH:",
-		expectedLocalError: "handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-BadExt",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadRenegotiationInfo: true,
-			},
-		},
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":RENEGOTIATION_MISMATCH:",
-		expectedLocalError: "handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-BadExt2",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadRenegotiationInfoEnd: true,
-			},
-		},
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":RENEGOTIATION_MISMATCH:",
-		expectedLocalError: "handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-Downgrade",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfoAfterInitial: true,
-			},
-		},
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":RENEGOTIATION_MISMATCH:",
-		expectedLocalError: "handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-Upgrade",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfoInInitial: true,
-			},
-		},
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":RENEGOTIATION_MISMATCH:",
-		expectedLocalError: "handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-NoExt-Allowed",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfo: true,
-			},
-		},
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-			"-expect-no-secure-renegotiation",
-		},
-	})
-
-	// Test that the server may switch ciphers on renegotiation without
-	// problems.
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-SwitchCiphers",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-		},
-		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-SwitchCiphers2",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		renegotiateCiphers: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-
-	// Test that the server may not switch versions on renegotiation.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-SwitchVersion",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			// Pick a cipher which exists at both versions.
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-			Bugs: ProtocolBugs{
-				NegotiateVersionOnRenego: VersionTLS11,
-				// Avoid failing early at the record layer.
-				SendRecordVersion: VersionTLS12,
-			},
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SSL_VERSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-SameClientVersion",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion: VersionTLS10,
-			Bugs: ProtocolBugs{
-				RequireSameRenegoClientVersion: true,
-			},
-		},
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name:        "Renegotiate-FalseStart",
-		renegotiate: 1,
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			NextProtos:   []string{"foo"},
-		},
-		flags: []string{
-			"-false-start",
-			"-select-next-proto", "foo",
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-		shimWritesFirst: true,
-	})
-
-	// Client-side renegotiation controls.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Forbidden-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate:        1,
-		shouldFail:         true,
-		expectedError:      ":NO_RENEGOTIATION:",
-		expectedLocalError: "remote error: no renegotiation",
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Once-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-once",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Freely-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Once-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate:        2,
-		flags:              []string{"-renegotiate-once"},
-		shouldFail:         true,
-		expectedError:      ":NO_RENEGOTIATION:",
-		expectedLocalError: "remote error: no renegotiation",
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Freely-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate: 2,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "2",
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-NoIgnore",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendHelloRequestBeforeEveryAppDataRecord: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":NO_RENEGOTIATION:",
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Ignore",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendHelloRequestBeforeEveryAppDataRecord: true,
-			},
-		},
-		flags: []string{
-			"-renegotiate-ignore",
-			"-expect-total-renegotiations", "0",
-		},
-	})
-
-	// Renegotiation may be enabled and then disabled immediately after the
-	// handshake.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-ForbidAfterHandshake",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate:        1,
-		flags:              []string{"-forbid-renegotiation-after-handshake"},
-		shouldFail:         true,
-		expectedError:      ":NO_RENEGOTIATION:",
-		expectedLocalError: "remote error: no renegotiation",
-	})
-
-	// Renegotiation is not allowed when there is an unfinished write.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-UnfinishedWrite",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate:             1,
-		readWithUnfinishedWrite: true,
-		flags: []string{
-			"-async",
-			"-renegotiate-freely",
-		},
-		shouldFail:    true,
-		expectedError: ":NO_RENEGOTIATION:",
-		// We do not successfully send the no_renegotiation alert in
-		// this case. https://crbug.com/boringssl/130
-	})
-
-	// We reject stray HelloRequests during the handshake in TLS 1.2.
-	testCases = append(testCases, testCase{
-		name: "StrayHelloRequest",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendHelloRequestBeforeEveryHandshakeMessage: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-	testCases = append(testCases, testCase{
-		name: "StrayHelloRequest-Packed",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				PackHandshakeFlight:                         true,
-				SendHelloRequestBeforeEveryHandshakeMessage: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-
-	// Test that HelloRequest is rejected if it comes in the same record as the
-	// server Finished.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-Packed",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				PackHandshakeFlight:          true,
-				PackHelloRequestWithFinished: true,
-			},
-		},
-		renegotiate:        1,
-		flags:              []string{"-renegotiate-freely"},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// Renegotiation is forbidden in TLS 1.3.
-	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRequestBeforeEveryAppDataRecord: true,
-			},
-		},
-		flags: []string{
-			"-renegotiate-freely",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-
-	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
-	testCases = append(testCases, testCase{
-		name: "StrayHelloRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRequestBeforeEveryHandshakeMessage: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_MESSAGE:",
-	})
-
-	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
-	// always reads as supporting it, regardless of whether it was
-	// negotiated.
-	testCases = append(testCases, testCase{
-		name: "AlwaysReportRenegotiationInfo-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NoRenegotiationInfo: true,
-			},
-		},
-		flags: []string{
-			"-expect-secure-renegotiation",
-		},
-	})
-
-	// Certificates may not change on renegotiation.
-	testCases = append(testCases, testCase{
-		name: "Renegotiation-CertificateChange",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: &rsaCertificate,
-			Bugs: ProtocolBugs{
-				RenegotiationCertificate: &rsaChainCertificate,
-			},
-		},
-		renegotiate:   1,
-		flags:         []string{"-renegotiate-freely"},
-		shouldFail:    true,
-		expectedError: ":SERVER_CERT_CHANGED:",
-	})
-	testCases = append(testCases, testCase{
-		name: "Renegotiation-CertificateChange-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: &rsaCertificate,
-			Bugs: ProtocolBugs{
-				RenegotiationCertificate: &rsa1024Certificate,
-			},
-		},
-		renegotiate:   1,
-		flags:         []string{"-renegotiate-freely"},
-		shouldFail:    true,
-		expectedError: ":SERVER_CERT_CHANGED:",
-	})
-
-	// We do not negotiate ALPN after the initial handshake. This is
-	// error-prone and only risks bugs in consumers.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Renegotiation-ForbidALPN",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				// Forcibly negotiate ALPN on both initial and
-				// renegotiation handshakes. The test stack will
-				// internally check the client does not offer
-				// it.
-				SendALPN: "foo",
-			},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar\x03baz",
-			"-expect-alpn", "foo",
-			"-renegotiate-freely",
-		},
-		renegotiate:   1,
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	// The server may send different stapled OCSP responses or SCT lists on
-	// renegotiation, but BoringSSL ignores this and reports the old values.
-	// Also test that non-fatal verify results are preserved.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Renegotiation-ChangeAuthProperties",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-			Bugs: ProtocolBugs{
-				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
-				SendSCTListOnRenegotiation:      testSCTList2,
-			},
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-			"-enable-ocsp-stapling",
-			"-expect-ocsp-response",
-			base64FlagValue(testOCSPResponse),
-			"-enable-signed-cert-timestamps",
-			"-expect-signed-cert-timestamps",
-			base64FlagValue(testSCTList),
-			"-verify-fail",
-			"-expect-verify-result",
-		},
-	})
-}
-
-func addDTLSReplayTests() {
-	for _, vers := range allVersions(dtls) {
-		// Test that sequence number replays are detected.
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "DTLS-Replay-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			messageCount: 200,
-			replayWrites: true,
-		})
-
-		// Test the incoming sequence number skipping by values larger
-		// than the retransmit window.
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "DTLS-Replay-LargeGaps-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Bugs: ProtocolBugs{
-					SequenceNumberMapping: func(in uint64) uint64 {
-						return in * 1023
-					},
-				},
-			},
-			messageCount: 200,
-			replayWrites: true,
-		})
-
-		// Test the incoming sequence number changing non-monotonically.
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "DTLS-Replay-NonMonotonic-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Bugs: ProtocolBugs{
-					SequenceNumberMapping: func(in uint64) uint64 {
-						// This mapping has numbers counting backwards in groups
-						// of 256, and then jumping forwards 511 numbers.
-						return in ^ 255
-					},
-				},
-			},
-			// This messageCount is large enough to make sure that the SequenceNumberMapping
-			// will reach the point where it jumps forwards after stepping backwards.
-			messageCount: 500,
-			replayWrites: true,
-		})
-	}
-}
-
-var testSignatureAlgorithms = []struct {
-	name     string
-	id       signatureAlgorithm
-	baseCert *Credential
-	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
-	// accepted.
-	curve CurveID
-}{
-	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
-	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
-	{"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0},
-	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
-	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
-	{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, 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, &ecdsaP224Certificate, CurveP224},
-	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP256Certificate, CurveP256},
-	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, &ecdsaP384Certificate, CurveP384},
-	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, &ecdsaP521Certificate, CurveP521},
-	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, &rsaCertificate, 0},
-	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, &rsaCertificate, 0},
-	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, &rsaCertificate, 0},
-	{"Ed25519", signatureEd25519, &ed25519Certificate, 0},
-	// Tests for key types prior to TLS 1.2.
-	{"RSA", 0, &rsaCertificate, 0},
-	{"ECDSA", 0, &ecdsaP256Certificate, CurveP256},
-}
-
-const (
-	fakeSigAlg1 signatureAlgorithm = 0x2a01
-	fakeSigAlg2 signatureAlgorithm = 0xff01
-)
-
-func addSignatureAlgorithmTests() {
-	// Not all ciphers involve a signature. Advertise a list which gives all
-	// versions a signing cipher.
-	signingCiphers := []uint16{
-		TLS_AES_256_GCM_SHA384,
-		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-	}
-
-	var allAlgorithms []signatureAlgorithm
-	for _, alg := range testSignatureAlgorithms {
-		if alg.id != 0 {
-			allAlgorithms = append(allAlgorithms, alg.id)
-		}
-	}
-
-	// Make sure each signature algorithm works. Include some fake values in
-	// the list and ensure they're ignored.
-	for _, alg := range testSignatureAlgorithms {
-		// Make a version of the certificate that will not sign any other algorithm.
-		cert := alg.baseCert
-		if alg.id != 0 {
-			cert = cert.WithSignatureAlgorithms(alg.id)
-		}
-
-		for _, ver := range tlsVersions {
-			if (ver.version < VersionTLS12) != (alg.id == 0) {
-				continue
-			}
-
-			suffix := "-" + alg.name + "-" + ver.name
-			for _, signTestType := range []testType{clientTest, serverTest} {
-				signPrefix := "Client-"
-				verifyPrefix := "Server-"
-				verifyTestType := serverTest
-				if signTestType == serverTest {
-					verifyTestType = clientTest
-					signPrefix, verifyPrefix = verifyPrefix, signPrefix
-				}
-
-				var shouldFail bool
-				isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
-				isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
-
-				// TLS 1.3 removes a number of signature algorithms.
-				if ver.version >= VersionTLS13 && (alg.curve == CurveP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
-					shouldFail = true
-				}
-
-				// The backported RSA-PKCS1 code points only exist for TLS 1.3
-				// client certificates.
-				if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
-					shouldFail = true
-				}
-
-				// By default, BoringSSL does not sign with these algorithms.
-				signDefault := !shouldFail
-				if isTLS13PKCS1 {
-					signDefault = false
-				}
-
-				// By default, BoringSSL does not accept these algorithms.
-				verifyDefault := !shouldFail
-				if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
-					verifyDefault = false
-				}
-
-				var curveFlags []string
-				var runnerCurves []CurveID
-				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. Also include X25519 to ensure the shim
-					// and runner have something in common for ECDH.
-					curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
-					runnerCurves = []CurveID{CurveX25519, alg.curve}
-				}
-
-				signError := func(shouldFail bool) string {
-					if !shouldFail {
-						return ""
-					}
-					// In TLS 1.3, the shim should report no common signature algorithms if
-					// it cannot generate a signature. In TLS 1.2 servers, signature
-					// algorithm and cipher selection are integrated, so it is reported as
-					// no shared cipher.
-					if ver.version <= VersionTLS12 && signTestType == serverTest {
-						return ":NO_SHARED_CIPHER:"
-					}
-					return ":NO_COMMON_SIGNATURE_ALGORITHMS:"
-				}
-				signLocalError := func(shouldFail bool) string {
-					if !shouldFail {
-						return ""
-					}
-					// The shim should send handshake_failure when it cannot
-					// negotiate parameters.
-					return "remote error: handshake failure"
-				}
-				verifyError := func(shouldFail bool) string {
-					if !shouldFail {
-						return ""
-					}
-					// If the shim rejects the signature algorithm, but the
-					// runner forcibly selects it anyway, the shim should notice.
-					return ":WRONG_SIGNATURE_TYPE:"
-				}
-				verifyLocalError := func(shouldFail bool) string {
-					if !shouldFail {
-						return ""
-					}
-					// The shim should send an illegal_parameter alert if the runner
-					// uses a signature algorithm it isn't allowed to use.
-					return "remote error: illegal parameter"
-				}
-
-				// Test the shim using the algorithm for signing.
-				signTest := testCase{
-					testType: signTestType,
-					name:     signPrefix + "Sign" + suffix,
-					config: Config{
-						MaxVersion:       ver.version,
-						CurvePreferences: runnerCurves,
-						VerifySignatureAlgorithms: []signatureAlgorithm{
-							fakeSigAlg1,
-							alg.id,
-							fakeSigAlg2,
-						},
-					},
-					shimCertificate:    cert,
-					flags:              curveFlags,
-					shouldFail:         shouldFail,
-					expectedError:      signError(shouldFail),
-					expectedLocalError: signLocalError(shouldFail),
-					expectations: connectionExpectations{
-						peerSignatureAlgorithm: alg.id,
-					},
-				}
-
-				// Test whether the shim enables the algorithm by default.
-				signDefaultTest := testCase{
-					testType: signTestType,
-					name:     signPrefix + "SignDefault" + suffix,
-					config: Config{
-						MaxVersion:       ver.version,
-						CurvePreferences: runnerCurves,
-						VerifySignatureAlgorithms: []signatureAlgorithm{
-							fakeSigAlg1,
-							alg.id,
-							fakeSigAlg2,
-						},
-					},
-					// cert has been configured with the specified algorithm,
-					// while alg.baseCert uses the defaults.
-					shimCertificate:    alg.baseCert,
-					flags:              curveFlags,
-					shouldFail:         !signDefault,
-					expectedError:      signError(!signDefault),
-					expectedLocalError: signLocalError(!signDefault),
-					expectations: connectionExpectations{
-						peerSignatureAlgorithm: alg.id,
-					},
-				}
-
-				// Test that the shim will select the algorithm when configured to only
-				// support it.
-				negotiateTest := testCase{
-					testType: signTestType,
-					name:     signPrefix + "Sign-Negotiate" + suffix,
-					config: Config{
-						MaxVersion:                ver.version,
-						CurvePreferences:          runnerCurves,
-						VerifySignatureAlgorithms: allAlgorithms,
-					},
-					shimCertificate: cert,
-					flags:           curveFlags,
-					expectations: connectionExpectations{
-						peerSignatureAlgorithm: alg.id,
-					},
-				}
-
-				if signTestType == serverTest {
-					// TLS 1.2 servers only sign on some cipher suites.
-					signTest.config.CipherSuites = signingCiphers
-					signDefaultTest.config.CipherSuites = signingCiphers
-					negotiateTest.config.CipherSuites = signingCiphers
-				} else {
-					// TLS 1.2 clients only sign when the server requests certificates.
-					signTest.config.ClientAuth = RequireAnyClientCert
-					signDefaultTest.config.ClientAuth = RequireAnyClientCert
-					negotiateTest.config.ClientAuth = RequireAnyClientCert
-				}
-				testCases = append(testCases, signTest, signDefaultTest)
-				if ver.version >= VersionTLS12 && !shouldFail {
-					testCases = append(testCases, negotiateTest)
-				}
-
-				// Test the shim using the algorithm for verifying.
-				verifyTest := testCase{
-					testType: verifyTestType,
-					name:     verifyPrefix + "Verify" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Credential: cert,
-						Bugs: ProtocolBugs{
-							SkipECDSACurveCheck:          shouldFail,
-							IgnoreSignatureVersionChecks: shouldFail,
-							// Some signature algorithms may not be advertised.
-							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
-						},
-					},
-					flags: curveFlags,
-					// Resume the session to assert the peer signature
-					// algorithm is reported on both handshakes.
-					resumeSession:      !shouldFail,
-					shouldFail:         shouldFail,
-					expectedError:      verifyError(shouldFail),
-					expectedLocalError: verifyLocalError(shouldFail),
-				}
-				if alg.id != 0 {
-					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
-					// The algorithm may be disabled by default, so explicitly enable it.
-					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
-				}
-
-				// Test whether the shim expects the algorithm enabled by default.
-				defaultTest := testCase{
-					testType: verifyTestType,
-					name:     verifyPrefix + "VerifyDefault" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Credential: cert,
-						Bugs: ProtocolBugs{
-							SkipECDSACurveCheck:          !verifyDefault,
-							IgnoreSignatureVersionChecks: !verifyDefault,
-							// Some signature algorithms may not be advertised.
-							IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
-						},
-					},
-					flags: append(
-						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
-						curveFlags...,
-					),
-					// Resume the session to assert the peer signature
-					// algorithm is reported on both handshakes.
-					resumeSession:      verifyDefault,
-					shouldFail:         !verifyDefault,
-					expectedError:      verifyError(!verifyDefault),
-					expectedLocalError: verifyLocalError(!verifyDefault),
-				}
-
-				// Test whether the shim handles invalid signatures for this algorithm.
-				invalidTest := testCase{
-					testType: verifyTestType,
-					name:     verifyPrefix + "InvalidSignature" + suffix,
-					config: Config{
-						MaxVersion: ver.version,
-						Credential: cert,
-						Bugs: ProtocolBugs{
-							InvalidSignature: true,
-						},
-					},
-					flags:         curveFlags,
-					shouldFail:    true,
-					expectedError: ":BAD_SIGNATURE:",
-				}
-				if alg.id != 0 {
-					// The algorithm may be disabled by default, so explicitly enable it.
-					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
-				}
-
-				if verifyTestType == serverTest {
-					// TLS 1.2 servers only verify when they request client certificates.
-					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
-					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
-					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
-				} else {
-					// TLS 1.2 clients only verify on some cipher suites.
-					verifyTest.config.CipherSuites = signingCiphers
-					defaultTest.config.CipherSuites = signingCiphers
-					invalidTest.config.CipherSuites = signingCiphers
-				}
-				testCases = append(testCases, verifyTest, defaultTest)
-				if !shouldFail {
-					testCases = append(testCases, invalidTest)
-				}
-			}
-		}
-	}
-
-	// Test the peer's verify preferences are available.
-	for _, ver := range tlsVersions {
-		if ver.version < VersionTLS12 {
-			continue
-		}
-		testCases = append(testCases, testCase{
-			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
-			config: Config{
-				MaxVersion: ver.version,
-				ClientAuth: RequireAnyClientCert,
-				VerifySignatureAlgorithms: []signatureAlgorithm{
-					signatureRSAPSSWithSHA256,
-					signatureEd25519,
-					signatureECDSAWithP256AndSHA256,
-				},
-			},
-			shimCertificate: &rsaCertificate,
-			flags: []string{
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
-			config: Config{
-				MaxVersion: ver.version,
-				VerifySignatureAlgorithms: []signatureAlgorithm{
-					signatureRSAPSSWithSHA256,
-					signatureEd25519,
-					signatureECDSAWithP256AndSHA256,
-				},
-			},
-			shimCertificate: &rsaCertificate,
-			flags: []string{
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
-				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
-			},
-		})
-
-	}
-
-	// Test that algorithm selection takes the key type into account.
-	testCases = append(testCases, testCase{
-		name: "ClientAuth-SignatureType",
-		config: Config{
-			ClientAuth: RequireAnyClientCert,
-			MaxVersion: VersionTLS12,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP521AndSHA512,
-				signatureRSAPKCS1WithSHA384,
-				signatureECDSAWithSHA1,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ClientAuth-SignatureType-TLS13",
-		config: Config{
-			ClientAuth: RequireAnyClientCert,
-			MaxVersion: VersionTLS13,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP521AndSHA512,
-				signatureRSAPKCS1WithSHA384,
-				signatureRSAPSSWithSHA384,
-				signatureECDSAWithSHA1,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerAuth-SignatureType",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP521AndSHA512,
-				signatureRSAPKCS1WithSHA384,
-				signatureECDSAWithSHA1,
-			},
-		},
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerAuth-SignatureType-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP521AndSHA512,
-				signatureRSAPKCS1WithSHA384,
-				signatureRSAPSSWithSHA384,
-				signatureECDSAWithSHA1,
-			},
-		},
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
-		},
-	})
-
-	// Test that signature verification takes the key type into account.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Verify-ClientAuth-SignatureType",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
-			Bugs: ProtocolBugs{
-				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
-			},
-		},
-		flags: []string{
-			"-require-any-client-certificate",
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Verify-ClientAuth-SignatureType-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			Bugs: ProtocolBugs{
-				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
-			},
-		},
-		flags: []string{
-			"-require-any-client-certificate",
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "Verify-ServerAuth-SignatureType",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
-			Bugs: ProtocolBugs{
-				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "Verify-ServerAuth-SignatureType-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			Bugs: ProtocolBugs{
-				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	// Test that, if the ClientHello list is missing, the server falls back
-	// to SHA-1 in TLS 1.2, but not TLS 1.3.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerAuth-SHA1-Fallback-RSA",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerAuth-SHA1-Fallback-ECDSA",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shimCertificate: &ecdsaP256Certificate,
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerAuth-NoFallback-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-	})
-
-	// The CertificateRequest list, however, may never be omitted. It is a
-	// syntax error for it to be empty.
-	testCases = append(testCases, testCase{
-		name: "ClientAuth-NoFallback-RSA",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shimCertificate:    &rsaCertificate,
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ClientAuth-NoFallback-ECDSA",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shimCertificate:    &ecdsaP256Certificate,
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ClientAuth-NoFallback-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
-			},
-		},
-		shimCertificate:    &rsaCertificate,
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	// Test that signature preferences are enforced. BoringSSL does not
-	// implement MD5 signatures.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ClientAuth-Enforced",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-			},
-		},
-		flags:         []string{"-require-any-client-certificate"},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ServerAuth-Enforced",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ClientAuth-Enforced-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-				IgnoreSignatureVersionChecks:            true,
-			},
-		},
-		flags:         []string{"-require-any-client-certificate"},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "ServerAuth-Enforced-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-				IgnoreSignatureVersionChecks:            true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	// Test that the negotiated signature algorithm respects the client and
-	// server preferences.
-	testCases = append(testCases, testCase{
-		name: "NoCommonAlgorithms",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA512,
-				signatureRSAPKCS1WithSHA1,
-			},
-		},
-		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
-		shouldFail:      true,
-		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-	})
-	testCases = append(testCases, testCase{
-		name: "NoCommonAlgorithms-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPSSWithSHA512,
-				signatureRSAPSSWithSHA384,
-			},
-		},
-		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-		shouldFail:      true,
-		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-	})
-	testCases = append(testCases, testCase{
-		name: "Agree-Digest-SHA256",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-				signatureRSAPKCS1WithSHA256,
-			},
-		},
-		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
-			signatureRSAPKCS1WithSHA256,
-			signatureRSAPKCS1WithSHA1,
-		),
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Agree-Digest-SHA1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA1,
-			},
-		},
-		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
-			signatureRSAPKCS1WithSHA512,
-			signatureRSAPKCS1WithSHA256,
-			signatureRSAPKCS1WithSHA1,
-		),
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "Agree-Digest-Default",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA256,
-				signatureECDSAWithP256AndSHA256,
-				signatureRSAPKCS1WithSHA1,
-				signatureECDSAWithSHA1,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
-		},
-	})
-
-	// Test that the signing preference list may include extra algorithms
-	// without negotiation problems.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "FilterExtraAlgorithms",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPKCS1WithSHA256,
-			},
-		},
-		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
-			signatureECDSAWithP256AndSHA256,
-			signatureRSAPKCS1WithSHA256,
-		),
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
-		},
-	})
-
-	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
-	// signature algorithms.
-	testCases = append(testCases, testCase{
-		name: "CheckLeafCurve",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Credential:   &ecdsaP256Certificate,
-		},
-		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
-		shouldFail:    true,
-		expectedError: ":BAD_ECC_CERT:",
-	})
-
-	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
-	testCases = append(testCases, testCase{
-		name: "CheckLeafCurve-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &ecdsaP256Certificate,
-		},
-		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
-	})
-
-	// In TLS 1.2, the ECDSA curve is not in the signature algorithm, so the
-	// shim should accept P-256 with SHA-384.
-	testCases = append(testCases, testCase{
-		name: "ECDSACurveMismatch-Verify-TLS12",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Credential:   ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
-		},
-	})
-
-	// In TLS 1.3, the ECDSA curve comes from the signature algorithm, so the
-	// shim should reject P-256 with SHA-384.
-	testCases = append(testCases, testCase{
-		name: "ECDSACurveMismatch-Verify-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
-			Bugs: ProtocolBugs{
-				SkipECDSACurveCheck: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	// Signature algorithm selection in TLS 1.3 should take the curve into
-	// account.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ECDSACurveMismatch-Sign-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP384AndSHA384,
-				signatureECDSAWithP256AndSHA256,
-			},
-		},
-		shimCertificate: &ecdsaP256Certificate,
-		expectations: connectionExpectations{
-			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
-		},
-	})
-
-	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
-	// server does not attempt to sign in that case.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "RSA-PSS-Large",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPSSWithSHA512,
-			},
-		},
-		shimCertificate: &rsa1024Certificate,
-		shouldFail:      true,
-		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-	})
-
-	// Test that RSA-PSS is enabled by default for TLS 1.2.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "RSA-PSS-Default-Verify",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-		},
-		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "RSA-PSS-Default-Sign",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureRSAPSSWithSHA256,
-			},
-		},
-		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-
-	// TLS 1.1 and below has no way to advertise support for or negotiate
-	// Ed25519's signature algorithm.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "NoEd25519-TLS11-ServerAuth-Verify",
-		config: Config{
-			MaxVersion: VersionTLS11,
-			Credential: &ed25519Certificate,
-			Bugs: ProtocolBugs{
-				// Sign with Ed25519 even though it is TLS 1.1.
-				SigningAlgorithmForLegacyVersions: signatureEd25519,
-			},
-		},
-		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
-		shouldFail:    true,
-		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoEd25519-TLS11-ServerAuth-Sign",
-		config: Config{
-			MaxVersion: VersionTLS11,
-		},
-		shimCertificate: &ed25519Certificate,
-		shouldFail:      true,
-		expectedError:   ":NO_SHARED_CIPHER:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoEd25519-TLS11-ClientAuth-Verify",
-		config: Config{
-			MaxVersion: VersionTLS11,
-			Credential: &ed25519Certificate,
-			Bugs: ProtocolBugs{
-				// Sign with Ed25519 even though it is TLS 1.1.
-				SigningAlgorithmForLegacyVersions: signatureEd25519,
-			},
-		},
-		flags: []string{
-			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
-			"-require-any-client-certificate",
-		},
-		shouldFail:    true,
-		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "NoEd25519-TLS11-ClientAuth-Sign",
-		config: Config{
-			MaxVersion: VersionTLS11,
-			ClientAuth: RequireAnyClientCert,
-		},
-		shimCertificate: &ed25519Certificate,
-		shouldFail:      true,
-		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-	})
-
-	// Test Ed25519 is not advertised by default.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Ed25519DefaultDisable-NoAdvertise",
-		config: Config{
-			Credential: &ed25519Certificate,
-		},
-		shouldFail:         true,
-		expectedLocalError: "tls: no common signature algorithms",
-	})
-
-	// Test Ed25519, when disabled, is not accepted if the peer ignores our
-	// preferences.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Ed25519DefaultDisable-NoAccept",
-		config: Config{
-			Credential: &ed25519Certificate,
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: illegal parameter",
-		expectedError:      ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	// Test that configuring verify preferences changes what the client
-	// advertises.
-	testCases = append(testCases, testCase{
-		name: "VerifyPreferences-Advertised",
-		config: Config{
-			Credential: rsaCertificate.WithSignatureAlgorithms(
-				signatureRSAPSSWithSHA256,
-				signatureRSAPSSWithSHA384,
-				signatureRSAPSSWithSHA512,
-			),
-		},
-		flags: []string{
-			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
-			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
-		},
-	})
-
-	// Test that the client advertises a set which the runner can find
-	// nothing in common with.
-	testCases = append(testCases, testCase{
-		name: "VerifyPreferences-NoCommonAlgorithms",
-		config: Config{
-			Credential: rsaCertificate.WithSignatureAlgorithms(
-				signatureRSAPSSWithSHA256,
-				signatureRSAPSSWithSHA512,
-			),
-		},
-		flags: []string{
-			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
-		},
-		shouldFail:         true,
-		expectedLocalError: "tls: no common signature algorithms",
-	})
-
-	// Test that the client enforces its preferences when configured.
-	testCases = append(testCases, testCase{
-		name: "VerifyPreferences-Enforced",
-		config: Config{
-			Credential: rsaCertificate.WithSignatureAlgorithms(
-				signatureRSAPSSWithSHA256,
-				signatureRSAPSSWithSHA512,
-			),
-			Bugs: ProtocolBugs{
-				IgnorePeerSignatureAlgorithmPreferences: true,
-			},
-		},
-		flags: []string{
-			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: illegal parameter",
-		expectedError:      ":WRONG_SIGNATURE_TYPE:",
-	})
-
-	// Test that explicitly configuring Ed25519 is as good as changing the
-	// boolean toggle.
-	testCases = append(testCases, testCase{
-		name: "VerifyPreferences-Ed25519",
-		config: Config{
-			Credential: &ed25519Certificate,
-		},
-		flags: []string{
-			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
-		},
-	})
-
-	for _, testType := range []testType{clientTest, serverTest} {
-		for _, ver := range tlsVersions {
-			if ver.version < VersionTLS12 {
-				continue
-			}
-
-			prefix := "Client-" + ver.name + "-"
-			noCommonAlgorithmsError := ":NO_COMMON_SIGNATURE_ALGORITHMS:"
-			if testType == serverTest {
-				prefix = "Server-" + ver.name + "-"
-				// In TLS 1.2 servers, cipher selection and algorithm
-				// selection are linked.
-				if ver.version <= VersionTLS12 {
-					noCommonAlgorithmsError = ":NO_SHARED_CIPHER:"
-				}
-			}
-
-			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
-			// even if specified in signing preferences.
-			testCases = append(testCases, testCase{
-				testType: testType,
-				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
-				config: Config{
-					MaxVersion:                ver.version,
-					CipherSuites:              signingCiphers,
-					ClientAuth:                RequireAnyClientCert,
-					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
-				},
-				shimCertificate: rsaCertificate.WithSignatureAlgorithms(
-					signatureRSAPKCS1WithMD5AndSHA1,
-					// Include a valid algorithm as well, to avoid an empty list
-					// if filtered out.
-					signatureRSAPKCS1WithSHA256,
-				),
-				shouldFail:    true,
-				expectedError: noCommonAlgorithmsError,
-			})
-
-			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
-			// even if specified in verify preferences.
-			testCases = append(testCases, testCase{
-				testType: testType,
-				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
-				config: Config{
-					MaxVersion: ver.version,
-					Credential: &rsaCertificate,
-					Bugs: ProtocolBugs{
-						IgnorePeerSignatureAlgorithmPreferences: true,
-						AlwaysSignAsLegacyVersion:               true,
-						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
-					},
-				},
-				shimCertificate: &rsaCertificate,
-				flags: []string{
-					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
-					// Include a valid algorithm as well, to avoid an empty list
-					// if filtered out.
-					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
-					"-require-any-client-certificate",
-				},
-				shouldFail:    true,
-				expectedError: ":WRONG_SIGNATURE_TYPE:",
-			})
-		}
-	}
-
-	// Test that, when there are no signature algorithms in common in TLS
-	// 1.2, the server will still consider the legacy RSA key exchange.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoCommonSignatureAlgorithms-TLS12-Fallback",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			CipherSuites: []uint16{
-				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-				TLS_RSA_WITH_AES_128_GCM_SHA256,
-			},
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				signatureECDSAWithP256AndSHA256,
-			},
-		},
-		expectations: connectionExpectations{
-			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
-		},
-	})
-}
-
-// timeouts is the default retransmit schedule for BoringSSL. It doubles and
-// caps at 60 seconds. On the 13th timeout, it gives up.
-var timeouts = []time.Duration{
-	400 * time.Millisecond,
-	800 * time.Millisecond,
-	1600 * time.Millisecond,
-	3200 * time.Millisecond,
-	6400 * time.Millisecond,
-	12800 * time.Millisecond,
-	25600 * time.Millisecond,
-	51200 * time.Millisecond,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-}
-
-// shortTimeouts is an alternate set of timeouts which would occur if the
-// initial timeout duration was set to 250ms.
-var shortTimeouts = []time.Duration{
-	250 * time.Millisecond,
-	500 * time.Millisecond,
-	1 * time.Second,
-	2 * time.Second,
-	4 * time.Second,
-	8 * time.Second,
-	16 * time.Second,
-	32 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-	60 * time.Second,
-}
-
-// dtlsPrevEpochExpiration is how long before the shim releases old epochs. Add
-// an extra second to allow the shim to be less precise.
-const dtlsPrevEpochExpiration = 4*time.Minute + 1*time.Second
-
-func addDTLSRetransmitTests() {
-	for _, shortTimeout := range []bool{false, true} {
-		for _, vers := range allVersions(dtls) {
-			suffix := "-" + vers.name
-			flags := []string{"-async"} // Retransmit tests require async.
-			useTimeouts := timeouts
-			if shortTimeout {
-				suffix += "-Short"
-				flags = append(flags, "-initial-timeout-duration-ms", "250")
-				useTimeouts = shortTimeouts
-			}
-
-			// Testing NewSessionTicket is tricky. First, BoringSSL sends two
-			// tickets in a row. These are conceptually separate flights, but we
-			// test them as one flight. Second, these tickets are sent
-			// concurrently with the runner's first test message. The shim's
-			// reply will come in before any retransmit challenges.
-			// handleNewSessionTicket corrects for both effects.
-			handleNewSessionTicket := func(f ACKFlightFunc) ACKFlightFunc {
-				if vers.version < VersionTLS13 {
-					return f
-				}
-				return func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-					// BoringSSL sends two NewSessionTickets in a row.
-					if received[0].Type == typeNewSessionTicket && len(received) < 2 {
-						c.MergeIntoNextFlight()
-						return
-					}
-					// NewSessionTicket is sent in parallel with the runner's
-					// first application data. Consume the shim's reply.
-					testMessage := makeTestMessage(0, 32)
-					if received[0].Type == typeNewSessionTicket {
-						c.ReadAppData(c.InEpoch(), expectedReply(testMessage))
-					}
-					// Run the test, without any stray messages in the way.
-					f(c, prev, received, records)
-					// The test loop is expecting a reply to the first message.
-					// Prime the shim to send it again.
-					if received[0].Type == typeNewSessionTicket {
-						c.WriteAppData(c.OutEpoch(), testMessage)
-					}
-				}
-			}
-
-			// In all versions, the sender will retransmit the whole flight if
-			// it times out and hears nothing.
-			writeFlightBasic := func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-				if len(received) > 0 {
-					// Exercise every timeout but the last one (which would fail the
-					// connection).
-					for _, t := range useTimeouts[:len(useTimeouts)-1] {
-						c.ExpectNextTimeout(t)
-						c.AdvanceClock(t)
-						c.ReadRetransmit()
-					}
-					c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
-				}
-				// Finally release the whole flight to the shim.
-				c.WriteFlight(next)
-			}
-			ackFlightBasic := handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-				if vers.version >= VersionTLS13 {
-					// In DTLS 1.3, final flights (either handshake or post-handshake)
-					// are retransmited until ACKed. Exercise every timeout but
-					// the last one (which would fail the connection).
-					for _, t := range useTimeouts[:len(useTimeouts)-1] {
-						c.ExpectNextTimeout(t)
-						c.AdvanceClock(t)
-						c.ReadRetransmit()
-					}
-					c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
-					// Finally ACK the flight.
-					c.WriteACK(c.OutEpoch(), records)
-					return
-				}
-				// In DTLS 1.2, the final flight is retransmitted on receipt of
-				// the previous flight. Test the peer is willing to retransmit
-				// it several times.
-				for i := 0; i < 5; i++ {
-					c.WriteFlight(prev)
-					c.ReadRetransmit()
-				}
-			})
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     "DTLS-Retransmit-Client-Basic" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						WriteFlightDTLS: writeFlightBasic,
-						ACKFlightDTLS:   ackFlightBasic,
-					},
-				},
-				resumeSession: true,
-				flags:         flags,
-			})
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				testType: serverTest,
-				name:     "DTLS-Retransmit-Server-Basic" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						WriteFlightDTLS: writeFlightBasic,
-						ACKFlightDTLS:   ackFlightBasic,
-					},
-				},
-				resumeSession: true,
-				flags:         flags,
-			})
-
-			if vers.version <= VersionTLS12 {
-				// In DTLS 1.2, receiving a part of the next flight should not stop
-				// the retransmission timer.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-PartialProgress" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								// Send a portion of the first message. The rest was lost.
-								msg := next[0]
-								split := len(msg.Data) / 2
-								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
-								// If we time out, the shim should still retransmit. It knows
-								// we received the whole flight, but the shim should use a
-								// retransmit to request the runner try again.
-								c.AdvanceClock(useTimeouts[0])
-								c.ReadRetransmit()
-								// "Retransmit" the rest of the flight. The shim should remember
-								// the portion that was already sent.
-								rest := []DTLSFragment{msg.Fragment(split, len(msg.Data)-split)}
-								for _, m := range next[1:] {
-									rest = append(rest, m.Fragment(0, len(m.Data)))
-								}
-								c.WriteFragments(rest)
-							},
-						},
-					},
-					flags: flags,
-				})
-			} else {
-				// In DTLS 1.3, receiving a part of the next flight implicitly ACKs
-				// the previous flight.
-				testCases = append(testCases, testCase{
-					testType: serverTest,
-					protocol: dtls,
-					name:     "DTLS-Retransmit-PartialProgress-Server" + suffix,
-					config: Config{
-						MaxVersion:    vers.version,
-						DefaultCurves: []CurveID{}, // Force HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) == 0 && next[0].Type == typeClientHello {
-									// Send the initial ClientHello as-is.
-									c.WriteFlight(next)
-									return
-								}
-
-								// Send a portion of the first message. The rest was lost.
-								msg := next[0]
-								split := len(msg.Data) / 2
-								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
-								// After waiting the current timeout, the shim should ACK
-								// the partial flight.
-								c.ExpectNextTimeout(useTimeouts[0] / 4)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-								// The partial flight is enough to ACK the previous flight.
-								// The shim should stop retransmitting and even stop the
-								// retransmit timer.
-								c.ExpectNoNextTimeout()
-								for _, t := range useTimeouts {
-									c.AdvanceClock(t)
-								}
-								// "Retransmit" the rest of the flight. The shim should remember
-								// the portion that was already sent.
-								rest := []DTLSFragment{msg.Fragment(split, len(msg.Data)-split)}
-								for _, m := range next[1:] {
-									rest = append(rest, m.Fragment(0, len(m.Data)))
-								}
-								c.WriteFragments(rest)
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				// When the shim is a client, receiving fragments before the version is
-				// known does not trigger this behavior.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-PartialProgress-Client" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								msg := next[0]
-								if msg.Type != typeServerHello {
-									// Post-handshake is tested separately.
-									c.WriteFlight(next)
-									return
-								}
-								// Send a portion of the ServerHello. The rest was lost.
-								split := len(msg.Data) / 2
-								c.WriteFragments([]DTLSFragment{msg.Fragment(0, split)})
-
-								// The shim did not know this was DTLS 1.3, so it still
-								// retransmits ClientHello.
-								c.ExpectNextTimeout(useTimeouts[0])
-								c.AdvanceClock(useTimeouts[0])
-								c.ReadRetransmit()
-
-								// Finish the ServerHello. The version is still not known,
-								// at the time the ServerHello fragment is processed, This
-								// is not as efficient as we could be; we could go back and
-								// implicitly ACK once the version is known. But the last
-								// byte of ServerHello will almost certainly be in the same
-								// packet as EncryptedExtensions, which will trigger the case
-								// below.
-								c.WriteFragments([]DTLSFragment{msg.Fragment(split, len(msg.Data)-split)})
-								c.ExpectNextTimeout(useTimeouts[1])
-								c.AdvanceClock(useTimeouts[1])
-								c.ReadRetransmit()
-
-								// Send EncryptedExtensions. The shim now knows the version.
-								c.WriteFragments([]DTLSFragment{next[1].Fragment(0, len(next[1].Data))})
-
-								// The shim should ACK the partial flight. The shim hasn't
-								// gotten to epoch 3 yet, so the ACK will come in epoch 2.
-								c.AdvanceClock(useTimeouts[2] / 4)
-								c.ReadACK(uint16(encryptionHandshake))
-
-								// This is enough to ACK the previous flight. The shim
-								// should stop retransmitting and even stop the timer.
-								c.ExpectNoNextTimeout()
-								for _, t := range useTimeouts[2:] {
-									c.AdvanceClock(t)
-								}
-
-								// "Retransmit" the rest of the flight. The shim should remember
-								// the portion that was already sent.
-								var rest []DTLSFragment
-								for _, m := range next[2:] {
-									rest = append(rest, m.Fragment(0, len(m.Data)))
-								}
-								c.WriteFragments(rest)
-							},
-						},
-					},
-					flags: flags,
-				})
-			}
-
-			// Test that exceeding the timeout schedule hits a read
-			// timeout.
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     "DTLS-Retransmit-Timeout" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-							for _, t := range useTimeouts[:len(useTimeouts)-1] {
-								c.ExpectNextTimeout(t)
-								c.AdvanceClock(t)
-								c.ReadRetransmit()
-							}
-							c.ExpectNextTimeout(useTimeouts[len(useTimeouts)-1])
-							c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
-							// The shim should give up at this point.
-						},
-					},
-				},
-				resumeSession: true,
-				flags:         flags,
-				shouldFail:    true,
-				expectedError: ":READ_TIMEOUT_EXPIRED:",
-			})
-
-			// Test that timeout handling has a fudge factor, due to API
-			// problems.
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     "DTLS-Retransmit-Fudge" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-							if len(received) > 0 {
-								c.ExpectNextTimeout(useTimeouts[0])
-								c.AdvanceClock(useTimeouts[0] - 10*time.Millisecond)
-								c.ReadRetransmit()
-							}
-							c.WriteFlight(next)
-						},
-					},
-				},
-				resumeSession: true,
-				flags:         flags,
-			})
-
-			// Test that the shim can retransmit at different MTUs.
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     "DTLS-Retransmit-ChangeMTU" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					// Request a client certificate, so the shim has more to send.
-					ClientAuth: RequireAnyClientCert,
-					Bugs: ProtocolBugs{
-						WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-							for i, mtu := range []int{300, 301, 302, 303, 299, 298, 297} {
-								c.SetMTU(mtu)
-								c.AdvanceClock(useTimeouts[i])
-								c.ReadRetransmit()
-							}
-							c.WriteFlight(next)
-						},
-					},
-				},
-				shimCertificate: &rsaChainCertificate,
-				flags:           flags,
-			})
-
-			// DTLS 1.3 uses explicit ACKs.
-			if vers.version >= VersionTLS13 {
-				// The two server flights (HelloRetryRequest and ServerHello..Finished)
-				// happen after the shim has learned the version, so they are more
-				// straightforward. In these tests, we trigger HelloRetryRequest,
-				// and also use ML-KEM with rsaChainCertificate and a limited MTU,
-				// to increase the number of records and exercise more complex
-				// ACK patterns.
-
-				// After ACKing everything, the shim should stop retransmitting.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKEverything" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						Credential:       &rsaChainCertificate,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							// Send smaller packets to exercise more ACK cases.
-							MaxPacketLength:          512,
-							MaxHandshakeRecordLength: 512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									c.ExpectNextTimeout(useTimeouts[0])
-									c.WriteACK(ackEpoch, records)
-									// After everything is ACKed, the shim should stop the timer
-									// and wait for the next flight.
-									c.ExpectNoNextTimeout()
-									for _, t := range useTimeouts {
-										c.AdvanceClock(t)
-									}
-								}
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								ackEpoch := received[len(received)-1].Epoch
-								c.ExpectNextTimeout(useTimeouts[0])
-								c.WriteACK(ackEpoch, records)
-								// After everything is ACKed, the shim should stop the timer.
-								c.ExpectNoNextTimeout()
-								for _, t := range useTimeouts {
-									c.AdvanceClock(t)
-								}
-							}),
-							SequenceNumberMapping: func(in uint64) uint64 {
-								// Perturb sequence numbers to test that ACKs are sorted.
-								return in ^ 63
-							},
-						},
-					},
-					shimCertificate: &rsaChainCertificate,
-					flags: slices.Concat(flags, []string{
-						"-mtu", "512",
-						"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-						// Request a client certificate so the client final flight is
-						// larger.
-						"-require-any-client-certificate",
-					}),
-				})
-
-				// ACK packets one by one, in reverse.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKReverse" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							MaxPacketLength: 512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									for _, t := range useTimeouts[:len(useTimeouts)-1] {
-										if len(records) > 0 {
-											c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[len(records)-1]})
-										}
-										c.AdvanceClock(t)
-										records = c.ReadRetransmit()
-									}
-								}
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								ackEpoch := received[len(received)-1].Epoch
-								for _, t := range useTimeouts[:len(useTimeouts)-1] {
-									if len(records) > 0 {
-										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[len(records)-1]})
-									}
-									c.AdvanceClock(t)
-									records = c.ReadRetransmit()
-								}
-							}),
-						},
-					},
-					shimCertificate: &rsaChainCertificate,
-					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// ACK packets one by one, forwards.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKForwards" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							MaxPacketLength: 512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									for _, t := range useTimeouts[:len(useTimeouts)-1] {
-										if len(records) > 0 {
-											c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
-										}
-										c.AdvanceClock(t)
-										records = c.ReadRetransmit()
-									}
-								}
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								ackEpoch := received[len(received)-1].Epoch
-								for _, t := range useTimeouts[:len(useTimeouts)-1] {
-									if len(records) > 0 {
-										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
-									}
-									c.AdvanceClock(t)
-									records = c.ReadRetransmit()
-								}
-							}),
-						},
-					},
-					shimCertificate: &rsaChainCertificate,
-					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// ACK 1/3 the packets each time.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKIterate" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						DefaultCurves:    []CurveID{}, // Force HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							MaxPacketLength: 512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									for i, t := range useTimeouts[:len(useTimeouts)-1] {
-										if len(records) > 0 {
-											ack := make([]DTLSRecordNumberInfo, 0, (len(records)+2)/3)
-											for i := 0; i < len(records); i += 3 {
-												ack = append(ack, records[i])
-											}
-											c.WriteACK(ackEpoch, ack)
-										}
-										// Change the MTU every iteration, to make the fragment
-										// patterns more complex.
-										c.SetMTU(512 + i)
-										c.AdvanceClock(t)
-										records = c.ReadRetransmit()
-									}
-								}
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								ackEpoch := received[len(received)-1].Epoch
-								for _, t := range useTimeouts[:len(useTimeouts)-1] {
-									if len(records) > 0 {
-										c.WriteACK(ackEpoch, []DTLSRecordNumberInfo{records[0]})
-									}
-									c.AdvanceClock(t)
-									records = c.ReadRetransmit()
-								}
-							}),
-						},
-					},
-					shimCertificate: &rsaChainCertificate,
-					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// ACKing packets that have already been ACKed is a no-op.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKDuplicate" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							SendHelloRetryRequestCookie: []byte("cookie"),
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									// Keep ACKing the same record over and over.
-									c.WriteACK(ackEpoch, records[:1])
-									c.AdvanceClock(useTimeouts[0])
-									c.ReadRetransmit()
-									c.WriteACK(ackEpoch, records[:1])
-									c.AdvanceClock(useTimeouts[1])
-									c.ReadRetransmit()
-								}
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								ackEpoch := received[len(received)-1].Epoch
-								// Keep ACKing the same record over and over.
-								c.WriteACK(ackEpoch, records[:1])
-								c.AdvanceClock(useTimeouts[0])
-								c.ReadRetransmit()
-								c.WriteACK(ackEpoch, records[:1])
-								c.AdvanceClock(useTimeouts[1])
-								c.ReadRetransmit()
-								// ACK everything to clear the timer.
-								c.WriteACK(ackEpoch, records)
-							}),
-						},
-					},
-					flags: flags,
-				})
-
-				// When ACKing ServerHello..Finished, the ServerHello might be
-				// ACKed at epoch 0 or epoch 2, depending on how far the client
-				// received. Test that epoch 0 is allowed by ACKing each packet
-				// at the record it was received.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKMatchingEpoch" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									for _, t := range useTimeouts[:len(useTimeouts)-1] {
-										if len(records) > 0 {
-											c.WriteACK(uint16(records[0].Epoch), []DTLSRecordNumberInfo{records[0]})
-										}
-										c.AdvanceClock(t)
-										records = c.ReadRetransmit()
-									}
-								}
-								c.WriteFlight(next)
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				// However, records in the handshake may not be ACKed at lower
-				// epoch than they were received.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKBadEpoch" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) == 0 {
-									// Send the ClientHello.
-									c.WriteFlight(next)
-								} else {
-									// Try to ACK ServerHello..Finished at epoch 0. The shim should reject this.
-									c.WriteACK(0, records)
-								}
-							},
-						},
-					},
-					flags:         flags,
-					shouldFail:    true,
-					expectedError: ":DECODE_ERROR:",
-				})
-
-				// The bad epoch check should notice when the epoch number
-				// would overflow 2^16.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKEpochOverflow" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) == 0 {
-									// Send the ClientHello.
-									c.WriteFlight(next)
-								} else {
-									r := records[0]
-									r.Epoch += 1 << 63
-									c.WriteACK(0, []DTLSRecordNumberInfo{r})
-								}
-							},
-						},
-					},
-					flags:         flags,
-					shouldFail:    true,
-					expectedError: ":DECODE_ERROR:",
-				})
-
-				// ACK some records from the first transmission, trigger a
-				// retransmit, but then ACK the rest of the first transmission.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKOldRecords" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						Bugs: ProtocolBugs{
-							MaxPacketLength: 512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									ackEpoch := received[len(received)-1].Epoch
-									c.WriteACK(ackEpoch, records[len(records)/2:])
-									c.AdvanceClock(useTimeouts[0])
-									c.ReadRetransmit()
-									c.WriteACK(ackEpoch, records[:len(records)/2])
-									// Everything should be ACKed now. The shim should not
-									// retransmit anything.
-									c.AdvanceClock(useTimeouts[1])
-									c.AdvanceClock(useTimeouts[2])
-									c.AdvanceClock(useTimeouts[3])
-								}
-								c.WriteFlight(next)
-							},
-						},
-					},
-					flags: slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// If the shim sends too many records, it will eventually forget them.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKForgottenRecords" + suffix,
-					config: Config{
-						MaxVersion:       vers.version,
-						CurvePreferences: []CurveID{CurveX25519MLKEM768},
-						Bugs: ProtocolBugs{
-							MaxPacketLength: 256,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) > 0 {
-									// Make the peer retransmit many times, with a small MTU.
-									for _, t := range useTimeouts[:len(useTimeouts)-2] {
-										c.AdvanceClock(t)
-										c.ReadRetransmit()
-									}
-									// ACK the first record the shim ever sent. It will have
-									// fallen off the queue by now, so it is expected to not
-									// impact the shim's retransmissions.
-									c.WriteACK(c.OutEpoch(), []DTLSRecordNumberInfo{{DTLSRecordNumber: records[0].DTLSRecordNumber}})
-									c.AdvanceClock(useTimeouts[len(useTimeouts)-2])
-									c.ReadRetransmit()
-								}
-								c.WriteFlight(next)
-							},
-						},
-					},
-					flags: slices.Concat(flags, []string{"-mtu", "256", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// The shim should ignore ACKs for a previous flight, and not get its
-				// internal state confused.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKPreviousFlight" + suffix,
-					config: Config{
-						MaxVersion:    vers.version,
-						DefaultCurves: []CurveID{}, // Force a HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[len(next)-1].Type == typeFinished {
-									// We are now sending client Finished, in response
-									// to the shim's ServerHello. ACK the shim's first
-									// record, which would have been part of
-									// HelloRetryRequest. This should not impact retransmit.
-									c.WriteACK(c.OutEpoch(), []DTLSRecordNumberInfo{{DTLSRecordNumber: DTLSRecordNumber{Epoch: 0, Sequence: 0}}})
-									c.AdvanceClock(useTimeouts[0])
-									c.ReadRetransmit()
-								}
-								c.WriteFlight(next)
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				// Records that contain a mix of discarded and processed fragments should
-				// not be ACKed.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-DoNotACKDiscardedFragments" + suffix,
-					config: Config{
-						MaxVersion:    vers.version,
-						DefaultCurves: []CurveID{}, // Force a HelloRetryRequest.
-						Bugs: ProtocolBugs{
-							PackHandshakeFragments: 4096,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								// Send the flight, but combine every fragment with a far future
-								// fragment, which the shim will discard. During the handshake,
-								// the shim has enough information to reject this entirely, but
-								// that would require coordinating with the handshake state
-								// machine. Instead, BoringSSL discards the fragment and skips
-								// ACKing the packet.
-								//
-								// runner implicitly tests that the shim ACKs the Finished flight
-								// (or, in case, that it is does not), so this exercises the final
-								// ACK.
-								for _, msg := range next {
-									shouldDiscard := DTLSFragment{Epoch: msg.Epoch, Sequence: 1000, ShouldDiscard: true}
-									c.WriteFragments([]DTLSFragment{shouldDiscard, msg.Fragment(0, len(msg.Data))})
-									// The shim has nothing to ACK and thus no ACK timer (which
-									// would be 1/4 of this value).
-									c.ExpectNextTimeout(useTimeouts[0])
-								}
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				// The server must continue to ACK the Finished flight even after
-				// receiving application data from the client.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					testType: serverTest,
-					name:     "DTLS-Retransmit-Server-ACKFinishedAfterAppData" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							// WriteFlightDTLS will handle consuming ACKs.
-							SkipImplicitACKRead: true,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[len(next)-1].Type != typeFinished {
-									c.WriteFlight(next)
-									return
-								}
-
-								// Write Finished. The shim should ACK it immediately.
-								c.WriteFlight(next)
-								c.ReadACK(c.InEpoch())
-
-								// Exchange some application data.
-								msg := []byte("hello")
-								c.WriteAppData(c.OutEpoch(), msg)
-								c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-								// Act as if the ACK was dropped and retransmit Finished.
-								// The shim should process the retransmit from epoch 2 and
-								// ACK, although it has already received data at epoch 3.
-								c.WriteFlight(next)
-								ackTimeout := useTimeouts[0] / 4
-								c.AdvanceClock(ackTimeout)
-								c.ReadACK(c.InEpoch())
-
-								// Partially retransmit Finished. The shim should continue
-								// to ACK.
-								c.WriteFragments([]DTLSFragment{next[0].Fragment(0, 1)})
-								c.WriteFragments([]DTLSFragment{next[0].Fragment(1, 1)})
-								c.AdvanceClock(ackTimeout)
-								c.ReadACK(c.InEpoch())
-
-								// Eventually, the shim assumes we have received the ACK
-								// and drops epoch 2. Retransmits now go unanswered.
-								c.AdvanceClock(dtlsPrevEpochExpiration)
-								c.WriteFlight(next)
-							},
-						},
-					},
-					// Disable tickets on the shim to avoid NewSessionTicket
-					// interfering with the test callback.
-					flags: slices.Concat(flags, []string{"-no-ticket"}),
-				})
-
-				// As a client, the shim must tolerate ACKs in response to its
-				// initial ClientHello, but it will not process them because the
-				// version is not yet known. The second ClientHello, in response
-				// to HelloRetryRequest, however, is ACKed.
-				//
-				// The shim must additionally process ACKs and retransmit its
-				// Finished flight, possibly interleaved with application data.
-				// (The server may send half-RTT data without Finished.)
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Client" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						// Require a client certificate, so the Finished flight
-						// is large.
-						ClientAuth: RequireAnyClientCert,
-						Bugs: ProtocolBugs{
-							SendHelloRetryRequestCookie: []byte("cookie"), // Send HelloRetryRequest
-							MaxPacketLength:             512,
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if len(received) == 0 || received[0].Type != typeClientHello {
-									// We test post-handshake flights separately.
-									c.WriteFlight(next)
-									return
-								}
-
-								// This is either HelloRetryRequest in response to ClientHello1,
-								// or ServerHello..Finished in response to ClientHello2.
-								first := records[0]
-								if len(prev) == 0 {
-									// This is HelloRetryRequest in response to ClientHello1. The client
-									// will accept the ACK, but it will ignore it. Do not expect
-									// retransmits to be impacted.
-									first.MessageStartSequence = 0
-									first.MessageStartOffset = 0
-									first.MessageEndSequence = 0
-									first.MessageEndOffset = 0
-								}
-								c.WriteACK(0, []DTLSRecordNumberInfo{first})
-								c.AdvanceClock(useTimeouts[0])
-								c.ReadRetransmit()
-								c.WriteFlight(next)
-							},
-							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								// The shim will process application data without an ACK.
-								msg := []byte("hello")
-								c.WriteAppData(c.OutEpoch(), msg)
-								c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-								// After a timeout, the shim will retransmit Finished.
-								c.AdvanceClock(useTimeouts[0])
-								c.ReadRetransmit()
-
-								// Application data still flows.
-								c.WriteAppData(c.OutEpoch(), msg)
-								c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-								// ACK part of the flight and check that retransmits
-								// are updated.
-								c.WriteACK(c.OutEpoch(), records[len(records)/3:2*len(records)/3])
-								c.AdvanceClock(useTimeouts[1])
-								records = c.ReadRetransmit()
-
-								// ACK the rest. Retransmits should stop.
-								c.WriteACK(c.OutEpoch(), records)
-								for _, t := range useTimeouts[2:] {
-									c.AdvanceClock(t)
-								}
-							},
-						},
-					},
-					shimCertificate: &rsaChainCertificate,
-					flags:           slices.Concat(flags, []string{"-mtu", "512", "-curves", strconv.Itoa(int(CurveX25519MLKEM768))}),
-				})
-
-				// If the client never receives an ACK for the Finished flight, it
-				// is eventually fatal.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Client-FinishedTimeout" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								for _, t := range useTimeouts[:len(useTimeouts)-1] {
-									c.AdvanceClock(t)
-									c.ReadRetransmit()
-								}
-								c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
-							},
-						},
-					},
-					flags:         flags,
-					shouldFail:    true,
-					expectedError: ":READ_TIMEOUT_EXPIRED:",
-				})
-
-				// Neither post-handshake messages nor application data implicitly
-				// ACK the Finished flight. The server may have sent either in
-				// half-RTT data. Test that the client continues to retransmit
-				// despite this.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Client-NoImplictACKFinished" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								// Merge the Finished flight into the NewSessionTicket.
-								c.MergeIntoNextFlight()
-							},
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[0].Type != typeNewSessionTicket {
-									c.WriteFlight(next)
-									return
-								}
-								if len(received) == 0 || received[0].Type != typeFinished {
-									panic("Finished should be merged with NewSessionTicket")
-								}
-								// Merge NewSessionTicket into the KeyUpdate.
-								if next[len(next)-1].Type != typeKeyUpdate {
-									c.MergeIntoNextFlight()
-									return
-								}
-
-								// Write NewSessionTicket and the KeyUpdate and
-								// read the ACK.
-								c.WriteFlight(next)
-								ackTimeout := useTimeouts[0] / 4
-								c.AdvanceClock(ackTimeout)
-								c.ReadACK(c.InEpoch())
-
-								// The retransmit timer is still running.
-								c.AdvanceClock(useTimeouts[0] - ackTimeout)
-								c.ReadRetransmit()
-
-								// Application data can flow at the old epoch.
-								msg := []byte("test")
-								c.WriteAppData(c.OutEpoch()-1, msg)
-								c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-								// The retransmit timer is still running.
-								c.AdvanceClock(useTimeouts[1])
-								c.ReadRetransmit()
-
-								// Advance the shim to the next epoch.
-								c.WriteAppData(c.OutEpoch(), msg)
-								c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-								// The retransmit timer is still running. The shim
-								// actually could implicitly ACK at this point, but
-								// RFC 9147 does not list this as an implicit ACK.
-								c.AdvanceClock(useTimeouts[2])
-								c.ReadRetransmit()
-
-								// Finally ACK the final flight. Now the shim will
-								// stop the timer.
-								c.WriteACK(c.OutEpoch(), records)
-								c.ExpectNoNextTimeout()
-							},
-						},
-					},
-					sendKeyUpdates:   1,
-					keyUpdateRequest: keyUpdateNotRequested,
-					flags:            flags,
-				})
-
-				// If the server never receives an ACK for NewSessionTicket, it
-				// is eventually fatal.
-				testCases = append(testCases, testCase{
-					testType: serverTest,
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Server-NewSessionTicketTimeout" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							ACKFlightDTLS: handleNewSessionTicket(func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if received[0].Type != typeNewSessionTicket {
-									c.WriteACK(c.OutEpoch(), records)
-									return
-								}
-								// Time the peer out.
-								for _, t := range useTimeouts[:len(useTimeouts)-1] {
-									c.AdvanceClock(t)
-									c.ReadRetransmit()
-								}
-								c.AdvanceClock(useTimeouts[len(useTimeouts)-1])
-							}),
-						},
-					},
-					flags:         flags,
-					shouldFail:    true,
-					expectedError: ":READ_TIMEOUT_EXPIRED:",
-				})
-
-				// If generating the reply to a flight takes time (generating a
-				// CertificateVerify for a client certificate), the shim should
-				// send an ACK.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-SlowReplyGeneration" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						ClientAuth: RequireAnyClientCert,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								c.WriteFlight(next)
-								if next[0].Type == typeServerHello {
-									// The shim will reply with Certificate..Finished, but
-									// take time to do so. In that time, it should schedule
-									// an ACK so the runner knows not to retransmit.
-									c.ReadACK(c.InEpoch())
-								}
-							},
-						},
-					},
-					shimCertificate: &rsaCertificate,
-					// Simulate it taking time to generate the reply.
-					flags: slices.Concat(flags, []string{"-private-key-delay-ms", strconv.Itoa(int(useTimeouts[0].Milliseconds()))}),
-				})
-
-				// BoringSSL's ACK policy may schedule both retransmit and ACK
-				// timers in parallel.
-				//
-				// TODO(crbug.com/42290594): This is only possible during the
-				// handshake because we're willing to ACK old flights without
-				// trying to distinguish these cases. However, post-handshake
-				// messages will exercise this, so that may be a better version
-				// of this test. In-handshake, it's kind of a waste to ACK this,
-				// so maybe we should stop.
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-BothTimers" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							// Arrange for there to be two server flights.
-							SendHelloRetryRequestCookie: []byte("cookie"),
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[0].Sequence == 0 || next[0].Type != typeServerHello {
-									// Send the first flight (HelloRetryRequest) as-is,
-									// as well as any post-handshake flights.
-									c.WriteFlight(next)
-									return
-								}
-
-								// The shim just send the ClientHello2 and is
-								// waiting for ServerHello..Finished. If it hears
-								// nothing, it will retransmit ClientHello2 on the
-								// assumption the packet was lost.
-								c.ExpectNextTimeout(useTimeouts[0])
-
-								// Retransmit a portion of HelloRetryRequest.
-								c.WriteFragments([]DTLSFragment{prev[0].Fragment(0, 1)})
-
-								// The shim does not actually need to ACK this,
-								// but BoringSSL does. Now both timers are active.
-								// Fire the first...
-								c.ExpectNextTimeout(useTimeouts[0] / 4)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(0)
-
-								// ...followed by the second.
-								c.ExpectNextTimeout(3 * useTimeouts[0] / 4)
-								c.AdvanceClock(3 * useTimeouts[0] / 4)
-								c.ReadRetransmit()
-
-								// The shim is now set for the next retransmit.
-								c.ExpectNextTimeout(useTimeouts[1])
-
-								// Start the ACK timer again.
-								c.WriteFragments([]DTLSFragment{prev[0].Fragment(0, 1)})
-								c.ExpectNextTimeout(useTimeouts[1] / 4)
-
-								// Expire both timers at once.
-								c.AdvanceClock(useTimeouts[1])
-								c.ReadACK(0)
-								c.ReadRetransmit()
-
-								c.WriteFlight(next)
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Client-ACKPostHandshake" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[0].Type != typeNewSessionTicket {
-									c.WriteFlight(next)
-									return
-								}
-
-								// The test should try to send two NewSessionTickets in a row.
-								if len(next) != 2 {
-									panic("unexpected message count")
-								}
-
-								// Send part of first ticket post-handshake message.
-								first0, second0 := next[0].Split(len(next[0].Data) / 2)
-								first1, second1 := next[1].Split(len(next[1].Data) / 2)
-								c.WriteFragments([]DTLSFragment{first0})
-
-								// The shim should ACK on a timer.
-								c.ExpectNextTimeout(useTimeouts[0] / 4)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-
-								// The shim is just waiting for us to retransmit.
-								c.ExpectNoNextTimeout()
-
-								// Send some more fragments.
-								c.WriteFragments([]DTLSFragment{first0, second1})
-
-								// The shim should ACK, again on a timer.
-								c.ExpectNextTimeout(useTimeouts[0] / 4)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-								c.ExpectNoNextTimeout()
-
-								// Finish up both messages. We implicitly test if shim
-								// processed these messages by checking that it returned a new
-								// session.
-								c.WriteFragments([]DTLSFragment{first1, second0})
-
-								// The shim should ACK again, once the timer expires.
-								//
-								// TODO(crbug.com/42290594): Should the shim ACK immediately?
-								// Otherwise KeyUpdates are delayed, which will complicated
-								// downstream testing.
-								c.ExpectNextTimeout(useTimeouts[0] / 4)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-								c.ExpectNoNextTimeout()
-							},
-						},
-					},
-					flags: flags,
-				})
-
-				testCases = append(testCases, testCase{
-					protocol: dtls,
-					name:     "DTLS-Retransmit-Client-ACKPostHandshakeTwice" + suffix,
-					config: Config{
-						MaxVersion: vers.version,
-						Bugs: ProtocolBugs{
-							WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-								if next[0].Type != typeNewSessionTicket {
-									c.WriteFlight(next)
-									return
-								}
-
-								// The test should try to send two NewSessionTickets in a row.
-								if len(next) != 2 {
-									panic("unexpected message count")
-								}
-
-								// Send the flight. The shim should ACK it.
-								c.WriteFlight(next)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-								c.ExpectNoNextTimeout()
-
-								// Retransmit the flight, as if we lost the ACK. The shim should
-								// ACK again.
-								c.WriteFlight(next)
-								c.AdvanceClock(useTimeouts[0] / 4)
-								c.ReadACK(c.InEpoch())
-								c.ExpectNoNextTimeout()
-							},
-						},
-					},
-					flags: flags,
-				})
-			}
-		}
-	}
-
-	// Test that the final Finished retransmitting isn't
-	// duplicated if the peer badly fragments everything.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "DTLS-RetransmitFinished-Fragmented",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				MaxHandshakeRecordLength: 2,
-				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-					c.WriteFlight(prev)
-					c.ReadRetransmit()
-				},
-			},
-		},
-		flags: []string{"-async"},
-	})
-
-	// If the shim sends the last Finished (server full or client resume
-	// handshakes), it must retransmit that Finished when it sees a
-	// post-handshake penultimate Finished from the runner. The above tests
-	// cover this. Conversely, if the shim sends the penultimate Finished
-	// (client full or server resume), test that it does not retransmit.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: clientTest,
-		name:     "DTLS-StrayRetransmitFinished-ClientFull",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					c.WriteFlight(next)
-					for _, msg := range next {
-						if msg.Type == typeFinished {
-							c.WriteFlight([]DTLSMessage{msg})
-						}
-					}
-				},
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "DTLS-StrayRetransmitFinished-ServerResume",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					c.WriteFlight(next)
-					for _, msg := range next {
-						if msg.Type == typeFinished {
-							c.WriteFlight([]DTLSMessage{msg})
-						}
-					}
-				},
-			},
-		},
-		resumeSession: true,
-	})
-}
-
-func addDTLSReorderTests() {
-	for _, vers := range allVersions(dtls) {
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "ReorderHandshakeFragments-Small-DTLS-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Bugs: ProtocolBugs{
-					ReorderHandshakeFragments: true,
-					// Small enough that every handshake message is
-					// fragmented.
-					MaxHandshakeRecordLength: 2,
-				},
-			},
-		})
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "ReorderHandshakeFragments-Large-DTLS-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Bugs: ProtocolBugs{
-					ReorderHandshakeFragments: true,
-					// Large enough that no handshake message is
-					// fragmented.
-					MaxHandshakeRecordLength: 2048,
-				},
-			},
-		})
-		testCases = append(testCases, testCase{
-			protocol: dtls,
-			name:     "MixCompleteMessageWithFragments-DTLS-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-				Bugs: ProtocolBugs{
-					ReorderHandshakeFragments:       true,
-					MixCompleteMessageWithFragments: true,
-					MaxHandshakeRecordLength:        2,
-				},
-			},
-		})
-	}
-}
-
-func addExportKeyingMaterialTests() {
-	for _, vers := range tlsVersions {
-		testCases = append(testCases, testCase{
-			name: "ExportKeyingMaterial-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			// Test the exporter in both initial and resumption
-			// handshakes.
-			resumeSession:        true,
-			exportKeyingMaterial: 1024,
-			exportLabel:          "label",
-			exportContext:        "context",
-			useExportContext:     true,
-		})
-		testCases = append(testCases, testCase{
-			name: "ExportKeyingMaterial-NoContext-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			exportKeyingMaterial: 1024,
-		})
-		testCases = append(testCases, testCase{
-			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			exportKeyingMaterial: 1024,
-			useExportContext:     true,
-		})
-		testCases = append(testCases, testCase{
-			name: "ExportKeyingMaterial-Small-" + vers.name,
-			config: Config{
-				MaxVersion: vers.version,
-			},
-			exportKeyingMaterial: 1,
-			exportLabel:          "label",
-			exportContext:        "context",
-			useExportContext:     true,
-		})
-
-		if vers.version >= VersionTLS13 {
-			// Test the exporters do not work while the client is
-			// sending 0-RTT data.
-			testCases = append(testCases, testCase{
-				name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + vers.name,
-				config: Config{
-					MaxVersion: vers.version,
-				},
-				resumeSession: true,
-				earlyData:     true,
-				flags: []string{
-					"-on-resume-export-keying-material", "1024",
-					"-on-resume-export-label", "label",
-					"-on-resume-export-context", "context",
-				},
-				shouldFail:    true,
-				expectedError: ":HANDSHAKE_NOT_COMPLETE:",
-			})
-
-			// Test the normal exporter on the server in half-RTT.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "ExportKeyingMaterial-Server-HalfRTT-" + vers.name,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						// The shim writes exported data immediately after
-						// the handshake returns, so disable the built-in
-						// early data test.
-						SendEarlyData:     [][]byte{},
-						ExpectHalfRTTData: [][]byte{},
-					},
-				},
-				resumeSession:        true,
-				earlyData:            true,
-				exportKeyingMaterial: 1024,
-				exportLabel:          "label",
-				exportContext:        "context",
-				useExportContext:     true,
-			})
-		}
-	}
-
-	// Exporters work during a False Start.
-	testCases = append(testCases, testCase{
-		name: "ExportKeyingMaterial-FalseStart",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			NextProtos:   []string{"foo"},
-			Bugs: ProtocolBugs{
-				ExpectFalseStart: true,
-			},
-		},
-		flags: []string{
-			"-false-start",
-			"-advertise-alpn", "\x03foo",
-			"-expect-alpn", "foo",
-		},
-		shimWritesFirst:      true,
-		exportKeyingMaterial: 1024,
-		exportLabel:          "label",
-		exportContext:        "context",
-		useExportContext:     true,
-	})
-
-	// Exporters do not work in the middle of a renegotiation. Test this by
-	// triggering the exporter after every SSL_read call and configuring the
-	// shim to run asynchronously.
-	testCases = append(testCases, testCase{
-		name: "ExportKeyingMaterial-Renegotiate",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-async",
-			"-use-exporter-between-reads",
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-		shouldFail:    true,
-		expectedError: "failed to export keying material",
-	})
-}
-
-func addExportTrafficSecretsTests() {
-	for _, cipherSuite := range []testCipherSuite{
-		// Test a SHA-256 and SHA-384 based cipher suite.
-		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
-		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
-	} {
-		testCases = append(testCases, testCase{
-			name: "ExportTrafficSecrets-" + cipherSuite.name,
-			config: Config{
-				MinVersion:   VersionTLS13,
-				CipherSuites: []uint16{cipherSuite.id},
-			},
-			exportTrafficSecrets: true,
-		})
-	}
-}
-
-func addTLSUniqueTests() {
-	for _, isClient := range []bool{false, true} {
-		for _, isResumption := range []bool{false, true} {
-			for _, hasEMS := range []bool{false, true} {
-				var suffix string
-				if isResumption {
-					suffix = "Resume-"
-				} else {
-					suffix = "Full-"
-				}
-
-				if hasEMS {
-					suffix += "EMS-"
-				} else {
-					suffix += "NoEMS-"
-				}
-
-				if isClient {
-					suffix += "Client"
-				} else {
-					suffix += "Server"
-				}
-
-				test := testCase{
-					name:          "TLSUnique-" + suffix,
-					testTLSUnique: true,
-					config: Config{
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							NoExtendedMasterSecret: !hasEMS,
-						},
-					},
-				}
-
-				if isResumption {
-					test.resumeSession = true
-					test.resumeConfig = &Config{
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							NoExtendedMasterSecret: !hasEMS,
-						},
-					}
-				}
-
-				if isResumption && !hasEMS {
-					test.shouldFail = true
-					test.expectedError = "failed to get tls-unique"
-				}
-
-				testCases = append(testCases, test)
-			}
-		}
-	}
-}
-
-func addCustomExtensionTests() {
-	// Test an unknown extension from the server.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnknownExtension-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				CustomExtension: "custom extension",
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnknownExtension-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				CustomExtension: "custom extension",
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnknownUnencryptedExtension-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				CustomUnencryptedExtension: "custom extension",
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-		// The shim must send an alert, but alerts at this point do not
-		// get successfully decrypted by the runner.
-		expectedLocalError: "local error: bad record MAC",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendUnencryptedALPN: "foo",
-			},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-		// The shim must send an alert, but alerts at this point do not
-		// get successfully decrypted by the runner.
-		expectedLocalError: "local error: bad record MAC",
-	})
-
-	// Test a known but unoffered extension from the server.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnofferedExtension-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendALPN: "alpn",
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "UnofferedExtension-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendALPN: "alpn",
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-}
-
-func addRSAClientKeyExchangeTests() {
-	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
-			config: Config{
-				// Ensure the ClientHello version and final
-				// version are different, to detect if the
-				// server uses the wrong one.
-				MaxVersion:   VersionTLS11,
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
-				Bugs: ProtocolBugs{
-					BadRSAClientKeyExchange: bad,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-		})
-	}
-
-	// The server must compare whatever was in ClientHello.version for the
-	// RSA premaster.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SendClientVersion-RSA",
-		config: Config{
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				SendClientVersion: 0x1234,
-			},
-		},
-		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-}
-
-var testCurves = []struct {
-	name string
-	id   CurveID
-}{
-	{"P-224", CurveP224},
-	{"P-256", CurveP256},
-	{"P-384", CurveP384},
-	{"P-521", CurveP521},
-	{"X25519", CurveX25519},
-	{"Kyber", CurveX25519Kyber768},
-	{"MLKEM", CurveX25519MLKEM768},
-}
-
-const bogusCurve = 0x1234
-
-func isPqGroup(r CurveID) bool {
-	return r == CurveX25519Kyber768 || r == CurveX25519MLKEM768
-}
-
-func isECDHGroup(r CurveID) bool {
-	return r == CurveP224 || r == CurveP256 || r == CurveP384 || r == CurveP521
-}
-
-func isX25519Group(r CurveID) bool {
-	return r == CurveX25519 || r == CurveX25519Kyber768 || r == CurveX25519MLKEM768
-}
-
-func addCurveTests() {
-	// A set of cipher suites that ensures some curve-using mode is used.
-	// Without this, servers may fall back to RSA key exchange.
-	ecdheCiphers := []uint16{
-		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-		TLS_AES_256_GCM_SHA384,
-	}
-
-	for _, curve := range testCurves {
-		for _, ver := range tlsVersions {
-			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
-				continue
-			}
-			for _, testType := range []testType{clientTest, serverTest} {
-				suffix := fmt.Sprintf("%s-%s-%s", testType, curve.name, ver.name)
-
-				testCases = append(testCases, testCase{
-					testType: testType,
-					name:     "CurveTest-" + suffix,
-					config: Config{
-						MaxVersion:       ver.version,
-						CipherSuites:     ecdheCiphers,
-						CurvePreferences: []CurveID{curve.id},
-					},
-					flags: append(
-						[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
-						flagInts("-curves", shimConfig.AllCurves)...,
-					),
-					expectations: connectionExpectations{
-						curveID: curve.id,
-					},
-				})
-
-				badKeyShareLocalError := "remote error: illegal parameter"
-				if testType == clientTest && ver.version >= VersionTLS13 {
-					// If the shim is a TLS 1.3 client and the runner sends a bad
-					// key share, the runner never reads the client's cleartext
-					// alert because the runner has already started encrypting by
-					// the time the client sees it.
-					badKeyShareLocalError = "local error: bad record MAC"
-				}
-
-				testCases = append(testCases, testCase{
-					testType: testType,
-					name:     "CurveTest-Invalid-TruncateKeyShare-" + suffix,
-					config: Config{
-						MaxVersion:       ver.version,
-						CipherSuites:     ecdheCiphers,
-						CurvePreferences: []CurveID{curve.id},
-						Bugs: ProtocolBugs{
-							TruncateKeyShare: true,
-						},
-					},
-					flags:              flagInts("-curves", shimConfig.AllCurves),
-					shouldFail:         true,
-					expectedError:      ":BAD_ECPOINT:",
-					expectedLocalError: badKeyShareLocalError,
-				})
-
-				testCases = append(testCases, testCase{
-					testType: testType,
-					name:     "CurveTest-Invalid-PadKeyShare-" + suffix,
-					config: Config{
-						MaxVersion:       ver.version,
-						CipherSuites:     ecdheCiphers,
-						CurvePreferences: []CurveID{curve.id},
-						Bugs: ProtocolBugs{
-							PadKeyShare: true,
-						},
-					},
-					flags:              flagInts("-curves", shimConfig.AllCurves),
-					shouldFail:         true,
-					expectedError:      ":BAD_ECPOINT:",
-					expectedLocalError: badKeyShareLocalError,
-				})
-
-				if isECDHGroup(curve.id) {
-					testCases = append(testCases, testCase{
-						testType: testType,
-						name:     "CurveTest-Invalid-Compressed-" + suffix,
-						config: Config{
-							MaxVersion:       ver.version,
-							CipherSuites:     ecdheCiphers,
-							CurvePreferences: []CurveID{curve.id},
-							Bugs: ProtocolBugs{
-								SendCompressedCoordinates: true,
-							},
-						},
-						flags:              flagInts("-curves", shimConfig.AllCurves),
-						shouldFail:         true,
-						expectedError:      ":BAD_ECPOINT:",
-						expectedLocalError: badKeyShareLocalError,
-					})
-					testCases = append(testCases, testCase{
-						testType: testType,
-						name:     "CurveTest-Invalid-NotOnCurve-" + suffix,
-						config: Config{
-							MaxVersion:       ver.version,
-							CipherSuites:     ecdheCiphers,
-							CurvePreferences: []CurveID{curve.id},
-							Bugs: ProtocolBugs{
-								ECDHPointNotOnCurve: true,
-							},
-						},
-						flags:              flagInts("-curves", shimConfig.AllCurves),
-						shouldFail:         true,
-						expectedError:      ":BAD_ECPOINT:",
-						expectedLocalError: badKeyShareLocalError,
-					})
-				}
-
-				if isX25519Group(curve.id) {
-					// Implementations should mask off the high order bit in X25519.
-					testCases = append(testCases, testCase{
-						testType: testType,
-						name:     "CurveTest-SetX25519HighBit-" + suffix,
-						config: Config{
-							MaxVersion:       ver.version,
-							CipherSuites:     ecdheCiphers,
-							CurvePreferences: []CurveID{curve.id},
-							Bugs: ProtocolBugs{
-								SetX25519HighBit: true,
-							},
-						},
-						flags: flagInts("-curves", shimConfig.AllCurves),
-						expectations: connectionExpectations{
-							curveID: curve.id,
-						},
-					})
-
-					// Implementations should reject low order points.
-					testCases = append(testCases, testCase{
-						testType: testType,
-						name:     "CurveTest-Invalid-LowOrderX25519Point-" + suffix,
-						config: Config{
-							MaxVersion:       ver.version,
-							CipherSuites:     ecdheCiphers,
-							CurvePreferences: []CurveID{curve.id},
-							Bugs: ProtocolBugs{
-								LowOrderX25519Point: true,
-							},
-						},
-						flags:              flagInts("-curves", shimConfig.AllCurves),
-						shouldFail:         true,
-						expectedError:      ":BAD_ECPOINT:",
-						expectedLocalError: badKeyShareLocalError,
-					})
-				}
-
-				if curve.id == CurveX25519MLKEM768 && testType == serverTest {
-					testCases = append(testCases, testCase{
-						testType: testType,
-						name:     "CurveTest-Invalid-MLKEMEncapKeyNotReduced-" + suffix,
-						config: Config{
-							MaxVersion:       ver.version,
-							CipherSuites:     ecdheCiphers,
-							CurvePreferences: []CurveID{curve.id},
-							Bugs: ProtocolBugs{
-								MLKEMEncapKeyNotReduced: true,
-							},
-						},
-						flags:              flagInts("-curves", shimConfig.AllCurves),
-						shouldFail:         true,
-						expectedError:      ":BAD_ECPOINT:",
-						expectedLocalError: badKeyShareLocalError,
-					})
-				}
-			}
-		}
-	}
-
-	// The server must be tolerant to bogus curves.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "UnknownCurve",
-		config: Config{
-			MaxVersion:       VersionTLS12,
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{bogusCurve, CurveP256},
-		},
-	})
-
-	// The server must be tolerant to bogus curves.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "UnknownCurve-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{bogusCurve, CurveP256},
-		},
-	})
-
-	// The server must not consider ECDHE ciphers when there are no
-	// supported curves.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoSupportedCurves",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				NoSupportedCurves: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":NO_SHARED_CIPHER:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoSupportedCurves-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NoSupportedCurves: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":NO_SHARED_GROUP:",
-	})
-
-	// The server must fall back to another cipher when there are no
-	// supported curves.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "NoCommonCurves",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			CipherSuites: []uint16{
-				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-				TLS_RSA_WITH_AES_128_GCM_SHA256,
-			},
-			CurvePreferences: []CurveID{CurveP224},
-		},
-		expectations: connectionExpectations{
-			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
-		},
-	})
-
-	// The client must reject bogus curves and disabled curves.
-	testCases = append(testCases, testCase{
-		name: "BadECDHECurve",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				SendCurve: bogusCurve,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-	testCases = append(testCases, testCase{
-		name: "BadECDHECurve-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendCurve: bogusCurve,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "UnsupportedCurve",
-		config: Config{
-			MaxVersion:       VersionTLS12,
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{CurveP256},
-			Bugs: ProtocolBugs{
-				IgnorePeerCurvePreferences: true,
-			},
-		},
-		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		// TODO(davidben): Add a TLS 1.3 version where
-		// HelloRetryRequest requests an unsupported curve.
-		name: "UnsupportedCurve-ServerHello-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendCurve: CurveP256,
-			},
-		},
-		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	// The previous curve ID should be reported on TLS 1.2 resumption.
-	testCases = append(testCases, testCase{
-		name: "CurveID-Resume-Client",
-		config: Config{
-			MaxVersion:       VersionTLS12,
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CurveID-Resume-Server",
-		config: Config{
-			MaxVersion:       VersionTLS12,
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
-		resumeSession: true,
-	})
-
-	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
-	// one should be reported.
-	testCases = append(testCases, testCase{
-		name: "CurveID-Resume-Client-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		resumeConfig: &Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveP256},
-		},
-		flags: []string{
-			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
-			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
-		},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CurveID-Resume-Server-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		resumeConfig: &Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveP256},
-		},
-		flags: []string{
-			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
-			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
-		},
-		resumeSession: true,
-	})
-
-	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
-	testCases = append(testCases, testCase{
-		name: "PointFormat-ServerHello-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{pointFormatUncompressed},
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "PointFormat-EncryptedExtensions-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{pointFormatUncompressed},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-
-	// Server-sent supported groups/curves are legal in TLS 1.3. They are
-	// illegal in TLS 1.2, but some servers send them anyway, so we must
-	// tolerate them.
-	testCases = append(testCases, testCase{
-		name: "SupportedCurves-ServerHello-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendServerSupportedCurves: true,
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		name: "SupportedCurves-EncryptedExtensions-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendServerSupportedCurves: true,
-			},
-		},
-	})
-
-	// Test that we tolerate unknown point formats, as long as
-	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
-	// check they are still functional.
-	testCases = append(testCases, testCase{
-		name: "PointFormat-Client-Tolerance",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PointFormat-Server-Tolerance",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
-			},
-		},
-	})
-
-	// Test TLS 1.2 does not require the point format extension to be
-	// present.
-	testCases = append(testCases, testCase{
-		name: "PointFormat-Client-Missing",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{},
-			},
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PointFormat-Server-Missing",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{},
-			},
-		},
-	})
-
-	// If the point format extension is present, uncompressed points must be
-	// offered. BoringSSL requires this whether or not ECDHE is used.
-	testCases = append(testCases, testCase{
-		name: "PointFormat-Client-MissingUncompressed",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PointFormat-Server-MissingUncompressed",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-
-	// Post-quantum groups require TLS 1.3.
-	for _, curve := range testCurves {
-		if !isPqGroup(curve.id) {
-			continue
-		}
-
-		// Post-quantum groups should not be offered by a TLS 1.2 client.
-		testCases = append(testCases, testCase{
-			name: "TLS12ClientShouldNotOffer-" + curve.name,
-			config: Config{
-				Bugs: ProtocolBugs{
-					FailIfPostQuantumOffered: true,
-				},
-			},
-			flags: []string{
-				"-max-version", strconv.Itoa(VersionTLS12),
-				"-curves", strconv.Itoa(int(curve.id)),
-				"-curves", strconv.Itoa(int(CurveX25519)),
-			},
-		})
-
-		// Post-quantum groups should not be selected by a TLS 1.2 server.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "TLS12ServerShouldNotSelect-" + curve.name,
-			flags: []string{
-				"-max-version", strconv.Itoa(VersionTLS12),
-				"-curves", strconv.Itoa(int(curve.id)),
-				"-curves", strconv.Itoa(int(CurveX25519)),
-			},
-			expectations: connectionExpectations{
-				curveID: CurveX25519,
-			},
-		})
-
-		// If a TLS 1.2 server selects a post-quantum group anyway, the client
-		// should not accept it.
-		testCases = append(testCases, testCase{
-			name: "ClientShouldNotAllowInTLS12-" + curve.name,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					SendCurve: curve.id,
-				},
-			},
-			flags: []string{
-				"-curves", strconv.Itoa(int(curve.id)),
-				"-curves", strconv.Itoa(int(CurveX25519)),
-			},
-			shouldFail:         true,
-			expectedError:      ":WRONG_CURVE:",
-			expectedLocalError: "remote error: illegal parameter",
-		})
-	}
-
-	// ML-KEM and Kyber should not be offered by default as a client.
-	testCases = append(testCases, testCase{
-		name: "PostQuantumNotEnabledByDefaultInClients",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				FailIfPostQuantumOffered: true,
-			},
-		},
-	})
-
-	// If ML-KEM is offered, both X25519 and ML-KEM should have a key-share.
-	testCases = append(testCases, testCase{
-		name: "NotJustMLKEMKeyShare",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768, CurveX25519},
-			},
-		},
-		flags: []string{
-			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-			"-curves", strconv.Itoa(int(CurveX25519)),
-			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
-		},
-	})
-
-	// ... and the other way around
-	testCases = append(testCases, testCase{
-		name: "MLKEMKeyShareIncludedSecond",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519MLKEM768},
-			},
-		},
-		flags: []string{
-			"-curves", strconv.Itoa(int(CurveX25519)),
-			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-			"-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.
-	testCases = append(testCases, testCase{
-		name: "MLKEMKeyShareIncludedThird",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519MLKEM768},
-			},
-		},
-		flags: []string{
-			"-curves", strconv.Itoa(int(CurveX25519)),
-			"-curves", strconv.Itoa(int(CurveP256)),
-			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
-		},
-	})
-
-	// If ML-KEM is the only configured curve, the key share is sent.
-	testCases = append(testCases, testCase{
-		name: "JustConfiguringMLKEMWorks",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768},
-			},
-		},
-		flags: []string{
-			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
-		},
-	})
-
-	// If both ML-KEM and Kyber are configured, only the preferred one's
-	// key share should be sent.
-	testCases = append(testCases, testCase{
-		name: "BothMLKEMAndKyber",
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectedKeyShares: []CurveID{CurveX25519MLKEM768},
-			},
-		},
-		flags: []string{
-			"-curves", strconv.Itoa(int(CurveX25519MLKEM768)),
-			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
-			"-expect-curve-id", strconv.Itoa(int(CurveX25519MLKEM768)),
-		},
-	})
-
-	// As a server, ML-KEM is not yet supported by default.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PostQuantumNotEnabledByDefaultForAServer",
-		config: Config{
-			MinVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveX25519MLKEM768, CurveX25519Kyber768, CurveX25519},
-			DefaultCurves:    []CurveID{CurveX25519MLKEM768, CurveX25519Kyber768},
-		},
-		flags: []string{
-			"-server-preference",
-			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
-		},
-	})
-
-	// In TLS 1.2, the curve list is also used to signal ECDSA curves.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CheckECDSACurve-TLS12",
-		config: Config{
-			MinVersion:       VersionTLS12,
-			MaxVersion:       VersionTLS12,
-			CurvePreferences: []CurveID{CurveP384},
-		},
-		shimCertificate: &ecdsaP256Certificate,
-		shouldFail:      true,
-		expectedError:   ":WRONG_CURVE:",
-	})
-
-	// If the ECDSA certificate is ineligible due to a curve mismatch, the
-	// server may still consider a PSK cipher suite.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CheckECDSACurve-PSK-TLS12",
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-			CipherSuites: []uint16{
-				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-				TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
-			},
-			CurvePreferences:     []CurveID{CurveP384},
-			PreSharedKey:         []byte("12345"),
-			PreSharedKeyIdentity: "luggage combo",
-		},
-		shimCertificate: &ecdsaP256Certificate,
-		expectations: connectionExpectations{
-			cipher: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
-		},
-		flags: []string{
-			"-psk", "12345",
-			"-psk-identity", "luggage combo",
-		},
-	})
-
-	// In TLS 1.3, the curve list only controls ECDH.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CheckECDSACurve-NotApplicable-TLS13",
-		config: Config{
-			MinVersion:       VersionTLS13,
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveP384},
-		},
-		shimCertificate: &ecdsaP256Certificate,
-	})
-}
-
-func addTLS13RecordTests() {
-	for _, protocol := range []protocol{tls, dtls} {
-		testCases = append(testCases, testCase{
-			protocol: protocol,
-			name:     "TLS13-RecordPadding-" + protocol.String(),
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					RecordPadding: 10,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			protocol: protocol,
-			name:     "TLS13-EmptyRecords-" + protocol.String(),
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					OmitRecordContents: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-		})
-
-		testCases = append(testCases, testCase{
-			protocol: protocol,
-			name:     "TLS13-OnlyPadding-" + protocol.String(),
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					OmitRecordContents: true,
-					RecordPadding:      10,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-		})
-
-		if protocol == tls {
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     "TLS13-WrongOuterRecord-" + protocol.String(),
-				config: Config{
-					MaxVersion: VersionTLS13,
-					MinVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						OuterRecordType: recordTypeHandshake,
-					},
-				},
-				shouldFail:    true,
-				expectedError: ":INVALID_OUTER_RECORD_TYPE:",
-			})
-		}
-	}
-}
-
-func addSessionTicketTests() {
-	testCases = append(testCases, testCase{
-		// In TLS 1.2 and below, empty NewSessionTicket messages
-		// mean the server changed its mind on sending a ticket.
-		name: "SendEmptySessionTicket-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendEmptySessionTicket: true,
-			},
-		},
-		flags: []string{"-expect-no-session"},
-	})
-
-	testCases = append(testCases, testCase{
-		// In TLS 1.3, empty NewSessionTicket messages are not
-		// allowed.
-		name: "SendEmptySessionTicket-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendEmptySessionTicket: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	// Test that the server ignores unknown PSK modes.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-SendUnknownModeSessionTicket-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
-			},
-		},
-		resumeSession: true,
-		expectations: connectionExpectations{
-			version: VersionTLS13,
-		},
-	})
-
-	// Test that the server does not send session tickets with no matching key exchange mode.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendPSKKeyExchangeModes:  []byte{0x1a},
-				ExpectNoNewSessionTicket: true,
-			},
-		},
-	})
-
-	// Test that the server does not accept a session with no matching key exchange mode.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-SendBadKEModeSessionTicket-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendPSKKeyExchangeModes: []byte{0x1a},
-			},
-		},
-		resumeSession:        true,
-		expectResumeRejected: true,
-	})
-
-	// Test that the server rejects ClientHellos with pre_shared_key but without
-	// psk_key_exchange_modes.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-SendNoKEMModesWithPSK-Server",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendPSKKeyExchangeModes: []byte{},
-			},
-		},
-		resumeSession:      true,
-		shouldFail:         true,
-		expectedLocalError: "remote error: missing extension",
-		expectedError:      ":MISSING_EXTENSION:",
-	})
-
-	// Test that the client ticket age is sent correctly.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-TestValidTicketAge-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectTicketAge: 10 * time.Second,
-			},
-		},
-		resumeSession: true,
-		flags: []string{
-			"-resumption-delay", "10",
-		},
-	})
-
-	// Test that the client ticket age is enforced.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-TestBadTicketAge-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectTicketAge: 1000 * time.Second,
-			},
-		},
-		resumeSession:      true,
-		shouldFail:         true,
-		expectedLocalError: "tls: invalid ticket age",
-	})
-
-	// Test that the server's ticket age skew reporting works.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Forward",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 15 * time.Second,
-			},
-		},
-		resumeSession:        true,
-		resumeRenewedSession: true,
-		flags: []string{
-			"-resumption-delay", "10",
-			"-expect-ticket-age-skew", "5",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Backward",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 5 * time.Second,
-			},
-		},
-		resumeSession:        true,
-		resumeRenewedSession: true,
-		flags: []string{
-			"-resumption-delay", "10",
-			"-expect-ticket-age-skew", "-5",
-		},
-	})
-
-	// Test that ticket age skew up to 60 seconds in either direction is accepted.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 70 * time.Second,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-resumption-delay", "10",
-			"-expect-ticket-age-skew", "60",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 10 * time.Second,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-resumption-delay", "70",
-			"-expect-ticket-age-skew", "-60",
-		},
-	})
-
-	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 71 * time.Second,
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-resumption-delay", "10",
-			"-expect-ticket-age-skew", "61",
-			"-on-resume-expect-early-data-reason", "ticket_age_skew",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketAge: 10 * time.Second,
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-resumption-delay", "71",
-			"-expect-ticket-age-skew", "-61",
-			"-on-resume-expect-early-data-reason", "ticket_age_skew",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-SendTicketEarlyDataSupport",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			MaxEarlyDataSize: 16384,
-		},
-		flags: []string{
-			"-enable-early-data",
-			"-expect-ticket-supports-early-data",
-		},
-	})
-
-	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			MaxEarlyDataSize: 16384,
-		},
-		flags: []string{
-			"-expect-ticket-supports-early-data",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-DuplicateTicketEarlyDataSupport",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			MaxEarlyDataSize: 16384,
-			Bugs: ProtocolBugs{
-				DuplicateTicketEarlyData: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":DUPLICATE_EXTENSION:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-ExpectTicketEarlyDataSupport",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectTicketEarlyData: true,
-			},
-		},
-		flags: []string{
-			"-enable-early-data",
-		},
-	})
-
-	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
-	// is honored.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-HonorServerSessionTicketLifetime",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketLifetime: 20 * time.Second,
-			},
-		},
-		flags: []string{
-			"-resumption-delay", "19",
-		},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13-HonorServerSessionTicketLifetime-2",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendTicketLifetime: 20 * time.Second,
-				// The client should not offer the expired session.
-				ExpectNoTLS13PSK: true,
-			},
-		},
-		flags: []string{
-			"-resumption-delay", "21",
-		},
-		resumeSession:        true,
-		expectResumeRejected: true,
-	})
-
-	for _, ver := range tlsVersions {
-		// Prior to TLS 1.3, disabling session tickets enables session IDs.
-		useStatefulResumption := ver.version < VersionTLS13
-
-		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     ver.name + "-NoTicket-NoMint",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					ExpectNoNewSessionTicket: true,
-					RequireSessionIDs:        useStatefulResumption,
-				},
-			},
-			resumeSession: useStatefulResumption,
-			flags:         []string{"-no-ticket"},
-		})
-
-		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     ver.name + "-NoTicket-NoAccept",
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			resumeSession:        true,
-			expectResumeRejected: true,
-			// Set SSL_OP_NO_TICKET on the second connection, after the first
-			// has established tickets.
-			flags: []string{"-on-resume-no-ticket"},
-		})
-
-		// SSL_OP_NO_TICKET implies the client must not offer ticket-based
-		// sessions. The client not only should not send the session ticket
-		// extension, but if the server echos the session ID, the client should
-		// reject this.
-		if ver.version < VersionTLS13 {
-			testCases = append(testCases, testCase{
-				name: ver.name + "-NoTicket-NoOffer",
-				config: Config{
-					MinVersion: ver.version,
-					MaxVersion: ver.version,
-				},
-				resumeConfig: &Config{
-					MinVersion: ver.version,
-					MaxVersion: ver.version,
-					Bugs: ProtocolBugs{
-						ExpectNoTLS12TicketSupport: true,
-						// Pretend to accept the session, even though the client
-						// did not offer it. The client should reject this as
-						// invalid. A buggy client will still fail because it
-						// expects resumption, but with a different error.
-						// Ideally, we would test this by actually resuming the
-						// previous session, even though the client did not
-						// provide a ticket.
-						EchoSessionIDInFullHandshake: true,
-					},
-				},
-				resumeSession:        true,
-				expectResumeRejected: true,
-				// Set SSL_OP_NO_TICKET on the second connection, after the first
-				// has established tickets.
-				flags:              []string{"-on-resume-no-ticket"},
-				shouldFail:         true,
-				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
-				expectedLocalError: "remote error: illegal parameter",
-			})
-		}
-	}
-}
-
-func addChangeCipherSpecTests() {
-	// Test missing ChangeCipherSpecs.
-	testCases = append(testCases, testCase{
-		name: "SkipChangeCipherSpec-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SkipChangeCipherSpec: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipChangeCipherSpec-Server",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SkipChangeCipherSpec: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipChangeCipherSpec-Server-NPN",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			NextProtos: []string{"bar"},
-			Bugs: ProtocolBugs{
-				SkipChangeCipherSpec: true,
-			},
-		},
-		flags: []string{
-			"-advertise-npn", "\x03foo\x03bar\x03baz",
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-
-	// Test synchronization between the handshake and ChangeCipherSpec.
-	// Partial post-CCS handshake messages before ChangeCipherSpec should be
-	// rejected. Test both with and without handshake packing to handle both
-	// when the partial post-CCS message is in its own record and when it is
-	// attached to the pre-CCS message.
-	for _, packed := range []bool{false, true} {
-		var suffix string
-		if packed {
-			suffix = "-Packed"
-		}
-
-		testCases = append(testCases, testCase{
-			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-					PackHandshakeFlight:            packed,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		})
-		testCases = append(testCases, testCase{
-			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			resumeSession: true,
-			resumeConfig: &Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-					PackHandshakeFlight:            packed,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-					PackHandshakeFlight:            packed,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-			},
-			resumeSession: true,
-			resumeConfig: &Config{
-				MaxVersion: VersionTLS12,
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-					PackHandshakeFlight:            packed,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
-			config: Config{
-				MaxVersion: VersionTLS12,
-				NextProtos: []string{"bar"},
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-					PackHandshakeFlight:            packed,
-				},
-			},
-			flags: []string{
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		})
-	}
-
-	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
-	// and ChangeCipherSpec + Finished in the second flight. Test the server's
-	// behavior when the Finished message is fragmented across not only
-	// ChangeCipherSpec but also the flight boundary.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				PartialClientFinishedWithClientHello: true,
-			},
-		},
-		resumeSession:      true,
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
-	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
-	// Test the client's behavior when the Finished message is fragmented across
-	// not only ChangeCipherSpec but also the flight boundary.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "PartialFinishedWithServerHelloDone",
-		config: Config{
-			MaxVersion:             VersionTLS12,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				PartialFinishedWithServerHelloDone: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// Test that, in DTLS 1.2, key changes are not allowed when there are
-	// buffered messages. Do this sending all messages in reverse, so that later
-	// ones are buffered, and leaving Finished unencrypted.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "KeyChangeWithBufferedMessages-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					next = slices.Clone(next)
-					slices.Reverse(next)
-					for i := range next {
-						next[i].Epoch = 0
-					}
-					c.WriteFlight(next)
-				},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":EXCESS_HANDSHAKE_DATA:",
-	})
-
-	// Test synchronization between encryption changes and the handshake in
-	// TLS 1.3, where ChangeCipherSpec is implicit.
-	testCases = append(testCases, testCase{
-		name: "PartialEncryptedExtensionsWithServerHello",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				PartialEncryptedExtensionsWithServerHello: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":EXCESS_HANDSHAKE_DATA:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialClientFinishedWithClientHello",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				PartialClientFinishedWithClientHello: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":EXCESS_HANDSHAKE_DATA:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialClientFinishedWithSecondClientHello",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Trigger a curve-based HelloRetryRequest.
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				PartialClientFinishedWithSecondClientHello: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":EXCESS_HANDSHAKE_DATA:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialEndOfEarlyDataWithClientHello",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				PartialEndOfEarlyDataWithClientHello: true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":EXCESS_HANDSHAKE_DATA:",
-	})
-
-	// Test that early ChangeCipherSpecs are handled correctly.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyChangeCipherSpec-server-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				EarlyChangeCipherSpec: 1,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyChangeCipherSpec-server-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				EarlyChangeCipherSpec: 2,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "StrayChangeCipherSpec",
-		config: Config{
-			// TODO(davidben): Once DTLS 1.3 exists, test
-			// that stray ChangeCipherSpec messages are
-			// rejected.
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					c.WriteFragments([]DTLSFragment{{IsChangeCipherSpec: true, Data: []byte{1}}})
-					c.WriteFlight(next)
-				},
-			},
-		},
-	})
-
-	// Test that the contents of ChangeCipherSpec are checked.
-	testCases = append(testCases, testCase{
-		name: "BadChangeCipherSpec-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadChangeCipherSpec: []byte{2},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-	})
-	testCases = append(testCases, testCase{
-		name: "BadChangeCipherSpec-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadChangeCipherSpec: []byte{1, 1},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "BadChangeCipherSpec-DTLS-1",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadChangeCipherSpec: []byte{2},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "BadChangeCipherSpec-DTLS-2",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				BadChangeCipherSpec: []byte{1, 1},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-	})
-}
-
-// addEndOfFlightTests adds tests where the runner adds extra data in the final
-// record of each handshake flight. Depending on the implementation strategy,
-// this data may be carried over to the next flight (assuming no key change) or
-// may be rejected. To avoid differences with split handshakes and generally
-// reject misbehavior, BoringSSL treats this as an error. When possible, these
-// tests pull the extra data from the subsequent flight to distinguish the data
-// being carried over from a general syntax error.
-//
-// These tests are similar to tests in |addChangeCipherSpecTests| that send
-// extra data at key changes. Not all key changes are at the end of a flight and
-// not all flights end at a key change.
-func addEndOfFlightTests() {
-	// TLS 1.3 client handshakes.
-	//
-	// Data following the second TLS 1.3 ClientHello is covered by
-	// PartialClientFinishedWithClientHello,
-	// PartialClientFinishedWithSecondClientHello, and
-	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialSecondClientHelloAfterFirst",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Trigger a curve-based HelloRetryRequest.
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				PartialSecondClientHelloAfterFirst: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// TLS 1.3 server handshakes.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "PartialServerHelloWithHelloRetryRequest",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				PartialServerHelloWithHelloRetryRequest: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// TLS 1.2 client handshakes.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "PartialClientKeyExchangeWithClientHello",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				PartialClientKeyExchangeWithClientHello: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// TLS 1.2 server handshakes.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "PartialNewSessionTicketWithServerHelloDone",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				PartialNewSessionTicketWithServerHelloDone: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	for _, vers := range tlsVersions {
-		for _, testType := range []testType{clientTest, serverTest} {
-			suffix := "-Client"
-			if testType == serverTest {
-				suffix = "-Server"
-			}
-			suffix += "-" + vers.name
-
-			testCases = append(testCases, testCase{
-				testType: testType,
-				name:     "TrailingDataWithFinished" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						TrailingDataWithFinished: true,
-					},
-				},
-				shouldFail:         true,
-				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-				expectedLocalError: "remote error: unexpected message",
-			})
-			testCases = append(testCases, testCase{
-				testType: testType,
-				name:     "TrailingDataWithFinished-Resume" + suffix,
-				config: Config{
-					MaxVersion: vers.version,
-				},
-				resumeConfig: &Config{
-					MaxVersion: vers.version,
-					Bugs: ProtocolBugs{
-						TrailingDataWithFinished: true,
-					},
-				},
-				resumeSession:      true,
-				shouldFail:         true,
-				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-				expectedLocalError: "remote error: unexpected message",
-			})
-		}
-	}
-}
-
-type perMessageTest struct {
-	messageType uint8
-	test        testCase
-}
-
-// makePerMessageTests returns a series of test templates which cover each
-// message in the TLS handshake. These may be used with bugs like
-// WrongMessageType to fully test a per-message bug.
-func makePerMessageTests() []perMessageTest {
-	var ret []perMessageTest
-	// The following tests are limited to TLS 1.2, so QUIC is not tested.
-	for _, protocol := range []protocol{tls, dtls} {
-		suffix := "-" + protocol.String()
-
-		ret = append(ret, perMessageTest{
-			messageType: typeClientHello,
-			test: testCase{
-				protocol: protocol,
-				testType: serverTest,
-				name:     "ClientHello" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		if protocol == dtls {
-			ret = append(ret, perMessageTest{
-				messageType: typeHelloVerifyRequest,
-				test: testCase{
-					protocol: protocol,
-					name:     "HelloVerifyRequest" + suffix,
-					config: Config{
-						MaxVersion: VersionTLS12,
-					},
-				},
-			})
-		}
-
-		ret = append(ret, perMessageTest{
-			messageType: typeServerHello,
-			test: testCase{
-				protocol: protocol,
-				name:     "ServerHello" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificate,
-			test: testCase{
-				protocol: protocol,
-				name:     "ServerCertificate" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateStatus,
-			test: testCase{
-				protocol: protocol,
-				name:     "CertificateStatus" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-					Credential: rsaCertificate.WithOCSP(testOCSPResponse),
-				},
-				flags: []string{"-enable-ocsp-stapling"},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeServerKeyExchange,
-			test: testCase{
-				protocol: protocol,
-				name:     "ServerKeyExchange" + suffix,
-				config: Config{
-					MaxVersion:   VersionTLS12,
-					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateRequest,
-			test: testCase{
-				protocol: protocol,
-				name:     "CertificateRequest" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-					ClientAuth: RequireAnyClientCert,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeServerHelloDone,
-			test: testCase{
-				protocol: protocol,
-				name:     "ServerHelloDone" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificate,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "ClientCertificate" + suffix,
-				config: Config{
-					Credential: &rsaCertificate,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{"-require-any-client-certificate"},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateVerify,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "CertificateVerify" + suffix,
-				config: Config{
-					Credential: &rsaCertificate,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{"-require-any-client-certificate"},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeClientKeyExchange,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "ClientKeyExchange" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		if protocol != dtls {
-			ret = append(ret, perMessageTest{
-				messageType: typeNextProtocol,
-				test: testCase{
-					testType: serverTest,
-					protocol: protocol,
-					name:     "NextProtocol" + suffix,
-					config: Config{
-						MaxVersion: VersionTLS12,
-						NextProtos: []string{"bar"},
-					},
-					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
-				},
-			})
-
-			ret = append(ret, perMessageTest{
-				messageType: typeChannelID,
-				test: testCase{
-					testType: serverTest,
-					protocol: protocol,
-					name:     "ChannelID" + suffix,
-					config: Config{
-						MaxVersion: VersionTLS12,
-						ChannelID:  &channelIDKey,
-					},
-					flags: []string{
-						"-expect-channel-id",
-						base64FlagValue(channelIDBytes),
-					},
-				},
-			})
-		}
-
-		ret = append(ret, perMessageTest{
-			messageType: typeFinished,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "ClientFinished" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeNewSessionTicket,
-			test: testCase{
-				protocol: protocol,
-				name:     "NewSessionTicket" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeFinished,
-			test: testCase{
-				protocol: protocol,
-				name:     "ServerFinished" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-			},
-		})
-
-	}
-
-	for _, protocol := range []protocol{tls, quic, dtls} {
-		suffix := "-" + protocol.String()
-		ret = append(ret, perMessageTest{
-			messageType: typeClientHello,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "TLS13-ClientHello" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeServerHello,
-			test: testCase{
-				name:     "TLS13-ServerHello" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeEncryptedExtensions,
-			test: testCase{
-				name:     "TLS13-EncryptedExtensions" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateRequest,
-			test: testCase{
-				name:     "TLS13-CertificateRequest" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					ClientAuth: RequireAnyClientCert,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificate,
-			test: testCase{
-				name:     "TLS13-ServerCertificate" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateVerify,
-			test: testCase{
-				name:     "TLS13-ServerCertificateVerify" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeFinished,
-			test: testCase{
-				name:     "TLS13-ServerFinished" + suffix,
-				protocol: protocol,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificate,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "TLS13-ClientCertificate" + suffix,
-				config: Config{
-					Credential: &rsaCertificate,
-					MaxVersion: VersionTLS13,
-				},
-				flags: []string{"-require-any-client-certificate"},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeCertificateVerify,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "TLS13-ClientCertificateVerify" + suffix,
-				config: Config{
-					Credential: &rsaCertificate,
-					MaxVersion: VersionTLS13,
-				},
-				flags: []string{"-require-any-client-certificate"},
-			},
-		})
-
-		ret = append(ret, perMessageTest{
-			messageType: typeFinished,
-			test: testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     "TLS13-ClientFinished" + suffix,
-				config: Config{
-					MaxVersion: VersionTLS13,
-				},
-			},
-		})
-
-		// Only TLS uses EndOfEarlyData.
-		if protocol == tls {
-			ret = append(ret, perMessageTest{
-				messageType: typeEndOfEarlyData,
-				test: testCase{
-					testType: serverTest,
-					protocol: protocol,
-					name:     "TLS13-EndOfEarlyData" + suffix,
-					config: Config{
-						MaxVersion: VersionTLS13,
-					},
-					resumeSession: true,
-					earlyData:     true,
-				},
-			})
-		}
-	}
-
-	return ret
-}
-
-func addWrongMessageTypeTests() {
-	for _, t := range makePerMessageTests() {
-		t.test.name = "WrongMessageType-" + t.test.name
-		if t.test.resumeConfig != nil {
-			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
-		} else {
-			t.test.config.Bugs.SendWrongMessageType = t.messageType
-		}
-		t.test.shouldFail = true
-		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
-		t.test.expectedLocalError = "remote error: unexpected message"
-
-		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
-			// In TLS 1.3, if the server believes it has sent ServerHello,
-			// but the client cannot process it, the client will send an
-			// unencrypted alert while the server expects encryption. This
-			// decryption failure is reported differently for each protocol, so
-			// leave it unchecked.
-			t.test.expectedLocalError = ""
-		}
-
-		testCases = append(testCases, t.test)
-	}
-}
-
-func addTrailingMessageDataTests() {
-	for _, t := range makePerMessageTests() {
-		t.test.name = "TrailingMessageData-" + t.test.name
-		if t.test.resumeConfig != nil {
-			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
-		} else {
-			t.test.config.Bugs.SendTrailingMessageData = t.messageType
-		}
-		t.test.shouldFail = true
-		t.test.expectedError = ":DECODE_ERROR:"
-		t.test.expectedLocalError = "remote error: error decoding message"
-
-		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
-			// In TLS 1.3, if the server believes it has sent ServerHello,
-			// but the client cannot process it, the client will send an
-			// unencrypted alert while the server expects encryption. This
-			// decryption failure is reported differently for each protocol, so
-			// leave it unchecked.
-			t.test.expectedLocalError = ""
-		}
-
-		if t.messageType == typeClientHello {
-			// We have a different error for ClientHello parsing.
-			t.test.expectedError = ":CLIENTHELLO_PARSE_FAILED:"
-		}
-
-		if t.messageType == typeFinished {
-			// Bad Finished messages read as the verify data having
-			// the wrong length.
-			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
-			t.test.expectedLocalError = "remote error: error decrypting message"
-		}
-
-		testCases = append(testCases, t.test)
-	}
-}
-
-func addTLS13HandshakeTests() {
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "NegotiatePSKResumption-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NegotiatePSKResumption: true,
-			},
-		},
-		resumeSession: true,
-		shouldFail:    true,
-		expectedError: ":MISSING_KEY_SHARE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "MissingKeyShare-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				MissingKeyShare: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":MISSING_KEY_SHARE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "MissingKeyShare-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				MissingKeyShare: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":MISSING_KEY_SHARE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DuplicateKeyShares-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				DuplicateKeyShares: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DUPLICATE_KEY_SHARE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-			},
-		},
-	})
-
-	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
-	// resumption.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ResumeTLS12SessionID-TLS13",
-		config: Config{
-			MaxVersion:             VersionTLS12,
-			SessionTicketsDisabled: true,
-		},
-		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
-		resumeSession: true,
-	})
-
-	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
-	// a TLS 1.2 session ID.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS12SessionID-TLS13",
-		config: Config{
-			MaxVersion:             VersionTLS12,
-			SessionTicketsDisabled: true,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession:        true,
-		expectResumeRejected: true,
-	})
-
-	// Test that the server correctly echoes back session IDs of
-	// various lengths. The first test additionally asserts that
-	// BoringSSL always sends the ChangeCipherSpec messages for
-	// compatibility mode, rather than negotiating it based on the
-	// ClientHello.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EmptySessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendClientHelloSessionID: []byte{},
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Server-ShortSessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendClientHelloSessionID: make([]byte, 16),
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Server-FullSessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendClientHelloSessionID: make([]byte, 32),
-			},
-		},
-	})
-
-	// The server should reject ClientHellos whose session IDs are too long.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Server-TooLongSessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendClientHelloSessionID: make([]byte, 33),
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":CLIENTHELLO_PARSE_FAILED:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Server-TooLongSessionID-TLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendClientHelloSessionID: make([]byte, 33),
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":CLIENTHELLO_PARSE_FAILED:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	// Test that the client correctly accepts or rejects short session IDs from
-	// the server. Our tests use 32 bytes by default, so the boundary condition
-	// is already covered.
-	testCases = append(testCases, testCase{
-		name: "Client-ShortSessionID",
-		config: Config{
-			MaxVersion:             VersionTLS12,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				NewSessionIDLength: 1,
-			},
-		},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		name: "Client-TooLongSessionID",
-		config: Config{
-			MaxVersion:             VersionTLS12,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				NewSessionIDLength: 33,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	// Test that the client sends a fake session ID in TLS 1.3. We cover both
-	// normal and resumption handshakes to capture interactions with the
-	// session resumption path.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS13SessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectClientHelloSessionID: true,
-			},
-		},
-		resumeSession: true,
-	})
-
-	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TLS12NoSessionID-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExpectNoSessionID: true,
-			},
-		},
-		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-on-initial-expect-early-data-reason", "no_session_offered",
-			"-on-resume-expect-early-data-reason", "accept",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Reject-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AlwaysRejectEarlyData: true,
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-retry-expect-early-data-reason", "peer_declined",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		messageCount:  2,
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-on-initial-expect-early-data-reason", "no_session_offered",
-			"-on-resume-expect-early-data-reason", "accept",
-		},
-	})
-
-	// The above tests the most recent ticket. Additionally test that 0-RTT
-	// works on the first ticket issued by the server.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-FirstTicket-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				UseFirstSessionTicket: true,
-			},
-		},
-		messageCount:  2,
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-on-resume-expect-early-data-reason", "accept",
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-				OmitEarlyDataExtension:  true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Require a HelloRetryRequest for every curve.
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-				OmitEarlyDataExtension:  true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_RECORD:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-TooMuchData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 16384 + 1,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-Interleaved-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-				InterleaveEarlyData:     true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-HRR-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-			},
-			DefaultCurves: []CurveID{},
-		},
-		// Though the session is not resumed and we send HelloRetryRequest,
-		// early data being disabled takes priority as the reject reason.
-		flags: []string{"-expect-early-data-reason", "disabled"},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 4,
-				InterleaveEarlyData:     true,
-			},
-			DefaultCurves: []CurveID{},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_RECORD:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendFakeEarlyDataLength: 16384 + 1,
-			},
-			DefaultCurves: []CurveID{},
-		},
-		shouldFail:    true,
-		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
-	})
-
-	// Test that skipping early data looking for cleartext correctly
-	// processes an alert record.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendEarlyAlert:          true,
-				SendFakeEarlyDataLength: 4,
-			},
-			DefaultCurves: []CurveID{},
-		},
-		shouldFail:    true,
-		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendEarlyDataOnSecondClientHello: true,
-			},
-			DefaultCurves: []CurveID{},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: bad record MAC",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EmptyEncryptedExtensions-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				EmptyEncryptedExtensions: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: error decoding message",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EncryptedExtensionsWithKeyShare-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				EncryptedExtensionsWithKeyShare: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: unsupported extension",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SendHelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Require a HelloRetryRequest for every curve.
-			DefaultCurves:    []CurveID{},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		expectations: connectionExpectations{
-			curveID: CurveX25519,
-		},
-		flags: []string{"-expect-hrr"},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SendHelloRetryRequest-2-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			DefaultCurves:    []CurveID{CurveP384},
-			CurvePreferences: []CurveID{CurveX25519, CurveP384},
-		},
-		// Although the ClientHello did not predict our preferred curve,
-		// we always select it whether it is predicted or not.
-		expectations: connectionExpectations{
-			curveID: CurveX25519,
-		},
-		flags: []string{"-expect-hrr"},
-	})
-
-	testCases = append(testCases, testCase{
-		name: "UnknownCurve-HelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCurve: bogusCurve,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-CipherChange-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
-				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CIPHER_RETURNED:",
-	})
-
-	// Test that the client does not offer a PSK in the second ClientHello if the
-	// HelloRetryRequest is incompatible with it.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			CipherSuites: []uint16{
-				TLS_AES_128_GCM_SHA256,
-			},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				ExpectNoTLS13PSKAfterHRR: true,
-			},
-			CipherSuites: []uint16{
-				TLS_AES_256_GCM_SHA384,
-			},
-		},
-		resumeSession:        true,
-		expectResumeRejected: true,
-	})
-
-	testCases = append(testCases, testCase{
-		name: "DisabledCurve-HelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveP256},
-			Bugs: ProtocolBugs{
-				IgnorePeerCurvePreferences: true,
-			},
-		},
-		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "UnnecessaryHelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			CurvePreferences: []CurveID{CurveX25519},
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCurve: CurveX25519,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SecondHelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SecondHelloRetryRequest: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-Empty-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AlwaysSendHelloRetryRequest: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-DuplicateCurve-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires a HelloRetryRequest against BoringSSL's default
-			// configuration. Assert this ExpectMissingKeyShare.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				ExpectMissingKeyShare:                true,
-				DuplicateHelloRetryRequestExtensions: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":DUPLICATE_EXTENSION:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-Cookie-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte("cookie"),
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-DuplicateCookie-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie:          []byte("cookie"),
-				DuplicateHelloRetryRequestExtensions: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":DUPLICATE_EXTENSION:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-EmptyCookie-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte{},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-Cookie-Curve-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte("cookie"),
-				ExpectMissingKeyShare:       true,
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequest-Unknown-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				CustomHelloRetryRequestExtension: "extension",
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SecondClientHelloMissingKeyShare-TLS13",
-		config: Config{
-			MaxVersion:    VersionTLS13,
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				SecondClientHelloMissingKeyShare: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":MISSING_KEY_SHARE:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SecondClientHelloWrongCurve-TLS13",
-		config: Config{
-			MaxVersion:    VersionTLS13,
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				MisinterpretHelloRetryRequestCurve: CurveP521,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequestVersionMismatch-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendServerHelloVersion: 0x0305,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "HelloRetryRequestCurveMismatch-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				// Send P-384 (correct) in the HelloRetryRequest.
-				SendHelloRetryRequestCurve: CurveP384,
-				// But send P-256 in the ServerHello.
-				SendCurve: CurveP256,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	// Test the server selecting a curve that requires a HelloRetryRequest
-	// without sending it.
-	testCases = append(testCases, testCase{
-		name: "SkipHelloRetryRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SkipHelloRetryRequest: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":WRONG_CURVE:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SecondServerHelloNoVersion-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				OmitServerSupportedVersionExtension: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
-	})
-	testCases = append(testCases, testCase{
-		name: "SecondServerHelloWrongVersion-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// P-384 requires HelloRetryRequest in BoringSSL.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				SendServerSupportedVersionExtension: 0x1234,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "RequestContextInHandshake-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				SendRequestContext: []byte("request context"),
-			},
-		},
-		shimCertificate: &rsaCertificate,
-		shouldFail:      true,
-		expectedError:   ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "UnknownExtensionInCertificateRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				SendCustomCertificateRequest: 0x1212,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-	})
-
-	testCases = append(testCases, testCase{
-		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				OmitCertificateRequestAlgorithms: true,
-			},
-		},
-		shimCertificate: &rsaCertificate,
-		shouldFail:      true,
-		expectedError:   ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TrailingKeyShareData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				TrailingKeyShareData: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "AlwaysSelectPSKIdentity-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AlwaysSelectPSKIdentity: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "InvalidPSKIdentity-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SelectPSKIdentityOnResume: 1,
-			},
-		},
-		resumeSession: true,
-		shouldFail:    true,
-		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ExtraPSKIdentity-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ExtraPSKIdentity:   true,
-				SendExtraPSKBinder: true,
-			},
-		},
-		resumeSession: true,
-	})
-
-	// Test that unknown NewSessionTicket extensions are tolerated.
-	testCases = append(testCases, testCase{
-		name: "CustomTicketExtension-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				CustomTicketExtension: "1234",
-			},
-		},
-	})
-
-	// Test the client handles 0-RTT being rejected by a full handshake
-	// and correctly reports a certificate change.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-RejectTicket-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &rsaCertificate,
-		},
-		resumeConfig: &Config{
-			MaxVersion:             VersionTLS13,
-			Credential:             &ecdsaP256Certificate,
-			SessionTicketsDisabled: true,
-		},
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-retry-expect-early-data-reason", "session_not_resumed",
-			// Test the peer certificate is reported correctly in each of the
-			// three logical connections.
-			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
-			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
-			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
-			// Session tickets are disabled, so the runner will not send a ticket.
-			"-on-retry-expect-no-session",
-		},
-	})
-
-	// Test the server rejects 0-RTT if it does not recognize the ticket.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-RejectTicket-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Corrupt the ticket.
-				FilterTicket: func(in []byte) ([]byte, error) {
-					in[len(in)-1] ^= 1
-					return in, nil
-				},
-			},
-		},
-		messageCount:            2,
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-resume-expect-early-data-reason", "session_not_resumed",
-		},
-	})
-
-	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-HRR-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-retry-expect-early-data-reason", "hello_retry_request",
-		},
-	})
-
-	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-HRR-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			// Require a HelloRetryRequest for every curve.
-			DefaultCurves: []CurveID{},
-		},
-		messageCount:            2,
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-resume-expect-early-data-reason", "hello_retry_request",
-		},
-	})
-
-	// Test the client handles a 0-RTT reject from both ticket rejection and
-	// HelloRetryRequest.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Credential: &rsaCertificate,
-		},
-		resumeConfig: &Config{
-			MaxVersion:             VersionTLS13,
-			Credential:             &ecdsaP256Certificate,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
-			},
-		},
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			// The client sees HelloRetryRequest before the resumption result,
-			// though neither value is inherently preferable.
-			"-on-retry-expect-early-data-reason", "hello_retry_request",
-			// Test the peer certificate is reported correctly in each of the
-			// three logical connections.
-			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
-			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
-			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
-			// Session tickets are disabled, so the runner will not send a ticket.
-			"-on-retry-expect-no-session",
-		},
-	})
-
-	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-			// Require a HelloRetryRequest for every curve.
-			DefaultCurves: []CurveID{},
-			Bugs: ProtocolBugs{
-				// Corrupt the ticket.
-				FilterTicket: func(in []byte) ([]byte, error) {
-					in[len(in)-1] ^= 1
-					return in, nil
-				},
-			},
-		},
-		messageCount:            2,
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			// The server sees the missed resumption before HelloRetryRequest,
-			// though neither value is inherently preferable.
-			"-on-resume-expect-early-data-reason", "session_not_resumed",
-		},
-	})
-
-	// The client must check the server does not send the early_data
-	// extension while rejecting the session.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataWithoutResume-Client-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			MaxEarlyDataSize: 16384,
-		},
-		resumeConfig: &Config{
-			MaxVersion:             VersionTLS13,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				SendEarlyDataExtension: true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-
-	// The client must fail with a dedicated error code if the server
-	// responds with TLS 1.2 when offering 0-RTT.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataVersionDowngrade-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS12,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
-	})
-
-	// Same as above, but the server also sends a warning alert before the
-	// ServerHello. Although the shim predicts TLS 1.3 for 0-RTT, it should
-	// still interpret data before ServerHello in a TLS-1.2-compatible way.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataVersionDowngrade-Client-TLS13-WarningAlert",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendSNIWarningAlert: true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
-	})
-
-	// Test that the client rejects an (unsolicited) early_data extension if
-	// the server sent an HRR.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
-				SendEarlyDataExtension:      true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		// The client will first process an early data reject from the HRR.
-		expectEarlyDataRejected: true,
-		shouldFail:              true,
-		expectedError:           ":UNEXPECTED_EXTENSION:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "SkipChangeCipherSpec-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SkipChangeCipherSpec: true,
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SkipChangeCipherSpec-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SkipChangeCipherSpec: true,
-			},
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "TooManyChangeCipherSpec-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendExtraChangeCipherSpec: 33,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TooManyChangeCipherSpec-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendExtraChangeCipherSpec: 33,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
-	})
-
-	testCases = append(testCases, testCase{
-		name: "SendPostHandshakeChangeCipherSpec-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendPostHandshakeChangeCipherSpec: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_RECORD:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	fooString := "foo"
-	barString := "bar"
-
-	// Test that the client reports the correct ALPN after a 0-RTT reject
-	// that changed it.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-ALPNMismatch-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ALPNProtocol: &fooString,
-			},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ALPNProtocol: &barString,
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar",
-			// The client does not learn ALPN was the cause.
-			"-on-retry-expect-early-data-reason", "peer_declined",
-			// In the 0-RTT state, we surface the predicted ALPN. After
-			// processing the reject, we surface the real one.
-			"-on-initial-expect-alpn", "foo",
-			"-on-resume-expect-alpn", "foo",
-			"-on-retry-expect-alpn", "bar",
-		},
-	})
-
-	// Test that the client reports the correct ALPN after a 0-RTT reject if
-	// ALPN was omitted from the first connection.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar",
-			// The client does not learn ALPN was the cause.
-			"-on-retry-expect-early-data-reason", "peer_declined",
-			// In the 0-RTT state, we surface the predicted ALPN. After
-			// processing the reject, we surface the real one.
-			"-on-initial-expect-alpn", "",
-			"-on-resume-expect-alpn", "",
-			"-on-retry-expect-alpn", "foo",
-		},
-	})
-
-	// Test that the client reports the correct ALPN after a 0-RTT reject if
-	// ALPN was omitted from the second connection.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar",
-			// The client does not learn ALPN was the cause.
-			"-on-retry-expect-early-data-reason", "peer_declined",
-			// In the 0-RTT state, we surface the predicted ALPN. After
-			// processing the reject, we surface the real one.
-			"-on-initial-expect-alpn", "foo",
-			"-on-resume-expect-alpn", "foo",
-			"-on-retry-expect-alpn", "",
-		},
-	})
-
-	// Test that the client enforces ALPN match on 0-RTT accept.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				ALPNProtocol: &fooString,
-			},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AlwaysAcceptEarlyData: true,
-				ALPNProtocol:          &barString,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar",
-			"-on-initial-expect-alpn", "foo",
-			"-on-resume-expect-alpn", "foo",
-			"-on-retry-expect-alpn", "bar",
-		},
-		shouldFail:         true,
-		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	// Test that the client does not offer early data if it is incompatible
-	// with ALPN preferences.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			MaxEarlyDataSize: 16384,
-			NextProtos:       []string{"foo", "bar"},
-		},
-		resumeSession: true,
-		flags: []string{
-			"-enable-early-data",
-			"-expect-ticket-supports-early-data",
-			"-expect-no-offer-early-data",
-			// Offer different ALPN values in the initial and resumption.
-			"-on-initial-advertise-alpn", "\x03foo",
-			"-on-initial-expect-alpn", "foo",
-			"-on-resume-advertise-alpn", "\x03bar",
-			"-on-resume-expect-alpn", "bar",
-			// The ALPN mismatch comes from the client, so it reports it as the
-			// reason.
-			"-on-resume-expect-early-data-reason", "alpn_mismatch",
-		},
-	})
-
-	// Test that the client does not offer 0-RTT to servers which never
-	// advertise it.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession: true,
-		flags: []string{
-			"-enable-early-data",
-			"-on-resume-expect-no-offer-early-data",
-			// The client declines to offer 0-RTT because of the session.
-			"-on-resume-expect-early-data-reason", "unsupported_for_session",
-		},
-	})
-
-	// Test that the server correctly rejects 0-RTT when the previous
-	// session did not allow early data on resumption.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
-				ExpectEarlyDataAccepted: false,
-			},
-		},
-		resumeSession: true,
-		// This test configures early data manually instead of the earlyData
-		// option, to customize the -enable-early-data flag.
-		flags: []string{
-			"-on-resume-enable-early-data",
-			"-expect-reject-early-data",
-			// The server rejects 0-RTT because of the session.
-			"-on-resume-expect-early-data-reason", "unsupported_for_session",
-		},
-	})
-
-	// Test that we reject early data where ALPN is omitted from the first
-	// connection, but negotiated in the second.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-initial-select-alpn", "",
-			"-on-resume-select-alpn", "foo",
-			"-on-resume-expect-early-data-reason", "alpn_mismatch",
-		},
-	})
-
-	// Test that we reject early data where ALPN is omitted from the second
-	// connection, but negotiated in the first.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-initial-select-alpn", "foo",
-			"-on-resume-select-alpn", "",
-			"-on-resume-expect-early-data-reason", "alpn_mismatch",
-		},
-	})
-
-	// Test that we reject early data with mismatched ALPN.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-ALPNMismatch-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"foo"},
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			NextProtos: []string{"bar"},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-initial-select-alpn", "foo",
-			"-on-resume-select-alpn", "bar",
-			"-on-resume-expect-early-data-reason", "alpn_mismatch",
-		},
-	})
-
-	// Test that the client offering 0-RTT and Channel ID forbids the server
-	// from accepting both.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			RequestChannelID: true,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		expectations: connectionExpectations{
-			channelID: true,
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
-		expectedLocalError: "remote error: illegal parameter",
-		flags: []string{
-			"-send-channel-id", channelIDKeyPath,
-		},
-	})
-
-	// Test that the client offering Channel ID and 0-RTT allows the server
-	// to decline 0-RTT.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
-		config: Config{
-			MaxVersion:       VersionTLS13,
-			RequestChannelID: true,
-			Bugs: ProtocolBugs{
-				AlwaysRejectEarlyData: true,
-			},
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		expectations: connectionExpectations{
-			channelID: true,
-		},
-		flags: []string{
-			"-send-channel-id", channelIDKeyPath,
-			// The client never learns the reason was Channel ID.
-			"-on-retry-expect-early-data-reason", "peer_declined",
-		},
-	})
-
-	// Test that the client offering Channel ID and 0-RTT allows the server
-	// to decline Channel ID.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-send-channel-id", channelIDKeyPath,
-		},
-	})
-
-	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
-	// if it would negotiate Channel ID.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			ChannelID:  &channelIDKey,
-		},
-		resumeSession:           true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		expectations: connectionExpectations{
-			channelID: true,
-		},
-		flags: []string{
-			"-expect-channel-id",
-			base64FlagValue(channelIDBytes),
-			"-on-resume-expect-early-data-reason", "channel_id",
-		},
-	})
-
-	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
-	// if not offered Channel ID.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		expectations: connectionExpectations{
-			channelID: false,
-		},
-		flags: []string{
-			"-enable-channel-id",
-			"-on-resume-expect-early-data-reason", "accept",
-		},
-	})
-
-	// Test that the server errors on 0-RTT streams without EndOfEarlyData.
-	// The subsequent records should fail to decrypt.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SkipEndOfEarlyData: true,
-			},
-		},
-		resumeSession:      true,
-		earlyData:          true,
-		shouldFail:         true,
-		expectedLocalError: "remote error: bad record MAC",
-		expectedError:      ":BAD_DECRYPT:",
-	})
-
-	// Test that EndOfEarlyData is rejected in QUIC. Since we leave application
-	// data to the QUIC implementation, we never accept any data at all in
-	// the 0-RTT epoch, so the error is that the encryption level is rejected
-	// outright.
-	//
-	// TODO(crbug.com/381113363): Test this for DTLS 1.3 as well.
-	testCases = append(testCases, testCase{
-		protocol: quic,
-		testType: serverTest,
-		name:     "EarlyData-UnexpectedEndOfEarlyData-QUIC",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendEndOfEarlyDataInQUICAndDTLS: true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":WRONG_ENCRYPTION_LEVEL_RECEIVED:",
-	})
-
-	// Test that the server errors on 0-RTT streams with a stray handshake
-	// message in them.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendStrayEarlyHandshake: true,
-			},
-		},
-		resumeSession:      true,
-		earlyData:          true,
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// Test that the client reports TLS 1.3 as the version while sending
-	// early data.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Client-VersionAPI-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-expect-version", strconv.Itoa(VersionTLS13),
-			// EMS and RI are always reported as supported when we report
-			// TLS 1.3.
-			"-expect-extended-master-secret",
-			"-expect-secure-renegotiation",
-		},
-	})
-
-	// Test that client and server both notice handshake errors after data
-	// has started flowing.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Client-BadFinished-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				BadFinished: true,
-			},
-		},
-		resumeSession:      true,
-		earlyData:          true,
-		shouldFail:         true,
-		expectedError:      ":DIGEST_CHECK_FAILED:",
-		expectedLocalError: "remote error: error decrypting message",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyData-Server-BadFinished-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				BadFinished: true,
-			},
-		},
-		resumeSession:      true,
-		earlyData:          true,
-		shouldFail:         true,
-		expectedError:      ":DIGEST_CHECK_FAILED:",
-		expectedLocalError: "remote error: error decrypting message",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		resumeConfig: &Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				NonEmptyEndOfEarlyData: true,
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerSkipCertificateVerify-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			Credential: &rsaChainCertificate,
-			Bugs: ProtocolBugs{
-				SkipCertificateVerify: true,
-			},
-		},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-		shimCertificate: &rsaCertificate,
-		flags: []string{
-			"-require-any-client-certificate",
-		},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ClientSkipCertificateVerify-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			Credential: &rsaChainCertificate,
-			Bugs: ProtocolBugs{
-				SkipCertificateVerify: true,
-			},
-		},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-		shimCertificate:    &rsaCertificate,
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// PSK/resumption handshakes should not accept CertificateRequest or
-	// Certificate messages.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "CertificateInResumption-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AlwaysSendCertificate: true,
-			},
-		},
-		resumeSession:      true,
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "CertificateRequestInResumption-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				AlwaysSendCertificateRequest: true,
-			},
-		},
-		shimCertificate:    &rsaCertificate,
-		resumeSession:      true,
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
-	// report a reason of protocol_version.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyDataEnabled-Client-MaxTLS12",
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-		flags: []string{
-			"-enable-early-data",
-			"-max-version", strconv.Itoa(VersionTLS12),
-			"-expect-early-data-reason", "protocol_version",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyDataEnabled-Server-MaxTLS12",
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-		flags: []string{
-			"-enable-early-data",
-			"-max-version", strconv.Itoa(VersionTLS12),
-			"-expect-early-data-reason", "protocol_version",
-		},
-	})
-
-	// The server additionally reports protocol_version if it enabled TLS 1.3,
-	// but the peer negotiated TLS 1.2. (The corresponding situation does not
-	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
-	// is a fatal error.)
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		expectations: connectionExpectations{
-			version: VersionTLS12,
-		},
-		flags: []string{
-			"-enable-early-data",
-			"-expect-early-data-reason", "protocol_version",
-		},
-	})
-
-	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
-	// different PRF hash. Test that the client handles this correctly.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
-		},
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			// The client initially reports the old cipher suite while sending
-			// early data. After processing the 0-RTT reject, it reports the
-			// true cipher suite.
-			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
-			// P-384 requires a HelloRetryRequest against BoringSSL's default
-			// configuration. Assert this with ExpectMissingKeyShare.
-			CurvePreferences: []CurveID{CurveP384},
-			Bugs: ProtocolBugs{
-				ExpectMissingKeyShare: true,
-			},
-		},
-		resumeSession:           true,
-		expectResumeRejected:    true,
-		earlyData:               true,
-		expectEarlyDataRejected: true,
-		flags: []string{
-			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			// The client initially reports the old cipher suite while sending
-			// early data. After processing the 0-RTT reject, it reports the
-			// true cipher suite.
-			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
-		},
-	})
-
-	// Test that the client enforces cipher suite match on 0-RTT accept.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-CipherMismatch-Client-TLS13",
-		config: Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
-		},
-		resumeConfig: &Config{
-			MaxVersion:   VersionTLS13,
-			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
-			Bugs: ProtocolBugs{
-				AlwaysAcceptEarlyData: true,
-			},
-		},
-		resumeSession:      true,
-		earlyData:          true,
-		shouldFail:         true,
-		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-
-	// Test that the client can write early data when it has received a partial
-	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
-	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
-	// separate records, i.e. that PackHandshakeFlight is disabled.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-WriteAfterServerHello",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Write the server response before expecting early data.
-				ExpectEarlyData:     [][]byte{},
-				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-async",
-			"-on-resume-early-write-after-message",
-			strconv.Itoa(int(typeServerHello)),
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "EarlyData-WriteAfterEncryptedExtensions",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Write the server response before expecting early data.
-				ExpectEarlyData:     [][]byte{},
-				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
-			},
-		},
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-async",
-			"-on-resume-early-write-after-message",
-			strconv.Itoa(int(typeEncryptedExtensions)),
-		},
-	})
-}
-
-func addTLS13CipherPreferenceTests() {
-	// Test that client preference is honored if the shim has AES hardware
-	// and ChaCha20-Poly1305 is preferred otherwise.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			CipherSuites: []uint16{
-				TLS_CHACHA20_POLY1305_SHA256,
-				TLS_AES_128_GCM_SHA256,
-			},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		flags: []string{
-			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
-			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			CipherSuites: []uint16{
-				TLS_AES_128_GCM_SHA256,
-				TLS_CHACHA20_POLY1305_SHA256,
-			},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		flags: []string{
-			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
-		},
-	})
-
-	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
-	// whether it has AES hardware.
-	testCases = append(testCases, testCase{
-		name: "TLS13-CipherPreference-Client",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Use the client cipher order. (This is the default but
-			// is listed to be explicit.)
-			PreferServerCipherSuites: false,
-		},
-		flags: []string{
-			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
-			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
-		},
-	})
-}
-
-func addPeekTests() {
-	// Test SSL_peek works, including on empty records.
-	testCases = append(testCases, testCase{
-		name:             "Peek-Basic",
-		sendEmptyRecords: 1,
-		flags:            []string{"-peek-then-read"},
-	})
-
-	// Test SSL_peek can drive the initial handshake.
-	testCases = append(testCases, testCase{
-		name: "Peek-ImplicitHandshake",
-		flags: []string{
-			"-peek-then-read",
-			"-implicit-handshake",
-		},
-	})
-
-	// Test SSL_peek can discover and drive a renegotiation.
-	testCases = append(testCases, testCase{
-		name: "Peek-Renegotiate",
-		config: Config{
-			MaxVersion: VersionTLS12,
-		},
-		renegotiate: 1,
-		flags: []string{
-			"-peek-then-read",
-			"-renegotiate-freely",
-			"-expect-total-renegotiations", "1",
-		},
-	})
-
-	// Test SSL_peek can discover a close_notify.
-	testCases = append(testCases, testCase{
-		name: "Peek-Shutdown",
-		config: Config{
-			Bugs: ProtocolBugs{
-				ExpectCloseNotify: true,
-			},
-		},
-		flags: []string{
-			"-peek-then-read",
-			"-check-close-notify",
-		},
-	})
-
-	// Test SSL_peek can discover an alert.
-	testCases = append(testCases, testCase{
-		name: "Peek-Alert",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendSpuriousAlert: alertRecordOverflow,
-			},
-		},
-		flags:         []string{"-peek-then-read"},
-		shouldFail:    true,
-		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
-	})
-
-	// Test SSL_peek can handle KeyUpdate.
-	testCases = append(testCases, testCase{
-		name: "Peek-KeyUpdate",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		sendKeyUpdates:   1,
-		keyUpdateRequest: keyUpdateNotRequested,
-		flags:            []string{"-peek-then-read"},
-	})
-}
-
-func addRecordVersionTests() {
-	for _, ver := range tlsVersions {
-		// Test that the record version is enforced.
-		testCases = append(testCases, testCase{
-			name: "CheckRecordVersion-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					SendRecordVersion: 0x03ff,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":WRONG_VERSION_NUMBER:",
-		})
-
-		// Test that the ClientHello may use any record version, for
-		// compatibility reasons.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "LooseInitialRecordVersion-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					SendInitialRecordVersion: 0x03ff,
-				},
-			},
-		})
-
-		// Test that garbage ClientHello record versions are rejected.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "GarbageInitialRecordVersion-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					SendInitialRecordVersion: 0xffff,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":WRONG_VERSION_NUMBER:",
-		})
-	}
-}
-
-func addCertificateTests() {
-	for _, ver := range tlsVersions {
-		// Test that a certificate chain with intermediate may be sent
-		// and received as both client and server.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "SendReceiveIntermediate-Client-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaChainCertificate,
-				ClientAuth: RequireAnyClientCert,
-			},
-			expectations: connectionExpectations{
-				peerCertificate: &rsaChainCertificate,
-			},
-			shimCertificate: &rsaChainCertificate,
-			flags: []string{
-				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "SendReceiveIntermediate-Server-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaChainCertificate,
-			},
-			expectations: connectionExpectations{
-				peerCertificate: &rsaChainCertificate,
-			},
-			shimCertificate: &rsaChainCertificate,
-			flags: []string{
-				"-require-any-client-certificate",
-				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
-			},
-		})
-
-		// Test that garbage leaf certificates are properly rejected.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "GarbageCertificate-Client-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &garbageCertificate,
-			},
-			shouldFail:         true,
-			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
-			expectedLocalError: "remote error: error decoding message",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "GarbageCertificate-Server-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &garbageCertificate,
-			},
-			flags:              []string{"-require-any-client-certificate"},
-			shouldFail:         true,
-			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
-			expectedLocalError: "remote error: error decoding message",
-		})
-	}
-}
-
-func addRetainOnlySHA256ClientCertTests() {
-	for _, ver := range tlsVersions {
-		// Test that enabling
-		// SSL_CTX_set_retain_only_sha256_of_client_certs without
-		// actually requesting a client certificate is a no-op.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RetainOnlySHA256-NoCert-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-			},
-			flags: []string{
-				"-on-initial-retain-only-sha256-client-cert",
-				"-on-resume-retain-only-sha256-client-cert",
-			},
-			resumeSession: true,
-		})
-
-		// Test that when retaining only a SHA-256 certificate is
-		// enabled, the hash appears as expected.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RetainOnlySHA256-Cert-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-verify-peer",
-				"-on-initial-retain-only-sha256-client-cert",
-				"-on-resume-retain-only-sha256-client-cert",
-				"-on-initial-expect-sha256-client-cert",
-				"-on-resume-expect-sha256-client-cert",
-			},
-			resumeSession: true,
-		})
-
-		// Test that when the config changes from on to off, a
-		// resumption is rejected because the server now wants the full
-		// certificate chain.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RetainOnlySHA256-OnOff-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-verify-peer",
-				"-on-initial-retain-only-sha256-client-cert",
-				"-on-initial-expect-sha256-client-cert",
-			},
-			resumeSession:        true,
-			expectResumeRejected: true,
-		})
-
-		// Test that when the config changes from off to on, a
-		// resumption is rejected because the server now wants just the
-		// hash.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RetainOnlySHA256-OffOn-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-verify-peer",
-				"-on-resume-retain-only-sha256-client-cert",
-				"-on-resume-expect-sha256-client-cert",
-			},
-			resumeSession:        true,
-			expectResumeRejected: true,
-		})
-	}
-}
-
-func addECDSAKeyUsageTests() {
-	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
-	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
-	if err != nil {
-		panic(err)
-	}
-
-	template := &x509.Certificate{
-		SerialNumber: serialNumber,
-		Subject: pkix.Name{
-			Organization: []string{"Acme Co"},
-		},
-		NotBefore: time.Now(),
-		NotAfter:  time.Now(),
-
-		// An ECC certificate with only the keyAgreement key usgae may
-		// be used with ECDH, but not ECDSA.
-		KeyUsage:              x509.KeyUsageKeyAgreement,
-		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
-		BasicConstraintsValid: true,
-	}
-
-	cert := generateSingleCertChain(template, &ecdsaP256Key)
-
-	for _, ver := range tlsVersions {
-		if ver.version < VersionTLS12 {
-			continue
-		}
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "ECDSAKeyUsage-Client-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &cert,
-			},
-			shouldFail:    true,
-			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "ECDSAKeyUsage-Server-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &cert,
-			},
-			flags:         []string{"-require-any-client-certificate"},
-			shouldFail:    true,
-			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-		})
-	}
-}
-
-func addRSAKeyUsageTests() {
-	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
-
-	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
-	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
-	if err != nil {
-		panic(err)
-	}
-
-	dsTemplate := x509.Certificate{
-		SerialNumber: serialNumber,
-		Subject: pkix.Name{
-			Organization: []string{"Acme Co"},
-		},
-		NotBefore: time.Now(),
-		NotAfter:  time.Now(),
-
-		KeyUsage:              x509.KeyUsageDigitalSignature,
-		BasicConstraintsValid: true,
-	}
-
-	encTemplate := x509.Certificate{
-		SerialNumber: serialNumber,
-		Subject: pkix.Name{
-			Organization: []string{"Acme Co"},
-		},
-		NotBefore: time.Now(),
-		NotAfter:  time.Now(),
-
-		KeyUsage:              x509.KeyUsageKeyEncipherment,
-		BasicConstraintsValid: true,
-	}
-
-	dsCert := generateSingleCertChain(&dsTemplate, priv)
-
-	encCert := generateSingleCertChain(&encTemplate, priv)
-
-	dsSuites := []uint16{
-		TLS_AES_128_GCM_SHA256,
-		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-	}
-	encSuites := []uint16{
-		TLS_RSA_WITH_AES_128_GCM_SHA256,
-		TLS_RSA_WITH_AES_128_CBC_SHA,
-	}
-
-	for _, ver := range tlsVersions {
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
-			config: Config{
-				MinVersion:   ver.version,
-				MaxVersion:   ver.version,
-				Credential:   &encCert,
-				CipherSuites: dsSuites,
-			},
-			shouldFail:    true,
-			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
-			config: Config{
-				MinVersion:   ver.version,
-				MaxVersion:   ver.version,
-				Credential:   &dsCert,
-				CipherSuites: dsSuites,
-			},
-		})
-
-		// TLS 1.3 removes the encipherment suites.
-		if ver.version < VersionTLS13 {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
-				config: Config{
-					MinVersion:   ver.version,
-					MaxVersion:   ver.version,
-					Credential:   &encCert,
-					CipherSuites: encSuites,
-				},
-			})
-
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
-				config: Config{
-					MinVersion:   ver.version,
-					MaxVersion:   ver.version,
-					Credential:   &dsCert,
-					CipherSuites: encSuites,
-				},
-				shouldFail:    true,
-				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-			})
-
-			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
-				config: Config{
-					MinVersion:   ver.version,
-					MaxVersion:   ver.version,
-					Credential:   &dsCert,
-					CipherSuites: encSuites,
-				},
-				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
-			})
-
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
-				config: Config{
-					MinVersion:   ver.version,
-					MaxVersion:   ver.version,
-					Credential:   &encCert,
-					CipherSuites: dsSuites,
-				},
-				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
-			})
-		}
-
-		if ver.version >= VersionTLS13 {
-			// In 1.3 and above, we enforce keyUsage even when disabled.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
-				config: Config{
-					MinVersion:   ver.version,
-					MaxVersion:   ver.version,
-					Credential:   &encCert,
-					CipherSuites: dsSuites,
-				},
-				flags:         []string{"-ignore-rsa-key-usage"},
-				shouldFail:    true,
-				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-			})
-		}
-
-		// The server only uses signatures and always enforces it.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &encCert,
-			},
-			shouldFail:    true,
-			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
-			flags:         []string{"-require-any-client-certificate"},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Credential: &dsCert,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		})
-
-	}
-}
-
-func addExtraHandshakeTests() {
-	// An extra SSL_do_handshake is normally a no-op. These tests use -async
-	// to ensure there is no transport I/O.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ExtraHandshake-Client-TLS12",
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-		},
-		flags: []string{
-			"-async",
-			"-no-op-extra-handshake",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ExtraHandshake-Server-TLS12",
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-		},
-		flags: []string{
-			"-async",
-			"-no-op-extra-handshake",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ExtraHandshake-Client-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-		},
-		flags: []string{
-			"-async",
-			"-no-op-extra-handshake",
-		},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ExtraHandshake-Server-TLS13",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-		},
-		flags: []string{
-			"-async",
-			"-no-op-extra-handshake",
-		},
-	})
-
-	// An extra SSL_do_handshake is a no-op in server 0-RTT.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ExtraHandshake-Server-EarlyData-TLS13",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			MinVersion: VersionTLS13,
-		},
-		messageCount:  2,
-		resumeSession: true,
-		earlyData:     true,
-		flags: []string{
-			"-async",
-			"-no-op-extra-handshake",
-		},
-	})
-
-	// An extra SSL_do_handshake drives the handshake to completion in False
-	// Start. We test this by handshaking twice and asserting the False
-	// Start does not appear to happen. See AlertBeforeFalseStartTest for
-	// how the test works.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ExtraHandshake-FalseStart",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			NextProtos:   []string{"foo"},
-			Bugs: ProtocolBugs{
-				ExpectFalseStart:          true,
-				AlertBeforeFalseStartTest: alertAccessDenied,
-			},
-		},
-		flags: []string{
-			"-handshake-twice",
-			"-false-start",
-			"-advertise-alpn", "\x03foo",
-			"-expect-alpn", "foo",
-		},
-		shimWritesFirst:    true,
-		shouldFail:         true,
-		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
-		expectedLocalError: "tls: peer did not false start: EOF",
-	})
-}
-
-// Test that omitted and empty extensions blocks are tolerated.
-func addOmitExtensionsTests() {
-	// Check the ExpectOmitExtensions setting works.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ExpectOmitExtensions",
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				ExpectOmitExtensions: true,
-			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "tls: ServerHello did not omit extensions",
-	})
-
-	for _, ver := range tlsVersions {
-		if ver.version > VersionTLS12 {
-			continue
-		}
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "OmitExtensions-ClientHello-" + ver.name,
-			config: Config{
-				MinVersion:             ver.version,
-				MaxVersion:             ver.version,
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					OmitExtensions: true,
-					// With no client extensions, the ServerHello must not have
-					// extensions. It should then omit the extensions field.
-					ExpectOmitExtensions: true,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "EmptyExtensions-ClientHello-" + ver.name,
-			config: Config{
-				MinVersion:             ver.version,
-				MaxVersion:             ver.version,
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					EmptyExtensions: true,
-					// With no client extensions, the ServerHello must not have
-					// extensions. It should then omit the extensions field.
-					ExpectOmitExtensions: true,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "OmitExtensions-ServerHello-" + ver.name,
-			config: Config{
-				MinVersion:             ver.version,
-				MaxVersion:             ver.version,
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					OmitExtensions: true,
-					// Disable all ServerHello extensions so
-					// OmitExtensions works.
-					NoExtendedMasterSecret:        true,
-					NoRenegotiationInfo:           true,
-					NoOCSPStapling:                true,
-					NoSignedCertificateTimestamps: true,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "EmptyExtensions-ServerHello-" + ver.name,
-			config: Config{
-				MinVersion:             ver.version,
-				MaxVersion:             ver.version,
-				SessionTicketsDisabled: true,
-				Bugs: ProtocolBugs{
-					EmptyExtensions: true,
-					// Disable all ServerHello extensions so
-					// EmptyExtensions works.
-					NoExtendedMasterSecret:        true,
-					NoRenegotiationInfo:           true,
-					NoOCSPStapling:                true,
-					NoSignedCertificateTimestamps: true,
-				},
-			},
-		})
-	}
-}
-
-const (
-	shrinkingCompressionAlgID = 0xff01
-	expandingCompressionAlgID = 0xff02
-	randomCompressionAlgID    = 0xff03
-)
-
-var (
-	// shrinkingPrefix is the first two bytes of a Certificate message.
-	shrinkingPrefix = []byte{0, 0}
-	// expandingPrefix is just some arbitrary byte string. This has to match the
-	// value in the shim.
-	expandingPrefix = []byte{1, 2, 3, 4}
-)
-
-var shrinkingCompression = CertCompressionAlg{
-	Compress: func(uncompressed []byte) []byte {
-		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
-			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
-		}
-		return uncompressed[len(shrinkingPrefix):]
-	},
-	Decompress: func(out []byte, compressed []byte) bool {
-		if len(out) != len(shrinkingPrefix)+len(compressed) {
-			return false
-		}
-
-		copy(out, shrinkingPrefix)
-		copy(out[len(shrinkingPrefix):], compressed)
-		return true
-	},
-}
-
-var expandingCompression = CertCompressionAlg{
-	Compress: func(uncompressed []byte) []byte {
-		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
-		ret = append(ret, expandingPrefix...)
-		return append(ret, uncompressed...)
-	},
-	Decompress: func(out []byte, compressed []byte) bool {
-		if !bytes.HasPrefix(compressed, expandingPrefix) {
-			return false
-		}
-		copy(out, compressed[len(expandingPrefix):])
-		return true
-	},
-}
-
-var randomCompression = CertCompressionAlg{
-	Compress: func(uncompressed []byte) []byte {
-		ret := make([]byte, 1+len(uncompressed))
-		if _, err := rand.Read(ret[:1]); err != nil {
-			panic(err)
-		}
-		copy(ret[1:], uncompressed)
-		return ret
-	},
-	Decompress: func(out []byte, compressed []byte) bool {
-		if len(compressed) != 1+len(out) {
-			return false
-		}
-		copy(out, compressed[1:])
-		return true
-	},
-}
-
-func addCertCompressionTests() {
-	for _, ver := range tlsVersions {
-		if ver.version < VersionTLS12 {
-			continue
-		}
-
-		// Duplicate compression algorithms is an error, even if nothing is
-		// configured.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "DuplicateCertCompressionExt-" + ver.name,
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					DuplicateCompressedCertAlgs: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":ERROR_PARSING_EXTENSION:",
-		})
-
-		// With compression algorithms configured, an duplicate values should still
-		// be an error.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "DuplicateCertCompressionExt2-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				Bugs: ProtocolBugs{
-					DuplicateCompressedCertAlgs: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":ERROR_PARSING_EXTENSION:",
-		})
-
-		if ver.version < VersionTLS13 {
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "CertCompressionIgnoredBefore13-" + ver.name,
-				flags:    []string{"-install-cert-compression-algs"},
-				config: Config{
-					MinVersion: ver.version,
-					MaxVersion: ver.version,
-					CertCompressionAlgs: map[uint16]CertCompressionAlg{
-						expandingCompressionAlgID: expandingCompression,
-					},
-				},
-			})
-
-			continue
-		}
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CertCompressionExpands-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					expandingCompressionAlgID: expandingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: expandingCompressionAlgID,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CertCompressionShrinks-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: shrinkingCompressionAlgID,
-				},
-			},
-		})
-
-		// Test that the shim behaves consistently if the compression function
-		// is non-deterministic. This is intended to model version differences
-		// between the shim and handshaker with handshake hints, but it is also
-		// useful in confirming we only call the callbacks once.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CertCompressionRandom-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					randomCompressionAlgID: randomCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: randomCompressionAlgID,
-				},
-			},
-		})
-
-		// With both algorithms configured, the server should pick its most
-		// preferable. (Which is expandingCompressionAlgID.)
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CertCompressionPriority-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-					expandingCompressionAlgID: expandingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: expandingCompressionAlgID,
-				},
-			},
-		})
-
-		// With no common algorithms configured, the server should decline
-		// compression.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "CertCompressionNoCommonAlgs-" + ver.name,
-			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					expandingCompressionAlgID: expandingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectUncompressedCert: true,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "CertCompressionExpandsClient-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					expandingCompressionAlgID: expandingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: expandingCompressionAlgID,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "CertCompressionShrinksClient-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: shrinkingCompressionAlgID,
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "CertCompressionBadAlgIDClient-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert:   shrinkingCompressionAlgID,
-					SendCertCompressionAlgID: 1234,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "CertCompressionTooSmallClient-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert:     shrinkingCompressionAlgID,
-					SendCertUncompressedLength: 12,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":CERT_DECOMPRESSION_FAILED:",
-		})
-
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			name:     "CertCompressionTooLargeClient-" + ver.name,
-			flags:    []string{"-install-cert-compression-algs"},
-			config: Config{
-				MinVersion: ver.version,
-				MaxVersion: ver.version,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert:     shrinkingCompressionAlgID,
-					SendCertUncompressedLength: 1 << 20,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
-		})
-	}
-}
-
-func addJDK11WorkaroundTests() {
-	// Test the client treats the JDK 11 downgrade random like the usual one.
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Client-RejectJDK11DowngradeRandom",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendJDK11DowngradeRandom: true,
-			},
-		},
-		shouldFail:         true,
-		expectedError:      ":TLS13_DOWNGRADE:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "Client-AcceptJDK11DowngradeRandom",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			Bugs: ProtocolBugs{
-				SendJDK11DowngradeRandom: true,
-			},
-		},
-		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
-	})
-
-	clientHelloTests := []struct {
-		clientHello []byte
-		isJDK11     bool
-	}{
-		{
-			// A default JDK 11 ClientHello.
-			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
-			true,
-		},
-		{
-			// The above with supported_versions and
-			// psk_key_exchange_modes in the wrong order.
-			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
-			false,
-		},
-		{
-			// The above with a padding extension added at the end.
-			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
-			false,
-		},
-		{
-			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
-			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
-			true,
-		},
-		{
-			// A JDK 11 ClientHello offering a TLS 1.2 session.
-			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
-			true,
-		},
-		{
-			// A JDK 11 ClientHello with EMS disabled.
-			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
-			true,
-		},
-		{
-			// A JDK 11 ClientHello with OCSP stapling disabled.
-			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
-			true,
-		},
-		{
-			// A JDK 11 ClientHello configured with a smaller set of
-			// ciphers.
-			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
-			true,
-		},
-		{
-			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
-			// which JDK 11 does not support.
-			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
-			false,
-		},
-		{
-			// The above with X25519 added, which JDK 11 does not
-			// support.
-			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
-			false,
-		},
-		{
-			// A JDK 11 ClientHello with ALPN protocols configured.
-			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
-			true,
-		},
-	}
-	for i, t := range clientHelloTests {
-		expectedVersion := uint16(VersionTLS13)
-		if t.isJDK11 {
-			expectedVersion = VersionTLS12
-		}
-
-		// In each of these tests, we set DefaultCurves to P-256 to
-		// match the test inputs. SendClientHelloWithFixes requires the
-		// key_shares extension to match in type.
-
-		// With the workaround enabled, we should negotiate TLS 1.2 on
-		// JDK 11 ClientHellos.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     fmt.Sprintf("Server-JDK11-%d", i),
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: []CurveID{CurveP256},
-				Bugs: ProtocolBugs{
-					SendClientHelloWithFixes:   t.clientHello,
-					ExpectJDK11DowngradeRandom: t.isJDK11,
-				},
-			},
-			expectations: connectionExpectations{
-				version: expectedVersion,
-			},
-			flags: []string{"-jdk11-workaround"},
-		})
-
-		// With the workaround disabled, we always negotiate TLS 1.3.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: []CurveID{CurveP256},
-				Bugs: ProtocolBugs{
-					SendClientHelloWithFixes:   t.clientHello,
-					ExpectJDK11DowngradeRandom: false,
-				},
-			},
-			expectations: connectionExpectations{
-				version: VersionTLS13,
-			},
-		})
-
-		// If the server does not support TLS 1.3, the workaround should
-		// be a no-op. In particular, it should not send the downgrade
-		// signal.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
-			config: Config{
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: []CurveID{CurveP256},
-				Bugs: ProtocolBugs{
-					SendClientHelloWithFixes:   t.clientHello,
-					ExpectJDK11DowngradeRandom: false,
-				},
-			},
-			expectations: connectionExpectations{
-				version: VersionTLS12,
-			},
-			flags: []string{
-				"-jdk11-workaround",
-				"-max-version", strconv.Itoa(VersionTLS12),
-			},
-		})
-	}
-}
-
-func addDelegatedCredentialTests() {
-	p256DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
-		dcAlgo: signatureECDSAWithP256AndSHA256,
-		algo:   signatureRSAPSSWithSHA256,
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-NoClientSupport",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-Basic",
-		config: Config{
-			MinVersion:                    VersionTLS13,
-			MaxVersion:                    VersionTLS13,
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "0"},
-		expectations: connectionExpectations{
-			peerCertificate: p256DC,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-ExactAlgorithmMatch",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			// Test that the server doesn't mix up the two signature algorithm
-			// fields. These options are a match because the signature_algorithms
-			// extension matches against the signature on the delegated
-			// credential, while the delegated_credential extension matches
-			// against the signature made by the delegated credential.
-			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "0"},
-		expectations: connectionExpectations{
-			peerCertificate: p256DC,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-SigAlgoMissing",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			// If the client doesn't support the signature in the delegated credential,
-			// the server should not use delegated credentials.
-			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA384},
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-	})
-
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-CertVerifySigAlgoMissing",
-		config: Config{
-			MinVersion: VersionTLS13,
-			MaxVersion: VersionTLS13,
-			// If the client doesn't support the delegated credential's
-			// CertificateVerify algorithm, the server should not use delegated
-			// credentials.
-			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-	})
-
-	// Delegated credentials are not supported at TLS 1.2, even if the client
-	// sends the extension.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-TLS12-Forbidden",
-		config: Config{
-			MinVersion:                    VersionTLS12,
-			MaxVersion:                    VersionTLS12,
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-		},
-		shimCredentials: []*Credential{p256DC, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-		expectations: connectionExpectations{
-			peerCertificate: &rsaCertificate,
-		},
-	})
-
-	// Generate another delegated credential, so we can get the keys out of sync.
-	dcWrongKey := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
-		algo: signatureRSAPSSWithSHA256,
-	})
-	dcWrongKey.DelegatedCredential = p256DC.DelegatedCredential
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-KeyMismatch",
-		// The handshake hints version of the test will, as a side effect, use a
-		// custom private key. Custom private keys can't be checked for key
-		// mismatches.
-		skipHints:       true,
-		shimCredentials: []*Credential{dcWrongKey},
-		shouldFail:      true,
-		expectedError:   ":KEY_VALUES_MISMATCH:",
-	})
-
-	// RSA delegated credentials should be rejected at configuration time.
-	rsaDC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
-		algo:   signatureRSAPSSWithSHA256,
-		dcAlgo: signatureRSAPSSWithSHA256,
-	})
-	testCases = append(testCases, testCase{
-		testType:        serverTest,
-		name:            "DelegatedCredentials-NoRSA",
-		shimCredentials: []*Credential{rsaDC},
-		shouldFail:      true,
-		expectedError:   ":INVALID_SIGNATURE_ALGORITHM:",
-	})
-
-	// If configured with multiple delegated credentials, the server can cleanly
-	// select the first one that works.
-	p384DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
-		dcAlgo: signatureECDSAWithP384AndSHA384,
-		algo:   signatureRSAPSSWithSHA256,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DelegatedCredentials-Multiple",
-		config: Config{
-			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
-		},
-		shimCredentials: []*Credential{p256DC, p384DC},
-		flags:           []string{"-expect-selected-credential", "1"},
-		expectations: connectionExpectations{
-			peerCertificate: p384DC,
-		},
-	})
-}
-
-type echCipher struct {
-	name   string
-	cipher HPKECipherSuite
-}
-
-var echCiphers = []echCipher{
-	{
-		name:   "HKDF-SHA256-AES-128-GCM",
-		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
-	},
-	{
-		name:   "HKDF-SHA256-AES-256-GCM",
-		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
-	},
-	{
-		name:   "HKDF-SHA256-ChaCha20-Poly1305",
-		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
-	},
-}
-
-// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
-// keypair and using |template| as a template for the ECHConfig. If fields are
-// omitted, defaults are used.
-func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
-	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
-	if err != nil {
-		panic(err)
-	}
-	templateCopy := *template
-	if templateCopy.KEM == 0 {
-		templateCopy.KEM = hpke.X25519WithHKDFSHA256
-	}
-	if len(templateCopy.PublicKey) == 0 {
-		templateCopy.PublicKey = publicKey
-	}
-	if len(templateCopy.CipherSuites) == 0 {
-		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
-		for i, cipher := range echCiphers {
-			templateCopy.CipherSuites[i] = cipher.cipher
-		}
-	}
-	if len(templateCopy.PublicName) == 0 {
-		templateCopy.PublicName = "public.example"
-	}
-	if templateCopy.MaxNameLen == 0 {
-		templateCopy.MaxNameLen = 64
-	}
-	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
-}
-
-func addEncryptedClientHelloTests() {
-	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
-	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
-	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
-	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
-	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
-	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
-
-	echSecretCertificate := generateSingleCertChain(&x509.Certificate{
-		SerialNumber: big.NewInt(57005),
-		Subject: pkix.Name{
-			CommonName: "test cert",
-		},
-		NotBefore:             time.Now().Add(-time.Hour),
-		NotAfter:              time.Now().Add(time.Hour),
-		DNSNames:              []string{"secret.example"},
-		IsCA:                  true,
-		BasicConstraintsValid: true,
-	}, &rsa2048Key)
-	echPublicCertificate := generateSingleCertChain(&x509.Certificate{
-		SerialNumber: big.NewInt(57005),
-		Subject: pkix.Name{
-			CommonName: "test cert",
-		},
-		NotBefore:             time.Now().Add(-time.Hour),
-		NotAfter:              time.Now().Add(time.Hour),
-		DNSNames:              []string{"public.example"},
-		IsCA:                  true,
-		BasicConstraintsValid: true,
-	}, &rsa2048Key)
-	echLongNameCertificate := generateSingleCertChain(&x509.Certificate{
-		SerialNumber: big.NewInt(57005),
-		Subject: pkix.Name{
-			CommonName: "test cert",
-		},
-		NotBefore:             time.Now().Add(-time.Hour),
-		NotAfter:              time.Now().Add(time.Hour),
-		DNSNames:              []string{"test0123456789.example"},
-		IsCA:                  true,
-		BasicConstraintsValid: true,
-	}, &ecdsaP256Key)
-
-	for _, protocol := range []protocol{tls, quic, dtls} {
-		prefix := protocol.String() + "-"
-
-		// There are two ClientHellos, so many of our tests have
-		// HelloRetryRequest variations.
-		for _, hrr := range []bool{false, true} {
-			var suffix string
-			var defaultCurves []CurveID
-			if hrr {
-				suffix = "-HelloRetryRequest"
-				// Require a HelloRetryRequest for every curve.
-				defaultCurves = []CurveID{}
-			}
-
-			// Test the server can accept ECH.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					DefaultCurves:   defaultCurves,
-				},
-				resumeSession: true,
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test the server can accept ECH with a minimal ClientHelloOuter.
-			// This confirms that the server does not unexpectedly pick up
-			// fields from the wrong ClientHello.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					DefaultCurves:   defaultCurves,
-					Bugs: ProtocolBugs{
-						MinimalClientHelloOuter: true,
-					},
-				},
-				resumeSession: true,
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test that the server can decline ECH. In particular, it must send
-			// retry configs.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-Decline" + suffix,
-				config: Config{
-					ServerName:    "secret.example",
-					DefaultCurves: defaultCurves,
-					// The client uses an ECHConfig that the server does not understand
-					// so we can observe which retry configs the server sends back.
-					ClientECHConfig: echConfig.ECHConfig,
-					Bugs: ProtocolBugs{
-						OfferSessionInClientHelloOuter: true,
-						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
-					},
-				},
-				resumeSession: true,
-				flags: []string{
-					// Configure three ECHConfigs on the shim, only two of which
-					// should be sent in retry configs.
-					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig1.Key),
-					"-ech-is-retry-config", "0",
-					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig2.Key),
-					"-ech-is-retry-config", "1",
-					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig3.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "public.example",
-				},
-			})
-
-			// Test that the server considers a ClientHelloInner indicating TLS
-			// 1.2 to be a fatal error.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					Bugs: ProtocolBugs{
-						AllowTLS12InClientHelloInner: true,
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
-			})
-
-			// When inner ECH extension is absent from the ClientHelloInner, the
-			// server should fail the connection.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					Bugs: ProtocolBugs{
-						OmitECHInner:       !hrr,
-						OmitSecondECHInner: hrr,
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
-			})
-
-			// Test that the server can decode ech_outer_extensions.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionKeyShare,
-						extensionSupportedCurves,
-						// Include a custom extension, to test that unrecognized
-						// extensions are also decoded.
-						extensionCustom,
-					},
-					Bugs: ProtocolBugs{
-						CustomExtension:                    "test",
-						OnlyCompressSecondClientHelloInner: hrr,
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test that the server allows referenced ClientHelloOuter
-			// extensions to be interleaved with other extensions. Only the
-			// relative order must match.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionKeyShare,
-						extensionSupportedCurves,
-						extensionCustom,
-					},
-					Bugs: ProtocolBugs{
-						CustomExtension:                    "test",
-						OnlyCompressSecondClientHelloInner: hrr,
-						ECHOuterExtensionOrder: []uint16{
-							extensionServerName,
-							extensionKeyShare,
-							extensionSupportedVersions,
-							extensionPSKKeyExchangeModes,
-							extensionSupportedCurves,
-							extensionSignatureAlgorithms,
-							extensionCustom,
-						},
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test that the server rejects references to extensions in the
-			// wrong order.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionKeyShare,
-						extensionSupportedCurves,
-					},
-					Bugs: ProtocolBugs{
-						CustomExtension:                    "test",
-						OnlyCompressSecondClientHelloInner: hrr,
-						ECHOuterExtensionOrder: []uint16{
-							extensionSupportedCurves,
-							extensionKeyShare,
-						},
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_OUTER_EXTENSION:",
-			})
-
-			// Test that the server rejects duplicated values in ech_outer_extensions.
-			// Besides causing the server to reconstruct an invalid ClientHelloInner
-			// with duplicated extensions, this behavior would be vulnerable to DoS
-			// attacks.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionSupportedCurves,
-						extensionSupportedCurves,
-					},
-					Bugs: ProtocolBugs{
-						OnlyCompressSecondClientHelloInner: hrr,
-						// Don't duplicate the extension in ClientHelloOuter.
-						ECHOuterExtensionOrder: []uint16{
-							extensionSupportedCurves,
-						},
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_OUTER_EXTENSION:",
-			})
-
-			// Test that the server rejects references to missing extensions in
-			// ech_outer_extensions.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionCustom,
-					},
-					Bugs: ProtocolBugs{
-						OnlyCompressSecondClientHelloInner: hrr,
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_OUTER_EXTENSION:",
-			})
-
-			// Test that the server rejects a references to the ECH extension in
-			// ech_outer_extensions. The ECH extension is not authenticated in the
-			// AAD and would result in an invalid ClientHelloInner.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					DefaultCurves:   defaultCurves,
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHOuterExtensions: []uint16{
-						extensionEncryptedClientHello,
-					},
-					Bugs: ProtocolBugs{
-						OnlyCompressSecondClientHelloInner: hrr,
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: illegal parameter",
-				expectedError:      ":INVALID_OUTER_EXTENSION:",
-			})
-
-			// Test the message callback is correctly reported with ECH.
-			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
-			expectMsgCallback := clientAndServerHello
-			if protocol == tls {
-				expectMsgCallback += "write ccs\n"
-			}
-			if hrr {
-				expectMsgCallback += clientAndServerHello
-			}
-			// EncryptedExtensions onwards.
-			expectMsgCallback += `write hs 8
-write hs 11
-write hs 15
-write hs 20
-read hs 20
-write ack
-write hs 4
-write hs 4
-read ack
-read ack
-`
-			if protocol != dtls {
-				expectMsgCallback = strings.ReplaceAll(expectMsgCallback, "write ack\n", "")
-				expectMsgCallback = strings.ReplaceAll(expectMsgCallback, "read ack\n", "")
-			}
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-MessageCallback" + suffix,
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					DefaultCurves:   defaultCurves,
-					Bugs: ProtocolBugs{
-						NoCloseNotify: true, // Align QUIC and TCP traces.
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-ech-accept",
-					"-expect-msg-callback", expectMsgCallback,
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-		}
-
-		// Test that ECH, which runs before an async early callback, interacts
-		// correctly in the state machine.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-AsyncEarlyCallback",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-			},
-			flags: []string{
-				"-async",
-				"-use-early-callback",
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-server-name", "secret.example",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-
-		// Test that we successfully rewind the TLS state machine and disable ECH in the
-		// case that the select_cert_cb signals that ECH is not possible for the SNI in
-		// ClientHelloInner.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-FailCallbackNeedRewind",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-			},
-			flags: []string{
-				"-async",
-				"-fail-early-callback-ech-rewind",
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-server-name", "public.example",
-			},
-			expectations: connectionExpectations{
-				echAccepted: false,
-			},
-		})
-
-		// Test that we correctly handle falling back to a ClientHelloOuter with
-		// no SNI (public name).
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-RewindWithNoPublicName",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					OmitPublicName: true,
-				},
-			},
-			flags: []string{
-				"-async",
-				"-fail-early-callback-ech-rewind",
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-no-server-name",
-			},
-			expectations: connectionExpectations{
-				echAccepted: false,
-			},
-		})
-
-		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
-		// it uses the second ECHConfig.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-SecondECHConfig",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig1.ECHConfig,
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig1.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-server-name", "secret.example",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-
-		// Test ECH-enabled server with two ECHConfigs that have the same config
-		// ID can decrypt client's ECH when it uses the second ECHConfig.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-RepeatedConfigID",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfigRepeatID.ECHConfig,
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-server-name", "secret.example",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-
-		// Test all supported ECH cipher suites.
-		for i, cipher := range echCiphers {
-			otherCipher := echCiphers[(i+1)%len(echCiphers)]
-
-			// Test the ECH server can handle the specified cipher.
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test that client can offer the specified cipher and skip over
-			// unrecognized ones.
-			cipherConfig := generateServerECHConfig(&ECHConfig{
-				ConfigID: 42,
-				CipherSuites: []HPKECipherSuite{
-					{KDF: 0x1111, AEAD: 0x2222},
-					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
-					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
-					cipher.cipher,
-				},
-			})
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{cipherConfig},
-					Credential:       &echSecretCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
-					"-host-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-
-			// Test that the ECH server rejects the specified cipher if not
-			// listed in its ECHConfig.
-			otherCipherConfig := generateServerECHConfig(&ECHConfig{
-				ConfigID:     42,
-				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
-			})
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
-					Bugs: ProtocolBugs{
-						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
-					},
-				},
-				flags: []string{
-					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-server-name", "public.example",
-				},
-			})
-		}
-
-		// Test that the ECH server handles a short enc value by falling back to
-		// ClientHelloOuter.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-ShortEnc",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
-					TruncateClientECHEnc:  true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-server-name", "public.example",
-			},
-		})
-
-		// Test that the server handles decryption failure by falling back to
-		// ClientHelloOuter.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
-					CorruptEncryptedClientHello: true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-			},
-		})
-
-		// Test that the server treats decryption failure in the second
-		// ClientHello as fatal.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				// Force a HelloRetryRequest.
-				DefaultCurves: []CurveID{},
-				Bugs: ProtocolBugs{
-					CorruptSecondEncryptedClientHello: true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-			},
-			shouldFail:         true,
-			expectedError:      ":DECRYPTION_FAILED:",
-			expectedLocalError: "remote error: error decrypting message",
-		})
-
-		// Test that the server treats a missing second ECH extension as fatal.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				// Force a HelloRetryRequest.
-				DefaultCurves: []CurveID{},
-				Bugs: ProtocolBugs{
-					OmitSecondEncryptedClientHello: true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-			},
-			shouldFail:         true,
-			expectedError:      ":MISSING_EXTENSION:",
-			expectedLocalError: "remote error: missing extension",
-		})
-
-		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-				// Force a HelloRetryRequest.
-				DefaultCurves: []CurveID{},
-				Bugs: ProtocolBugs{
-					CorruptSecondEncryptedClientHelloConfigID: true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-			},
-			shouldFail:         true,
-			expectedError:      ":DECODE_ERROR:",
-			expectedLocalError: "remote error: illegal parameter",
-		})
-
-		// Test early data works with ECH, in both accept and reject cases.
-		// TODO(crbug.com/381113363): Enable these tests for DTLS once we
-		// support early data in DTLS 1.3.
-		if protocol != dtls {
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-EarlyData",
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-				},
-				resumeSession: true,
-				earlyData:     true,
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-EarlyDataRejected",
-				config: Config{
-					ServerName:      "secret.example",
-					ClientECHConfig: echConfig.ECHConfig,
-					Bugs: ProtocolBugs{
-						// Cause the server to reject 0-RTT with a bad ticket age.
-						SendTicketAge: 1 * time.Hour,
-					},
-				},
-				resumeSession:           true,
-				earlyData:               true,
-				expectEarlyDataRejected: true,
-				flags: []string{
-					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-					"-ech-server-key", base64FlagValue(echConfig.Key),
-					"-ech-is-retry-config", "1",
-					"-expect-ech-accept",
-				},
-				expectations: connectionExpectations{
-					echAccepted: true,
-				},
-			})
-		}
-
-		// Test servers with ECH disabled correctly ignore the extension and
-		// handshake with the ClientHelloOuter.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-Disabled",
-			config: Config{
-				ServerName:      "secret.example",
-				ClientECHConfig: echConfig.ECHConfig,
-			},
-			flags: []string{
-				"-expect-server-name", "public.example",
-			},
-		})
-
-		// Test that ECH can be used with client certificates. In particular,
-		// the name override logic should not interfere with the server.
-		// Test the server can accept ECH.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-ClientAuth",
-			config: Config{
-				Credential:      &rsaCertificate,
-				ClientECHConfig: echConfig.ECHConfig,
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-ech-accept",
-				"-require-any-client-certificate",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-Decline-ClientAuth",
-			config: Config{
-				Credential:      &rsaCertificate,
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig1.Key),
-				"-ech-is-retry-config", "1",
-				"-require-any-client-certificate",
-			},
-		})
-
-		// Test that the server accepts padding.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-Padding",
-			config: Config{
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					ClientECHPadding: 10,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-
-		// Test that the server rejects bad padding.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-BadPadding",
-			config: Config{
-				ClientECHConfig: echConfig.ECHConfig,
-				Bugs: ProtocolBugs{
-					ClientECHPadding:    10,
-					BadClientECHPadding: true,
-				},
-			},
-			flags: []string{
-				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
-				"-ech-server-key", base64FlagValue(echConfig.Key),
-				"-ech-is-retry-config", "1",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-			shouldFail:         true,
-			expectedError:      ":DECODE_ERROR",
-			expectedLocalError: "remote error: illegal parameter",
-		})
-
-		// Test the client's behavior when the server ignores ECH GREASE.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-GREASE-Client-TLS13",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ExpectClientECH: true,
-				},
-			},
-			flags: []string{"-enable-ech-grease"},
-		})
-
-		// Test the client's ECH GREASE behavior when responding to server's
-		// HelloRetryRequest. This test implicitly checks that the first and second
-		// ClientHello messages have identical ECH extensions.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				MinVersion: VersionTLS13,
-				// P-384 requires a HelloRetryRequest against BoringSSL's default
-				// configuration. Assert this with ExpectMissingKeyShare.
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					ExpectMissingKeyShare: true,
-					ExpectClientECH:       true,
-				},
-			},
-			flags: []string{"-enable-ech-grease", "-expect-hrr"},
-		})
-
-		unsupportedVersion := []byte{
-			// version
-			0xba, 0xdd,
-			// length
-			0x00, 0x05,
-			// contents
-			0x05, 0x04, 0x03, 0x02, 0x01,
-		}
-
-		// Test that the client accepts a well-formed encrypted_client_hello
-		// extension in response to ECH GREASE. The response includes one ECHConfig
-		// with a supported version and one with an unsupported version.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ExpectClientECH: true,
-					// Include an additional well-formed ECHConfig with an
-					// unsupported version. This ensures the client can skip
-					// unsupported configs.
-					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
-				},
-			},
-			flags: []string{"-enable-ech-grease"},
-		})
-
-		// TLS 1.2 ServerHellos cannot contain retry configs.
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
-				config: Config{
-					MinVersion:       VersionTLS12,
-					MaxVersion:       VersionTLS12,
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectClientECH:           true,
-						AlwaysSendECHRetryConfigs: true,
-					},
-				},
-				flags:              []string{"-enable-ech-grease"},
-				shouldFail:         true,
-				expectedLocalError: "remote error: unsupported extension",
-				expectedError:      ":UNEXPECTED_EXTENSION:",
-			})
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
-				config: Config{
-					MinVersion:       VersionTLS12,
-					MaxVersion:       VersionTLS12,
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectClientECH:           true,
-						AlwaysSendECHRetryConfigs: true,
-					},
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: unsupported extension",
-				expectedError:      ":UNEXPECTED_EXTENSION:",
-			})
-		}
-
-		// Retry configs must be rejected when ECH is accepted.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectClientECH:           true,
-					AlwaysSendECHRetryConfigs: true,
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: unsupported extension",
-			expectedError:      ":UNEXPECTED_EXTENSION:",
-		})
-
-		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					AlwaysSendECHHelloRetryRequest: true,
-					ExpectMissingKeyShare:          true, // Check we triggered HRR.
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: unsupported extension",
-			expectedError:      ":UNEXPECTED_EXTENSION:",
-		})
-
-		// GREASE should ignore ECH HelloRetryRequest extensions.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
-			config: Config{
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					AlwaysSendECHHelloRetryRequest: true,
-					ExpectMissingKeyShare:          true, // Check we triggered HRR.
-				},
-			},
-			flags: []string{"-enable-ech-grease"},
-		})
-
-		// Random ECH HelloRetryRequest extensions also signal ECH reject.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
-			config: Config{
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					AlwaysSendECHHelloRetryRequest: true,
-					ExpectMissingKeyShare:          true, // Check we triggered HRR.
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: ECH required",
-			expectedError:      ":ECH_REJECTED:",
-		})
-
-		// Test that the client aborts with a decode_error alert when it receives a
-		// syntactically-invalid encrypted_client_hello extension from the server.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					ExpectClientECH:     true,
-					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
-				},
-			},
-			flags:              []string{"-enable-ech-grease"},
-			shouldFail:         true,
-			expectedLocalError: "remote error: error decoding message",
-			expectedError:      ":ERROR_PARSING_EXTENSION:",
-		})
-
-		// Test that the server responds to an inner ECH extension with the
-		// acceptance confirmation.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-ECHInner",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AlwaysSendECHInner: true,
-				},
-			},
-			resumeSession: true,
-		})
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				// Force a HelloRetryRequest.
-				DefaultCurves: []CurveID{},
-				Bugs: ProtocolBugs{
-					AlwaysSendECHInner: true,
-				},
-			},
-			resumeSession: true,
-		})
-
-		// Test that server fails the handshake when it sees a non-empty
-		// inner ECH extension.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					AlwaysSendECHInner:  true,
-					SendInvalidECHInner: []byte{42, 42, 42},
-				},
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: error decoding message",
-			expectedError:      ":ERROR_PARSING_EXTENSION:",
-		})
-
-		// Test that a TLS 1.3 server that receives an inner ECH extension can
-		// negotiate TLS 1.2 without clobbering the downgrade signal.
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						// Omit supported_versions extension so the server negotiates
-						// TLS 1.2.
-						OmitSupportedVersions: true,
-						AlwaysSendECHInner:    true,
-					},
-				},
-				// Check that the client sees the TLS 1.3 downgrade signal in
-				// ServerHello.random.
-				shouldFail:         true,
-				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
-			})
-		}
-
-		// Test the client can negotiate ECH, with and without HelloRetryRequest.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client",
-			config: Config{
-				MinVersion:       VersionTLS13,
-				MaxVersion:       VersionTLS13,
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectServerName:      "secret.example",
-					ExpectOuterServerName: "public.example",
-				},
-				Credential: &echSecretCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				"-expect-ech-accept",
-			},
-			resumeSession: true,
-			expectations:  connectionExpectations{echAccepted: true},
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-HelloRetryRequest",
-			config: Config{
-				MinVersion:       VersionTLS13,
-				MaxVersion:       VersionTLS13,
-				CurvePreferences: []CurveID{CurveP384},
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectServerName:      "secret.example",
-					ExpectOuterServerName: "public.example",
-					ExpectMissingKeyShare: true, // Check we triggered HRR.
-				},
-				Credential: &echSecretCertificate,
-			},
-			resumeSession: true,
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				"-expect-ech-accept",
-				"-expect-hrr", // Check we triggered HRR.
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Test the client can negotiate ECH with early data.
-		// TODO(crbug.com/381113363): Enable these tests for DTLS once we
-		// support early data in DTLS 1.3.
-		if protocol != dtls {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-EarlyData",
-				config: Config{
-					MinVersion:       VersionTLS13,
-					MaxVersion:       VersionTLS13,
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectServerName: "secret.example",
-					},
-					Credential: &echSecretCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-host-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				resumeSession: true,
-				earlyData:     true,
-				expectations:  connectionExpectations{echAccepted: true},
-			})
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-EarlyDataRejected",
-				config: Config{
-					MinVersion:       VersionTLS13,
-					MaxVersion:       VersionTLS13,
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectServerName:      "secret.example",
-						AlwaysRejectEarlyData: true,
-					},
-					Credential: &echSecretCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-host-name", "secret.example",
-					"-expect-ech-accept",
-				},
-				resumeSession:           true,
-				earlyData:               true,
-				expectEarlyDataRejected: true,
-				expectations:            connectionExpectations{echAccepted: true},
-			})
-		}
-
-		if protocol != quic {
-			// Test that an ECH client does not offer a TLS 1.2 session.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-TLS12SessionID",
-				config: Config{
-					MaxVersion:             VersionTLS12,
-					SessionTicketsDisabled: true,
-				},
-				resumeConfig: &Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectNoTLS12Session: true,
-					},
-				},
-				flags: []string{
-					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-on-resume-expect-ech-accept",
-				},
-				resumeSession:        true,
-				expectResumeRejected: true,
-				resumeExpectations:   &connectionExpectations{echAccepted: true},
-			})
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-TLS12SessionTicket",
-				config: Config{
-					MaxVersion: VersionTLS12,
-				},
-				resumeConfig: &Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectNoTLS12Session: true,
-					},
-				},
-				flags: []string{
-					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-on-resume-expect-ech-accept",
-				},
-				resumeSession:        true,
-				expectResumeRejected: true,
-				resumeExpectations:   &connectionExpectations{echAccepted: true},
-			})
-		}
-
-		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
-		// extensions. The Go server will enforce this, so this test only needs
-		// to configure the feature on the shim. Other application extensions
-		// are sent implicitly.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NoNPN",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				// Enable NPN.
-				"-select-next-proto", "foo",
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Test that the client iterates over configurations in the
-		// ECHConfigList and selects the first with supported parameters.
-		unsupportedKEM := generateServerECHConfig(&ECHConfig{
-			KEM:       0x6666,
-			PublicKey: []byte{1, 2, 3, 4},
-		}).ECHConfig
-		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
-			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
-		}).ECHConfig
-		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
-			UnsupportedMandatoryExtension: true,
-		}).ECHConfig
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-SelectECHConfig",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(
-					unsupportedVersion,
-					unsupportedKEM.Raw,
-					unsupportedCipherSuites.Raw,
-					unsupportedMandatoryExtension.Raw,
-					echConfig.ECHConfig.Raw,
-					// |echConfig1| is also supported, but the client should
-					// select the first one.
-					echConfig1.ECHConfig.Raw,
-				)),
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-			},
-		})
-
-		// Test that the client skips sending ECH if all ECHConfigs are
-		// unsupported.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NoSupportedConfigs",
-			config: Config{
-				Bugs: ProtocolBugs{
-					ExpectNoClientECH: true,
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(
-					unsupportedVersion,
-					unsupportedKEM.Raw,
-					unsupportedCipherSuites.Raw,
-					unsupportedMandatoryExtension.Raw,
-				)),
-			},
-		})
-
-		// If ECH GREASE is enabled, the client should send ECH GREASE when no
-		// configured ECHConfig is suitable.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
-			config: Config{
-				Bugs: ProtocolBugs{
-					ExpectClientECH: true,
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(
-					unsupportedVersion,
-					unsupportedKEM.Raw,
-					unsupportedCipherSuites.Raw,
-					unsupportedMandatoryExtension.Raw,
-				)),
-				"-enable-ech-grease",
-			},
-		})
-
-		// If both ECH GREASE and suitable ECHConfigs are available, the
-		// client should send normal ECH.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-GREASE",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-			},
-			resumeSession: true,
-			expectations:  connectionExpectations{echAccepted: true},
-		})
-
-		// Test that GREASE extensions correctly interact with ECH. Both the
-		// inner and outer ClientHellos should include GREASE extensions.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-GREASEExtensions",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectGREASE: true,
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				"-enable-grease",
-			},
-			resumeSession: true,
-			expectations:  connectionExpectations{echAccepted: true},
-		})
-
-		// Test that the client tolerates unsupported extensions if the
-		// mandatory bit is not set.
-		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-UnsupportedExtension",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Syntax errors in the ECHConfigList should be rejected.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-InvalidECHConfigList",
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
-			},
-			shouldFail:    true,
-			expectedError: ":INVALID_ECH_CONFIG_LIST:",
-		})
-
-		// If the ClientHelloInner has no server_name extension, while the
-		// ClientHelloOuter has one, the client must check for unsolicited
-		// extensions based on the selected ClientHello.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					// ClientHelloOuter should have a server name.
-					ExpectOuterServerName: "public.example",
-					// The server will acknowledge the server_name extension.
-					// This option runs whether or not the client requested the
-					// extension.
-					SendServerNameAck: true,
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				// No -host-name flag.
-				"-expect-ech-accept",
-			},
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_EXTENSION:",
-			expectedLocalError: "remote error: unsupported extension",
-			expectations:       connectionExpectations{echAccepted: true},
-		})
-
-		// Most extensions are the same between ClientHelloInner and
-		// ClientHelloOuter and can be compressed.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				NextProtos:       []string{"proto"},
-				Bugs: ProtocolBugs{
-					ExpectECHOuterExtensions: []uint16{
-						extensionALPN,
-						extensionKeyShare,
-						extensionPSKKeyExchangeModes,
-						extensionSignatureAlgorithms,
-						extensionSupportedCurves,
-					},
-				},
-				Credential: &echSecretCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				"-advertise-alpn", "\x05proto",
-				"-expect-alpn", "proto",
-				"-host-name", "secret.example",
-			},
-			expectations: connectionExpectations{
-				echAccepted: true,
-				nextProto:   "proto",
-			},
-			skipQUICALPNConfig: true,
-		})
-
-		// If the server name happens to match the public name, it still should
-		// not be compressed. It is not publicly known that they match.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NeverCompressServerName",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				NextProtos:       []string{"proto"},
-				Bugs: ProtocolBugs{
-					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
-					ExpectServerName:                "public.example",
-					ExpectOuterServerName:           "public.example",
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				"-host-name", "public.example",
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
-		// should also compress supported_versions.
-		tls13Vers := VersionTLS13
-		if protocol == dtls {
-			tls13Vers = VersionDTLS13
-		}
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-CompressSupportedVersions",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectECHOuterExtensions: []uint16{
-						extensionSupportedVersions,
-					},
-				},
-				Credential: &echSecretCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				"-expect-ech-accept",
-				"-min-version", strconv.Itoa(int(tls13Vers)),
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Test that the client can still offer server names that exceed the
-		// maximum name length. It is only a padding hint.
-		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NameTooLong",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
-				Bugs: ProtocolBugs{
-					ExpectServerName: "test0123456789.example",
-				},
-				Credential: &echLongNameCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
-				"-host-name", "test0123456789.example",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Test the client can recognize when ECH is rejected.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
-				Bugs: ProtocolBugs{
-					ExpectServerName: "public.example",
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: ECH required",
-			expectedError:      ":ECH_REJECTED:",
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
-				CurvePreferences: []CurveID{CurveP384},
-				Bugs: ProtocolBugs{
-					ExpectServerName:      "public.example",
-					ExpectMissingKeyShare: true, // Check we triggered HRR.
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
-				"-expect-hrr", // Check we triggered HRR.
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: ECH required",
-			expectedError:      ":ECH_REJECTED:",
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
-			config: Config{
-				Bugs: ProtocolBugs{
-					ExpectServerName: "public.example",
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-no-ech-retry-configs",
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: ECH required",
-			expectedError:      ":ECH_REJECTED:",
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-TLS12",
-				config: Config{
-					MaxVersion: VersionTLS12,
-					Bugs: ProtocolBugs{
-						ExpectServerName: "public.example",
-					},
-					Credential: &echPublicCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					// TLS 1.2 cannot provide retry configs.
-					"-expect-no-ech-retry-configs",
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: ECH required",
-				expectedError:      ":ECH_REJECTED:",
-			})
-
-			// Test that the client disables False Start when ECH is rejected.
-			testCases = append(testCases, testCase{
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
-				config: Config{
-					MaxVersion:   VersionTLS12,
-					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-					NextProtos:   []string{"foo"},
-					Bugs: ProtocolBugs{
-						// The options below cause the server to, immediately
-						// after client Finished, send an alert and try to read
-						// application data without sending server Finished.
-						ExpectFalseStart:          true,
-						AlertBeforeFalseStartTest: alertAccessDenied,
-					},
-					Credential: &echPublicCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-false-start",
-					"-advertise-alpn", "\x03foo",
-					"-expect-alpn", "foo",
-				},
-				shimWritesFirst: true,
-				shouldFail:      true,
-				// Ensure the client does not send application data at the False
-				// Start point. EOF comes from the client closing the connection
-				// in response ot the alert.
-				expectedLocalError: "tls: peer did not false start: EOF",
-				// Ensures the client picks up the alert before reporting an
-				// authenticated |SSL_R_ECH_REJECTED|.
-				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
-			})
-		}
-
-		// Test that unsupported retry configs in a valid ECHConfigList are
-		// allowed. They will be skipped when configured in the retry.
-		retryConfigs := CreateECHConfigList(
-			unsupportedVersion,
-			unsupportedKEM.Raw,
-			unsupportedCipherSuites.Raw,
-			unsupportedMandatoryExtension.Raw,
-			echConfig2.ECHConfig.Raw)
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendECHRetryConfigs: retryConfigs,
-					ExpectServerName:    "public.example",
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
-			},
-			shouldFail:         true,
-			expectedLocalError: "remote error: ECH required",
-			expectedError:      ":ECH_REJECTED:",
-		})
-
-		// Test that the client rejects ClientHelloOuter handshakes that attempt
-		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectServerName: "secret.example",
-				},
-				Credential: &echSecretCertificate,
-			},
-			resumeConfig: &Config{
-				MaxVersion:       VersionTLS13,
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectServerName:                    "public.example",
-					UseInnerSessionWithClientHelloOuter: true,
-				},
-				Credential: &echPublicCertificate,
-			},
-			resumeSession: true,
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				"-on-initial-expect-ech-accept",
-			},
-			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_EXTENSION:",
-			expectations:       connectionExpectations{echAccepted: true},
-			resumeExpectations: &connectionExpectations{echAccepted: false},
-		})
-		if protocol == tls {
-			// This is only syntactically possible with TLS. In DTLS, we don't
-			// have middlebox compatibility mode, so the session ID will only
-			// filled in if we are offering a DTLS 1.2 session. But a DTLS 1.2
-			// would never be offered in ClientHelloInner. Without a session ID,
-			// the server syntactically cannot express a resumption at DTLS 1.2.
-			// In QUIC, the above is true, and 1.2 does not exist anyway.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectServerName: "secret.example",
-					},
-					Credential: &echSecretCertificate,
-				},
-				resumeConfig: &Config{
-					MinVersion:       VersionTLS12,
-					MaxVersion:       VersionTLS12,
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectServerName:                    "public.example",
-						UseInnerSessionWithClientHelloOuter: true,
-						// The client only ever offers TLS 1.3 sessions in
-						// ClientHelloInner. AcceptAnySession allows them to be
-						// resumed at TLS 1.2.
-						AcceptAnySession: true,
-					},
-					Credential: &echPublicCertificate,
-				},
-				resumeSession: true,
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-host-name", "secret.example",
-					"-on-initial-expect-ech-accept",
-				},
-				// From the client's perspective, the server echoed a session ID to
-				// signal resumption, but the selected ClientHello had nothing to
-				// resume.
-				shouldFail:         true,
-				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
-				expectedLocalError: "remote error: illegal parameter",
-				expectations:       connectionExpectations{echAccepted: true},
-				resumeExpectations: &connectionExpectations{echAccepted: false},
-			})
-		}
-
-		// Test that the client can process ECH rejects after an early data reject.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectServerName: "secret.example",
-				},
-				Credential: &echSecretCertificate,
-			},
-			resumeConfig: &Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig2},
-				Bugs: ProtocolBugs{
-					ExpectServerName: "public.example",
-				},
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				// Although the resumption connection does not accept ECH, the
-				// API will report ECH was accepted at the 0-RTT point.
-				"-expect-ech-accept",
-				// -on-retry refers to the retried handshake after 0-RTT reject,
-				// while ech-retry-configs refers to the ECHConfigs to use in
-				// the next connection attempt.
-				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
-			},
-			resumeSession:           true,
-			expectResumeRejected:    true,
-			earlyData:               true,
-			expectEarlyDataRejected: true,
-			expectations:            connectionExpectations{echAccepted: true},
-			resumeExpectations:      &connectionExpectations{echAccepted: false},
-			shouldFail:              true,
-			expectedLocalError:      "remote error: ECH required",
-			expectedError:           ":ECH_REJECTED:",
-		})
-		// TODO(crbug.com/381113363): Enable this test for DTLS once we
-		// support early data in DTLS 1.3.
-		if protocol != quic && protocol != dtls {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Bugs: ProtocolBugs{
-						ExpectServerName: "secret.example",
-					},
-					Credential: &echSecretCertificate,
-				},
-				resumeConfig: &Config{
-					MaxVersion: VersionTLS12,
-					Bugs: ProtocolBugs{
-						ExpectServerName: "public.example",
-					},
-					Credential: &echPublicCertificate,
-				},
-				flags: []string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-host-name", "secret.example",
-					// Although the resumption connection does not accept ECH, the
-					// API will report ECH was accepted at the 0-RTT point.
-					"-expect-ech-accept",
-				},
-				resumeSession:           true,
-				expectResumeRejected:    true,
-				earlyData:               true,
-				expectEarlyDataRejected: true,
-				expectations:            connectionExpectations{echAccepted: true},
-				resumeExpectations:      &connectionExpectations{echAccepted: false},
-				// ClientHellos with early data cannot negotiate TLS 1.2, with
-				// or without ECH. The shim should first report
-				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
-				// repair the first error by retrying without early data. That
-				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
-				// and ClientHelloOuter. The caller will then trigger a third
-				// attempt, which will succeed.
-				shouldFail:    true,
-				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
-			})
-		}
-
-		// Test that the client ignores ECHConfigs with invalid public names.
-		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-SkipInvalidPublicName",
-			config: Config{
-				Bugs: ProtocolBugs{
-					// No ECHConfigs are supported, so the client should fall
-					// back to cleartext.
-					ExpectNoClientECH: true,
-					ExpectServerName:  "secret.example",
-				},
-				Credential: &echSecretCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-			},
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
-			config: Config{
-				// The client should skip |invalidPublicName| and use |echConfig|.
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectOuterServerName: "public.example",
-					ExpectServerName:      "secret.example",
-				},
-				Credential: &echSecretCertificate,
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
-				"-host-name", "secret.example",
-				"-expect-ech-accept",
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-
-		// Test both sync and async mode, to test both with and without the
-		// client certificate callback.
-		for _, async := range []bool{false, true} {
-			var flags []string
-			var suffix string
-			if async {
-				flags = []string{"-async"}
-				suffix = "-Async"
-			}
-
-			// Test that ECH and client certificates can be used together.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					ClientAuth:       RequireAnyClientCert,
-				},
-				shimCertificate: &rsaCertificate,
-				flags: append([]string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-expect-ech-accept",
-				}, flags...),
-				expectations: connectionExpectations{echAccepted: true},
-			})
-
-			// Test that, when ECH is rejected, the client does not send a client
-			// certificate.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
-				config: Config{
-					MinVersion: VersionTLS13,
-					MaxVersion: VersionTLS13,
-					ClientAuth: RequireAnyClientCert,
-					Credential: &echPublicCertificate,
-				},
-				shimCertificate: &rsaCertificate,
-				flags: append([]string{
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				}, flags...),
-				shouldFail:         true,
-				expectedLocalError: "tls: client didn't provide a certificate",
-			})
-			if protocol != quic {
-				testCases = append(testCases, testCase{
-					testType: clientTest,
-					protocol: protocol,
-					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
-					config: Config{
-						MinVersion: VersionTLS12,
-						MaxVersion: VersionTLS12,
-						ClientAuth: RequireAnyClientCert,
-						Credential: &echPublicCertificate,
-					},
-					shimCertificate: &rsaCertificate,
-					flags: append([]string{
-						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					}, flags...),
-					shouldFail:         true,
-					expectedLocalError: "tls: client didn't provide a certificate",
-				})
-			}
-		}
-
-		// Test that ECH and Channel ID can be used together. Channel ID does
-		// not exist in DTLS.
-		if protocol != dtls {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-ChannelID",
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					RequestChannelID: true,
-				},
-				flags: []string{
-					"-send-channel-id", channelIDKeyPath,
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					"-expect-ech-accept",
-				},
-				resumeSession: true,
-				expectations: connectionExpectations{
-					channelID:   true,
-					echAccepted: true,
-				},
-			})
-
-			// Handshakes where ECH is rejected do not offer or accept Channel ID.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
-				config: Config{
-					MinVersion: VersionTLS13,
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						AlwaysNegotiateChannelID: true,
-					},
-					Credential: &echPublicCertificate,
-				},
-				flags: []string{
-					"-send-channel-id", channelIDKeyPath,
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				},
-				shouldFail:         true,
-				expectedLocalError: "remote error: unsupported extension",
-				expectedError:      ":UNEXPECTED_EXTENSION:",
-			})
-			if protocol != quic {
-				testCases = append(testCases, testCase{
-					testType: clientTest,
-					protocol: protocol,
-					name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
-					config: Config{
-						MinVersion: VersionTLS12,
-						MaxVersion: VersionTLS12,
-						Bugs: ProtocolBugs{
-							AlwaysNegotiateChannelID: true,
-						},
-						Credential: &echPublicCertificate,
-					},
-					flags: []string{
-						"-send-channel-id", channelIDKeyPath,
-						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					},
-					shouldFail:         true,
-					expectedLocalError: "remote error: unsupported extension",
-					expectedError:      ":UNEXPECTED_EXTENSION:",
-				})
-			}
-		}
-
-		// Test that ECH correctly overrides the host name for certificate
-		// verification.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
-			flags: []string{
-				"-verify-peer",
-				"-use-custom-verify-callback",
-				// When not offering ECH, verify the usual name in both full
-				// and resumption handshakes.
-				"-reverify-on-resume",
-				"-expect-no-ech-name-override",
-			},
-			resumeSession: true,
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
-			flags: []string{
-				"-verify-peer",
-				"-use-custom-verify-callback",
-				"-enable-ech-grease",
-				// When offering ECH GREASE, verify the usual name in both full
-				// and resumption handshakes.
-				"-reverify-on-resume",
-				"-expect-no-ech-name-override",
-			},
-			resumeSession: true,
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{
-					"-verify-peer",
-					"-use-custom-verify-callback",
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					// When ECH is rejected, verify the public name. This can
-					// only happen in full handshakes.
-					"-expect-ech-name-override", "public.example",
-				},
-				shouldFail:         true,
-				expectedError:      ":ECH_REJECTED:",
-				expectedLocalError: "remote error: ECH required",
-			})
-		}
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Credential: &echPublicCertificate,
-			},
-			flags: []string{
-				"-verify-peer",
-				"-use-custom-verify-callback",
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				// When ECH is rejected, verify the public name. This can
-				// only happen in full handshakes.
-				"-expect-ech-name-override", "public.example",
-			},
-			shouldFail:         true,
-			expectedError:      ":ECH_REJECTED:",
-			expectedLocalError: "remote error: ECH required",
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-Accept-NoOverrideName",
-			config: Config{
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-			},
-			flags: []string{
-				"-verify-peer",
-				"-use-custom-verify-callback",
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				// When ECH is accepted, verify the usual name in both full and
-				// resumption handshakes.
-				"-reverify-on-resume",
-				"-expect-no-ech-name-override",
-			},
-			resumeSession: true,
-			expectations:  connectionExpectations{echAccepted: true},
-		})
-		// TODO(crbug.com/381113363): Enable this test for DTLS once we
-		// support early data in DTLS 1.3.
-		if protocol != dtls {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				protocol: protocol,
-				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
-				config: Config{
-					ServerECHConfigs: []ServerECHConfig{echConfig},
-					Credential:       &echPublicCertificate,
-				},
-				resumeConfig: &Config{
-					Credential: &echPublicCertificate,
-				},
-				flags: []string{
-					"-verify-peer",
-					"-use-custom-verify-callback",
-					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-					// Although the resumption connection does not accept ECH, the
-					// API will report ECH was accepted at the 0-RTT point.
-					"-expect-ech-accept",
-					// The resumption connection verifies certificates twice. First,
-					// if reverification is enabled, we verify the 0-RTT certificate
-					// as if ECH as accepted. There should be no name override.
-					// Next, on the post-0-RTT-rejection retry, we verify the new
-					// server certificate. This picks up the ECH reject, so it
-					// should use public.example.
-					"-reverify-on-resume",
-					"-on-resume-expect-no-ech-name-override",
-					"-on-retry-expect-ech-name-override", "public.example",
-				},
-				resumeSession:           true,
-				expectResumeRejected:    true,
-				earlyData:               true,
-				expectEarlyDataRejected: true,
-				expectations:            connectionExpectations{echAccepted: true},
-				resumeExpectations:      &connectionExpectations{echAccepted: false},
-				shouldFail:              true,
-				expectedError:           ":ECH_REJECTED:",
-				expectedLocalError:      "remote error: ECH required",
-			})
-		}
-
-		// Test that the client checks both HelloRetryRequest and ServerHello
-		// for a confirmation signal.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
-			config: Config{
-				MinVersion:       VersionTLS13,
-				MaxVersion:       VersionTLS13,
-				CurvePreferences: []CurveID{CurveP384},
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectMissingKeyShare:          true, // Check we triggered HRR.
-					OmitServerHelloECHConfirmation: true,
-				},
-			},
-			resumeSession: true,
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-hrr", // Check we triggered HRR.
-			},
-			shouldFail:    true,
-			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
-		})
-
-		// Test the message callback is correctly reported, with and without
-		// HelloRetryRequest.
-		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
-		clientAndServerHelloInitial := clientAndServerHello
-		if protocol == tls {
-			clientAndServerHelloInitial += "write ccs\n"
-		}
-		// EncryptedExtensions onwards.
-		finishHandshake := `read hs 8
-read hs 11
-read hs 15
-read hs 20
-write hs 20
-read ack
-read hs 4
-read hs 4
-`
-		if protocol != dtls {
-			finishHandshake = strings.ReplaceAll(finishHandshake, "read ack\n", "")
-		}
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-MessageCallback",
-			config: Config{
-				MinVersion:       VersionTLS13,
-				MaxVersion:       VersionTLS13,
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					NoCloseNotify: true, // Align QUIC and TCP traces.
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				"-expect-msg-callback", clientAndServerHelloInitial + finishHandshake,
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
-			config: Config{
-				MinVersion:       VersionTLS13,
-				MaxVersion:       VersionTLS13,
-				CurvePreferences: []CurveID{CurveP384},
-				ServerECHConfigs: []ServerECHConfig{echConfig},
-				Bugs: ProtocolBugs{
-					ExpectMissingKeyShare: true, // Check we triggered HRR.
-					NoCloseNotify:         true, // Align QUIC and TCP traces.
-				},
-			},
-			flags: []string{
-				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
-				"-expect-ech-accept",
-				"-expect-hrr", // Check we triggered HRR.
-				"-expect-msg-callback", clientAndServerHelloInitial + clientAndServerHello + finishHandshake,
-			},
-			expectations: connectionExpectations{echAccepted: true},
-		})
-	}
-}
-
-func addHintMismatchTests() {
-	// Each of these tests skips split handshakes because split handshakes does
-	// not handle a mismatch between shim and handshaker. Handshake hints,
-	// however, are designed to tolerate the mismatch.
-	//
-	// Note also these tests do not specify -handshake-hints directly. Instead,
-	// we define normal tests, that run even without a handshaker, and rely on
-	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
-	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
-	// (While not useful, the tests will still pass without a handshaker.)
-	for _, protocol := range []protocol{tls, quic} {
-		// If the signing payload is different, the handshake still completes
-		// successfully. Different ALPN preferences will trigger a mismatch.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-SignatureInput",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				NextProtos: []string{"foo", "bar"},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-select-alpn", "foo",
-				"-on-handshaker-select-alpn", "bar",
-			},
-			expectations: connectionExpectations{
-				nextProto:     "foo",
-				nextProtoType: alpn,
-			},
-		})
-
-		// The shim and handshaker may have different curve preferences.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-KeyShare",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				// Send both curves in the key share list, to avoid getting
-				// mixed up with HelloRetryRequest.
-				DefaultCurves: []CurveID{CurveX25519, CurveP256},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
-				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
-			},
-			expectations: connectionExpectations{
-				curveID: CurveX25519,
-			},
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-ECDHE-Group",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion:    VersionTLS12,
-					MaxVersion:    VersionTLS12,
-					DefaultCurves: []CurveID{CurveX25519, CurveP256},
-				},
-				flags: []string{
-					"-allow-hint-mismatch",
-					"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
-					"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
-				},
-				expectations: connectionExpectations{
-					curveID: CurveX25519,
-				},
-			})
-		}
-
-		// If the handshaker does HelloRetryRequest, it will omit most hints.
-		// The shim should still work.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion:    VersionTLS13,
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: []CurveID{CurveX25519},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
-				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
-			},
-			expectations: connectionExpectations{
-				curveID: CurveX25519,
-			},
-		})
-
-		// If the shim does HelloRetryRequest, the hints from the handshaker
-		// will be ignored. This is not reported as a mismatch because hints
-		// would not have helped the shim anyway.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion:    VersionTLS13,
-				MaxVersion:    VersionTLS13,
-				DefaultCurves: []CurveID{CurveX25519},
-			},
-			flags: []string{
-				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
-				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
-			},
-			expectations: connectionExpectations{
-				curveID: CurveP256,
-			},
-		})
-
-		// The shim and handshaker may have different signature algorithm
-		// preferences.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS13",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				VerifySignatureAlgorithms: []signatureAlgorithm{
-					signatureRSAPSSWithSHA256,
-					signatureRSAPSSWithSHA384,
-				},
-			},
-			shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
-			flags:                 []string{"-allow-hint-mismatch"},
-			expectations: connectionExpectations{
-				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
-			},
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS12",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-					VerifySignatureAlgorithms: []signatureAlgorithm{
-						signatureRSAPSSWithSHA256,
-						signatureRSAPSSWithSHA384,
-					},
-				},
-				shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-				handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
-				flags:                 []string{"-allow-hint-mismatch"},
-				expectations: connectionExpectations{
-					peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
-				},
-			})
-		}
-
-		// The shim and handshaker may use different certificates. In TLS 1.3,
-		// the signature input includes the certificate, so we do not need to
-		// explicitly check for a public key match. In TLS 1.2, it does not.
-		ecdsaP256Certificate2 := generateSingleCertChain(nil, &channelIDKey)
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-Certificate-TLS13",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-			},
-			shimCertificate:       &ecdsaP256Certificate,
-			handshakerCertificate: &ecdsaP256Certificate2,
-			flags:                 []string{"-allow-hint-mismatch"},
-			expectations: connectionExpectations{
-				peerCertificate: &ecdsaP256Certificate,
-			},
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-Certificate-TLS12",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				shimCertificate:       &ecdsaP256Certificate,
-				handshakerCertificate: &ecdsaP256Certificate2,
-				flags:                 []string{"-allow-hint-mismatch"},
-				expectations: connectionExpectations{
-					peerCertificate: &ecdsaP256Certificate,
-				},
-			})
-		}
-
-		// The shim and handshaker may disagree on whether resumption is allowed.
-		// We run the first connection with tickets enabled, so the client is
-		// issued a ticket, then disable tickets on the second connection.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-NoTickets1-TLS13",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-			},
-			flags: []string{
-				"-on-resume-allow-hint-mismatch",
-				"-on-shim-on-resume-no-ticket",
-			},
-			resumeSession:        true,
-			expectResumeRejected: true,
-		})
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-NoTickets2-TLS13",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-			},
-			flags: []string{
-				"-on-resume-allow-hint-mismatch",
-				"-on-handshaker-on-resume-no-ticket",
-			},
-			resumeSession: true,
-		})
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-NoTickets1-TLS12",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{
-					"-on-resume-allow-hint-mismatch",
-					"-on-shim-on-resume-no-ticket",
-				},
-				resumeSession:        true,
-				expectResumeRejected: true,
-			})
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-NoTickets2-TLS12",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{
-					"-on-resume-allow-hint-mismatch",
-					"-on-handshaker-on-resume-no-ticket",
-				},
-				resumeSession: true,
-			})
-		}
-
-		// The shim and handshaker may disagree on whether to request a client
-		// certificate.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-CertificateRequest",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				Credential: &rsaCertificate,
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-require-any-client-certificate",
-			},
-		})
-
-		// The shim and handshaker may negotiate different versions altogether.
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-Version1",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS13,
-				},
-				flags: []string{
-					"-allow-hint-mismatch",
-					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
-					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
-				},
-				expectations: connectionExpectations{
-					version: VersionTLS12,
-				},
-			})
-			testCases = append(testCases, testCase{
-				name:               protocol.String() + "-HintMismatch-Version2",
-				testType:           serverTest,
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS13,
-				},
-				flags: []string{
-					"-allow-hint-mismatch",
-					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
-					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
-				},
-				expectations: connectionExpectations{
-					version: VersionTLS13,
-				},
-			})
-		}
-
-		// The shim and handshaker may disagree on the certificate compression
-		// algorithm, whether to enable certificate compression, or certificate
-		// compression inputs.
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: shrinkingCompressionAlgID,
-				},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-install-cert-compression-algs",
-			},
-		})
-		testCases = append(testCases, testCase{
-			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
-			testType:           serverTest,
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectUncompressedCert: true,
-				},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-handshaker-install-cert-compression-algs",
-			},
-		})
-		testCases = append(testCases, testCase{
-			testType:           serverTest,
-			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-					expandingCompressionAlgID: expandingCompression,
-				},
-				Bugs: ProtocolBugs{
-					// The shim's preferences should take effect.
-					ExpectedCompressedCert: shrinkingCompressionAlgID,
-				},
-			},
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
-				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
-			},
-		})
-		testCases = append(testCases, testCase{
-			testType:           serverTest,
-			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
-			protocol:           protocol,
-			skipSplitHandshake: true,
-			config: Config{
-				MinVersion: VersionTLS13,
-				MaxVersion: VersionTLS13,
-				CertCompressionAlgs: map[uint16]CertCompressionAlg{
-					shrinkingCompressionAlgID: shrinkingCompression,
-				},
-				Bugs: ProtocolBugs{
-					ExpectedCompressedCert: shrinkingCompressionAlgID,
-				},
-			},
-			// Configure the shim and handshaker with different OCSP responses,
-			// so the compression inputs do not match.
-			shimCertificate:       rsaCertificate.WithOCSP(testOCSPResponse),
-			handshakerCertificate: rsaCertificate.WithOCSP(testOCSPResponse2),
-			flags: []string{
-				"-allow-hint-mismatch",
-				"-install-cert-compression-algs",
-			},
-			expectations: connectionExpectations{
-				// The shim's configuration should take precendence.
-				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
-			},
-		})
-
-		// The shim and handshaker may disagree on cipher suite, to the point
-		// that one selects RSA key exchange (no applicable hint) and the other
-		// selects ECDHE_RSA (hints are useful).
-		if protocol != quic {
-			testCases = append(testCases, testCase{
-				testType:           serverTest,
-				name:               protocol.String() + "-HintMismatch-CipherMismatch1",
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{
-					"-allow-hint-mismatch",
-					"-on-shim-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-					"-on-handshaker-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
-				},
-				expectations: connectionExpectations{
-					cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-				},
-			})
-			testCases = append(testCases, testCase{
-				testType:           serverTest,
-				name:               protocol.String() + "-HintMismatch-CipherMismatch2",
-				protocol:           protocol,
-				skipSplitHandshake: true,
-				config: Config{
-					MinVersion: VersionTLS12,
-					MaxVersion: VersionTLS12,
-				},
-				flags: []string{
-					// There is no need to pass -allow-hint-mismatch. The
-					// handshaker will unnecessarily generate a signature hints.
-					// This is not reported as a mismatch because hints would
-					// not have helped the shim anyway.
-					"-on-shim-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
-					"-on-handshaker-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-				},
-				expectations: connectionExpectations{
-					cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
-				},
-			})
-		}
-	}
-}
-
-func addCompliancePolicyTests() {
-	for _, protocol := range []protocol{tls, quic} {
-		for _, suite := range testCipherSuites {
-			var isFIPSCipherSuite bool
-			switch suite.id {
-			case TLS_AES_128_GCM_SHA256,
-				TLS_AES_256_GCM_SHA384,
-				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-				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 cert Credential
-			if hasComponent(suite.name, "ECDSA") {
-				cert = ecdsaP384Certificate
-			} else {
-				cert = rsaCertificate
-			}
-
-			maxVersion := uint16(VersionTLS13)
-			if !isTLS13Suite(suite.name) {
-				if protocol == quic {
-					continue
-				}
-				maxVersion = VersionTLS12
-			}
-
-			policies := []struct {
-				flag          string
-				cipherSuiteOk bool
-			}{
-				{"-fips-202205", isFIPSCipherSuite},
-				{"-wpa-202304", isWPACipherSuite},
-			}
-
-			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},
-					},
-					shimCertificate: &cert,
-					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},
-						Credential:   &cert,
-					},
-					flags: []string{
-						policy.flag,
-					},
-					shouldFail: !policy.cipherSuiteOk,
-				})
-			}
-		}
-
-		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
-		// picks it without it being in the client's cipher list.
-		testCases = append(testCases, testCase{
-			testType: clientTest,
-			protocol: protocol,
-			name:     "Compliance-fips202205-" + protocol.String() + "-Client-ReallyWontAcceptChaCha",
-			config: Config{
-				MinVersion: VersionTLS12,
-				MaxVersion: maxVersion,
-				Bugs: ProtocolBugs{
-					SendCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
-				},
-			},
-			flags: []string{
-				"-fips-202205",
-			},
-			shouldFail:    true,
-			expectedError: ":WRONG_CIPHER_RETURNED:",
-		})
-
-		for _, curve := range testCurves {
-			var isFIPSCurve bool
-			switch curve.id {
-			case CurveP256, CurveP384:
-				isFIPSCurve = true
-			}
-
-			var isWPACurve bool
-			switch curve.id {
-			case CurveP384:
-				isWPACurve = true
-			}
-
-			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 {
-			// The TLS 1.0 and TLS 1.1 default signature algorithm does not
-			// apply to these tests.
-			if sigalg.id == 0 {
-				continue
-			}
-
-			var isFIPSSigAlg bool
-			switch sigalg.id {
-			case signatureRSAPKCS1WithSHA256,
-				signatureRSAPKCS1WithSHA384,
-				signatureRSAPKCS1WithSHA512,
-				signatureECDSAWithP256AndSHA256,
-				signatureECDSAWithP384AndSHA384,
-				signatureRSAPSSWithSHA256,
-				signatureRSAPSSWithSHA384,
-				signatureRSAPSSWithSHA512:
-				isFIPSSigAlg = true
-			}
-
-			var isWPASigAlg bool
-			switch sigalg.id {
-			case signatureRSAPKCS1WithSHA384,
-				signatureRSAPKCS1WithSHA512,
-				signatureECDSAWithP384AndSHA384,
-				signatureRSAPSSWithSHA384,
-				signatureRSAPSSWithSHA512:
-				isWPASigAlg = true
-			}
-
-			if sigalg.curve == CurveP224 {
-				// This can work in TLS 1.2, but not with TLS 1.3.
-				// For consistency it's not permitted in FIPS mode.
-				isFIPSSigAlg = false
-			}
-
-			maxVersion := uint16(VersionTLS13)
-			if hasComponent(sigalg.name, "PKCS1") {
-				if protocol == quic {
-					continue
-				}
-				maxVersion = VersionTLS12
-			}
-
-			policies := []struct {
-				flag     string
-				sigAlgOk bool
-			}{
-				{"-fips-202205", isFIPSSigAlg},
-				{"-wpa-202304", isWPASigAlg},
-			}
-
-			cert := sigalg.baseCert.WithSignatureAlgorithms(sigalg.id)
-			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},
-					},
-					// Use the base certificate. We wish to pick up the signature algorithm
-					// preferences from the FIPS policy.
-					shimCertificate: sigalg.baseCert,
-					flags:           []string{policy.flag},
-					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,
-						Credential: cert,
-					},
-					flags: []string{
-						policy.flag,
-					},
-					shouldFail: !policy.sigAlgOk,
-				})
-			}
-		}
-
-		// AES-256-GCM is the most preferred.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     "Compliance-cnsa202407-" + protocol.String() + "-AES-256-preferred",
-			config: Config{
-				MinVersion:   VersionTLS13,
-				MaxVersion:   VersionTLS13,
-				CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384},
-			},
-			flags: []string{
-				"-cnsa-202407",
-			},
-			expectations: connectionExpectations{cipher: TLS_AES_256_GCM_SHA384},
-		})
-
-		// AES-128-GCM is preferred over ChaCha20-Poly1305.
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			protocol: protocol,
-			name:     "Compliance-cnsa202407-" + protocol.String() + "-AES-128-preferred",
-			config: Config{
-				MinVersion:   VersionTLS13,
-				MaxVersion:   VersionTLS13,
-				CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
-			},
-			flags: []string{
-				"-cnsa-202407",
-			},
-			expectations: connectionExpectations{cipher: TLS_AES_128_GCM_SHA256},
-		})
-	}
-}
-
-func addCertificateSelectionTests() {
-	// Combinatorially test each selection criteria at different versions,
-	// protocols, and with the matching certificate before and after the
-	// mismatching one.
-	type certSelectTest struct {
-		name          string
-		testType      testType
-		minVersion    uint16
-		maxVersion    uint16
-		config        Config
-		match         *Credential
-		mismatch      *Credential
-		flags         []string
-		expectedError string
-	}
-	certSelectTests := []certSelectTest{
-		// TLS 1.0 through TLS 1.2 servers should incorporate TLS cipher suites
-		// into certificate selection.
-		{
-			name:       "Server-CipherSuite-ECDHE_ECDSA",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			name:       "Server-CipherSuite-ECDHE_RSA",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &rsaCertificate,
-			mismatch:      &ecdsaP256Certificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			name:       "Server-CipherSuite-RSA",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &rsaCertificate,
-			mismatch:      &ecdsaP256Certificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-
-		// Ed25519 counts as ECDSA for purposes of cipher suite matching.
-		{
-			name:       "Server-CipherSuite-ECDHE_ECDSA-Ed25519",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &ed25519Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			name:       "Server-CipherSuite-ECDHE_RSA-Ed25519",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &rsaCertificate,
-			mismatch:      &ed25519Certificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-
-		// If there is no ECDHE curve match, ECDHE cipher suites are
-		// disqualified in TLS 1.2 and below. This, in turn, impacts the
-		// available cipher suites for each credential.
-		{
-			name:       "Server-CipherSuite-NoECDHE",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CurvePreferences: []CurveID{CurveP256},
-			},
-			flags:         []string{"-curves", strconv.Itoa(int(CurveX25519))},
-			match:         &rsaCertificate,
-			mismatch:      &ecdsaP256Certificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-
-		// If the client offered a cipher that would allow a certificate, but it
-		// wasn't one of the ones we configured, the certificate should be
-		// skipped in favor of another one.
-		{
-			name:       "Server-CipherSuite-Prefs",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			flags:         []string{"-cipher", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
-			match:         &rsaCertificate,
-			mismatch:      &ecdsaP256Certificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-
-		// TLS 1.0 through 1.2 servers should incorporate the curve list into
-		// ECDSA certificate selection.
-		{
-			name:       "Server-Curve",
-			testType:   serverTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				CurvePreferences: []CurveID{CurveP256},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &ecdsaP384Certificate,
-			expectedError: ":WRONG_CURVE:",
-		},
-
-		// TLS 1.3 servers ignore the curve list. ECDSA certificate selection is
-		// solely determined by the signature algorithm list.
-		{
-			name:       "Server-IgnoreCurve",
-			testType:   serverTest,
-			minVersion: VersionTLS13,
-			config: Config{
-				CurvePreferences: []CurveID{CurveP256},
-			},
-			match: &ecdsaP384Certificate,
-		},
-
-		// TLS 1.2 servers also ignore the curve list for Ed25519. The signature
-		// algorithm list is sufficient for Ed25519.
-		{
-			name:       "Server-IgnoreCurveEd25519",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			config: Config{
-				CurvePreferences: []CurveID{CurveP256},
-			},
-			match: &ed25519Certificate,
-		},
-
-		// Without signature algorithm negotiation, Ed25519 is not usable in TLS
-		// 1.1 and below.
-		{
-			name:       "Server-NoEd25519",
-			testType:   serverTest,
-			maxVersion: VersionTLS11,
-			match:      &rsaCertificate,
-			mismatch:   &ed25519Certificate,
-		},
-
-		// TLS 1.2 and up should incorporate the signature algorithm list into
-		// certificate selection.
-		{
-			name:       "Server-SignatureAlgorithm",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-				CipherSuites: []uint16{
-					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			name:       "Server-SignatureAlgorithm",
-			testType:   serverTest,
-			minVersion: VersionTLS13,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-
-		// TLS 1.2's use of the signature algorithm list only disables the
-		// signing-based algorithms. If an RSA key exchange cipher suite is
-		// eligible, that is fine. (This is not a realistic configuration,
-		// however. No one would configure RSA before ECDSA.)
-		{
-			name:       "Server-SignatureAlgorithmImpactsECDHEOnly",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-				CipherSuites: []uint16{
-					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-					TLS_RSA_WITH_AES_128_CBC_SHA,
-				},
-			},
-			match: &rsaCertificate,
-		},
-
-		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
-		// embedded in the signature algorithm.
-		{
-			name:       "Server-SignatureAlgorithmECDSACurve",
-			testType:   serverTest,
-			minVersion: VersionTLS13,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &ecdsaP384Certificate,
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-
-		// TLS 1.2's use does not.
-		{
-			name:       "Server-SignatureAlgorithmECDSACurve",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match: &ecdsaP384Certificate,
-		},
-
-		// TLS 1.0 and 1.1 do not look at the signature algorithm.
-		{
-			name:       "Server-IgnoreSignatureAlgorithm",
-			testType:   serverTest,
-			maxVersion: VersionTLS11,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match: &rsaCertificate,
-		},
-
-		// Signature algorithm matches take preferences on the keys into
-		// consideration.
-		{
-			name:       "Server-SignatureAlgorithmKeyPrefs",
-			testType:   serverTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
-				CipherSuites:              []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			},
-			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			name:       "Server-SignatureAlgorithmKeyPrefs",
-			testType:   serverTest,
-			minVersion: VersionTLS13,
-			config: Config{
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
-			},
-			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-
-		// TLS 1.2 clients and below check the certificate against the old
-		// client certificate types field.
-		{
-			name:       "Client-ClientCertificateTypes-RSA",
-			testType:   clientTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:             RequestClientCert,
-				ClientCertificateTypes: []uint8{CertTypeRSASign},
-			},
-			match:         &rsaCertificate,
-			mismatch:      &ecdsaP256Certificate,
-			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
-		},
-		{
-			name:       "Client-ClientCertificateTypes-ECDSA",
-			testType:   clientTest,
-			maxVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:             RequestClientCert,
-				ClientCertificateTypes: []uint8{CertTypeECDSASign},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
-		},
-
-		// Ed25519 is considered ECDSA for purposes of client certificate types.
-		{
-			name:       "Client-ClientCertificateTypes-RSA-Ed25519",
-			testType:   clientTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:             RequestClientCert,
-				ClientCertificateTypes: []uint8{CertTypeRSASign},
-			},
-			match:         &rsaCertificate,
-			mismatch:      &ed25519Certificate,
-			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
-		},
-		{
-			name:       "Client-ClientCertificateTypes-ECDSA-Ed25519",
-			testType:   clientTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:             RequestClientCert,
-				ClientCertificateTypes: []uint8{CertTypeECDSASign},
-			},
-			match:         &ed25519Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
-		},
-
-		// TLS 1.2 and up should incorporate the signature algorithm list into
-		// certificate selection. (There is no signature algorithm list to look
-		// at in TLS 1.0 and 1.1.)
-		{
-			name:       "Client-SignatureAlgorithm",
-			testType:   clientTest,
-			minVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:                RequestClientCert,
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &rsaCertificate,
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-
-		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
-		// embedded in the signature algorithm.
-		{
-			name:       "Client-SignatureAlgorithmECDSACurve",
-			testType:   clientTest,
-			minVersion: VersionTLS13,
-			config: Config{
-				ClientAuth:                RequestClientCert,
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match:         &ecdsaP256Certificate,
-			mismatch:      &ecdsaP384Certificate,
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-
-		// TLS 1.2's use does not. It is not possible to determine what ECDSA
-		// curves are allowed by the server.
-		{
-			name:       "Client-SignatureAlgorithmECDSACurve",
-			testType:   clientTest,
-			minVersion: VersionTLS12,
-			maxVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:                RequestClientCert,
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
-			},
-			match: &ecdsaP384Certificate,
-		},
-
-		// Signature algorithm matches take preferences on the keys into
-		// consideration.
-		{
-			name:       "Client-SignatureAlgorithmKeyPrefs",
-			testType:   clientTest,
-			minVersion: VersionTLS12,
-			config: Config{
-				ClientAuth:                RequestClientCert,
-				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
-			},
-			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
-			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
-			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
-		},
-	}
-
-	for _, protocol := range []protocol{tls, dtls} {
-		for _, vers := range allVersions(protocol) {
-			suffix := fmt.Sprintf("%s-%s", protocol, vers)
-
-			// Test that the credential list is interpreted in preference order,
-			// with the default credential, if any, at the end.
-			testCases = append(testCases, testCase{
-				name:     fmt.Sprintf("CertificateSelection-Client-PreferenceOrder-%s", suffix),
-				testType: clientTest,
-				protocol: protocol,
-				config: Config{
-					MinVersion: vers.version,
-					MaxVersion: vers.version,
-					ClientAuth: RequestClientCert,
-				},
-				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
-				shimCertificate: &rsaCertificate,
-				flags:           []string{"-expect-selected-credential", "0"},
-				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
-			})
-			testCases = append(testCases, testCase{
-				name:     fmt.Sprintf("CertificateSelection-Server-PreferenceOrder-%s", suffix),
-				testType: serverTest,
-				protocol: protocol,
-				config: Config{
-					MinVersion: vers.version,
-					MaxVersion: vers.version,
-				},
-				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
-				shimCertificate: &rsaCertificate,
-				flags:           []string{"-expect-selected-credential", "0"},
-				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
-			})
-
-			// Test that the selected credential contributes the certificate chain, OCSP response,
-			// and SCT list.
-			testCases = append(testCases, testCase{
-				name:     fmt.Sprintf("CertificateSelection-Server-OCSP-SCT-%s", suffix),
-				testType: serverTest,
-				protocol: protocol,
-				config: Config{
-					MinVersion: vers.version,
-					MaxVersion: vers.version,
-					// Configure enough options so that, at all TLS versions, only an RSA
-					// certificate will be accepted.
-					CipherSuites: []uint16{
-						TLS_AES_128_GCM_SHA256,
-						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-					},
-					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
-				},
-				shimCredentials: []*Credential{
-					ecdsaP256Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
-					rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-				},
-				shimCertificate: ecdsaP384Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
-				flags:           []string{"-expect-selected-credential", "1"},
-				expectations: connectionExpectations{
-					peerCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
-				},
-			})
-
-			// Test that the credentials API works asynchronously. This tests both deferring the
-			// configuration to the certificate callback, and using a custom, async private key.
-			testCases = append(testCases, testCase{
-				name:     fmt.Sprintf("CertificateSelection-Client-Async-%s", suffix),
-				testType: clientTest,
-				protocol: protocol,
-				config: Config{
-					MinVersion: vers.version,
-					MaxVersion: vers.version,
-					ClientAuth: RequestClientCert,
-				},
-				shimCredentials: []*Credential{&ecdsaP256Certificate},
-				shimCertificate: &rsaCertificate,
-				flags:           []string{"-async", "-expect-selected-credential", "0"},
-				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
-			})
-			testCases = append(testCases, testCase{
-				name:     fmt.Sprintf("CertificateSelection-Server-Async-%s", suffix),
-				testType: serverTest,
-				protocol: protocol,
-				config: Config{
-					MinVersion: vers.version,
-					MaxVersion: vers.version,
-				},
-				shimCredentials: []*Credential{&ecdsaP256Certificate},
-				shimCertificate: &rsaCertificate,
-				flags:           []string{"-async", "-expect-selected-credential", "0"},
-				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
-			})
-
-			for _, test := range certSelectTests {
-				if test.minVersion != 0 && vers.version < test.minVersion {
-					continue
-				}
-				if test.maxVersion != 0 && vers.version > test.maxVersion {
-					continue
-				}
-
-				config := test.config
-				config.MinVersion = vers.version
-				config.MaxVersion = vers.version
-
-				// If the mismatch field is omitted, this is a positive test,
-				// just to confirm that the selection logic does not block a
-				// particular certificate.
-				if test.mismatch == nil {
-					testCases = append(testCases, testCase{
-						name:            fmt.Sprintf("CertificateSelection-%s-%s", test.name, suffix),
-						protocol:        protocol,
-						testType:        test.testType,
-						config:          config,
-						shimCredentials: []*Credential{test.match},
-						flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
-						expectations:    connectionExpectations{peerCertificate: test.match},
-					})
-					continue
-				}
-
-				testCases = append(testCases, testCase{
-					name:            fmt.Sprintf("CertificateSelection-%s-MatchFirst-%s", test.name, suffix),
-					protocol:        protocol,
-					testType:        test.testType,
-					config:          config,
-					shimCredentials: []*Credential{test.match, test.mismatch},
-					flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
-					expectations:    connectionExpectations{peerCertificate: test.match},
-				})
-				testCases = append(testCases, testCase{
-					name:            fmt.Sprintf("CertificateSelection-%s-MatchSecond-%s", test.name, suffix),
-					protocol:        protocol,
-					testType:        test.testType,
-					config:          config,
-					shimCredentials: []*Credential{test.mismatch, test.match},
-					flags:           append([]string{"-expect-selected-credential", "1"}, test.flags...),
-					expectations:    connectionExpectations{peerCertificate: test.match},
-				})
-				testCases = append(testCases, testCase{
-					name:            fmt.Sprintf("CertificateSelection-%s-MatchDefault-%s", test.name, suffix),
-					protocol:        protocol,
-					testType:        test.testType,
-					config:          config,
-					shimCredentials: []*Credential{test.mismatch},
-					shimCertificate: test.match,
-					flags:           append([]string{"-expect-selected-credential", "-1"}, test.flags...),
-					expectations:    connectionExpectations{peerCertificate: test.match},
-				})
-				testCases = append(testCases, testCase{
-					name:               fmt.Sprintf("CertificateSelection-%s-MatchNone-%s", test.name, suffix),
-					protocol:           protocol,
-					testType:           test.testType,
-					config:             config,
-					shimCredentials:    []*Credential{test.mismatch, test.mismatch, test.mismatch},
-					flags:              test.flags,
-					shouldFail:         true,
-					expectedLocalError: "remote error: handshake failure",
-					expectedError:      test.expectedError,
-				})
-			}
-		}
-	}
-}
-
-func addKeyUpdateTests() {
-	// TLS tests.
-	testCases = append(testCases, testCase{
-		name: "KeyUpdate-ToClient",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		sendKeyUpdates:   10,
-		keyUpdateRequest: keyUpdateNotRequested,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "KeyUpdate-ToServer",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		sendKeyUpdates:   10,
-		keyUpdateRequest: keyUpdateNotRequested,
-	})
-	testCases = append(testCases, testCase{
-		name: "KeyUpdate-FromClient",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		expectUnsolicitedKeyUpdate: true,
-		flags:                      []string{"-key-update"},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "KeyUpdate-FromServer",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		expectUnsolicitedKeyUpdate: true,
-		flags:                      []string{"-key-update"},
-	})
-	testCases = append(testCases, testCase{
-		name: "KeyUpdate-InvalidRequestMode",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		sendKeyUpdates:   1,
-		keyUpdateRequest: 42,
-		shouldFail:       true,
-		expectedError:    ":DECODE_ERROR:",
-	})
-	testCases = append(testCases, testCase{
-		// Test that shim responds to KeyUpdate requests.
-		name: "KeyUpdate-Requested",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				RejectUnsolicitedKeyUpdate: true,
-			},
-		},
-		// Test the shim receiving many KeyUpdates in a row.
-		sendKeyUpdates:   5,
-		messageCount:     5,
-		keyUpdateRequest: keyUpdateRequested,
-	})
-	testCases = append(testCases, testCase{
-		// Test that shim responds to KeyUpdate requests if peer's KeyUpdate is
-		// discovered while a write is pending.
-		name: "KeyUpdate-Requested-UnfinishedWrite",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				RejectUnsolicitedKeyUpdate: true,
-			},
-		},
-		// Test the shim receiving many KeyUpdates in a row.
-		sendKeyUpdates:          5,
-		messageCount:            5,
-		keyUpdateRequest:        keyUpdateRequested,
-		readWithUnfinishedWrite: true,
-		flags:                   []string{"-async"},
-	})
-
-	// DTLS tests.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ToClient-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		// Send many KeyUpdates to make sure record reassembly can handle it.
-		sendKeyUpdates:   10,
-		keyUpdateRequest: keyUpdateNotRequested,
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "KeyUpdate-ToServer-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		sendKeyUpdates:   10,
-		keyUpdateRequest: keyUpdateNotRequested,
-	})
-
-	// Test that the shim accounts for packet loss when processing KeyUpdate.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ToClient-PacketLoss-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					if next[0].Type != typeKeyUpdate {
-						c.WriteFlight(next)
-						return
-					}
-
-					// Send the KeyUpdate. The shim should ACK it.
-					c.WriteFlight(next)
-					ackTimeout := timeouts[0] / 4
-					c.AdvanceClock(ackTimeout)
-					c.ReadACK(c.InEpoch())
-
-					// The shim should continue reading data at the old epoch.
-					// The ACK may not have come through.
-					msg := []byte("test")
-					c.WriteAppData(c.OutEpoch()-1, msg)
-					c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-					// Re-send KeyUpdate. The shim should ACK it again. The ACK
-					// may not have come through.
-					c.WriteFlight(next)
-					c.AdvanceClock(ackTimeout)
-					c.ReadACK(c.InEpoch())
-
-					// The shim should be able to read data at the new epoch.
-					c.WriteAppData(c.OutEpoch(), msg)
-					c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-					// The shim continues to accept application data at the old
-					// epoch, for a period of time.
-					c.WriteAppData(c.OutEpoch()-1, msg)
-					c.ReadAppData(c.InEpoch(), expectedReply(msg))
-
-					// It will even ACK the retransmission, though it knows the
-					// shim has seen the ACK.
-					c.WriteFlight(next)
-					c.AdvanceClock(ackTimeout)
-					c.ReadACK(c.InEpoch())
-
-					// After some time has passed, the shim will discard the old
-					// epoch. The following writes should be ignored.
-					c.AdvanceClock(dtlsPrevEpochExpiration)
-					f := next[0].Fragment(0, len(next[0].Data))
-					f.ShouldDiscard = true
-					c.WriteFragments([]DTLSFragment{f})
-					c.WriteAppData(c.OutEpoch()-1, msg)
-				},
-			},
-		},
-		sendKeyUpdates:   10,
-		keyUpdateRequest: keyUpdateNotRequested,
-		flags:            []string{"-async"},
-	})
-
-	// In DTLS, we KeyUpdate before read, rather than write, because the
-	// KeyUpdate will not be applied before the shim reads the ACK.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-FromClient-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		// Perform several message exchanges to update keys several times.
-		messageCount: 10,
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "KeyUpdate-FromServer-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		// Perform several message exchanges to update keys several times.
-		messageCount: 10,
-		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
-		flags: []string{"-no-ticket"},
-	})
-
-	// If the shim has a pending unACKed flight, it defers sending KeyUpdate.
-	// BoringSSL does not support multiple outgoing flights at once.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-DeferredSend-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			// Request a client certificate, so the shim has more to send.
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				MaxPacketLength: 512,
-				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-					if received[len(received)-1].Type != typeFinished {
-						c.WriteACK(c.OutEpoch(), records)
-						return
-					}
-
-					// This test relies on the Finished flight being multiple
-					// records.
-					if len(records) <= 1 {
-						panic("shim sent Finished flight in one record")
-					}
-
-					// Before ACKing Finished, do some rounds of exchanging
-					// application data. Although the shim has already scheduled
-					// KeyUpdate, it should not send the KeyUpdate until it gets
-					// an ACK. (If it sent KeyUpdate, ReadAppData would report
-					// an unexpected record.)
-					msg := []byte("test")
-					for i := 0; i < 10; i++ {
-						c.WriteAppData(c.OutEpoch(), msg)
-						c.ReadAppData(c.InEpoch(), expectedReply(msg))
-					}
-
-					// ACK some of the Finished flight, but not all of it.
-					c.WriteACK(c.OutEpoch(), records[:1])
-
-					// The shim continues to defer KeyUpdate.
-					for i := 0; i < 10; i++ {
-						c.WriteAppData(c.OutEpoch(), msg)
-						c.ReadAppData(c.InEpoch(), expectedReply(msg))
-					}
-
-					// ACK the remainder.
-					c.WriteACK(c.OutEpoch(), records[1:])
-
-					// The shim should now send KeyUpdate. Return to the test
-					// harness, which will look for it.
-				},
-			},
-		},
-		shimCertificate:              &rsaChainCertificate,
-		shimSendsKeyUpdateBeforeRead: true,
-		flags:                        []string{"-mtu", "512"},
-	})
-
-	// The shim should not switch keys until it receives an ACK.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-WaitForACK-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				MaxPacketLength: 512,
-				ACKFlightDTLS: func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-					if received[0].Type != typeKeyUpdate {
-						c.WriteACK(c.OutEpoch(), records)
-						return
-					}
-
-					// Make the shim send application data. We have not yet
-					// ACKed KeyUpdate, so the shim should send at the previous
-					// epoch. Through each of these rounds, the shim will also
-					// try to KeyUpdate again. These calls will be suppressed
-					// because there is still an outstanding KeyUpdate.
-					msg := []byte("test")
-					for i := 0; i < 10; i++ {
-						c.WriteAppData(c.OutEpoch(), msg)
-						c.ReadAppData(c.InEpoch()-1, expectedReply(msg))
-					}
-
-					// ACK the KeyUpdate. Ideally we'd test a partial ACK, but
-					// BoringSSL's minimum MTU is such that KeyUpdate always
-					// fits in one record.
-					c.WriteACK(c.OutEpoch(), records)
-
-					// The shim should now send at the new epoch. Return to the
-					// test harness, which will enforce this.
-				},
-			},
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-	})
-
-	// Test that shim responds to KeyUpdate requests.
-	fixKeyUpdateReply := func(c *DTLSController, prev, received []DTLSMessage, records []DTLSRecordNumberInfo) {
-		c.WriteACK(c.OutEpoch(), records)
-		if received[0].Type != typeKeyUpdate {
-			return
-		}
-		// This works around an awkward testing mismatch. The test
-		// harness expects the shim to immediately change keys, but
-		// the shim writes app data before seeing the ACK. The app
-		// data will be sent at the previous epoch. Consume this and
-		// prime the shim to resend its reply at the new epoch.
-		msg := makeTestMessage(int(received[0].Sequence)-2, 32)
-		c.ReadAppData(c.InEpoch()-1, expectedReply(msg))
-		c.WriteAppData(c.OutEpoch(), msg)
-	}
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-Requested-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				RejectUnsolicitedKeyUpdate: true,
-				ACKFlightDTLS:              fixKeyUpdateReply,
-			},
-		},
-		// Test the shim receiving many KeyUpdates in a row. They will be
-		// combined into one reply KeyUpdate.
-		sendKeyUpdates:   5,
-		messageLen:       32,
-		messageCount:     5,
-		keyUpdateRequest: keyUpdateRequested,
-	})
-
-	mergeNewSessionTicketAndKeyUpdate := func(f WriteFlightFunc) WriteFlightFunc {
-		return func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-			// Send NewSessionTicket and the first KeyUpdate all together.
-			if next[0].Type == typeKeyUpdate {
-				panic("key update should have been merged into NewSessionTicket")
-			}
-			if next[0].Type != typeNewSessionTicket {
-				c.WriteFlight(next)
-				return
-			}
-			if next[0].Type == typeNewSessionTicket && next[len(next)-1].Type != typeKeyUpdate {
-				c.MergeIntoNextFlight()
-				return
-			}
-
-			f(c, prev, received, next, records)
-		}
-	}
-
-	// Test that the shim does not process KeyUpdate until it has processed all
-	// preceding messages.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ProcessInOrder-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					// Write the KeyUpdate. The shim should buffer and ACK it.
-					keyUpdate := next[len(next)-1]
-					c.WriteFlight([]DTLSMessage{keyUpdate})
-					ackTimeout := timeouts[0] / 4
-					c.AdvanceClock(ackTimeout)
-					c.ReadACK(c.InEpoch())
-
-					// The shim should not process KeyUpdate yet. It should not
-					// read from the new epoch.
-					msg1, msg2 := []byte("aaaa"), []byte("bbbb")
-					c.WriteAppData(c.OutEpoch(), msg1)
-					c.AdvanceClock(0) // Check there are no messages.
-
-					// It can read from the old epoch, however.
-					c.WriteAppData(c.OutEpoch()-1, msg2)
-					c.ReadAppData(c.InEpoch(), expectedReply(msg2))
-
-					// Write the rest of the flight.
-					c.WriteFlight(next[:len(next)-1])
-					c.AdvanceClock(ackTimeout)
-					c.ReadACK(c.InEpoch())
-
-					// Now the new epoch is functional.
-					c.WriteAppData(c.OutEpoch(), msg1)
-					c.ReadAppData(c.InEpoch(), expectedReply(msg1))
-				}),
-			},
-		},
-		sendKeyUpdates:   1,
-		keyUpdateRequest: keyUpdateNotRequested,
-		flags:            []string{"-async"},
-	})
-
-	// Messages after a KeyUpdate are not allowed.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ExtraMessage-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					extra := next[0]
-					extra.Sequence = next[len(next)-1].Sequence + 1
-					next = append(slices.Clip(next), extra)
-					c.WriteFlight(next)
-				}),
-			},
-		},
-		sendKeyUpdates:     1,
-		keyUpdateRequest:   keyUpdateNotRequested,
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ExtraMessageBuffered-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				WriteFlightDTLS: mergeNewSessionTicketAndKeyUpdate(func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					// Send the extra message first. The shim should accept and
-					// buffer it.
-					extra := next[0]
-					extra.Sequence = next[len(next)-1].Sequence + 1
-					c.WriteFlight([]DTLSMessage{extra})
-
-					// Now send the flight, including a KeyUpdate. The shim
-					// should now notice the extra message and reject.
-					c.WriteFlight(next)
-				}),
-			},
-		},
-		sendKeyUpdates:     1,
-		keyUpdateRequest:   keyUpdateNotRequested,
-		shouldFail:         true,
-		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// Test KeyUpdate overflow conditions. Both the epoch number and the message
-	// number may overflow, in either the read or write direction.
-
-	// When the sender is the client, the first KeyUpdate is message 2 at epoch
-	// 3, so the epoch number overflows first.
-	const maxClientKeyUpdates = 0xffff - 3
-
-	// Test that the shim, as a server, rejects KeyUpdates at epoch 0xffff. RFC
-	// 9147 does not prescribe this limit, but we enforce it. See
-	// https://mailarchive.ietf.org/arch/msg/tls/6y8wTv8Q_IPM-PCcbCAmDOYg6bM/
-	// and https://www.rfc-editor.org/errata/eid8050
-	writeFlightKeyUpdate := func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-		if next[0].Type == typeKeyUpdate {
-			// Exchange some data to avoid tripping KeyUpdate DoS limits.
-			msg := []byte("test")
-			c.WriteAppData(c.OutEpoch()-1, msg)
-			c.ReadAppData(c.InEpoch(), expectedReply(msg))
-		}
-		c.WriteFlight(next)
-	}
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "KeyUpdate-MaxReadEpoch-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AllowEpochOverflow: true,
-				WriteFlightDTLS:    writeFlightKeyUpdate,
-			},
-		},
-		// Avoid the NewSessionTicket messages interfering with the callback.
-		flags:            []string{"-no-ticket"},
-		sendKeyUpdates:   maxClientKeyUpdates,
-		keyUpdateRequest: keyUpdateNotRequested,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		protocol: dtls,
-		name:     "KeyUpdate-ReadEpochOverflow-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				AllowEpochOverflow: true,
-				WriteFlightDTLS:    writeFlightKeyUpdate,
-			},
-		},
-		// Avoid the NewSessionTicket messages interfering with the callback.
-		flags:              []string{"-no-ticket"},
-		sendKeyUpdates:     maxClientKeyUpdates + 1,
-		keyUpdateRequest:   keyUpdateNotRequested,
-		shouldFail:         true,
-		expectedError:      ":TOO_MANY_KEY_UPDATES:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-
-	// Test that the shim, as a client, notices its epoch overflow condition
-	// when asked to send too many KeyUpdates. The shim sends KeyUpdate before
-	// every read, including reading connection close, so the number of
-	// KeyUpdates is one more than the message count.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-MaxWriteEpoch-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		messageCount:                 maxClientKeyUpdates - 1,
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-WriteEpochOverflow-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// The shim does not notice the overflow until immediately after
-				// sending KeyUpdate, so tolerate the overflow on the runner.
-				AllowEpochOverflow: true,
-			},
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		messageCount:                 maxClientKeyUpdates,
-		shouldFail:                   true,
-		expectedError:                ":TOO_MANY_KEY_UPDATES:",
-	})
-
-	// When the sender is a server that doesn't send tickets, the first
-	// KeyUpdate is message 5 (SH, EE, C, CV, Fin) at epoch 3, so the message
-	// number overflows first.
-	const maxServerKeyUpdates = 0xffff - 5
-
-	// Test that the shim, as a client, does not allow the value to wraparound.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "KeyUpdate-ReadMessageOverflow-DTLS",
-		config: Config{
-			MaxVersion:             VersionTLS13,
-			SessionTicketsDisabled: true,
-			Bugs: ProtocolBugs{
-				AllowEpochOverflow: true,
-				WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) {
-					writeFlightKeyUpdate(c, prev, received, next, records)
-					if next[0].Type == typeKeyUpdate && next[0].Sequence == 0xffff {
-						// At this point, the shim has accepted message 0xffff.
-						// Check the shim does not now accept message 0 as the
-						// current message. Test this by sending a garbage
-						// message 0. A shim that overflows and processes the
-						// message will notice the syntax error. A shim that
-						// correctly interprets this as an old message will drop
-						// the record and simply ACK it.
-						//
-						// We do this rather than send a valid KeyUpdate because
-						// the shim will keep the old epoch active and drop
-						// decryption failures. Looking for the lack of an error
-						// is more straightforward.
-						c.WriteFlight([]DTLSMessage{{Epoch: c.OutEpoch(), Sequence: 0, Type: typeKeyUpdate, Data: []byte("INVALID")}})
-						c.ExpectNextTimeout(timeouts[0] / 4)
-						c.AdvanceClock(timeouts[0] / 4)
-						c.ReadACK(c.InEpoch())
-					}
-				},
-			},
-		},
-		sendKeyUpdates:   maxServerKeyUpdates + 1,
-		keyUpdateRequest: keyUpdateNotRequested,
-		flags:            []string{"-async", "-expect-no-session"},
-	})
-
-	// Test that the shim, as a server, notices its message overflow condition,
-	// when asked to send too many KeyUpdates.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "KeyUpdate-MaxWriteMessage-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		messageCount:                 maxServerKeyUpdates,
-		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
-		flags: []string{"-no-ticket"},
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "KeyUpdate-WriteMessageOverflow-DTLS",
-		config: Config{
-			MaxVersion: VersionTLS13,
-		},
-		shimSendsKeyUpdateBeforeRead: true,
-		messageCount:                 maxServerKeyUpdates + 1,
-		shouldFail:                   true,
-		expectedError:                ":overflow:",
-		// Avoid NewSessionTicket messages getting in the way of ReadKeyUpdate.
-		flags: []string{"-no-ticket"},
-	})
-}
-
-func addPAKETests() {
-	spakeCredential := Credential{
-		Type:         CredentialTypeSPAKE2PlusV1,
-		PAKEContext:  []byte("context"),
-		PAKEClientID: []byte("client"),
-		PAKEServerID: []byte("server"),
-		PAKEPassword: []byte("password"),
-	}
-
-	spakeWrongClientID := spakeCredential
-	spakeWrongClientID.PAKEClientID = []byte("wrong")
-
-	spakeWrongServerID := spakeCredential
-	spakeWrongServerID.PAKEServerID = []byte("wrong")
-
-	spakeWrongPassword := spakeCredential
-	spakeWrongPassword.PAKEPassword = []byte("wrong")
-
-	spakeWrongRole := spakeCredential
-	spakeWrongRole.WrongPAKERole = true
-
-	spakeWrongCodepoint := spakeCredential
-	spakeWrongCodepoint.OverridePAKECodepoint = 1234
-
-	testCases = append(testCases, testCase{
-		name:     "PAKE-No-Server-Support",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-		},
-		shouldFail:    true,
-		expectedError: ":MISSING_KEY_SHARE:",
-	})
-	testCases = append(testCases, testCase{
-		name:     "PAKE-Server",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				// We do not currently support resumption with PAKE, so PAKE
-				// servers should not issue session tickets.
-				ExpectNoNewSessionTicket: true,
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-	})
-	testCases = append(testCases, testCase{
-		// Send a ClientHello with the wrong PAKE client ID.
-		name:     "PAKE-Server-WrongClientID",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeWrongClientID,
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":PEER_PAKE_MISMATCH:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// Send a ClientHello with the wrong PAKE server ID.
-		name:     "PAKE-Server-WrongServerID",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeWrongServerID,
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":PEER_PAKE_MISMATCH:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// Send a ClientHello with the wrong PAKE codepoint.
-		name:     "PAKE-Server-WrongCodepoint",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeWrongCodepoint,
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":PEER_PAKE_MISMATCH:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// A server configured with a mix of PAKE and non-PAKE
-		// credentials will select the first that matches what the
-		// client offered. In doing so, it should skip unsupported
-		// PAKE algorithms.
-		name:     "PAKE-Server-MultiplePAKEs",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				OfferExtraPAKEs: []uint16{1, 2, 3, 4, 5},
-			},
-		},
-		shimCredentials: []*Credential{&spakeWrongClientID, &spakeWrongServerID, &spakeWrongRole, &spakeCredential, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "3"},
-	})
-	testCases = append(testCases, testCase{
-		// A server configured with a certificate credential before a
-		// PAKE credential will consider the certificate credential first.
-		name:     "PAKE-Server-CertificateBeforePAKE",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Pretend to offer a matching PAKE share, but expect the
-				// shim to select the credential first and negotiate a
-				// normal handshake.
-				OfferExtraPAKEClientID: spakeCredential.PAKEClientID,
-				OfferExtraPAKEServerID: spakeCredential.PAKEServerID,
-				OfferExtraPAKEs:        []uint16{spakeID},
-			},
-		},
-		shimCredentials: []*Credential{&rsaCertificate, &spakeCredential},
-		flags:           []string{"-expect-selected-credential", "0"},
-	})
-	testCases = append(testCases, testCase{
-		// A server configured with just a PAKE credential should reject normal
-		// clients.
-		name:     "PAKE-Server-NormalClient",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":PEER_PAKE_MISMATCH:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// ... and TLS 1.2 clients.
-		name:     "PAKE-Server-NormalTLS12Client",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":NO_SHARED_CIPHER:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// ... but you can configure a server with both PAKE and certificate-based
-		// SSL_CREDENTIALs and that works.
-		name:     "PAKE-ServerWithCertsToo-NormalClient",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-		},
-		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-	})
-	testCases = append(testCases, testCase{
-		// ... and for older clients.
-		name:     "PAKE-ServerWithCertsToo-NormalTLS12Client",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-		},
-		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
-		flags:           []string{"-expect-selected-credential", "1"},
-	})
-	testCases = append(testCases, testCase{
-		name:     "PAKE-Client",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				CheckClientHello: func(c *clientHelloMsg) error {
-					// PAKE connections don't use the key_share / supported_groups mechanism.
-					if c.hasKeyShares {
-						return errors.New("unexpected key_share extension")
-					}
-					if len(c.supportedCurves) != 0 {
-						return errors.New("unexpected supported_groups extension")
-					}
-					// PAKE connections don't use signature algorithms.
-					if len(c.signatureAlgorithms) != 0 {
-						return errors.New("unexpected signature_algorithms extension")
-					}
-					// We don't support resumption with PAKEs.
-					if len(c.pskKEModes) != 0 {
-						return errors.New("unexpected psk_key_exchange_modes extension")
-					}
-					return nil
-				},
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-	})
-	testCases = append(testCases, testCase{
-		// Although there is no reason to request new key shares, the PAKE
-		// client should handle cookie requests.
-		name:     "PAKE-Client-HRRCookie",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCookie: []byte("cookie"),
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-	})
-	testCases = append(testCases, testCase{
-		// A PAKE client will not offer key shares, so the client should
-		// reject a HelloRetryRequest requesting a different key share.
-		name:     "PAKE-Client-HRRKeyShare",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				SendHelloRetryRequestCurve: CurveX25519,
-			},
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_EXTENSION:",
-		expectedLocalError: "remote error: unsupported extension",
-	})
-	testCases = append(testCases, testCase{
-		// A server cannot reply with an HRR asking for a PAKE if the client didn't
-		// offer a PAKE in the ClientHello.
-		name:     "PAKE-NormalClient-PAKEInHRR",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				AlwaysSendHelloRetryRequest: true,
-				SendPAKEInHelloRetryRequest: true,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		// A PAKE client should not accept an empty ServerHello.
-		name:     "PAKE-Client-EmptyServerHello",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Trigger an empty ServerHello by making a normal server skip
-				// the key_share extension.
-				MissingKeyShare: true,
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":MISSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		// A PAKE client should not accept a key_share ServerHello.
-		name:     "PAKE-Client-KeyShareServerHello",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				// Trigger a key_share ServerHello by making a normal server
-				// skip the HelloRetryRequest it would otherwise send in
-				// response to the shim's key_share-less ClientHello.
-				SkipHelloRetryRequest: true,
-				// Ignore the client's lack of supported_groups.
-				IgnorePeerCurvePreferences: true,
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":UNEXPECTED_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		// A PAKE client should not accept a TLS 1.2 ServerHello.
-		name:     "PAKE-Client-TLS12ServerHello",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS12,
-			MaxVersion: VersionTLS12,
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":UNSUPPORTED_PROTOCOL:",
-	})
-	testCases = append(testCases, testCase{
-		// A server cannot send the PAKE extension to a non-PAKE client.
-		name:     "PAKE-NormalClient-UnsolicitedPAKEInServerHello",
-		testType: clientTest,
-		config: Config{
-			Bugs: ProtocolBugs{
-				UnsolicitedPAKE: spakeID,
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":UNEXPECTED_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		// A server cannot reply with a PAKE that the client did not offer.
-		name:     "PAKE-Client-WrongPAKEInServerHello",
-		testType: clientTest,
-		config: Config{
-			Bugs: ProtocolBugs{
-				UnsolicitedPAKE: 1234,
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":DECODE_ERROR:",
-	})
-	testCases = append(testCases, testCase{
-		name:     "PAKE-Extension-Duplicate",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				OfferExtraPAKEClientID: []byte("client"),
-				OfferExtraPAKEServerID: []byte("server"),
-				OfferExtraPAKEs:        []uint16{1234, 1234},
-			},
-		},
-		shouldFail:    true,
-		expectedError: ":ERROR_PARSING_EXTENSION:",
-	})
-	testCases = append(testCases, testCase{
-		// If the client sees a server with a wrong password, it should
-		// reject the confirmV value in the ServerHello.
-		name:     "PAKE-Client-WrongPassword",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeWrongPassword,
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":DECODE_ERROR:",
-	})
-	testCases = append(testCases, testCase{
-		name:     "PAKE-Client-Truncate",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				TruncatePAKEMessage: true,
-			},
-		},
-		shimCredentials: []*Credential{&spakeCredential},
-		shouldFail:      true,
-		expectedError:   ":DECODE_ERROR:",
-	})
-	testCases = append(testCases, testCase{
-		name:     "PAKE-Server-Truncate",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				TruncatePAKEMessage: true,
-			},
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":DECODE_ERROR:",
-		expectedLocalError: "remote error: illegal parameter",
-	})
-	testCases = append(testCases, testCase{
-		// Servers may not send CertificateRequest in a PAKE handshake.
-		name:     "PAKE-Client-UnexpectedCertificateRequest",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			ClientAuth: RequireAnyClientCert,
-			Bugs: ProtocolBugs{
-				AlwaysSendCertificateRequest: true,
-			},
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-	testCases = append(testCases, testCase{
-		// Servers may not send Certificate in a PAKE handshake.
-		name:     "PAKE-Client-UnexpectedCertificate",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				AlwaysSendCertificate:    true,
-				UseCertificateCredential: &rsaCertificate,
-				// Ignore the client's lack of signature_algorithms.
-				IgnorePeerSignatureAlgorithmPreferences: true,
-			},
-		},
-		shimCredentials:    []*Credential{&spakeCredential},
-		shouldFail:         true,
-		expectedError:      ":UNEXPECTED_MESSAGE:",
-		expectedLocalError: "remote error: unexpected message",
-	})
-	testCases = append(testCases, testCase{
-		// If a server is configured to request client certificates, it should
-		// still not do so when negotiating a PAKE.
-		name:     "PAKE-Server-DoNotRequestClientCertificate",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-		},
-		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
-		flags:           []string{"-require-any-client-certificate"},
-	})
-	testCases = append(testCases, testCase{
-		// Clients should ignore server PAKE credentials.
-		name:     "PAKE-Client-WrongRole",
-		testType: clientTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-		},
-		shimCredentials: []*Credential{&spakeWrongRole},
-		shouldFail:      true,
-		// The shim will send a non-PAKE ClientHello.
-		expectedLocalError: "tls: client not configured with PAKE",
-	})
-	testCases = append(testCases, testCase{
-		// Servers should ignore client PAKE credentials.
-		name:     "PAKE-Server-WrongRole",
-		testType: serverTest,
-		config: Config{
-			MinVersion: VersionTLS13,
-			Credential: &spakeCredential,
-		},
-		shimCredentials: []*Credential{&spakeWrongRole},
-		shouldFail:      true,
-		// The shim will fail the handshake because it has no usable credentials
-		// available.
-		expectedError:      ":UNKNOWN_CERTIFICATE_TYPE:",
-		expectedLocalError: "remote error: handshake failure",
-	})
-	testCases = append(testCases, testCase{
-		// On the client, we only support a single PAKE credential.
-		name:            "PAKE-Client-MultiplePAKEs",
-		testType:        clientTest,
-		shimCredentials: []*Credential{&spakeCredential, &spakeWrongPassword},
-		shouldFail:      true,
-		expectedError:   ":UNSUPPORTED_CREDENTIAL_LIST:",
-	})
-	testCases = append(testCases, testCase{
-		// On the client, we only support a single PAKE credential.
-		name:            "PAKE-Client-PAKEAndCertificate",
-		testType:        clientTest,
-		shimCredentials: []*Credential{&spakeCredential, &rsaCertificate},
-		shouldFail:      true,
-		expectedError:   ":UNSUPPORTED_CREDENTIAL_LIST:",
-	})
-	testCases = append(testCases, testCase{
-		// We currently do not support resumption with PAKE. Even if configured
-		// with a session, the client should not offer the session with PAKEs.
-		name:     "PAKE-Client-NoResume",
-		testType: clientTest,
-		// Make two connections. For the first connection, just establish a
-		// session without PAKE, to pick up a session.
-		config: Config{
-			Credential: &rsaCertificate,
-		},
-		// For the second connection, use SPAKE.
-		resumeSession: true,
-		resumeConfig: &Config{
-			Credential: &spakeCredential,
-			Bugs: ProtocolBugs{
-				// Check that the ClientHello does not offer a session, even
-				// though one was configured.
-				ExpectNoTLS13PSK: true,
-				// Respond with an unsolicted PSK extension in ServerHello, to
-				// check that the client rejects it.
-				AlwaysSelectPSKIdentity: true,
-			},
-		},
-		resumeShimCredentials: []*Credential{&spakeCredential},
-		shouldFail:            true,
-		expectedError:         ":UNEXPECTED_EXTENSION:",
-	})
-}
-
 func worker(dispatcher *shimDispatcher, statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
 	defer wg.Done()
 
@@ -23607,7 +2192,7 @@
 	addExportKeyingMaterialTests()
 	addExportTrafficSecretsTests()
 	addTLSUniqueTests()
-	addCustomExtensionTests()
+	addUnknownExtensionTests()
 	addRSAClientKeyExchangeTests()
 	addCurveTests()
 	addSessionTicketTests()
@@ -23636,6 +2221,7 @@
 	addCertificateSelectionTests()
 	addKeyUpdateTests()
 	addPAKETests()
+	addTrustAnchorTests()
 
 	toAppend, err := convertToSplitHandshakeTests(testCases)
 	if err != nil {
diff --git a/src/ssl/test/runner/signature_algorithm_tests.go b/src/ssl/test/runner/signature_algorithm_tests.go
new file mode 100644
index 0000000..d27d912
--- /dev/null
+++ b/src/ssl/test/runner/signature_algorithm_tests.go
@@ -0,0 +1,1169 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"fmt"
+	"strconv"
+)
+
+var testSignatureAlgorithms = []struct {
+	name     string
+	id       signatureAlgorithm
+	baseCert *Credential
+	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
+	// accepted.
+	curve CurveID
+}{
+	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
+	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
+	{"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0},
+	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
+	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
+	{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, 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, &ecdsaP224Certificate, CurveP224},
+	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP256Certificate, CurveP256},
+	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, &ecdsaP384Certificate, CurveP384},
+	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, &ecdsaP521Certificate, CurveP521},
+	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, &rsaCertificate, 0},
+	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, &rsaCertificate, 0},
+	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, &rsaCertificate, 0},
+	{"Ed25519", signatureEd25519, &ed25519Certificate, 0},
+	// Tests for key types prior to TLS 1.2.
+	{"RSA", 0, &rsaCertificate, 0},
+	{"ECDSA", 0, &ecdsaP256Certificate, CurveP256},
+}
+
+const (
+	fakeSigAlg1 signatureAlgorithm = 0x2a01
+	fakeSigAlg2 signatureAlgorithm = 0xff01
+)
+
+func addSignatureAlgorithmTests() {
+	// Not all ciphers involve a signature. Advertise a list which gives all
+	// versions a signing cipher.
+	signingCiphers := []uint16{
+		TLS_AES_256_GCM_SHA384,
+		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	}
+
+	var allAlgorithms []signatureAlgorithm
+	for _, alg := range testSignatureAlgorithms {
+		if alg.id != 0 {
+			allAlgorithms = append(allAlgorithms, alg.id)
+		}
+	}
+
+	// Make sure each signature algorithm works. Include some fake values in
+	// the list and ensure they're ignored.
+	for _, alg := range testSignatureAlgorithms {
+		// Make a version of the certificate that will not sign any other algorithm.
+		cert := alg.baseCert
+		if alg.id != 0 {
+			cert = cert.WithSignatureAlgorithms(alg.id)
+		}
+
+		for _, ver := range tlsVersions {
+			if (ver.version < VersionTLS12) != (alg.id == 0) {
+				continue
+			}
+
+			suffix := "-" + alg.name + "-" + ver.name
+			for _, signTestType := range []testType{clientTest, serverTest} {
+				signPrefix := "Client-"
+				verifyPrefix := "Server-"
+				verifyTestType := serverTest
+				if signTestType == serverTest {
+					verifyTestType = clientTest
+					signPrefix, verifyPrefix = verifyPrefix, signPrefix
+				}
+
+				var shouldFail bool
+				isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
+				isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
+
+				// TLS 1.3 removes a number of signature algorithms.
+				if ver.version >= VersionTLS13 && (alg.curve == CurveP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
+					shouldFail = true
+				}
+
+				// The backported RSA-PKCS1 code points only exist for TLS 1.3
+				// client certificates.
+				if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
+					shouldFail = true
+				}
+
+				// By default, BoringSSL does not sign with these algorithms.
+				signDefault := !shouldFail
+				if isTLS13PKCS1 {
+					signDefault = false
+				}
+
+				// By default, BoringSSL does not accept these algorithms.
+				verifyDefault := !shouldFail
+				if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
+					verifyDefault = false
+				}
+
+				var curveFlags []string
+				var runnerCurves []CurveID
+				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. Also include X25519 to ensure the shim
+					// and runner have something in common for ECDH.
+					curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
+					runnerCurves = []CurveID{CurveX25519, alg.curve}
+				}
+
+				signError := func(shouldFail bool) string {
+					if !shouldFail {
+						return ""
+					}
+					// In TLS 1.3, the shim should report no common signature algorithms if
+					// it cannot generate a signature. In TLS 1.2 servers, signature
+					// algorithm and cipher selection are integrated, so it is reported as
+					// no shared cipher.
+					if ver.version <= VersionTLS12 && signTestType == serverTest {
+						return ":NO_SHARED_CIPHER:"
+					}
+					return ":NO_COMMON_SIGNATURE_ALGORITHMS:"
+				}
+				signLocalError := func(shouldFail bool) string {
+					if !shouldFail {
+						return ""
+					}
+					// The shim should send handshake_failure when it cannot
+					// negotiate parameters.
+					return "remote error: handshake failure"
+				}
+				verifyError := func(shouldFail bool) string {
+					if !shouldFail {
+						return ""
+					}
+					// If the shim rejects the signature algorithm, but the
+					// runner forcibly selects it anyway, the shim should notice.
+					return ":WRONG_SIGNATURE_TYPE:"
+				}
+				verifyLocalError := func(shouldFail bool) string {
+					if !shouldFail {
+						return ""
+					}
+					// The shim should send an illegal_parameter alert if the runner
+					// uses a signature algorithm it isn't allowed to use.
+					return "remote error: illegal parameter"
+				}
+
+				// Test the shim using the algorithm for signing.
+				signTest := testCase{
+					testType: signTestType,
+					name:     signPrefix + "Sign" + suffix,
+					config: Config{
+						MaxVersion:       ver.version,
+						CurvePreferences: runnerCurves,
+						VerifySignatureAlgorithms: []signatureAlgorithm{
+							fakeSigAlg1,
+							alg.id,
+							fakeSigAlg2,
+						},
+					},
+					shimCertificate:    cert,
+					flags:              curveFlags,
+					shouldFail:         shouldFail,
+					expectedError:      signError(shouldFail),
+					expectedLocalError: signLocalError(shouldFail),
+					expectations: connectionExpectations{
+						peerSignatureAlgorithm: alg.id,
+					},
+				}
+
+				// Test whether the shim enables the algorithm by default.
+				signDefaultTest := testCase{
+					testType: signTestType,
+					name:     signPrefix + "SignDefault" + suffix,
+					config: Config{
+						MaxVersion:       ver.version,
+						CurvePreferences: runnerCurves,
+						VerifySignatureAlgorithms: []signatureAlgorithm{
+							fakeSigAlg1,
+							alg.id,
+							fakeSigAlg2,
+						},
+					},
+					// cert has been configured with the specified algorithm,
+					// while alg.baseCert uses the defaults.
+					shimCertificate:    alg.baseCert,
+					flags:              curveFlags,
+					shouldFail:         !signDefault,
+					expectedError:      signError(!signDefault),
+					expectedLocalError: signLocalError(!signDefault),
+					expectations: connectionExpectations{
+						peerSignatureAlgorithm: alg.id,
+					},
+				}
+
+				// Test that the shim will select the algorithm when configured to only
+				// support it.
+				negotiateTest := testCase{
+					testType: signTestType,
+					name:     signPrefix + "Sign-Negotiate" + suffix,
+					config: Config{
+						MaxVersion:                ver.version,
+						CurvePreferences:          runnerCurves,
+						VerifySignatureAlgorithms: allAlgorithms,
+					},
+					shimCertificate: cert,
+					flags:           curveFlags,
+					expectations: connectionExpectations{
+						peerSignatureAlgorithm: alg.id,
+					},
+				}
+
+				if signTestType == serverTest {
+					// TLS 1.2 servers only sign on some cipher suites.
+					signTest.config.CipherSuites = signingCiphers
+					signDefaultTest.config.CipherSuites = signingCiphers
+					negotiateTest.config.CipherSuites = signingCiphers
+				} else {
+					// TLS 1.2 clients only sign when the server requests certificates.
+					signTest.config.ClientAuth = RequireAnyClientCert
+					signDefaultTest.config.ClientAuth = RequireAnyClientCert
+					negotiateTest.config.ClientAuth = RequireAnyClientCert
+				}
+				testCases = append(testCases, signTest, signDefaultTest)
+				if ver.version >= VersionTLS12 && !shouldFail {
+					testCases = append(testCases, negotiateTest)
+				}
+
+				// Test the shim using the algorithm for verifying.
+				verifyTest := testCase{
+					testType: verifyTestType,
+					name:     verifyPrefix + "Verify" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Credential: cert,
+						Bugs: ProtocolBugs{
+							SkipECDSACurveCheck:          shouldFail,
+							IgnoreSignatureVersionChecks: shouldFail,
+							// Some signature algorithms may not be advertised.
+							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
+						},
+					},
+					flags: curveFlags,
+					// Resume the session to assert the peer signature
+					// algorithm is reported on both handshakes.
+					resumeSession:      !shouldFail,
+					shouldFail:         shouldFail,
+					expectedError:      verifyError(shouldFail),
+					expectedLocalError: verifyLocalError(shouldFail),
+				}
+				if alg.id != 0 {
+					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
+					// The algorithm may be disabled by default, so explicitly enable it.
+					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
+				}
+
+				// Test whether the shim expects the algorithm enabled by default.
+				defaultTest := testCase{
+					testType: verifyTestType,
+					name:     verifyPrefix + "VerifyDefault" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Credential: cert,
+						Bugs: ProtocolBugs{
+							SkipECDSACurveCheck:          !verifyDefault,
+							IgnoreSignatureVersionChecks: !verifyDefault,
+							// Some signature algorithms may not be advertised.
+							IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
+						},
+					},
+					flags: append(
+						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
+						curveFlags...,
+					),
+					// Resume the session to assert the peer signature
+					// algorithm is reported on both handshakes.
+					resumeSession:      verifyDefault,
+					shouldFail:         !verifyDefault,
+					expectedError:      verifyError(!verifyDefault),
+					expectedLocalError: verifyLocalError(!verifyDefault),
+				}
+
+				// Test whether the shim handles invalid signatures for this algorithm.
+				invalidTest := testCase{
+					testType: verifyTestType,
+					name:     verifyPrefix + "InvalidSignature" + suffix,
+					config: Config{
+						MaxVersion: ver.version,
+						Credential: cert,
+						Bugs: ProtocolBugs{
+							InvalidSignature: true,
+						},
+					},
+					flags:         curveFlags,
+					shouldFail:    true,
+					expectedError: ":BAD_SIGNATURE:",
+				}
+				if alg.id != 0 {
+					// The algorithm may be disabled by default, so explicitly enable it.
+					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
+				}
+
+				if verifyTestType == serverTest {
+					// TLS 1.2 servers only verify when they request client certificates.
+					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
+					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
+					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
+				} else {
+					// TLS 1.2 clients only verify on some cipher suites.
+					verifyTest.config.CipherSuites = signingCiphers
+					defaultTest.config.CipherSuites = signingCiphers
+					invalidTest.config.CipherSuites = signingCiphers
+				}
+				testCases = append(testCases, verifyTest, defaultTest)
+				if !shouldFail {
+					testCases = append(testCases, invalidTest)
+				}
+			}
+		}
+	}
+
+	// Test the peer's verify preferences are available.
+	for _, ver := range tlsVersions {
+		if ver.version < VersionTLS12 {
+			continue
+		}
+		testCases = append(testCases, testCase{
+			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				ClientAuth: RequireAnyClientCert,
+				VerifySignatureAlgorithms: []signatureAlgorithm{
+					signatureRSAPSSWithSHA256,
+					signatureEd25519,
+					signatureECDSAWithP256AndSHA256,
+				},
+			},
+			shimCertificate: &rsaCertificate,
+			flags: []string{
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				VerifySignatureAlgorithms: []signatureAlgorithm{
+					signatureRSAPSSWithSHA256,
+					signatureEd25519,
+					signatureECDSAWithP256AndSHA256,
+				},
+			},
+			shimCertificate: &rsaCertificate,
+			flags: []string{
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
+				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
+			},
+		})
+
+	}
+
+	// Test that algorithm selection takes the key type into account.
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-SignatureType",
+		config: Config{
+			ClientAuth: RequireAnyClientCert,
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureECDSAWithSHA1,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-SignatureType-TLS13",
+		config: Config{
+			ClientAuth: RequireAnyClientCert,
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureECDSAWithSHA1,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SignatureType",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureECDSAWithSHA1,
+			},
+		},
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SignatureType-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureECDSAWithSHA1,
+			},
+		},
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
+		},
+	})
+
+	// Test that signature verification takes the key type into account.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Verify-ClientAuth-SignatureType",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Verify-ClientAuth-SignatureType-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "Verify-ServerAuth-SignatureType",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "Verify-ServerAuth-SignatureType-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Test that, if the ClientHello list is missing, the server falls back
+	// to SHA-1 in TLS 1.2, but not TLS 1.3.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SHA1-Fallback-RSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SHA1-Fallback-ECDSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shimCertificate: &ecdsaP256Certificate,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-NoFallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+
+	// The CertificateRequest list, however, may never be omitted. It is a
+	// syntax error for it to be empty.
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-NoFallback-RSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shimCertificate:    &rsaCertificate,
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-NoFallback-ECDSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shimCertificate:    &ecdsaP256Certificate,
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-NoFallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shimCertificate:    &rsaCertificate,
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	// Test that signature preferences are enforced. BoringSSL does not
+	// implement MD5 signatures.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Enforced",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+			},
+		},
+		flags:         []string{"-require-any-client-certificate"},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerAuth-Enforced",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Enforced-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+				IgnoreSignatureVersionChecks:            true,
+			},
+		},
+		flags:         []string{"-require-any-client-certificate"},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerAuth-Enforced-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+				IgnoreSignatureVersionChecks:            true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Test that the negotiated signature algorithm respects the client and
+	// server preferences.
+	testCases = append(testCases, testCase{
+		name: "NoCommonAlgorithms",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA512,
+				signatureRSAPKCS1WithSHA1,
+			},
+		},
+		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
+		shouldFail:      true,
+		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+	testCases = append(testCases, testCase{
+		name: "NoCommonAlgorithms-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA512,
+				signatureRSAPSSWithSHA384,
+			},
+		},
+		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+		shouldFail:      true,
+		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Agree-Digest-SHA256",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+				signatureRSAPKCS1WithSHA256,
+			},
+		},
+		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
+			signatureRSAPKCS1WithSHA256,
+			signatureRSAPKCS1WithSHA1,
+		),
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Agree-Digest-SHA1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+		},
+		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
+			signatureRSAPKCS1WithSHA512,
+			signatureRSAPKCS1WithSHA256,
+			signatureRSAPKCS1WithSHA1,
+		),
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "Agree-Digest-Default",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+				signatureECDSAWithP256AndSHA256,
+				signatureRSAPKCS1WithSHA1,
+				signatureECDSAWithSHA1,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
+		},
+	})
+
+	// Test that the signing preference list may include extra algorithms
+	// without negotiation problems.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "FilterExtraAlgorithms",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+			},
+		},
+		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
+			signatureECDSAWithP256AndSHA256,
+			signatureRSAPKCS1WithSHA256,
+		),
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
+		},
+	})
+
+	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
+	// signature algorithms.
+	testCases = append(testCases, testCase{
+		name: "CheckLeafCurve",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Credential:   &ecdsaP256Certificate,
+		},
+		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
+		shouldFail:    true,
+		expectedError: ":BAD_ECC_CERT:",
+	})
+
+	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
+	testCases = append(testCases, testCase{
+		name: "CheckLeafCurve-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &ecdsaP256Certificate,
+		},
+		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
+	})
+
+	// In TLS 1.2, the ECDSA curve is not in the signature algorithm, so the
+	// shim should accept P-256 with SHA-384.
+	testCases = append(testCases, testCase{
+		name: "ECDSACurveMismatch-Verify-TLS12",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Credential:   ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
+		},
+	})
+
+	// In TLS 1.3, the ECDSA curve comes from the signature algorithm, so the
+	// shim should reject P-256 with SHA-384.
+	testCases = append(testCases, testCase{
+		name: "ECDSACurveMismatch-Verify-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
+			Bugs: ProtocolBugs{
+				SkipECDSACurveCheck: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Signature algorithm selection in TLS 1.3 should take the curve into
+	// account.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ECDSACurveMismatch-Sign-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP384AndSHA384,
+				signatureECDSAWithP256AndSHA256,
+			},
+		},
+		shimCertificate: &ecdsaP256Certificate,
+		expectations: connectionExpectations{
+			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+		},
+	})
+
+	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
+	// server does not attempt to sign in that case.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "RSA-PSS-Large",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA512,
+			},
+		},
+		shimCertificate: &rsa1024Certificate,
+		shouldFail:      true,
+		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+
+	// Test that RSA-PSS is enabled by default for TLS 1.2.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "RSA-PSS-Default-Verify",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "RSA-PSS-Default-Sign",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA256,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	// TLS 1.1 and below has no way to advertise support for or negotiate
+	// Ed25519's signature algorithm.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "NoEd25519-TLS11-ServerAuth-Verify",
+		config: Config{
+			MaxVersion: VersionTLS11,
+			Credential: &ed25519Certificate,
+			Bugs: ProtocolBugs{
+				// Sign with Ed25519 even though it is TLS 1.1.
+				SigningAlgorithmForLegacyVersions: signatureEd25519,
+			},
+		},
+		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
+		shouldFail:    true,
+		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoEd25519-TLS11-ServerAuth-Sign",
+		config: Config{
+			MaxVersion: VersionTLS11,
+		},
+		shimCertificate: &ed25519Certificate,
+		shouldFail:      true,
+		expectedError:   ":NO_SHARED_CIPHER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoEd25519-TLS11-ClientAuth-Verify",
+		config: Config{
+			MaxVersion: VersionTLS11,
+			Credential: &ed25519Certificate,
+			Bugs: ProtocolBugs{
+				// Sign with Ed25519 even though it is TLS 1.1.
+				SigningAlgorithmForLegacyVersions: signatureEd25519,
+			},
+		},
+		flags: []string{
+			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "NoEd25519-TLS11-ClientAuth-Sign",
+		config: Config{
+			MaxVersion: VersionTLS11,
+			ClientAuth: RequireAnyClientCert,
+		},
+		shimCertificate: &ed25519Certificate,
+		shouldFail:      true,
+		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+
+	// Test Ed25519 is not advertised by default.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Ed25519DefaultDisable-NoAdvertise",
+		config: Config{
+			Credential: &ed25519Certificate,
+		},
+		shouldFail:         true,
+		expectedLocalError: "tls: no common signature algorithms",
+	})
+
+	// Test Ed25519, when disabled, is not accepted if the peer ignores our
+	// preferences.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Ed25519DefaultDisable-NoAccept",
+		config: Config{
+			Credential: &ed25519Certificate,
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Test that configuring verify preferences changes what the client
+	// advertises.
+	testCases = append(testCases, testCase{
+		name: "VerifyPreferences-Advertised",
+		config: Config{
+			Credential: rsaCertificate.WithSignatureAlgorithms(
+				signatureRSAPSSWithSHA256,
+				signatureRSAPSSWithSHA384,
+				signatureRSAPSSWithSHA512,
+			),
+		},
+		flags: []string{
+			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
+			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
+		},
+	})
+
+	// Test that the client advertises a set which the runner can find
+	// nothing in common with.
+	testCases = append(testCases, testCase{
+		name: "VerifyPreferences-NoCommonAlgorithms",
+		config: Config{
+			Credential: rsaCertificate.WithSignatureAlgorithms(
+				signatureRSAPSSWithSHA256,
+				signatureRSAPSSWithSHA512,
+			),
+		},
+		flags: []string{
+			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
+		},
+		shouldFail:         true,
+		expectedLocalError: "tls: no common signature algorithms",
+	})
+
+	// Test that the client enforces its preferences when configured.
+	testCases = append(testCases, testCase{
+		name: "VerifyPreferences-Enforced",
+		config: Config{
+			Credential: rsaCertificate.WithSignatureAlgorithms(
+				signatureRSAPSSWithSHA256,
+				signatureRSAPSSWithSHA512,
+			),
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+			},
+		},
+		flags: []string{
+			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Test that explicitly configuring Ed25519 is as good as changing the
+	// boolean toggle.
+	testCases = append(testCases, testCase{
+		name: "VerifyPreferences-Ed25519",
+		config: Config{
+			Credential: &ed25519Certificate,
+		},
+		flags: []string{
+			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
+		},
+	})
+
+	for _, testType := range []testType{clientTest, serverTest} {
+		for _, ver := range tlsVersions {
+			if ver.version < VersionTLS12 {
+				continue
+			}
+
+			prefix := "Client-" + ver.name + "-"
+			noCommonAlgorithmsError := ":NO_COMMON_SIGNATURE_ALGORITHMS:"
+			if testType == serverTest {
+				prefix = "Server-" + ver.name + "-"
+				// In TLS 1.2 servers, cipher selection and algorithm
+				// selection are linked.
+				if ver.version <= VersionTLS12 {
+					noCommonAlgorithmsError = ":NO_SHARED_CIPHER:"
+				}
+			}
+
+			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
+			// even if specified in signing preferences.
+			testCases = append(testCases, testCase{
+				testType: testType,
+				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
+				config: Config{
+					MaxVersion:                ver.version,
+					CipherSuites:              signingCiphers,
+					ClientAuth:                RequireAnyClientCert,
+					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
+				},
+				shimCertificate: rsaCertificate.WithSignatureAlgorithms(
+					signatureRSAPKCS1WithMD5AndSHA1,
+					// Include a valid algorithm as well, to avoid an empty list
+					// if filtered out.
+					signatureRSAPKCS1WithSHA256,
+				),
+				shouldFail:    true,
+				expectedError: noCommonAlgorithmsError,
+			})
+
+			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
+			// even if specified in verify preferences.
+			testCases = append(testCases, testCase{
+				testType: testType,
+				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
+				config: Config{
+					MaxVersion: ver.version,
+					Credential: &rsaCertificate,
+					Bugs: ProtocolBugs{
+						IgnorePeerSignatureAlgorithmPreferences: true,
+						AlwaysSignAsLegacyVersion:               true,
+						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
+					},
+				},
+				shimCertificate: &rsaCertificate,
+				flags: []string{
+					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
+					// Include a valid algorithm as well, to avoid an empty list
+					// if filtered out.
+					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
+					"-require-any-client-certificate",
+				},
+				shouldFail:    true,
+				expectedError: ":WRONG_SIGNATURE_TYPE:",
+			})
+		}
+	}
+
+	// Test that, when there are no signature algorithms in common in TLS
+	// 1.2, the server will still consider the legacy RSA key exchange.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoCommonSignatureAlgorithms-TLS12-Fallback",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			CipherSuites: []uint16{
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+			},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP256AndSHA256,
+			},
+		},
+		expectations: connectionExpectations{
+			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
+		},
+	})
+}
+
+func addBadECDSASignatureTests() {
+	for badR := BadValue(1); badR < NumBadValues; badR++ {
+		for badS := BadValue(1); badS < NumBadValues; badS++ {
+			testCases = append(testCases, testCase{
+				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
+				config: Config{
+					MaxVersion:   VersionTLS12,
+					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+					Credential:   &ecdsaP256Certificate,
+					Bugs: ProtocolBugs{
+						BadECDSAR: badR,
+						BadECDSAS: badS,
+					},
+				},
+				shouldFail:    true,
+				expectedError: ":BAD_SIGNATURE:",
+			})
+			testCases = append(testCases, testCase{
+				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
+				config: Config{
+					MaxVersion: VersionTLS13,
+					Credential: &ecdsaP256Certificate,
+					Bugs: ProtocolBugs{
+						BadECDSAR: badR,
+						BadECDSAS: badS,
+					},
+				},
+				shouldFail:    true,
+				expectedError: ":BAD_SIGNATURE:",
+			})
+		}
+	}
+}
diff --git a/src/ssl/test/runner/state_machine_tests.go b/src/ssl/test/runner/state_machine_tests.go
new file mode 100644
index 0000000..b510019
--- /dev/null
+++ b/src/ssl/test/runner/state_machine_tests.go
@@ -0,0 +1,1491 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+)
+
+type stateMachineTestConfig struct {
+	protocol          protocol
+	async             bool
+	splitHandshake    bool
+	packHandshake     bool
+	implicitHandshake bool
+}
+
+// Adds tests that try to cover the range of the handshake state machine, under
+// various conditions. Some of these are redundant with other tests, but they
+// only cover the synchronous case.
+func addAllStateMachineCoverageTests() {
+	for _, async := range []bool{false, true} {
+		for _, protocol := range []protocol{tls, dtls, quic} {
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol: protocol,
+				async:    async,
+			})
+			// QUIC doesn't work with the implicit handshake API. Additionally,
+			// splitting or packing handshake records is meaningless in QUIC.
+			if protocol != quic {
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:          protocol,
+					async:             async,
+					implicitHandshake: true,
+				})
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:       protocol,
+					async:          async,
+					splitHandshake: true,
+				})
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:      protocol,
+					async:         async,
+					packHandshake: true,
+				})
+			}
+		}
+	}
+}
+
+func addStateMachineCoverageTests(config stateMachineTestConfig) {
+	var tests []testCase
+
+	// Basic handshake, with resumption. Client and server,
+	// session ID and session ticket.
+	// The following tests have a max version of 1.2, so they are not suitable
+	// for use with QUIC.
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			name: "Basic-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+			// Ensure session tickets are used, not session IDs.
+			noSessionCache: true,
+			flags:          []string{"-expect-no-hrr"},
+		})
+		tests = append(tests, testCase{
+			name: "Basic-Client-RenewTicket",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					RenewTicketOnResume: true,
+				},
+			},
+			flags:                []string{"-expect-ticket-renewal"},
+			resumeSession:        true,
+			resumeRenewedSession: true,
+		})
+		tests = append(tests, testCase{
+			name: "Basic-Client-NoTicket",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+			resumeSession: true,
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					RequireSessionTickets: true,
+				},
+			},
+			resumeSession: true,
+			flags: []string{
+				"-expect-no-session-id",
+				"-expect-no-hrr",
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-NoTickets",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+			resumeSession: true,
+			flags:         []string{"-expect-session-id"},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-EarlyCallback",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:         []string{"-use-early-callback"},
+			resumeSession: true,
+		})
+	}
+
+	// TLS 1.3 basic handshake shapes.
+	tests = append(tests, testCase{
+		name: "TLS13-1RTT-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		// 0-RTT being disabled overrides all other 0-RTT reasons.
+		flags: []string{"-expect-early-data-reason", "disabled"},
+	})
+
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "TLS13-1RTT-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		flags: []string{
+			// TLS 1.3 uses tickets, so the session should not be
+			// cached statefully.
+			"-expect-no-session-id",
+			// 0-RTT being disabled overrides all other 0-RTT reasons.
+			"-expect-early-data-reason", "disabled",
+		},
+	})
+
+	tests = append(tests, testCase{
+		name: "TLS13-HelloRetryRequest-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			// P-384 requires a HelloRetryRequest against BoringSSL's default
+			// configuration. Assert this with ExpectMissingKeyShare.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectMissingKeyShare: true,
+			},
+		},
+		// Cover HelloRetryRequest during an ECDHE-PSK resumption.
+		resumeSession: true,
+		flags:         []string{"-expect-hrr"},
+	})
+
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "TLS13-HelloRetryRequest-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves: []CurveID{},
+		},
+		// Cover HelloRetryRequest during an ECDHE-PSK resumption.
+		resumeSession: true,
+		flags:         []string{"-expect-hrr"},
+	})
+
+	// TLS 1.3 early data tests. DTLS 1.3 doesn't support early data yet.
+	// These tests are disabled for QUIC as well because they test features
+	// that do not apply to QUIC's use of TLS 1.3.
+	//
+	// TODO(crbug.com/381113363): Enable these tests for DTLS once we
+	// support early data in DTLS 1.3.
+	if config.protocol != dtls && config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "TLS13-EarlyData-TooMuchData-Client",
+			config: Config{
+				MaxVersion:       VersionTLS13,
+				MinVersion:       VersionTLS13,
+				MaxEarlyDataSize: 2,
+			},
+			resumeConfig: &Config{
+				MaxVersion:       VersionTLS13,
+				MinVersion:       VersionTLS13,
+				MaxEarlyDataSize: 2,
+				Bugs: ProtocolBugs{
+					ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
+				},
+			},
+			resumeShimPrefix: shimInitialWrite[2:],
+			resumeSession:    true,
+			earlyData:        true,
+		})
+
+		// Unfinished writes can only be tested when operations are async. EarlyData
+		// can't be tested as part of an ImplicitHandshake in this case since
+		// otherwise the early data will be sent as normal data.
+		if config.async && !config.implicitHandshake {
+			tests = append(tests, testCase{
+				testType: clientTest,
+				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
+				config: Config{
+					MaxVersion: VersionTLS13,
+					MinVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						// Write the server response before expecting early data.
+						ExpectEarlyData:     [][]byte{},
+						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
+					},
+				},
+				resumeSession: true,
+				earlyData:     true,
+				flags:         []string{"-on-resume-read-with-unfinished-write"},
+			})
+
+			// Rejected unfinished writes are discarded (from the
+			// perspective of the calling application) on 0-RTT
+			// reject.
+			tests = append(tests, testCase{
+				testType: clientTest,
+				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
+				config: Config{
+					MaxVersion: VersionTLS13,
+					MinVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						AlwaysRejectEarlyData: true,
+					},
+				},
+				resumeSession:           true,
+				earlyData:               true,
+				expectEarlyDataRejected: true,
+				flags:                   []string{"-on-resume-read-with-unfinished-write"},
+			})
+		}
+
+		// Early data has no size limit in QUIC.
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "TLS13-MaxEarlyData-Server",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
+					ExpectEarlyDataAccepted: true,
+				},
+			},
+			messageCount:  2,
+			resumeSession: true,
+			earlyData:     true,
+			shouldFail:    true,
+			expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
+		})
+	}
+
+	// Test that early data is disabled for DTLS 1.3.
+	if config.protocol == dtls {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			protocol: dtls,
+			name:     "DTLS13-EarlyData",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+			},
+			resumeSession: true,
+			earlyData:     true,
+		})
+	}
+
+	// TLS client auth.
+	// The following tests have a max version of 1.2, so they are not suitable
+	// for use with QUIC.
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-NoCertificate-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequestClientCert,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-NoCertificate-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			// Setting SSL_VERIFY_PEER allows anonymous clients.
+			flags: []string{"-verify-peer"},
+		})
+	}
+	if config.protocol != dtls {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-NoCertificate-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				ClientAuth: RequestClientCert,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-NoCertificate-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			// Setting SSL_VERIFY_PEER allows anonymous clients.
+			flags: []string{"-verify-peer"},
+		})
+	}
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-RSA-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			shimCertificate: &rsaCertificate,
+		})
+	}
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-RSA-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		shimCertificate: &rsaCertificate,
+	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-ECDSA-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			shimCertificate: &ecdsaP256Certificate,
+		})
+	}
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-ECDSA-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		shimCertificate: &ecdsaP256Certificate,
+	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-NoCertificate-OldCallback",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequestClientCert,
+			},
+			flags: []string{"-use-old-client-cert-callback"},
+		})
+	}
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequestClientCert,
+		},
+		flags: []string{"-use-old-client-cert-callback"},
+	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-OldCallback",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			shimCertificate: &rsaCertificate,
+			flags: []string{
+				"-use-old-client-cert-callback",
+			},
+		})
+	}
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-OldCallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		shimCertificate: &rsaCertificate,
+		flags: []string{
+			"-use-old-client-cert-callback",
+		},
+	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+	}
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &rsaCertificate,
+		},
+		flags: []string{"-require-any-client-certificate"},
+	})
+
+	// Test each key exchange on the server side for async keys.
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-RSA",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+			},
+			shimCertificate: &rsaCertificate,
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-ECDHE-RSA",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			},
+			shimCertificate: &rsaCertificate,
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-ECDHE-ECDSA",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			},
+			shimCertificate: &ecdsaP256Certificate,
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-Ed25519",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			},
+			shimCertificate: &ed25519Certificate,
+			flags: []string{
+				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
+			},
+		})
+
+		// No session ticket support; server doesn't send NewSessionTicket.
+		tests = append(tests, testCase{
+			name: "SessionTicketsDisabled-Client",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "SessionTicketsDisabled-Server",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+		})
+
+		// Skip ServerKeyExchange in PSK key exchange if there's no
+		// identity hint.
+		tests = append(tests, testCase{
+			name: "EmptyPSKHint-Client",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+				PreSharedKey: []byte("secret"),
+			},
+			flags: []string{"-psk", "secret"},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "EmptyPSKHint-Server",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+				PreSharedKey: []byte("secret"),
+			},
+			flags: []string{"-psk", "secret"},
+		})
+	}
+
+	// OCSP stapling tests.
+	for _, vers := range allVersions(config.protocol) {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "OCSPStapling-Client-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				"-expect-ocsp-response",
+				base64FlagValue(testOCSPResponse),
+				"-verify-peer",
+			},
+			resumeSession: true,
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "OCSPStapling-Server-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+			},
+			expectations: connectionExpectations{
+				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			resumeSession:   true,
+		})
+
+		// The client OCSP callback is an alternate certificate
+		// verification callback.
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientOCSPCallback-Pass-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				"-use-ocsp-callback",
+			},
+		})
+		var expectedLocalError string
+		if !config.async {
+			// TODO(davidben): Asynchronous fatal alerts are never
+			// sent. https://crbug.com/boringssl/130.
+			expectedLocalError = "remote error: bad certificate status response"
+		}
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientOCSPCallback-Fail-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				"-use-ocsp-callback",
+				"-fail-ocsp-callback",
+			},
+			shouldFail:         true,
+			expectedLocalError: expectedLocalError,
+			expectedError:      ":OCSP_CB_ERROR:",
+		})
+		// The callback still runs if the server does not send an OCSP
+		// response.
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-enable-ocsp-stapling",
+				"-use-ocsp-callback",
+				"-fail-ocsp-callback",
+			},
+			shouldFail:         true,
+			expectedLocalError: expectedLocalError,
+			expectedError:      ":OCSP_CB_ERROR:",
+		})
+
+		// The server OCSP callback is a legacy mechanism for
+		// configuring OCSP, used by unreliable server software.
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+			},
+			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			expectations: connectionExpectations{
+				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			},
+			flags: []string{
+				"-use-ocsp-callback",
+				"-set-ocsp-in-callback",
+			},
+			resumeSession: true,
+		})
+
+		// The callback may decline OCSP, in which case  we act as if
+		// the client did not support it, even if a response was
+		// configured.
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ServerOCSPCallback-Decline-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+			},
+			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			expectations: connectionExpectations{
+				// There should be no OCSP response from the peer.
+				peerCertificate: &rsaCertificate,
+			},
+			flags: []string{
+				"-use-ocsp-callback",
+				"-decline-ocsp-callback",
+			},
+			resumeSession: true,
+		})
+
+		// The callback may also signal an internal error.
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ServerOCSPCallback-Fail-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+			},
+			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
+			flags: []string{
+				"-use-ocsp-callback",
+				"-fail-ocsp-callback",
+			},
+			shouldFail:    true,
+			expectedError: ":OCSP_CB_ERROR:",
+		})
+	}
+
+	// Certificate verification tests.
+	for _, vers := range allVersions(config.protocol) {
+		for _, useCustomCallback := range []bool{false, true} {
+			for _, testType := range []testType{clientTest, serverTest} {
+				suffix := "-Client"
+				if testType == serverTest {
+					suffix = "-Server"
+				}
+				suffix += "-" + vers.name
+				if useCustomCallback {
+					suffix += "-CustomCallback"
+				}
+
+				// The custom callback and legacy callback have different default
+				// alerts.
+				verifyFailLocalError := "remote error: handshake failure"
+				if useCustomCallback {
+					verifyFailLocalError = "remote error: unknown certificate"
+				}
+
+				// We do not reliably send asynchronous fatal alerts. See
+				// https://crbug.com/boringssl/130.
+				if config.async {
+					verifyFailLocalError = ""
+				}
+
+				flags := []string{"-verify-peer"}
+				if testType == serverTest {
+					flags = append(flags, "-require-any-client-certificate")
+				}
+				if useCustomCallback {
+					flags = append(flags, "-use-custom-verify-callback")
+				}
+
+				tests = append(tests, testCase{
+					testType: testType,
+					name:     "CertificateVerificationSucceed" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Credential: &rsaCertificate,
+					},
+					flags:         append([]string{"-expect-verify-result"}, flags...),
+					resumeSession: true,
+				})
+				tests = append(tests, testCase{
+					testType: testType,
+					name:     "CertificateVerificationFail" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Credential: &rsaCertificate,
+					},
+					flags:              append([]string{"-verify-fail"}, flags...),
+					shouldFail:         true,
+					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
+					expectedLocalError: verifyFailLocalError,
+				})
+				// Tests that although the verify callback fails on resumption, by default we don't call it.
+				tests = append(tests, testCase{
+					testType: testType,
+					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
+					config: Config{
+						MaxVersion: vers.version,
+						Credential: &rsaCertificate,
+					},
+					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
+					resumeSession: true,
+				})
+				if testType == clientTest && useCustomCallback {
+					tests = append(tests, testCase{
+						testType: testType,
+						name:     "CertificateVerificationFailsOnResume" + suffix,
+						config: Config{
+							MaxVersion: vers.version,
+							Credential: &rsaCertificate,
+						},
+						flags: append([]string{
+							"-on-resume-verify-fail",
+							"-reverify-on-resume",
+						}, flags...),
+						resumeSession:      true,
+						shouldFail:         true,
+						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
+						expectedLocalError: verifyFailLocalError,
+					})
+					tests = append(tests, testCase{
+						testType: testType,
+						name:     "CertificateVerificationPassesOnResume" + suffix,
+						config: Config{
+							MaxVersion: vers.version,
+							Credential: &rsaCertificate,
+						},
+						flags: append([]string{
+							"-reverify-on-resume",
+						}, flags...),
+						resumeSession: true,
+					})
+					// TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3.
+					if vers.version >= VersionTLS13 && config.protocol != dtls {
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+							},
+							resumeConfig: &Config{
+								MaxVersion:             vers.version,
+								SessionTicketsDisabled: true,
+							},
+							resumeSession:           true,
+							expectResumeRejected:    true,
+							earlyData:               true,
+							expectEarlyDataRejected: true,
+							flags: append([]string{
+								"-reverify-on-resume",
+								// Session tickets are disabled, so the runner will not send a ticket.
+								"-on-retry-expect-no-session",
+							}, flags...),
+						})
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+								Bugs: ProtocolBugs{
+									AlwaysRejectEarlyData: true,
+								},
+							},
+							resumeSession:           true,
+							expectResumeRejected:    false,
+							earlyData:               true,
+							expectEarlyDataRejected: true,
+							flags: append([]string{
+								"-reverify-on-resume",
+							}, flags...),
+						})
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+							},
+							resumeConfig: &Config{
+								MaxVersion:             vers.version,
+								SessionTicketsDisabled: true,
+							},
+							resumeSession:           true,
+							expectResumeRejected:    true,
+							earlyData:               true,
+							expectEarlyDataRejected: true,
+							shouldFail:              true,
+							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
+							flags: append([]string{
+								"-reverify-on-resume",
+								// Session tickets are disabled, so the runner will not send a ticket.
+								"-on-retry-expect-no-session",
+								"-on-retry-verify-fail",
+							}, flags...),
+						})
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+								Bugs: ProtocolBugs{
+									AlwaysRejectEarlyData: true,
+								},
+							},
+							resumeSession:           true,
+							expectResumeRejected:    false,
+							earlyData:               true,
+							expectEarlyDataRejected: true,
+							shouldFail:              true,
+							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
+							expectedLocalError:      verifyFailLocalError,
+							flags: append([]string{
+								"-reverify-on-resume",
+								"-on-retry-verify-fail",
+							}, flags...),
+						})
+						// This tests that we only call the verify callback once.
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+							},
+							resumeSession: true,
+							earlyData:     true,
+							flags: append([]string{
+								"-reverify-on-resume",
+							}, flags...),
+						})
+						tests = append(tests, testCase{
+							testType: testType,
+							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
+							config: Config{
+								MaxVersion: vers.version,
+							},
+							resumeSession: true,
+							earlyData:     true,
+							shouldFail:    true,
+							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
+							// We do not set expectedLocalError here because the shim rejects
+							// the connection without an alert.
+							flags: append([]string{
+								"-reverify-on-resume",
+								"-on-resume-verify-fail",
+							}, flags...),
+						})
+					}
+				}
+			}
+		}
+
+		// By default, the client is in a soft fail mode where the peer
+		// certificate is verified but failures are non-fatal.
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "CertificateVerificationSoftFail-" + vers.name,
+			config: Config{
+				MaxVersion: vers.version,
+				Credential: &rsaCertificate,
+			},
+			flags: []string{
+				"-verify-fail",
+				"-expect-verify-result",
+			},
+			resumeSession: true,
+		})
+	}
+
+	tests = append(tests, testCase{
+		name:               "ShimSendAlert",
+		flags:              []string{"-send-alert"},
+		shimWritesFirst:    true,
+		shouldFail:         true,
+		expectedLocalError: "remote error: decompression failure",
+	})
+
+	if config.protocol == tls {
+		tests = append(tests, testCase{
+			name: "Renegotiate-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			renegotiate: 1,
+			flags: []string{
+				"-renegotiate-freely",
+				"-expect-total-renegotiations", "1",
+			},
+		})
+
+		tests = append(tests, testCase{
+			name: "Renegotiate-Client-Explicit",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			renegotiate: 1,
+			flags: []string{
+				"-renegotiate-explicit",
+				"-expect-total-renegotiations", "1",
+			},
+		})
+
+		halfHelloRequestError := ":UNEXPECTED_RECORD:"
+		if config.packHandshake {
+			// If the HelloRequest is sent in the same record as the server Finished,
+			// BoringSSL rejects it before the handshake completes.
+			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
+		}
+		tests = append(tests, testCase{
+			name: "SendHalfHelloRequest",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					PackHelloRequestWithFinished: config.packHandshake,
+				},
+			},
+			sendHalfHelloRequest: true,
+			flags:                []string{"-renegotiate-ignore"},
+			shouldFail:           true,
+			expectedError:        halfHelloRequestError,
+		})
+
+		// NPN on client and server; results in post-ChangeCipherSpec message.
+		tests = append(tests, testCase{
+			name: "NPN-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"foo"},
+			},
+			flags:         []string{"-select-next-proto", "foo"},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				nextProto:     "foo",
+				nextProtoType: npn,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "NPN-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"bar"},
+			},
+			flags: []string{
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+				"-expect-next-proto", "bar",
+			},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				nextProto:     "bar",
+				nextProtoType: npn,
+			},
+		})
+
+		// The client may select no protocol after seeing the server list.
+		tests = append(tests, testCase{
+			name: "NPN-Client-ClientSelectEmpty",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"foo"},
+			},
+			flags:         []string{"-select-empty-next-proto"},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				noNextProto:   true,
+				nextProtoType: npn,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "NPN-Server-ClientSelectEmpty",
+			config: Config{
+				MaxVersion:          VersionTLS12,
+				NextProtos:          []string{"no-match"},
+				NoFallbackNextProto: true,
+			},
+			flags: []string{
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+				"-expect-no-next-proto",
+			},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				noNextProto:   true,
+				nextProtoType: npn,
+			},
+		})
+
+		// The server may negotiate NPN, despite offering no protocols. In this
+		// case, the server must still be prepared for the client to select a
+		// fallback protocol.
+		tests = append(tests, testCase{
+			name: "NPN-Client-ServerAdvertiseEmpty",
+			config: Config{
+				MaxVersion:               VersionTLS12,
+				NegotiateNPNWithNoProtos: true,
+			},
+			flags:         []string{"-select-next-proto", "foo"},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				nextProto:     "foo",
+				nextProtoType: npn,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "NPN-Server-ServerAdvertiseEmpty",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"foo"},
+			},
+			flags: []string{
+				"-advertise-empty-npn",
+				"-expect-next-proto", "foo",
+			},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				nextProto:     "foo",
+				nextProtoType: npn,
+			},
+		})
+
+		// Client does False Start and negotiates NPN.
+		tests = append(tests, testCase{
+			name: "FalseStart",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart: true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-select-next-proto", "foo",
+			},
+			shimWritesFirst: true,
+			resumeSession:   true,
+		})
+
+		// Client does False Start and negotiates ALPN.
+		tests = append(tests, testCase{
+			name: "FalseStart-ALPN",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart: true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-advertise-alpn", "\x03foo",
+				"-expect-alpn", "foo",
+			},
+			shimWritesFirst: true,
+			resumeSession:   true,
+		})
+
+		// False Start without session tickets.
+		tests = append(tests, testCase{
+			name: "FalseStart-SessionTicketsDisabled",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:             []string{"foo"},
+				SessionTicketsDisabled: true,
+				Bugs: ProtocolBugs{
+					ExpectFalseStart: true,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-select-next-proto", "foo",
+			},
+			shimWritesFirst: true,
+		})
+
+		// Server parses a V2ClientHello. Test different lengths for the
+		// challenge field.
+		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
+			tests = append(tests, testCase{
+				testType: serverTest,
+				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
+				config: Config{
+					// Choose a cipher suite that does not involve
+					// elliptic curves, so no extensions are
+					// involved.
+					MaxVersion:   VersionTLS12,
+					CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+					Bugs: ProtocolBugs{
+						SendV2ClientHello:            true,
+						V2ClientHelloChallengeLength: challengeLength,
+					},
+				},
+				flags: []string{
+					"-expect-msg-callback",
+					`read v2clienthello
+write hs 2
+write hs 11
+write hs 14
+read hs 16
+read ccs
+read hs 20
+write ccs
+write hs 20
+read alert 1 0
+`,
+				},
+			})
+		}
+
+		// Channel ID and NPN at the same time, to ensure their relative
+		// ordering is correct.
+		tests = append(tests, testCase{
+			name: "ChannelID-NPN-Client",
+			config: Config{
+				MaxVersion:       VersionTLS12,
+				RequestChannelID: true,
+				NextProtos:       []string{"foo"},
+			},
+			flags: []string{
+				"-send-channel-id", channelIDKeyPath,
+				"-select-next-proto", "foo",
+			},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				channelID:     true,
+				nextProto:     "foo",
+				nextProtoType: npn,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ChannelID-NPN-Server",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ChannelID:  &channelIDKey,
+				NextProtos: []string{"bar"},
+			},
+			flags: []string{
+				"-expect-channel-id",
+				base64FlagValue(channelIDBytes),
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+				"-expect-next-proto", "bar",
+			},
+			resumeSession: true,
+			expectations: connectionExpectations{
+				channelID:     true,
+				nextProto:     "bar",
+				nextProtoType: npn,
+			},
+		})
+
+		// Bidirectional shutdown with the runner initiating.
+		tests = append(tests, testCase{
+			name: "Shutdown-Runner",
+			config: Config{
+				Bugs: ProtocolBugs{
+					ExpectCloseNotify: true,
+				},
+			},
+			flags: []string{"-check-close-notify"},
+		})
+	}
+	if config.protocol != dtls {
+		// Test Channel ID
+		for _, ver := range allVersions(config.protocol) {
+			if ver.version < VersionTLS10 {
+				continue
+			}
+			// Client sends a Channel ID.
+			tests = append(tests, testCase{
+				name: "ChannelID-Client-" + ver.name,
+				config: Config{
+					MaxVersion:       ver.version,
+					RequestChannelID: true,
+				},
+				flags:         []string{"-send-channel-id", channelIDKeyPath},
+				resumeSession: true,
+				expectations: connectionExpectations{
+					channelID: true,
+				},
+			})
+
+			// Server accepts a Channel ID.
+			tests = append(tests, testCase{
+				testType: serverTest,
+				name:     "ChannelID-Server-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					ChannelID:  &channelIDKey,
+				},
+				flags: []string{
+					"-expect-channel-id",
+					base64FlagValue(channelIDBytes),
+				},
+				resumeSession: true,
+				expectations: connectionExpectations{
+					channelID: true,
+				},
+			})
+
+			tests = append(tests, testCase{
+				testType: serverTest,
+				name:     "InvalidChannelIDSignature-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					ChannelID:  &channelIDKey,
+					Bugs: ProtocolBugs{
+						InvalidChannelIDSignature: true,
+					},
+				},
+				flags:         []string{"-enable-channel-id"},
+				shouldFail:    true,
+				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
+			})
+
+			if ver.version < VersionTLS13 {
+				// Channel ID requires ECDHE ciphers.
+				tests = append(tests, testCase{
+					testType: serverTest,
+					name:     "ChannelID-NoECDHE-" + ver.name,
+					config: Config{
+						MaxVersion:   ver.version,
+						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						ChannelID:    &channelIDKey,
+					},
+					expectations: connectionExpectations{
+						channelID: false,
+					},
+					flags: []string{"-enable-channel-id"},
+				})
+
+				// Sanity-check setting expectations.channelID false works.
+				tests = append(tests, testCase{
+					testType: serverTest,
+					name:     "ChannelID-ECDHE-" + ver.name,
+					config: Config{
+						MaxVersion:   ver.version,
+						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+						ChannelID:    &channelIDKey,
+					},
+					expectations: connectionExpectations{
+						channelID: false,
+					},
+					flags:              []string{"-enable-channel-id"},
+					shouldFail:         true,
+					expectedLocalError: "channel ID unexpectedly negotiated",
+				})
+			}
+		}
+
+		if !config.implicitHandshake {
+			// Bidirectional shutdown with the shim initiating. The runner,
+			// in the meantime, sends garbage before the close_notify which
+			// the shim must ignore. This test is disabled under implicit
+			// handshake tests because the shim never reads or writes.
+
+			// Tests that require checking for a close notify alert don't work with
+			// QUIC because alerts are handled outside of the TLS stack in QUIC.
+			if config.protocol != quic {
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim",
+					config: Config{
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown:     true,
+					sendEmptyRecords:  1,
+					sendWarningAlerts: 1,
+					flags:             []string{"-check-close-notify"},
+				})
+
+				// The shim should reject unexpected application data
+				// when shutting down.
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim-ApplicationData",
+					config: Config{
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown:     true,
+					messageCount:      1,
+					sendEmptyRecords:  1,
+					sendWarningAlerts: 1,
+					flags:             []string{"-check-close-notify"},
+					shouldFail:        true,
+					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
+				})
+
+				// Test that SSL_shutdown still processes KeyUpdate.
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim-KeyUpdate",
+					config: Config{
+						MinVersion: VersionTLS13,
+						MaxVersion: VersionTLS13,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown:    true,
+					sendKeyUpdates:   1,
+					keyUpdateRequest: keyUpdateRequested,
+					flags:            []string{"-check-close-notify"},
+				})
+
+				// Test that SSL_shutdown processes HelloRequest
+				// correctly.
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim-HelloRequest-Ignore",
+					config: Config{
+						MinVersion: VersionTLS12,
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							SendHelloRequestBeforeEveryAppDataRecord: true,
+							ExpectCloseNotify:                        true,
+						},
+					},
+					shimShutsDown: true,
+					flags: []string{
+						"-renegotiate-ignore",
+						"-check-close-notify",
+					},
+				})
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim-HelloRequest-Reject",
+					config: Config{
+						MinVersion: VersionTLS12,
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown: true,
+					renegotiate:   1,
+					shouldFail:    true,
+					expectedError: ":NO_RENEGOTIATION:",
+					flags:         []string{"-check-close-notify"},
+				})
+				tests = append(tests, testCase{
+					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
+					config: Config{
+						MinVersion: VersionTLS12,
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown: true,
+					renegotiate:   1,
+					shouldFail:    true,
+					expectedError: ":NO_RENEGOTIATION:",
+					flags: []string{
+						"-check-close-notify",
+						"-renegotiate-freely",
+					},
+				})
+
+				tests = append(tests, testCase{
+					testType: serverTest,
+					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
+					config: Config{
+						MaxVersion: VersionTLS12,
+						Bugs: ProtocolBugs{
+							ExpectCloseNotify: true,
+						},
+					},
+					shimShutsDown: true,
+					renegotiate:   1,
+					shouldFail:    true,
+					expectedError: ":NO_RENEGOTIATION:",
+					flags: []string{
+						"-check-close-notify",
+					},
+				})
+			}
+		}
+	}
+	if config.protocol == dtls {
+		tests = append(tests, testCase{
+			name: "SkipHelloVerifyRequest",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SkipHelloVerifyRequest: true,
+				},
+			},
+		})
+		tests = append(tests, testCase{
+			name: "DTLS13-HelloVerifyRequest",
+			config: Config{
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ForceHelloVerifyRequest: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":INVALID_MESSAGE:",
+		})
+		tests = append(tests, testCase{
+			name: "DTLS13-HelloVerifyRequestEmptyCookie",
+			config: Config{
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ForceHelloVerifyRequest:       true,
+					EmptyHelloVerifyRequestCookie: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":INVALID_MESSAGE:",
+		})
+	}
+
+	for _, test := range tests {
+		test.protocol = config.protocol
+		test.name += "-" + config.protocol.String()
+		if config.async {
+			test.name += "-Async"
+			test.flags = append(test.flags, "-async")
+		} else {
+			test.name += "-Sync"
+		}
+		if config.splitHandshake {
+			test.name += "-SplitHandshakeRecords"
+			test.config.Bugs.MaxHandshakeRecordLength = 1
+			if config.protocol == dtls {
+				test.config.Bugs.MaxPacketLength = 256
+				test.flags = append(test.flags, "-mtu", "256")
+			}
+		}
+		if config.packHandshake {
+			test.name += "-PackHandshake"
+			if config.protocol == dtls {
+				test.config.Bugs.MaxHandshakeRecordLength = 2
+				test.config.Bugs.PackHandshakeFragments = 20
+				test.config.Bugs.PackHandshakeRecords = 1500
+				test.config.Bugs.PackAppDataWithHandshake = true
+			} else {
+				test.config.Bugs.PackHandshakeFlight = true
+			}
+		}
+		if config.implicitHandshake {
+			test.name += "-ImplicitHandshake"
+			test.flags = append(test.flags, "-implicit-handshake")
+		}
+		testCases = append(testCases, test)
+	}
+}
diff --git a/src/ssl/test/runner/tls13_tests.go b/src/ssl/test/runner/tls13_tests.go
new file mode 100644
index 0000000..2b08ec8
--- /dev/null
+++ b/src/ssl/test/runner/tls13_tests.go
@@ -0,0 +1,2066 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "strconv"
+
+func addTLS13RecordTests() {
+	for _, protocol := range []protocol{tls, dtls} {
+		testCases = append(testCases, testCase{
+			protocol: protocol,
+			name:     "TLS13-RecordPadding-" + protocol.String(),
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					RecordPadding: 10,
+				},
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			protocol: protocol,
+			name:     "TLS13-EmptyRecords-" + protocol.String(),
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					OmitRecordContents: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+		})
+
+		testCases = append(testCases, testCase{
+			protocol: protocol,
+			name:     "TLS13-OnlyPadding-" + protocol.String(),
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					OmitRecordContents: true,
+					RecordPadding:      10,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+		})
+
+		if protocol == tls {
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "TLS13-WrongOuterRecord-" + protocol.String(),
+				config: Config{
+					MaxVersion: VersionTLS13,
+					MinVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						OuterRecordType: recordTypeHandshake,
+					},
+				},
+				shouldFail:    true,
+				expectedError: ":INVALID_OUTER_RECORD_TYPE:",
+			})
+		}
+	}
+}
+
+func addTLS13HandshakeTests() {
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "NegotiatePSKResumption-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiatePSKResumption: true,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "MissingKeyShare-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				MissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MissingKeyShare-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				MissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DuplicateKeyShares-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				DuplicateKeyShares: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DUPLICATE_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+		},
+	})
+
+	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
+	// resumption.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ResumeTLS12SessionID-TLS13",
+		config: Config{
+			MaxVersion:             VersionTLS12,
+			SessionTicketsDisabled: true,
+		},
+		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
+		resumeSession: true,
+	})
+
+	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
+	// a TLS 1.2 session ID.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS12SessionID-TLS13",
+		config: Config{
+			MaxVersion:             VersionTLS12,
+			SessionTicketsDisabled: true,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+
+	// Test that the server correctly echoes back session IDs of
+	// various lengths. The first test additionally asserts that
+	// BoringSSL always sends the ChangeCipherSpec messages for
+	// compatibility mode, rather than negotiating it based on the
+	// ClientHello.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EmptySessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientHelloSessionID: []byte{},
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Server-ShortSessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientHelloSessionID: make([]byte, 16),
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Server-FullSessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientHelloSessionID: make([]byte, 32),
+			},
+		},
+	})
+
+	// The server should reject ClientHellos whose session IDs are too long.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Server-TooLongSessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientHelloSessionID: make([]byte, 33),
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":CLIENTHELLO_PARSE_FAILED:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Server-TooLongSessionID-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendClientHelloSessionID: make([]byte, 33),
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":CLIENTHELLO_PARSE_FAILED:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	// Test that the client correctly accepts or rejects short session IDs from
+	// the server. Our tests use 32 bytes by default, so the boundary condition
+	// is already covered.
+	testCases = append(testCases, testCase{
+		name: "Client-ShortSessionID",
+		config: Config{
+			MaxVersion:             VersionTLS12,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				NewSessionIDLength: 1,
+			},
+		},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		name: "Client-TooLongSessionID",
+		config: Config{
+			MaxVersion:             VersionTLS12,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				NewSessionIDLength: 33,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	// Test that the client sends a fake session ID in TLS 1.3. We cover both
+	// normal and resumption handshakes to capture interactions with the
+	// session resumption path.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13SessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectClientHelloSessionID: true,
+			},
+		},
+		resumeSession: true,
+	})
+
+	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS12NoSessionID-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectNoSessionID: true,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-on-initial-expect-early-data-reason", "no_session_offered",
+			"-on-resume-expect-early-data-reason", "accept",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Reject-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysRejectEarlyData: true,
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-retry-expect-early-data-reason", "peer_declined",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+		},
+		messageCount:  2,
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-on-initial-expect-early-data-reason", "no_session_offered",
+			"-on-resume-expect-early-data-reason", "accept",
+		},
+	})
+
+	// The above tests the most recent ticket. Additionally test that 0-RTT
+	// works on the first ticket issued by the server.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-FirstTicket-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				UseFirstSessionTicket: true,
+			},
+		},
+		messageCount:  2,
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-on-resume-expect-early-data-reason", "accept",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				OmitEarlyDataExtension:  true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				OmitEarlyDataExtension:  true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_RECORD:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-TooMuchData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 16384 + 1,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-Interleaved-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				InterleaveEarlyData:     true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		// Though the session is not resumed and we send HelloRetryRequest,
+		// early data being disabled takes priority as the reject reason.
+		flags: []string{"-expect-early-data-reason", "disabled"},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				InterleaveEarlyData:     true,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 16384 + 1,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+	})
+
+	// Test that skipping early data looking for cleartext correctly
+	// processes an alert record.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyAlert:          true,
+				SendFakeEarlyDataLength: 4,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyDataOnSecondClientHello: true,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: bad record MAC",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EmptyEncryptedExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				EmptyEncryptedExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EncryptedExtensionsWithKeyShare-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				EncryptedExtensionsWithKeyShare: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: unsupported extension",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendHelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves:    []CurveID{},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		expectations: connectionExpectations{
+			curveID: CurveX25519,
+		},
+		flags: []string{"-expect-hrr"},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendHelloRetryRequest-2-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			DefaultCurves:    []CurveID{CurveP384},
+			CurvePreferences: []CurveID{CurveX25519, CurveP384},
+		},
+		// Although the ClientHello did not predict our preferred curve,
+		// we always select it whether it is predicted or not.
+		expectations: connectionExpectations{
+			curveID: CurveX25519,
+		},
+		flags: []string{"-expect-hrr"},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnknownCurve-HelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-CipherChange-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
+				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CIPHER_RETURNED:",
+	})
+
+	// Test that the client does not offer a PSK in the second ClientHello if the
+	// HelloRetryRequest is incompatible with it.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			CipherSuites: []uint16{
+				TLS_AES_128_GCM_SHA256,
+			},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectNoTLS13PSKAfterHRR: true,
+			},
+			CipherSuites: []uint16{
+				TLS_AES_256_GCM_SHA384,
+			},
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+
+	testCases = append(testCases, testCase{
+		name: "DisabledCurve-HelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				IgnorePeerCurvePreferences: true,
+			},
+		},
+		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnnecessaryHelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCurve: CurveX25519,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SecondHelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SecondHelloRetryRequest: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Empty-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSendHelloRetryRequest: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCurve-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires a HelloRetryRequest against BoringSSL's default
+			// configuration. Assert this ExpectMissingKeyShare.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectMissingKeyShare:                true,
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCookie-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie:          []byte("cookie"),
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-EmptyCookie-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie-Curve-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+				ExpectMissingKeyShare:       true,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Unknown-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomHelloRetryRequestExtension: "extension",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SecondClientHelloMissingKeyShare-TLS13",
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				SecondClientHelloMissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SecondClientHelloWrongCurve-TLS13",
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				MisinterpretHelloRetryRequestCurve: CurveP521,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequestVersionMismatch-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendServerHelloVersion: 0x0305,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequestCurveMismatch-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				// Send P-384 (correct) in the HelloRetryRequest.
+				SendHelloRetryRequestCurve: CurveP384,
+				// But send P-256 in the ServerHello.
+				SendCurve: CurveP256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	// Test the server selecting a curve that requires a HelloRetryRequest
+	// without sending it.
+	testCases = append(testCases, testCase{
+		name: "SkipHelloRetryRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SkipHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SecondServerHelloNoVersion-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				OmitServerSupportedVersionExtension: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
+	})
+	testCases = append(testCases, testCase{
+		name: "SecondServerHelloWrongVersion-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendServerSupportedVersionExtension: 0x1234,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "RequestContextInHandshake-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				SendRequestContext: []byte("request context"),
+			},
+		},
+		shimCertificate: &rsaCertificate,
+		shouldFail:      true,
+		expectedError:   ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnknownExtensionInCertificateRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				SendCustomCertificateRequest: 0x1212,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+	})
+
+	testCases = append(testCases, testCase{
+		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				OmitCertificateRequestAlgorithms: true,
+			},
+		},
+		shimCertificate: &rsaCertificate,
+		shouldFail:      true,
+		expectedError:   ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrailingKeyShareData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				TrailingKeyShareData: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "AlwaysSelectPSKIdentity-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSelectPSKIdentity: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "InvalidPSKIdentity-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SelectPSKIdentityOnResume: 1,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraPSKIdentity-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExtraPSKIdentity:   true,
+				SendExtraPSKBinder: true,
+			},
+		},
+		resumeSession: true,
+	})
+
+	// Test that unknown NewSessionTicket extensions are tolerated.
+	testCases = append(testCases, testCase{
+		name: "CustomTicketExtension-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomTicketExtension: "1234",
+			},
+		},
+	})
+
+	// Test the client handles 0-RTT being rejected by a full handshake
+	// and correctly reports a certificate change.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-RejectTicket-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &rsaCertificate,
+		},
+		resumeConfig: &Config{
+			MaxVersion:             VersionTLS13,
+			Credential:             &ecdsaP256Certificate,
+			SessionTicketsDisabled: true,
+		},
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-retry-expect-early-data-reason", "session_not_resumed",
+			// Test the peer certificate is reported correctly in each of the
+			// three logical connections.
+			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
+			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
+			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
+			// Session tickets are disabled, so the runner will not send a ticket.
+			"-on-retry-expect-no-session",
+		},
+	})
+
+	// Test the server rejects 0-RTT if it does not recognize the ticket.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-RejectTicket-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Corrupt the ticket.
+				FilterTicket: func(in []byte) ([]byte, error) {
+					in[len(in)-1] ^= 1
+					return in, nil
+				},
+			},
+		},
+		messageCount:            2,
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-resume-expect-early-data-reason", "session_not_resumed",
+		},
+	})
+
+	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-HRR-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-retry-expect-early-data-reason", "hello_retry_request",
+		},
+	})
+
+	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-HRR-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves: []CurveID{},
+		},
+		messageCount:            2,
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-resume-expect-early-data-reason", "hello_retry_request",
+		},
+	})
+
+	// Test the client handles a 0-RTT reject from both ticket rejection and
+	// HelloRetryRequest.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Credential: &rsaCertificate,
+		},
+		resumeConfig: &Config{
+			MaxVersion:             VersionTLS13,
+			Credential:             &ecdsaP256Certificate,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+			},
+		},
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			// The client sees HelloRetryRequest before the resumption result,
+			// though neither value is inherently preferable.
+			"-on-retry-expect-early-data-reason", "hello_retry_request",
+			// Test the peer certificate is reported correctly in each of the
+			// three logical connections.
+			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
+			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
+			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
+			// Session tickets are disabled, so the runner will not send a ticket.
+			"-on-retry-expect-no-session",
+		},
+	})
+
+	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				// Corrupt the ticket.
+				FilterTicket: func(in []byte) ([]byte, error) {
+					in[len(in)-1] ^= 1
+					return in, nil
+				},
+			},
+		},
+		messageCount:            2,
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			// The server sees the missed resumption before HelloRetryRequest,
+			// though neither value is inherently preferable.
+			"-on-resume-expect-early-data-reason", "session_not_resumed",
+		},
+	})
+
+	// The client must check the server does not send the early_data
+	// extension while rejecting the session.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataWithoutResume-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:             VersionTLS13,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				SendEarlyDataExtension: true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// The client must fail with a dedicated error code if the server
+	// responds with TLS 1.2 when offering 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataVersionDowngrade-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
+	})
+
+	// Same as above, but the server also sends a warning alert before the
+	// ServerHello. Although the shim predicts TLS 1.3 for 0-RTT, it should
+	// still interpret data before ServerHello in a TLS-1.2-compatible way.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataVersionDowngrade-Client-TLS13-WarningAlert",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSNIWarningAlert: true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
+	})
+
+	// Test that the client rejects an (unsolicited) early_data extension if
+	// the server sent an HRR.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+				SendEarlyDataExtension:      true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		// The client will first process an early data reject from the HRR.
+		expectEarlyDataRejected: true,
+		shouldFail:              true,
+		expectedError:           ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "SkipChangeCipherSpec-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipChangeCipherSpec-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TooManyChangeCipherSpec-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtraChangeCipherSpec: 33,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TooManyChangeCipherSpec-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtraChangeCipherSpec: 33,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendPostHandshakeChangeCipherSpec-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPostHandshakeChangeCipherSpec: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_RECORD:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	fooString := "foo"
+	barString := "bar"
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject
+	// that changed it.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-ALPNMismatch-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &fooString,
+			},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &barString,
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			// The client does not learn ALPN was the cause.
+			"-on-retry-expect-early-data-reason", "peer_declined",
+			// In the 0-RTT state, we surface the predicted ALPN. After
+			// processing the reject, we surface the real one.
+			"-on-initial-expect-alpn", "foo",
+			"-on-resume-expect-alpn", "foo",
+			"-on-retry-expect-alpn", "bar",
+		},
+	})
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject if
+	// ALPN was omitted from the first connection.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			// The client does not learn ALPN was the cause.
+			"-on-retry-expect-early-data-reason", "peer_declined",
+			// In the 0-RTT state, we surface the predicted ALPN. After
+			// processing the reject, we surface the real one.
+			"-on-initial-expect-alpn", "",
+			"-on-resume-expect-alpn", "",
+			"-on-retry-expect-alpn", "foo",
+		},
+	})
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject if
+	// ALPN was omitted from the second connection.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			// The client does not learn ALPN was the cause.
+			"-on-retry-expect-early-data-reason", "peer_declined",
+			// In the 0-RTT state, we surface the predicted ALPN. After
+			// processing the reject, we surface the real one.
+			"-on-initial-expect-alpn", "foo",
+			"-on-resume-expect-alpn", "foo",
+			"-on-retry-expect-alpn", "",
+		},
+	})
+
+	// Test that the client enforces ALPN match on 0-RTT accept.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &fooString,
+			},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysAcceptEarlyData: true,
+				ALPNProtocol:          &barString,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			"-on-initial-expect-alpn", "foo",
+			"-on-resume-expect-alpn", "foo",
+			"-on-retry-expect-alpn", "bar",
+		},
+		shouldFail:         true,
+		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	// Test that the client does not offer early data if it is incompatible
+	// with ALPN preferences.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			NextProtos:       []string{"foo", "bar"},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-ticket-supports-early-data",
+			"-expect-no-offer-early-data",
+			// Offer different ALPN values in the initial and resumption.
+			"-on-initial-advertise-alpn", "\x03foo",
+			"-on-initial-expect-alpn", "foo",
+			"-on-resume-advertise-alpn", "\x03bar",
+			"-on-resume-expect-alpn", "bar",
+			// The ALPN mismatch comes from the client, so it reports it as the
+			// reason.
+			"-on-resume-expect-early-data-reason", "alpn_mismatch",
+		},
+	})
+
+	// Test that the client does not offer 0-RTT to servers which never
+	// advertise it.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-on-resume-expect-no-offer-early-data",
+			// The client declines to offer 0-RTT because of the session.
+			"-on-resume-expect-early-data-reason", "unsupported_for_session",
+		},
+	})
+
+	// Test that the server correctly rejects 0-RTT when the previous
+	// session did not allow early data on resumption.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession: true,
+		// This test configures early data manually instead of the earlyData
+		// option, to customize the -enable-early-data flag.
+		flags: []string{
+			"-on-resume-enable-early-data",
+			"-expect-reject-early-data",
+			// The server rejects 0-RTT because of the session.
+			"-on-resume-expect-early-data-reason", "unsupported_for_session",
+		},
+	})
+
+	// Test that we reject early data where ALPN is omitted from the first
+	// connection, but negotiated in the second.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-initial-select-alpn", "",
+			"-on-resume-select-alpn", "foo",
+			"-on-resume-expect-early-data-reason", "alpn_mismatch",
+		},
+	})
+
+	// Test that we reject early data where ALPN is omitted from the second
+	// connection, but negotiated in the first.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-initial-select-alpn", "foo",
+			"-on-resume-select-alpn", "",
+			"-on-resume-expect-early-data-reason", "alpn_mismatch",
+		},
+	})
+
+	// Test that we reject early data with mismatched ALPN.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-ALPNMismatch-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"bar"},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-initial-select-alpn", "foo",
+			"-on-resume-select-alpn", "bar",
+			"-on-resume-expect-early-data-reason", "alpn_mismatch",
+		},
+	})
+
+	// Test that the client offering 0-RTT and Channel ID forbids the server
+	// from accepting both.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			RequestChannelID: true,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		expectations: connectionExpectations{
+			channelID: true,
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
+		expectedLocalError: "remote error: illegal parameter",
+		flags: []string{
+			"-send-channel-id", channelIDKeyPath,
+		},
+	})
+
+	// Test that the client offering Channel ID and 0-RTT allows the server
+	// to decline 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			RequestChannelID: true,
+			Bugs: ProtocolBugs{
+				AlwaysRejectEarlyData: true,
+			},
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		expectations: connectionExpectations{
+			channelID: true,
+		},
+		flags: []string{
+			"-send-channel-id", channelIDKeyPath,
+			// The client never learns the reason was Channel ID.
+			"-on-retry-expect-early-data-reason", "peer_declined",
+		},
+	})
+
+	// Test that the client offering Channel ID and 0-RTT allows the server
+	// to decline Channel ID.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-send-channel-id", channelIDKeyPath,
+		},
+	})
+
+	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
+	// if it would negotiate Channel ID.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ChannelID:  &channelIDKey,
+		},
+		resumeSession:           true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		expectations: connectionExpectations{
+			channelID: true,
+		},
+		flags: []string{
+			"-expect-channel-id",
+			base64FlagValue(channelIDBytes),
+			"-on-resume-expect-early-data-reason", "channel_id",
+		},
+	})
+
+	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
+	// if not offered Channel ID.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		expectations: connectionExpectations{
+			channelID: false,
+		},
+		flags: []string{
+			"-enable-channel-id",
+			"-on-resume-expect-early-data-reason", "accept",
+		},
+	})
+
+	// Test that the server errors on 0-RTT streams without EndOfEarlyData.
+	// The subsequent records should fail to decrypt.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SkipEndOfEarlyData: true,
+			},
+		},
+		resumeSession:      true,
+		earlyData:          true,
+		shouldFail:         true,
+		expectedLocalError: "remote error: bad record MAC",
+		expectedError:      ":BAD_DECRYPT:",
+	})
+
+	// Test that EndOfEarlyData is rejected in QUIC. Since we leave application
+	// data to the QUIC implementation, we never accept any data at all in
+	// the 0-RTT epoch, so the error is that the encryption level is rejected
+	// outright.
+	//
+	// TODO(crbug.com/381113363): Test this for DTLS 1.3 as well.
+	testCases = append(testCases, testCase{
+		protocol: quic,
+		testType: serverTest,
+		name:     "EarlyData-UnexpectedEndOfEarlyData-QUIC",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEndOfEarlyDataInQUICAndDTLS: true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":WRONG_ENCRYPTION_LEVEL_RECEIVED:",
+	})
+
+	// Test that the server errors on 0-RTT streams with a stray handshake
+	// message in them.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendStrayEarlyHandshake: true,
+			},
+		},
+		resumeSession:      true,
+		earlyData:          true,
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// Test that the client reports TLS 1.3 as the version while sending
+	// early data.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Client-VersionAPI-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-expect-version", strconv.Itoa(VersionTLS13),
+			// EMS and RI are always reported as supported when we report
+			// TLS 1.3.
+			"-expect-extended-master-secret",
+			"-expect-secure-renegotiation",
+		},
+	})
+
+	// Test that client and server both notice handshake errors after data
+	// has started flowing.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Client-BadFinished-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				BadFinished: true,
+			},
+		},
+		resumeSession:      true,
+		earlyData:          true,
+		shouldFail:         true,
+		expectedError:      ":DIGEST_CHECK_FAILED:",
+		expectedLocalError: "remote error: error decrypting message",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyData-Server-BadFinished-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				BadFinished: true,
+			},
+		},
+		resumeSession:      true,
+		earlyData:          true,
+		shouldFail:         true,
+		expectedError:      ":DIGEST_CHECK_FAILED:",
+		expectedLocalError: "remote error: error decrypting message",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NonEmptyEndOfEarlyData: true,
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerSkipCertificateVerify-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			Credential: &rsaChainCertificate,
+			Bugs: ProtocolBugs{
+				SkipCertificateVerify: true,
+			},
+		},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+		shimCertificate: &rsaCertificate,
+		flags: []string{
+			"-require-any-client-certificate",
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientSkipCertificateVerify-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			Credential: &rsaChainCertificate,
+			Bugs: ProtocolBugs{
+				SkipCertificateVerify: true,
+			},
+		},
+		expectations: connectionExpectations{
+			peerCertificate: &rsaCertificate,
+		},
+		shimCertificate:    &rsaCertificate,
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// PSK/resumption handshakes should not accept CertificateRequest or
+	// Certificate messages.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "CertificateInResumption-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSendCertificate: true,
+			},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "CertificateRequestInResumption-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				AlwaysSendCertificateRequest: true,
+			},
+		},
+		shimCertificate:    &rsaCertificate,
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_MESSAGE:",
+		expectedLocalError: "remote error: unexpected message",
+	})
+
+	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
+	// report a reason of protocol_version.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyDataEnabled-Client-MaxTLS12",
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+		flags: []string{
+			"-enable-early-data",
+			"-max-version", strconv.Itoa(VersionTLS12),
+			"-expect-early-data-reason", "protocol_version",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyDataEnabled-Server-MaxTLS12",
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+		flags: []string{
+			"-enable-early-data",
+			"-max-version", strconv.Itoa(VersionTLS12),
+			"-expect-early-data-reason", "protocol_version",
+		},
+	})
+
+	// The server additionally reports protocol_version if it enabled TLS 1.3,
+	// but the peer negotiated TLS 1.2. (The corresponding situation does not
+	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
+	// is a fatal error.)
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-reason", "protocol_version",
+		},
+	})
+
+	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
+	// different PRF hash. Test that the client handles this correctly.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
+		},
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			// The client initially reports the old cipher suite while sending
+			// early data. After processing the 0-RTT reject, it reports the
+			// true cipher suite.
+			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
+			// P-384 requires a HelloRetryRequest against BoringSSL's default
+			// configuration. Assert this with ExpectMissingKeyShare.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectMissingKeyShare: true,
+			},
+		},
+		resumeSession:           true,
+		expectResumeRejected:    true,
+		earlyData:               true,
+		expectEarlyDataRejected: true,
+		flags: []string{
+			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			// The client initially reports the old cipher suite while sending
+			// early data. After processing the 0-RTT reject, it reports the
+			// true cipher suite.
+			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
+		},
+	})
+
+	// Test that the client enforces cipher suite match on 0-RTT accept.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-CipherMismatch-Client-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				AlwaysAcceptEarlyData: true,
+			},
+		},
+		resumeSession:      true,
+		earlyData:          true,
+		shouldFail:         true,
+		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	// Test that the client can write early data when it has received a partial
+	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
+	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
+	// separate records, i.e. that PackHandshakeFlight is disabled.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-WriteAfterServerHello",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Write the server response before expecting early data.
+				ExpectEarlyData:     [][]byte{},
+				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-async",
+			"-on-resume-early-write-after-message",
+			strconv.Itoa(int(typeServerHello)),
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EarlyData-WriteAfterEncryptedExtensions",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				// Write the server response before expecting early data.
+				ExpectEarlyData:     [][]byte{},
+				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
+			},
+		},
+		resumeSession: true,
+		earlyData:     true,
+		flags: []string{
+			"-async",
+			"-on-resume-early-write-after-message",
+			strconv.Itoa(int(typeEncryptedExtensions)),
+		},
+	})
+}
+
+func addTLS13CipherPreferenceTests() {
+	// Test that client preference is honored if the shim has AES hardware
+	// and ChaCha20-Poly1305 is preferred otherwise.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			CipherSuites: []uint16{
+				TLS_CHACHA20_POLY1305_SHA256,
+				TLS_AES_128_GCM_SHA256,
+			},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			CipherSuites: []uint16{
+				TLS_AES_128_GCM_SHA256,
+				TLS_CHACHA20_POLY1305_SHA256,
+			},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+
+	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
+	// whether it has AES hardware.
+	testCases = append(testCases, testCase{
+		name: "TLS13-CipherPreference-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Use the client cipher order. (This is the default but
+			// is listed to be explicit.)
+			PreferServerCipherSuites: false,
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+}
diff --git a/src/ssl/test/runner/trust_anchor_tests.go b/src/ssl/test/runner/trust_anchor_tests.go
new file mode 100644
index 0000000..bdb7812
--- /dev/null
+++ b/src/ssl/test/runner/trust_anchor_tests.go
@@ -0,0 +1,277 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+import "golang.org/x/crypto/cryptobyte"
+
+func trustAnchorListFlagValue(ids ...[]byte) string {
+	b := cryptobyte.NewBuilder(nil)
+	for _, id := range ids {
+		addUint8LengthPrefixedBytes(b, id)
+	}
+	return base64FlagValue(b.BytesOrPanic())
+}
+
+func addTrustAnchorTests() {
+	id1 := []byte{1}
+	id2 := []byte{2, 2}
+	id3 := []byte{3, 3, 3}
+
+	// Unsolicited trust_anchors extensions should be rejected.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-Unsolicited-Certificate",
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysMatchTrustAnchorID: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: unsupported extension",
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-Unsolicited-EncryptedExtensions",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Bugs: ProtocolBugs{
+				AlwaysSendAvailableTrustAnchors: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: unsupported extension",
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+	})
+
+	// Test that the client sends trust anchors when configured, and correctly
+	// reports the server's response.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-ClientRequest-Match",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Credential:            rsaChainCertificate.WithTrustAnchorID(id1),
+			Bugs: ProtocolBugs{
+				ExpectPeerRequestedTrustAnchors: [][]byte{id1, id3},
+			},
+		},
+		flags: []string{
+			"-requested-trust-anchors", trustAnchorListFlagValue(id1, id3),
+			"-expect-peer-match-trust-anchor",
+			"-expect-peer-available-trust-anchors", trustAnchorListFlagValue(id1, id2),
+		},
+	})
+	// The client should not like it if the server indicates the match with a non-empty
+	// extension.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-ClientRequest-Match-Non-Empty-Extension",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Credential:            rsaChainCertificate.WithTrustAnchorID(id1),
+			Bugs: ProtocolBugs{
+				SendNonEmptyTrustAnchorMatch:    true,
+				ExpectPeerRequestedTrustAnchors: [][]byte{id1, id3},
+			},
+		},
+		flags: []string{
+			"-requested-trust-anchors", trustAnchorListFlagValue(id1, id3),
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decoding message",
+		expectedError:      ":ERROR_PARSING_EXTENSION:",
+	})
+	// The client should not like it if the server indicates the match on the incorrect
+	// certificate in the Certificate message.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-ClientRequest-Match-On-Incorrect-Certificate",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Credential:            rsaChainCertificate.WithTrustAnchorID(id1),
+			Bugs: ProtocolBugs{
+				SendTrustAnchorWrongCertificate: true,
+				ExpectPeerRequestedTrustAnchors: [][]byte{id1, id3},
+			},
+		},
+		flags: []string{
+			"-requested-trust-anchors", trustAnchorListFlagValue(id1, id3),
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: unsupported extension",
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-ClientRequest-NoMatch",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Bugs: ProtocolBugs{
+				ExpectPeerRequestedTrustAnchors: [][]byte{id3},
+			},
+		},
+		flags: []string{
+			"-requested-trust-anchors", trustAnchorListFlagValue(id3),
+			"-expect-no-peer-match-trust-anchor",
+			"-expect-peer-available-trust-anchors", trustAnchorListFlagValue(id1, id2),
+		},
+	})
+
+	// An empty trust anchor ID is a syntax error, so most be rejected in both
+	// ClientHello and EncryptedExtensions.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-EmptyID-ClientHello",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			RequestTrustAnchors: [][]byte{{}},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-EmptyID-EncryptedExtensions",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{{}},
+		},
+		flags:         []string{"-requested-trust-anchors", trustAnchorListFlagValue(id1)},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	// Test the server selection logic, as well as whether it correctly reports
+	// available trust anchors and the match status. (The general selection flow
+	// is covered in addCertificateSelectionTests.)
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-ServerSelect-Match",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			RequestTrustAnchors: [][]byte{id2},
+			Bugs: ProtocolBugs{
+				ExpectPeerAvailableTrustAnchors: [][]byte{id1, id2},
+				ExpectPeerMatchTrustAnchor:      ptrTo(true),
+			},
+		},
+		shimCredentials: []*Credential{
+			rsaCertificate.WithTrustAnchorID(id1),
+			rsaCertificate.WithTrustAnchorID(id2),
+		},
+		flags: []string{"-expect-selected-credential", "1"},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-ServerSelect-None",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			RequestTrustAnchors: [][]byte{id1},
+		},
+		shimCredentials: []*Credential{
+			rsaCertificate.WithTrustAnchorID(id2),
+			rsaCertificate.WithTrustAnchorID(id3),
+		},
+		shouldFail:    true,
+		expectedError: ":NO_MATCHING_ISSUER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-ServerSelect-Fallback",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			RequestTrustAnchors: [][]byte{id1},
+			Bugs: ProtocolBugs{
+				ExpectPeerAvailableTrustAnchors: [][]byte{id2, id3},
+				ExpectPeerMatchTrustAnchor:      ptrTo(false),
+			},
+		},
+		shimCredentials: []*Credential{
+			rsaCertificate.WithTrustAnchorID(id2),
+			rsaCertificate.WithTrustAnchorID(id3),
+			&rsaCertificate,
+		},
+		flags: []string{"-expect-selected-credential", "2"},
+	})
+
+	// The ClientHello list may be empty. The client must be able to send it and
+	// receive available trust anchors.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-ClientRequestEmpty",
+		config: Config{
+			MinVersion:            VersionTLS13,
+			AvailableTrustAnchors: [][]byte{id1, id2},
+			Bugs: ProtocolBugs{
+				ExpectPeerRequestedTrustAnchors: [][]byte{},
+			},
+		},
+		flags: []string{
+			"-requested-trust-anchors", trustAnchorListFlagValue(),
+			"-expect-peer-available-trust-anchors", trustAnchorListFlagValue(id1, id2),
+		},
+	})
+	// The server must be able to process it, and send available trust anchors.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-ServerReceiveEmptyRequest",
+		config: Config{
+			MinVersion:          VersionTLS13,
+			RequestTrustAnchors: [][]byte{},
+			Bugs: ProtocolBugs{
+				ExpectPeerAvailableTrustAnchors: [][]byte{id1, id2},
+				ExpectPeerMatchTrustAnchor:      ptrTo(false),
+			},
+		},
+		shimCredentials: []*Credential{
+			rsaCertificate.WithTrustAnchorID(id1),
+			rsaCertificate.WithTrustAnchorID(id2),
+			&rsaCertificate,
+		},
+		flags: []string{"-expect-selected-credential", "2"},
+	})
+
+	// This extension requires TLS 1.3. If a server receives this and negotiates
+	// TLS 1.2, it should ignore the extension and not accidentally send
+	// something in ServerHello (implicitly checked by runner).
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TrustAnchors-TLS12-Server",
+		config: Config{
+			MaxVersion:          VersionTLS12,
+			RequestTrustAnchors: [][]byte{id1},
+		},
+		shimCredentials: []*Credential{
+			rsaCertificate.WithTrustAnchorID(id1),
+			&rsaCertificate,
+		},
+		// The first credential is skipped because the extension is ignored.
+		flags: []string{"-expect-selected-credential", "1"},
+	})
+	// The client should reject the extension in TLS 1.2 ServerHello.
+	testCases = append(testCases, testCase{
+		name: "TrustAnchors-TLS12-Client",
+		config: Config{
+			MaxVersion:            VersionTLS12,
+			AvailableTrustAnchors: [][]byte{id1},
+			Bugs: ProtocolBugs{
+				AlwaysSendAvailableTrustAnchors: true,
+			},
+		},
+		flags:              []string{"-requested-trust-anchors", trustAnchorListFlagValue(id1)},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+}
diff --git a/src/ssl/test/runner/version_tests.go b/src/ssl/test/runner/version_tests.go
new file mode 100644
index 0000000..95d0e78
--- /dev/null
+++ b/src/ssl/test/runner/version_tests.go
@@ -0,0 +1,611 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package runner
+
+func addVersionNegotiationTests() {
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, shimVers := range allVersions(protocol) {
+			// Assemble flags to disable all newer versions on the shim.
+			var flags []string
+			for _, vers := range allVersions(protocol) {
+				if vers.version > shimVers.version {
+					flags = append(flags, vers.excludeFlag)
+				}
+			}
+
+			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
+
+			// Test configuring the runner's maximum version.
+			for _, runnerVers := range allVersions(protocol) {
+				expectedVersion := shimVers.version
+				if runnerVers.version < shimVers.version {
+					expectedVersion = runnerVers.version
+				}
+
+				suffix := shimVers.name + "-" + runnerVers.name
+				suffix += "-" + protocol.String()
+
+				// Determine the expected initial record-layer versions.
+				clientVers := shimVers.version
+				if clientVers > VersionTLS10 {
+					clientVers = VersionTLS10
+				}
+				clientVers = recordVersionToWire(clientVers, protocol)
+				serverVers := expectedVersion
+				if expectedVersion >= VersionTLS13 {
+					serverVers = VersionTLS12
+				}
+				serverVers = recordVersionToWire(serverVers, protocol)
+
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: clientTest,
+					name:     "VersionNegotiation-Client-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: clientVers,
+						},
+					},
+					flags: flags,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					// The version name check does not recognize the
+					// |excludeFlag| construction in |flags|.
+					skipVersionNameCheck: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: clientTest,
+					name:     "VersionNegotiation-Client2-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: clientVers,
+						},
+					},
+					flags: flags2,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+				})
+
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "VersionNegotiation-Server-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: serverVers,
+						},
+					},
+					flags: flags,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					// The version name check does not recognize the
+					// |excludeFlag| construction in |flags|.
+					skipVersionNameCheck: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "VersionNegotiation-Server2-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							ExpectInitialRecordVersion: serverVers,
+						},
+					},
+					flags: flags2,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+				})
+			}
+		}
+	}
+
+	// Test the version extension at all versions.
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, vers := range allVersions(protocol) {
+			suffix := vers.name + "-" + protocol.String()
+
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "VersionNegotiationExtension-" + suffix,
+				config: Config{
+					Bugs: ProtocolBugs{
+						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
+						IgnoreTLS13DowngradeRandom: true,
+					},
+				},
+				expectations: connectionExpectations{
+					version: vers.version,
+				},
+			})
+		}
+	}
+
+	// If all versions are unknown, negotiation fails.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedVersions",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{0x1111},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "NoSupportedVersions-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{0x1111},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientHelloVersionTooHigh",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientVersion:          0x0304,
+				OmitSupportedVersions:      true,
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ConflictingVersionNegotiation",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          VersionTLS12,
+				SendSupportedVersions:      []uint16{VersionTLS11},
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		// The extension takes precedence over the ClientHello version.
+		expectations: connectionExpectations{
+			version: VersionTLS11,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ConflictingVersionNegotiation-2",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          VersionTLS11,
+				SendSupportedVersions:      []uint16{VersionTLS12},
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		// The extension takes precedence over the ClientHello version.
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+
+	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
+	// the ServerHello.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "SupportedVersionSelection-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendServerSupportedVersionExtension: VersionTLS12,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// Test that the maximum version is selected regardless of the
+	// client-sent order.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "IgnoreClientVersionOrder",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS13,
+		},
+	})
+
+	// Test for version tolerance.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MinorVersionTolerance",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          0x03ff,
+				OmitSupportedVersions:      true,
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MajorVersionTolerance",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          0x0400,
+				OmitSupportedVersions:      true,
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		// TLS 1.3 must be negotiated with the supported_versions
+		// extension, not ClientHello.version.
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "VersionTolerance-TLS13",
+		config: Config{
+			Bugs: ProtocolBugs{
+				// Although TLS 1.3 does not use
+				// ClientHello.version, it still tolerates high
+				// values there.
+				SendClientVersion: 0x0400,
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS13,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MinorVersionTolerance-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          0xfe00,
+				OmitSupportedVersions:      true,
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MajorVersionTolerance-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:          0xfdff,
+				OmitSupportedVersions:      true,
+				IgnoreTLS13DowngradeRandom: true,
+			},
+		},
+		expectations: connectionExpectations{
+			version: VersionTLS12,
+		},
+	})
+
+	// Test that versions below 3.0 are rejected.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "VersionTooLow",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0x0200,
+				OmitSupportedVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "VersionTooLow-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0xffff,
+				OmitSupportedVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerBogusVersion",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendServerHelloVersion: 0x1234,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	// Test TLS 1.3's downgrade signal.
+	for _, protocol := range []protocol{tls, dtls} {
+		for _, vers := range allVersions(protocol) {
+			if vers.version >= VersionTLS13 {
+				continue
+			}
+			clientShimError := "tls: downgrade from TLS 1.3 detected"
+			if vers.version < VersionTLS12 {
+				clientShimError = "tls: downgrade from TLS 1.2 detected"
+			}
+			// for _, test := range downgradeTests {
+			// The client should enforce the downgrade sentinel.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				name:     "Downgrade-" + vers.name + "-Client-" + protocol.String(),
+				config: Config{
+					Bugs: ProtocolBugs{
+						NegotiateVersion: vers.wire(protocol),
+					},
+				},
+				expectations: connectionExpectations{
+					version: vers.version,
+				},
+				shouldFail:         true,
+				expectedError:      ":TLS13_DOWNGRADE:",
+				expectedLocalError: "remote error: illegal parameter",
+			})
+
+			// The server should emit the downgrade signal.
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "Downgrade-" + vers.name + "-Server-" + protocol.String(),
+				config: Config{
+					Bugs: ProtocolBugs{
+						SendSupportedVersions: []uint16{vers.wire(protocol)},
+					},
+				},
+				expectations: connectionExpectations{
+					version: vers.version,
+				},
+				shouldFail:         true,
+				expectedLocalError: clientShimError,
+			})
+		}
+	}
+
+	// SSL 3.0 support has been removed. Test that the shim does not
+	// support it.
+	testCases = append(testCases, testCase{
+		name: "NoSSL3-Client",
+		config: Config{
+			MinVersion: VersionSSL30,
+			MaxVersion: VersionSSL30,
+		},
+		shouldFail:         true,
+		expectedLocalError: "tls: client did not offer any supported protocol versions",
+	})
+	testCases = append(testCases, testCase{
+		name: "NoSSL3-Client-Unsolicited",
+		config: Config{
+			MinVersion: VersionSSL30,
+			MaxVersion: VersionSSL30,
+			Bugs: ProtocolBugs{
+				// The above test asserts the client does not
+				// offer SSL 3.0 in the supported_versions
+				// list. Additionally assert that it rejects an
+				// unsolicited SSL 3.0 ServerHello.
+				NegotiateVersion: VersionSSL30,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNSUPPORTED_PROTOCOL:",
+		expectedLocalError: "remote error: protocol version not supported",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSSL3-Server",
+		config: Config{
+			MinVersion: VersionSSL30,
+			MaxVersion: VersionSSL30,
+		},
+		shouldFail:         true,
+		expectedError:      ":UNSUPPORTED_PROTOCOL:",
+		expectedLocalError: "remote error: protocol version not supported",
+	})
+}
+
+func addMinimumVersionTests() {
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, shimVers := range allVersions(protocol) {
+			// Assemble flags to disable all older versions on the shim.
+			var flags []string
+			for _, vers := range allVersions(protocol) {
+				if vers.version < shimVers.version {
+					flags = append(flags, vers.excludeFlag)
+				}
+			}
+
+			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
+
+			for _, runnerVers := range allVersions(protocol) {
+				suffix := shimVers.name + "-" + runnerVers.name
+				suffix += "-" + protocol.String()
+
+				var expectedVersion uint16
+				var shouldFail bool
+				var expectedError, expectedLocalError string
+				if runnerVers.version >= shimVers.version {
+					expectedVersion = runnerVers.version
+				} else {
+					shouldFail = true
+					expectedError = ":UNSUPPORTED_PROTOCOL:"
+					expectedLocalError = "remote error: protocol version not supported"
+				}
+
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: clientTest,
+					name:     "MinimumVersion-Client-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							// Ensure the server does not decline to
+							// select a version (versions extension) or
+							// cipher (some ciphers depend on versions).
+							NegotiateVersion:            runnerVers.wire(protocol),
+							IgnorePeerCipherPreferences: shouldFail,
+						},
+					},
+					flags: flags,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					shouldFail:         shouldFail,
+					expectedError:      expectedError,
+					expectedLocalError: expectedLocalError,
+					// The version name check does not recognize the
+					// |excludeFlag| construction in |flags|.
+					skipVersionNameCheck: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: clientTest,
+					name:     "MinimumVersion-Client2-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							// Ensure the server does not decline to
+							// select a version (versions extension) or
+							// cipher (some ciphers depend on versions).
+							NegotiateVersion:            runnerVers.wire(protocol),
+							IgnorePeerCipherPreferences: shouldFail,
+						},
+					},
+					flags: flags2,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					shouldFail:         shouldFail,
+					expectedError:      expectedError,
+					expectedLocalError: expectedLocalError,
+				})
+
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "MinimumVersion-Server-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+					},
+					flags: flags,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					shouldFail:         shouldFail,
+					expectedError:      expectedError,
+					expectedLocalError: expectedLocalError,
+					// The version name check does not recognize the
+					// |excludeFlag| construction in |flags|.
+					skipVersionNameCheck: true,
+				})
+				testCases = append(testCases, testCase{
+					protocol: protocol,
+					testType: serverTest,
+					name:     "MinimumVersion-Server2-" + suffix,
+					config: Config{
+						MaxVersion: runnerVers.version,
+					},
+					flags: flags2,
+					expectations: connectionExpectations{
+						version: expectedVersion,
+					},
+					shouldFail:         shouldFail,
+					expectedError:      expectedError,
+					expectedLocalError: expectedLocalError,
+				})
+			}
+		}
+	}
+}
+
+func addRecordVersionTests() {
+	for _, ver := range tlsVersions {
+		// Test that the record version is enforced.
+		testCases = append(testCases, testCase{
+			name: "CheckRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendRecordVersion: 0x03ff,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		})
+
+		// Test that the ClientHello may use any record version, for
+		// compatibility reasons.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "LooseInitialRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendInitialRecordVersion: 0x03ff,
+				},
+			},
+		})
+
+		// Test that garbage ClientHello record versions are rejected.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "GarbageInitialRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendInitialRecordVersion: 0xffff,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		})
+	}
+}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 4d220f6..a847397 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -37,11 +37,17 @@
 #include <openssl/ssl.h>
 
 #include "../../crypto/internal.h"
-#include "../internal.h"
 #include "handshake_util.h"
 #include "mock_quic_transport.h"
 #include "test_state.h"
 
+#if defined(OPENSSL_WINDOWS)
+// Windows defines struct timeval in winsock2.h.
+#include <winsock2.h>
+#else
+#include <sys/time.h>
+#endif
+
 namespace {
 
 template <typename Config>
@@ -66,6 +72,28 @@
                       }};
 }
 
+template <typename Config>
+Flag<Config> OptionalBoolTrueFlag(const char *name,
+                                  std::optional<bool> Config::*field,
+                                  bool skip_handshaker = false) {
+  return Flag<Config>{name, false, skip_handshaker,
+                      [=](Config *config, const char *) -> bool {
+                        config->*field = true;
+                        return true;
+                      }};
+}
+
+template <typename Config>
+Flag<Config> OptionalBoolFalseFlag(const char *name,
+                                   std::optional<bool> Config::*field,
+                                   bool skip_handshaker = false) {
+  return Flag<Config>{name, false, skip_handshaker,
+                      [=](Config *config, const char *) -> bool {
+                        config->*field = false;
+                        return true;
+                      }};
+}
+
 template <typename T>
 bool StringToInt(T *out, const char *str) {
   static_assert(std::is_integral<T>::value, "not an integral type");
@@ -188,6 +216,17 @@
 }
 
 template <typename Config>
+Flag<Config> OptionalBase64Flag(
+    const char *name, std::optional<std::vector<uint8_t>> Config::*field,
+    bool skip_handshaker = false) {
+  return Flag<Config>{name, true, skip_handshaker,
+                      [=](Config *config, const char *param) -> bool {
+                        (config->*field).emplace();
+                        return DecodeBase64(&*(config->*field), param);
+                      }};
+}
+
+template <typename Config>
 Flag<Config> Base64VectorFlag(const char *name,
                               std::vector<std::vector<uint8_t>> Config::*field,
                               bool skip_handshaker = false) {
@@ -280,6 +319,9 @@
         BoolFlag("-quic", &TestConfig::is_quic),
         IntFlag("-resume-count", &TestConfig::resume_count),
         StringFlag("-write-settings", &TestConfig::write_settings),
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+        BoolFlag("-fuzzer-mode", &TestConfig::fuzzer_mode),
+#endif
         BoolFlag("-fallback-scsv", &TestConfig::fallback_scsv),
         IntVectorFlag("-verify-prefs", &TestConfig::verify_prefs),
         IntVectorFlag("-expect-peer-verify-pref",
@@ -341,8 +383,7 @@
                              &TestConfig::application_settings),
         OptionalStringFlag("-expect-peer-application-settings",
                            &TestConfig::expect_peer_application_settings),
-        BoolFlag("-alps-use-new-codepoint",
-                 &TestConfig::alps_use_new_codepoint),
+        IntFlag("-alps-use-new-codepoint", &TestConfig::alps_use_new_codepoint),
         Base64Flag("-quic-transport-params",
                    &TestConfig::quic_transport_params),
         Base64Flag("-expect-quic-transport-params",
@@ -401,7 +442,6 @@
         BoolFlag("-shim-shuts-down", &TestConfig::shim_shuts_down),
         BoolFlag("-verify-fail", &TestConfig::verify_fail),
         BoolFlag("-verify-peer", &TestConfig::verify_peer),
-        BoolFlag("-verify-peer-if-no-obc", &TestConfig::verify_peer_if_no_obc),
         BoolFlag("-expect-verify-result", &TestConfig::expect_verify_result),
         IntFlag("-expect-total-renegotiations",
                 &TestConfig::expect_total_renegotiations),
@@ -497,6 +537,14 @@
         BoolFlag("-fips-202205", &TestConfig::fips_202205),
         BoolFlag("-wpa-202304", &TestConfig::wpa_202304),
         BoolFlag("-cnsa-202407", &TestConfig::cnsa_202407),
+        OptionalBoolTrueFlag("-expect-peer-match-trust-anchor",
+                             &TestConfig::expect_peer_match_trust_anchor),
+        OptionalBoolFalseFlag("-expect-no-peer-match-trust-anchor",
+                              &TestConfig::expect_peer_match_trust_anchor),
+        OptionalBase64Flag("-expect-peer-available-trust-anchors",
+                           &TestConfig::expect_peer_available_trust_anchors),
+        OptionalBase64Flag("-requested-trust-anchors",
+                           &TestConfig::requested_trust_anchors),
         OptionalIntFlag("-expect-selected-credential",
                         &TestConfig::expect_selected_credential),
         // Credential flags are stateful. First, use one of the
@@ -527,6 +575,8 @@
                        &TestConfig::signed_cert_timestamps),
             Base64Flag("-signed-cert-timestamps",
                        &CredentialConfig::signed_cert_timestamps)),
+        CredentialFlag(BoolFlag("-must-match-issuer",
+                                &CredentialConfig::must_match_issuer)),
         CredentialFlag(
             Base64Flag("-pake-context", &CredentialConfig::pake_context)),
         CredentialFlag(
@@ -537,7 +587,15 @@
             Base64Flag("-pake-password", &CredentialConfig::pake_password)),
         CredentialFlag(
             BoolFlag("-wrong-pake-role", &CredentialConfig::wrong_pake_role)),
+        CredentialFlag(
+            Base64Flag("-trust-anchor-id", &CredentialConfig::trust_anchor_id)),
         IntFlag("-private-key-delay-ms", &TestConfig::private_key_delay_ms),
+        BoolFlag("-resumption-across-names-enabled",
+                 &TestConfig::resumption_across_names_enabled),
+        OptionalBoolTrueFlag("-expect-resumable-across-names",
+                             &TestConfig::expect_resumable_across_names),
+        OptionalBoolFalseFlag("-expect-not-resumable-across-names",
+                              &TestConfig::expect_resumable_across_names),
     };
     std::sort(ret.begin(), ret.end(), FlagNameComparator{});
     return ret;
@@ -780,7 +838,9 @@
 
   if (content_type == SSL3_RT_HEADER) {
     if (config->is_dtls) {
-      if (len > DTLS1_RT_MAX_HEADER_LENGTH) {
+      // Starting DTLS 1.3, record headers are variable-length, but they will
+      // not be longer than DTLS 1.2's 13-byte header.
+      if (len > 13) {
         fprintf(stderr, "DTLS record header is too long: %zu.\n", len);
       }
       return;
@@ -1033,6 +1093,26 @@
     return false;
   }
 
+  if (config->expect_peer_match_trust_anchor.has_value() &&
+      !!SSL_peer_matched_trust_anchor(ssl) !=
+          config->expect_peer_match_trust_anchor.value()) {
+    fprintf(stderr, "Peer unexpected %s a requested trust anchor",
+            SSL_peer_matched_trust_anchor(ssl) ? "matched" : "failed to match");
+    return false;
+  }
+
+  if (config->expect_peer_available_trust_anchors.has_value()) {
+    const uint8_t *peer_ids;
+    size_t peer_ids_len;
+    SSL_get0_peer_available_trust_anchors(ssl, &peer_ids, &peer_ids_len);
+    if (bssl::Span(peer_ids, peer_ids_len) !=
+        *config->expect_peer_available_trust_anchors) {
+      fprintf(stderr,
+              "Peer's available trust anchors did not match expectations.");
+      return false;
+    }
+  }
+
   if (GetTestState(ssl)->cert_verified) {
     fprintf(stderr, "Certificate verified twice.\n");
     return false;
@@ -1471,6 +1551,18 @@
     }
   }
 
+  if (cred_config.must_match_issuer) {
+    SSL_CREDENTIAL_set_must_match_issuer(cred.get(), 1);
+  }
+
+  if (!cred_config.trust_anchor_id.empty()) {
+    if (!SSL_CREDENTIAL_set1_trust_anchor_id(
+            cred.get(), cred_config.trust_anchor_id.data(),
+            cred_config.trust_anchor_id.size())) {
+      return nullptr;
+    }
+  }
+
   if (!SetCredentialInfo(cred.get(), std::move(info))) {
     return nullptr;
   }
@@ -1974,6 +2066,10 @@
     SSL_CTX_set_tlsext_status_cb(ssl_ctx.get(), LegacyOCSPCallback);
   }
 
+  if (resumption_across_names_enabled) {
+    SSL_CTX_set_resumption_across_names_enabled(ssl_ctx.get(), 1);
+  }
+
   if (old_ctx) {
     uint8_t keys[48];
     if (!SSL_CTX_get_tlsext_ticket_keys(old_ctx, &keys, sizeof(keys)) ||
@@ -2192,12 +2288,6 @@
   if (verify_peer) {
     mode = SSL_VERIFY_PEER;
   }
-  if (verify_peer_if_no_obc) {
-    // Set SSL_VERIFY_FAIL_IF_NO_PEER_CERT so testing whether client
-    // certificates were requested is easy.
-    mode = SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
-           SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-  }
   if (use_custom_verify_callback) {
     SSL_set_custom_verify(ssl.get(), mode, CustomVerifyCallback);
   } else if (mode != SSL_VERIFY_NONE) {
@@ -2332,6 +2422,12 @@
       !SSL_set_srtp_profiles(ssl.get(), srtp_profiles.c_str())) {
     return nullptr;
   }
+  if (requested_trust_anchors.has_value() &&
+      !SSL_set1_requested_trust_anchors(ssl.get(),
+                                        requested_trust_anchors->data(),
+                                        requested_trust_anchors->size())) {
+    return nullptr;
+  }
   if (enable_ocsp_stapling) {
     SSL_enable_ocsp_stapling(ssl.get());
   }
@@ -2397,8 +2493,10 @@
   if (max_send_fragment > 0) {
     SSL_set_max_send_fragment(ssl.get(), max_send_fragment);
   }
-  if (alps_use_new_codepoint) {
-    SSL_set_alps_use_new_codepoint(ssl.get(), 1);
+  // Using new ALPS codepoint as default, only explicitly set when it uses the
+  // old ALPS codepoint.
+  if (alps_use_new_codepoint == 0) {
+    SSL_set_alps_use_new_codepoint(ssl.get(), 0);
   }
   if (quic_use_legacy_codepoint != -1) {
     SSL_set_quic_use_legacy_codepoint(ssl.get(), quic_use_legacy_codepoint);
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 15d434f..885f062 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -39,10 +39,12 @@
   std::vector<uint8_t> delegated_credential;
   std::vector<uint8_t> ocsp_response;
   std::vector<uint8_t> signed_cert_timestamps;
+  bool must_match_issuer = false;
   std::vector<uint8_t> pake_context;
   std::vector<uint8_t> pake_client_id;
   std::vector<uint8_t> pake_server_id;
   std::vector<uint8_t> pake_password;
+  std::vector<uint8_t> trust_anchor_id;
   bool wrong_pake_role = false;
 };
 
@@ -55,6 +57,9 @@
   bool is_quic = false;
   int resume_count = 0;
   std::string write_settings;
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+  bool fuzzer_mode = false;
+#endif
   bool fallback_scsv = false;
   std::vector<uint16_t> signing_prefs;
   std::vector<uint16_t> verify_prefs;
@@ -107,7 +112,7 @@
   bool defer_alps = false;
   std::vector<std::pair<std::string, std::string>> application_settings;
   std::optional<std::string> expect_peer_application_settings;
-  bool alps_use_new_codepoint = false;
+  int alps_use_new_codepoint = 1;
   std::vector<uint8_t> quic_transport_params;
   std::vector<uint8_t> expect_quic_transport_params;
   // Set quic_use_legacy_codepoint to 0 or 1 to configure, -1 uses default.
@@ -156,7 +161,6 @@
   bool shim_shuts_down = false;
   bool verify_fail = false;
   bool verify_peer = false;
-  bool verify_peer_if_no_obc = false;
   bool expect_verify_result = false;
   std::vector<uint8_t> signed_cert_timestamps;
   int expect_total_renegotiations = 0;
@@ -228,9 +232,14 @@
   bool fips_202205 = false;
   bool wpa_202304 = false;
   bool cnsa_202407 = false;
+  std::optional<bool> expect_peer_match_trust_anchor;
+  std::optional<std::vector<uint8_t>> expect_peer_available_trust_anchors;
+  std::optional<std::vector<uint8_t>> requested_trust_anchors;
   std::optional<int> expect_selected_credential;
   std::vector<CredentialConfig> credentials;
   int private_key_delay_ms = 0;
+  bool resumption_across_names_enabled = false;
+  std::optional<bool> expect_resumable_across_names;
 
   std::vector<const char *> handshaker_args;
 
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 8202041..db615e0 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -197,7 +197,8 @@
       return false;
     }
 
-    if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
+    const bool is_leaf = sk_CRYPTO_BUFFER_num(certs.get()) == 0;
+    if (is_leaf) {
       pkey = ssl_cert_parse_pubkey(&certificate);
       if (!pkey) {
         ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -234,8 +235,13 @@
     SSLExtension sct(
         TLSEXT_TYPE_certificate_timestamp,
         !ssl->server && hs->config->signed_cert_timestamps_enabled);
+    SSLExtension trust_anchors(
+        TLSEXT_TYPE_trust_anchors,
+        !ssl->server && is_leaf &&
+            hs->config->requested_trust_anchors.has_value());
     uint8_t alert = SSL_AD_DECODE_ERROR;
-    if (!ssl_parse_extensions(&extensions, &alert, {&status_request, &sct},
+    if (!ssl_parse_extensions(&extensions, &alert,
+                              {&status_request, &sct, &trust_anchors},
                               /*ignore_unknown=*/false)) {
       ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
       return false;
@@ -280,6 +286,15 @@
         }
       }
     }
+
+    if (trust_anchors.present) {
+      if (CBS_len(&trust_anchors.data) != 0) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
+        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        return false;
+      }
+      hs->peer_matched_trust_anchor = true;
+    }
   }
 
   // Store a null certificate list rather than an empty one if the peer didn't
@@ -378,9 +393,9 @@
 
   bool finished_ok =
       CBS_mem_equal(&msg.body, verify_data.data(), verify_data.size());
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  finished_ok = true;
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    finished_ok = true;
+  }
   if (!finished_ok) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
     OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
@@ -472,6 +487,16 @@
     }
   }
 
+  if (hs->matched_peer_trust_anchor) {
+    // Let the peer know we matched a requested trust anchor.
+    CBB empty_contents;
+    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_trust_anchors) ||        //
+        !CBB_add_u16_length_prefixed(&extensions, &empty_contents) ||  //
+        !CBB_flush(&extensions)) {
+      return false;
+    }
+  }
+
   for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cred->chain.get()); i++) {
     CRYPTO_BUFFER *cert_buf = sk_CRYPTO_BUFFER_value(cred->chain.get(), i);
     CBB child;
@@ -642,8 +667,7 @@
   }
 
   // In DTLS, the actual key update is deferred until KeyUpdate is ACKed.
-  if (!SSL_is_dtls(ssl) &&
-      !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
+  if (!SSL_is_dtls(ssl) && !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
     return false;
   }
 
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index cf36d0c..eca654f 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -1189,8 +1189,9 @@
   }
 
   SSLExtension early_data(TLSEXT_TYPE_early_data);
+  SSLExtension flags(TLSEXT_TYPE_tls_flags);
   uint8_t alert = SSL_AD_DECODE_ERROR;
-  if (!ssl_parse_extensions(&extensions, &alert, {&early_data},
+  if (!ssl_parse_extensions(&extensions, &alert, {&early_data, &flags},
                             /*ignore_unknown=*/true)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
     return nullptr;
@@ -1213,6 +1214,17 @@
     }
   }
 
+  if (flags.present) {
+    SSLFlags parsed;
+    if (!ssl_parse_flags_extension_request(&flags.data, &parsed, &alert)) {
+      ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
+      return nullptr;
+    }
+    if (parsed & kSSLFlagResumptionAcrossNames) {
+      session->is_resumable_across_names = true;
+    }
+  }
+
   // Historically, OpenSSL filled in fake session IDs for ticket-based sessions.
   // Envoy's tests depend on this, although perhaps they shouldn't.
   session->session_id.ResizeForOverwrite(SHA256_DIGEST_LENGTH);
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index c18fe16..ee8a459 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -296,7 +296,6 @@
   uint8_t key_[kKeySize];
 };
 
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
 class NullRecordNumberEncrypter : public RecordNumberEncrypter {
  public:
   size_t KeySize() override { return 0; }
@@ -306,7 +305,6 @@
     return true;
   }
 };
-#endif  // BORINGSSL_UNSAFE_FUZZER_MODE
 
 }  // namespace
 
@@ -314,10 +312,9 @@
     const SSL_CIPHER *cipher, Span<const uint8_t> traffic_secret) {
   const EVP_MD *digest = ssl_get_handshake_digest(TLS1_3_VERSION, cipher);
   UniquePtr<RecordNumberEncrypter> ret;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  ret = MakeUnique<NullRecordNumberEncrypter>();
-#else
-  if (cipher->algorithm_enc == SSL_AES128GCM) {
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    ret = MakeUnique<NullRecordNumberEncrypter>();
+  } else if (cipher->algorithm_enc == SSL_AES128GCM) {
     ret = MakeUnique<AES128RecordNumberEncrypter>();
   } else if (cipher->algorithm_enc == SSL_AES256GCM) {
     ret = MakeUnique<AES256RecordNumberEncrypter>();
@@ -326,7 +323,6 @@
   } else {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
   }
-#endif  // BORINGSSL_UNSAFE_FUZZER_MODE
   if (ret == nullptr) {
     return nullptr;
   }
@@ -474,7 +470,7 @@
 
 static const char kTLS13LabelExportKeying[] = "exporter";
 
-bool tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
+bool tls13_export_keying_material(const SSL *ssl, Span<uint8_t> out,
                                   Span<const uint8_t> secret,
                                   std::string_view label,
                                   Span<const uint8_t> context) {
@@ -628,9 +624,9 @@
   bool binder_ok =
       CBS_len(&binder) == verify_data_len &&
       CRYPTO_memcmp(CBS_data(&binder), verify_data, verify_data_len) == 0;
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  binder_ok = true;
-#endif
+  if (CRYPTO_fuzzer_mode_enabled()) {
+    binder_ok = true;
+  }
   if (!binder_ok) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
     return false;
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index e34ecf4..98bac6e 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -192,6 +192,7 @@
       session->ticket_max_early_data =
           SSL_is_quic(ssl) ? 0xffffffff : kMaxEarlyDataAccepted;
     }
+    session->is_resumable_across_names = ssl->resumption_across_names_enabled;
 
     static_assert(kMaxTickets < 256, "Too many tickets");
     assert(i < 256);
@@ -230,6 +231,14 @@
       }
     }
 
+    SSLFlags flags = 0;
+    if (session->is_resumable_across_names) {
+      flags |= kSSLFlagResumptionAcrossNames;
+    }
+    if (!ssl_add_flags_extension(&extensions, flags)) {
+      return false;
+    }
+
     // Add a fake extension. See RFC 8701.
     if (!CBB_add_u16(&extensions,
                      ssl_get_grease_value(hs, ssl_grease_ticket_extension)) ||
@@ -711,7 +720,8 @@
   ScopedCBB cbb;
   CBB body, session_id, extensions;
   if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
-      !CBB_add_u16(&body, TLS1_2_VERSION) ||
+      !CBB_add_u16(&body,
+                   SSL_is_dtls(ssl) ? DTLS1_2_VERSION : TLS1_2_VERSION) ||
       !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
       !CBB_add_bytes(&session_id, hs->session_id.data(),
@@ -907,15 +917,12 @@
     }
   }
 
-  uint16_t server_hello_version = TLS1_2_VERSION;
-  if (SSL_is_dtls(ssl)) {
-    server_hello_version = DTLS1_2_VERSION;
-  }
   Array<uint8_t> server_hello;
   ScopedCBB cbb;
   CBB body, extensions, session_id;
   if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
-      !CBB_add_u16(&body, server_hello_version) ||
+      !CBB_add_u16(&body,
+                   SSL_is_dtls(ssl) ? DTLS1_2_VERSION : TLS1_2_VERSION) ||
       !CBB_add_bytes(&body, ssl->s3->server_random,
                      sizeof(ssl->s3->server_random)) ||
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
@@ -979,11 +986,6 @@
   if (!ssl->s3->session_reused && !hs->pake_verifier) {
     // Determine whether to request a client certificate.
     hs->cert_request = !!(hs->config->verify_mode & SSL_VERIFY_PEER);
-    // Only request a certificate if Channel ID isn't negotiated.
-    if ((hs->config->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
-        hs->channel_id_negotiated) {
-      hs->cert_request = false;
-    }
   }
 
   // Send a CertificateRequest, if necessary.
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 553f794..fca3e85 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -47,14 +47,11 @@
 // ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher
 // state needs record-splitting and zero otherwise.
 bool ssl_needs_record_splitting(const SSL *ssl) {
-#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
-  return !ssl->s3->aead_write_ctx->is_null_cipher() &&
+  return !CRYPTO_fuzzer_mode_enabled() &&
+         !ssl->s3->aead_write_ctx->is_null_cipher() &&
          ssl_protocol_version(ssl) < TLS1_1_VERSION &&
          (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 &&
          SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher());
-#else
-  return false;
-#endif
 }
 
 size_t ssl_record_prefix_len(const SSL *ssl) {
diff --git a/src/third_party/fiat/README.chromium b/src/third_party/fiat/README.chromium
index b19c040..b2915c1 100644
--- a/src/third_party/fiat/README.chromium
+++ b/src/third_party/fiat/README.chromium
@@ -3,7 +3,7 @@
 URL: https://github.com/mit-plv/fiat-crypto
 Version: git (see METADATA)
 Revision: 6ccc6638716d4632304baf1adbb5c47c3a12ea6f
-License: Apache 2.0
+License: Apache-2.0
 License File: LICENSE
 Security Critical: yes
 Shipped: yes
diff --git a/src/third_party/googletest/.github/workflows/gtest-ci.yml b/src/third_party/googletest/.github/workflows/gtest-ci.yml
deleted file mode 100644
index 03a8cc5..0000000
--- a/src/third_party/googletest/.github/workflows/gtest-ci.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: ci
-
-on:
-  push:
-  pull_request:
-
-env:
-  BAZEL_CXXOPTS: -std=c++14
-
-jobs:
-  Linux:
-    runs-on: ubuntu-latest
-    steps:
-
-    - uses: actions/checkout@v3
-      with:
-        fetch-depth: 0
-
-    - name: Tests
-      run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
-
-  macOS:
-    runs-on: macos-latest
-    steps:
-
-    - uses: actions/checkout@v3
-      with:
-        fetch-depth: 0
-
-    - name: Tests
-      run:  bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
-
-
-  Windows:
-    runs-on: windows-latest
-    steps:
-
-    - uses: actions/checkout@v3
-      with:
-        fetch-depth: 0
-
-    - name: Tests
-      run: bazel test --cxxopt=/std:c++14 --features=external_include_paths --test_output=errors ...
diff --git a/src/third_party/googletest/.gitignore b/src/third_party/googletest/.gitignore
index fede02f..f0df39d 100644
--- a/src/third_party/googletest/.gitignore
+++ b/src/third_party/googletest/.gitignore
@@ -8,6 +8,7 @@
 bazel-googletest
 bazel-out
 bazel-testlogs
+MODULE.bazel.lock
 # python
 *.pyc
 
diff --git a/src/third_party/googletest/BUILD.bazel b/src/third_party/googletest/BUILD.bazel
index b1e3b7f..0306468 100644
--- a/src/third_party/googletest/BUILD.bazel
+++ b/src/third_party/googletest/BUILD.bazel
@@ -56,6 +56,12 @@
     constraint_values = ["@platforms//os:openbsd"],
 )
 
+# NOTE: Fuchsia is not an officially supported platform.
+config_setting(
+    name = "fuchsia",
+    constraint_values = ["@platforms//os:fuchsia"],
+)
+
 config_setting(
     name = "msvc_compiler",
     flag_values = {
@@ -132,19 +138,30 @@
     }),
     deps = select({
         ":has_absl": [
-            "@com_google_absl//absl/container:flat_hash_set",
-            "@com_google_absl//absl/debugging:failure_signal_handler",
-            "@com_google_absl//absl/debugging:stacktrace",
-            "@com_google_absl//absl/debugging:symbolize",
-            "@com_google_absl//absl/flags:flag",
-            "@com_google_absl//absl/flags:parse",
-            "@com_google_absl//absl/flags:reflection",
-            "@com_google_absl//absl/flags:usage",
-            "@com_google_absl//absl/strings",
-            "@com_google_absl//absl/types:any",
-            "@com_google_absl//absl/types:optional",
-            "@com_google_absl//absl/types:variant",
-            "@com_googlesource_code_re2//:re2",
+            "@abseil-cpp//absl/container:flat_hash_set",
+            "@abseil-cpp//absl/debugging:failure_signal_handler",
+            "@abseil-cpp//absl/debugging:stacktrace",
+            "@abseil-cpp//absl/debugging:symbolize",
+            "@abseil-cpp//absl/flags:flag",
+            "@abseil-cpp//absl/flags:parse",
+            "@abseil-cpp//absl/flags:reflection",
+            "@abseil-cpp//absl/flags:usage",
+            "@abseil-cpp//absl/strings",
+            "@abseil-cpp//absl/types:any",
+            "@abseil-cpp//absl/types:optional",
+            "@abseil-cpp//absl/types:variant",
+            "@re2//:re2",
+        ],
+        "//conditions:default": [],
+    }) + select({
+        # `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process,
+        # expects it to crash and inspects its logs with the given matcher,
+        # so that's why these libraries are needed.
+        # Otherwise, builds targeting Fuchsia would fail to compile.
+        ":fuchsia": [
+            "@fuchsia_sdk//pkg/fdio",
+            "@fuchsia_sdk//pkg/syslog",
+            "@fuchsia_sdk//pkg/zx",
         ],
         "//conditions:default": [],
     }),
diff --git a/src/third_party/googletest/CMakeLists.txt b/src/third_party/googletest/CMakeLists.txt
index 089ac98..c784f3c 100644
--- a/src/third_party/googletest/CMakeLists.txt
+++ b/src/third_party/googletest/CMakeLists.txt
@@ -1,10 +1,10 @@
 # Note: CMake support is community-based. The maintainers do not use CMake
 # internally.
 
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.16)
 
 project(googletest-distribution)
-set(GOOGLETEST_VERSION 1.14.0)
+set(GOOGLETEST_VERSION 1.16.0)
 
 if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
   set(CMAKE_CXX_EXTENSIONS OFF)
@@ -15,11 +15,20 @@
 include(CMakeDependentOption)
 include(GNUInstallDirs)
 
-#Note that googlemock target already builds googletest
+# Note that googlemock target already builds googletest.
 option(BUILD_GMOCK "Builds the googlemock subproject" ON)
 option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
 option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF)
 
+if(GTEST_HAS_ABSL)
+  if(NOT TARGET absl::base)
+    find_package(absl REQUIRED)
+  endif()
+  if(NOT TARGET re2::re2)
+    find_package(re2 REQUIRED)
+  endif()
+endif()
+
 if(BUILD_GMOCK)
   add_subdirectory( googlemock )
 else()
diff --git a/src/third_party/googletest/CONTRIBUTORS b/src/third_party/googletest/CONTRIBUTORS
index 77397a5..ccea41e 100644
--- a/src/third_party/googletest/CONTRIBUTORS
+++ b/src/third_party/googletest/CONTRIBUTORS
@@ -55,6 +55,7 @@
 Russ Rufer <russ@pentad.com>
 Sean Mcafee <eefacm@gmail.com>
 Sigurður Ásgeirsson <siggi@google.com>
+Soyeon Kim <sxshx818@naver.com>
 Sverre Sundsdal <sundsdal@gmail.com>
 Szymon Sobik <sobik.szymon@gmail.com>
 Takeshi Yoshino <tyoshino@google.com>
diff --git a/src/third_party/googletest/METADATA b/src/third_party/googletest/METADATA
index 0766f88..7679179 100644
--- a/src/third_party/googletest/METADATA
+++ b/src/third_party/googletest/METADATA
@@ -6,6 +6,6 @@
     type: HOMEPAGE
     value: "https://github.com/google/googletest"
   }
-  version: "8a6feabf04bec8fb125e0df0ad1195c42350725f"
-  last_upgrade_date { year: 2023 month: 9 day: 1 }
+  version: "54501746a6cfd366b6e7bab3c902e0f8d5826521"
+  last_upgrade_date { year: 2025 month: 2 day: 24 }
 }
diff --git a/src/third_party/googletest/MODULE.bazel b/src/third_party/googletest/MODULE.bazel
new file mode 100644
index 0000000..66eee54
--- /dev/null
+++ b/src/third_party/googletest/MODULE.bazel
@@ -0,0 +1,76 @@
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * 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.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 COPYRIGHT
+# OWNER 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.
+
+# https://bazel.build/external/overview#bzlmod
+
+module(
+    name = "googletest",
+    version = "head",
+    compatibility_level = 1,
+)
+
+# Only direct dependencies need to be listed below.
+# Please keep the versions in sync with the versions in the WORKSPACE file.
+
+bazel_dep(
+    name = "abseil-cpp",
+    version = "20250127.0",
+)
+bazel_dep(
+    name = "platforms",
+    version = "0.0.10",
+)
+bazel_dep(
+    name = "re2",
+    version = "2024-07-02",
+)
+
+bazel_dep(
+    name = "rules_python",
+    version = "1.1.0",
+    dev_dependency = True,
+)
+
+# https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage
+python = use_extension(
+    "@rules_python//python/extensions:python.bzl",
+    "python",
+    dev_dependency = True,
+)
+python.toolchain(
+    ignore_root_user_error = True,
+    is_default = True,
+    python_version = "3.12",
+)
+
+# See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed.
+fuchsia_sdk = use_extension("//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
+fuchsia_sdk.create_fake()
+use_repo(fuchsia_sdk, "fuchsia_sdk")
diff --git a/src/third_party/googletest/README.md b/src/third_party/googletest/README.md
index c1c1446..2a2a722 100644
--- a/src/third_party/googletest/README.md
+++ b/src/third_party/googletest/README.md
@@ -9,7 +9,7 @@
 We recommend
 [updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
 We do publish occasional semantic versions, tagged with
-`v${major}.${minor}.${patch}` (e.g. `v1.14.0`).
+`v${major}.${minor}.${patch}` (e.g. `v1.16.0`).
 
 #### Documentation Updates
 
@@ -17,25 +17,24 @@
 https://google.github.io/googletest/. We recommend browsing the documentation on
 GitHub Pages rather than directly in the repository.
 
-#### Release 1.14.0
+#### Release 1.16.0
 
-[Release 1.14.0](https://github.com/google/googletest/releases/tag/v1.14.0) is
+[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is
 now available.
 
-The 1.14.x branch requires at least C++14.
+The 1.16.x branch requires at least C++14.
+
+The 1.16.x branch will be the last to support C++14. Future development will
+[require at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
 
 #### Continuous Integration
 
-We use Google's internal systems for continuous integration. \
-GitHub Actions were added for the convenience of open-source contributors. They
-are exclusively maintained by the open-source community and not used by the
-GoogleTest team.
+We use Google's internal systems for continuous integration.
 
 #### Coming Soon
 
 *   We are planning to take a dependency on
     [Abseil](https://github.com/abseil/abseil-cpp).
-*   More documentation improvements are planned.
 
 ## Welcome to **GoogleTest**, Google's C++ test framework!
 
diff --git a/src/third_party/googletest/WORKSPACE b/src/third_party/googletest/WORKSPACE
index f819ffe..4c76102 100644
--- a/src/third_party/googletest/WORKSPACE
+++ b/src/third_party/googletest/WORKSPACE
@@ -1,4 +1,34 @@
-workspace(name = "com_google_googletest")
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * 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.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 COPYRIGHT
+# OWNER 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.
+
+workspace(name = "googletest")
 
 load("//:googletest_deps.bzl", "googletest_deps")
 googletest_deps()
@@ -6,22 +36,26 @@
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
-  name = "rules_python",  # 2023-07-31T20:39:27Z
-  sha256 = "1250b59a33c591a1c4ba68c62e95fc88a84c334ec35a2e23f46cbc1b9a5a8b55",
-  strip_prefix = "rules_python-e355becc30275939d87116a4ec83dad4bb50d9e1",
-  urls = ["https://github.com/bazelbuild/rules_python/archive/e355becc30275939d87116a4ec83dad4bb50d9e1.zip"],
+    name = "rules_python",
+    sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
+    strip_prefix = "rules_python-1.1.0",
+    url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
+)
+# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
+load("@rules_python//python:repositories.bzl", "py_repositories")
+py_repositories()
+
+http_archive(
+  name = "bazel_skylib",
+  sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
+  urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
 )
 
 http_archive(
-  name = "bazel_skylib",  # 2023-05-31T19:24:07Z
-  sha256 = "08c0386f45821ce246bbbf77503c973246ed6ee5c3463e41efc197fa9bc3a7f4",
-  strip_prefix = "bazel-skylib-288731ef9f7f688932bd50e704a91a45ec185f9b",
-  urls = ["https://github.com/bazelbuild/bazel-skylib/archive/288731ef9f7f688932bd50e704a91a45ec185f9b.zip"],
-)
-
-http_archive(
-  name = "platforms",  # 2023-07-28T19:44:27Z
-  sha256 = "40eb313613ff00a5c03eed20aba58890046f4d38dec7344f00bb9a8867853526",
-  strip_prefix = "platforms-4ad40ef271da8176d4fc0194d2089b8a76e19d7b",
-  urls = ["https://github.com/bazelbuild/platforms/archive/4ad40ef271da8176d4fc0194d2089b8a76e19d7b.zip"],
+    name = "platforms",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+        "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+    ],
+    sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
 )
diff --git a/src/third_party/googletest/WORKSPACE.bzlmod b/src/third_party/googletest/WORKSPACE.bzlmod
new file mode 100644
index 0000000..381432c
--- /dev/null
+++ b/src/third_party/googletest/WORKSPACE.bzlmod
@@ -0,0 +1,35 @@
+# Copyright 2024 Google Inc.
+# All Rights Reserved.
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * 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.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 COPYRIGHT
+# OWNER 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.
+
+# https://bazel.build/external/migration#workspace.bzlmod
+#
+# This file is intentionally empty. When bzlmod is enabled and this
+# file exists, the content of WORKSPACE is ignored. This prevents
+# bzlmod builds from unintentionally depending on the WORKSPACE file.
diff --git a/src/third_party/googletest/ci/linux-presubmit.sh b/src/third_party/googletest/ci/linux-presubmit.sh
index a1caa27..6491e79 100644
--- a/src/third_party/googletest/ci/linux-presubmit.sh
+++ b/src/third_party/googletest/ci/linux-presubmit.sh
@@ -31,39 +31,59 @@
 
 set -euox pipefail
 
-readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20230816"
-readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120"
+readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
 
 if [[ -z ${GTEST_ROOT:-} ]]; then
   GTEST_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20"
 fi
 
-# Test the CMake build
-for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
-  for cmake_off_on in OFF ON; do
-    time docker run \
-      --volume="${GTEST_ROOT}:/src:ro" \
-      --tmpfs="/build:exec" \
-      --workdir="/build" \
-      --rm \
-      --env="CC=${cc}" \
-      --env=CXXFLAGS="-Werror -Wdeprecated" \
-      ${LINUX_LATEST_CONTAINER} \
-      /bin/bash -c "
-        cmake /src \
-          -DCMAKE_CXX_STANDARD=14 \
-          -Dgtest_build_samples=ON \
-          -Dgtest_build_tests=ON \
-          -Dgmock_build_tests=ON \
-          -Dcxx_no_exception=${cmake_off_on} \
-          -Dcxx_no_rtti=${cmake_off_on} && \
-        make -j$(nproc) && \
-        ctest -j$(nproc) --output-on-failure"
-  done
+# Test CMake + GCC
+for cmake_off_on in OFF ON; do
+  time docker run \
+    --volume="${GTEST_ROOT}:/src:ro" \
+    --tmpfs="/build:exec" \
+    --workdir="/build" \
+    --rm \
+    --env="CC=/usr/local/bin/gcc" \
+    --env=CXXFLAGS="-Werror -Wdeprecated" \
+    ${LINUX_LATEST_CONTAINER} \
+    /bin/bash -c "
+      cmake /src \
+        -DCMAKE_CXX_STANDARD=17 \
+        -Dgtest_build_samples=ON \
+        -Dgtest_build_tests=ON \
+        -Dgmock_build_tests=ON \
+        -Dcxx_no_exception=${cmake_off_on} \
+        -Dcxx_no_rtti=${cmake_off_on} && \
+      make -j$(nproc) && \
+      ctest -j$(nproc) --output-on-failure"
+done
+
+# Test CMake + Clang
+for cmake_off_on in OFF ON; do
+  time docker run \
+    --volume="${GTEST_ROOT}:/src:ro" \
+    --tmpfs="/build:exec" \
+    --workdir="/build" \
+    --rm \
+    --env="CC=/opt/llvm/clang/bin/clang" \
+    --env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
+    ${LINUX_LATEST_CONTAINER} \
+    /bin/bash -c "
+      cmake /src \
+        -DCMAKE_CXX_STANDARD=17 \
+        -Dgtest_build_samples=ON \
+        -Dgtest_build_tests=ON \
+        -Dgmock_build_tests=ON \
+        -Dcxx_no_exception=${cmake_off_on} \
+        -Dcxx_no_rtti=${cmake_off_on} && \
+      make -j$(nproc) && \
+      ctest -j$(nproc) --output-on-failure"
 done
 
 # Do one test with an older version of GCC
@@ -72,7 +92,7 @@
   --workdir="/src" \
   --rm \
   --env="CC=/usr/local/bin/gcc" \
-  --env="BAZEL_CXXOPTS=-std=c++14" \
+  --env="BAZEL_CXXOPTS=-std=c++17" \
   ${LINUX_GCC_FLOOR_CONTAINER} \
     /usr/local/bin/bazel test ... \
       --copt="-Wall" \
@@ -80,7 +100,7 @@
       --copt="-Wuninitialized" \
       --copt="-Wundef" \
       --copt="-Wno-error=pragmas" \
-      --distdir="/bazel-distdir" \
+      --enable_bzlmod=false \
       --features=external_include_paths \
       --keep_going \
       --show_timestamps \
@@ -102,7 +122,7 @@
         --copt="-Wuninitialized" \
         --copt="-Wundef" \
         --define="absl=${absl}" \
-        --distdir="/bazel-distdir" \
+        --enable_bzlmod=true \
         --features=external_include_paths \
         --keep_going \
         --show_timestamps \
@@ -127,7 +147,7 @@
         --copt="-Wuninitialized" \
         --copt="-Wundef" \
         --define="absl=${absl}" \
-        --distdir="/bazel-distdir" \
+        --enable_bzlmod=true \
         --features=external_include_paths \
         --keep_going \
         --linkopt="--gcc-toolchain=/usr/local" \
diff --git a/src/third_party/googletest/ci/macos-presubmit.sh b/src/third_party/googletest/ci/macos-presubmit.sh
index 681ebc2..5370ed6 100644
--- a/src/third_party/googletest/ci/macos-presubmit.sh
+++ b/src/third_party/googletest/ci/macos-presubmit.sh
@@ -31,6 +31,9 @@
 
 set -euox pipefail
 
+# Use Xcode 16.0
+sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
+
 if [[ -z ${GTEST_ROOT:-} ]]; then
   GTEST_ROOT="$(realpath $(dirname ${0})/..)"
 fi
@@ -40,20 +43,20 @@
   BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
   cd ${BUILD_DIR}
   time cmake ${GTEST_ROOT} \
-    -DCMAKE_CXX_STANDARD=14 \
+    -DCMAKE_CXX_STANDARD=17 \
     -Dgtest_build_samples=ON \
     -Dgtest_build_tests=ON \
     -Dgmock_build_tests=ON \
     -Dcxx_no_exception=${cmake_off_on} \
     -Dcxx_no_rtti=${cmake_off_on}
-  time make
+  time make -j$(nproc)
   time ctest -j$(nproc) --output-on-failure
 done
 
 # Test the Bazel build
 
 # If we are running on Kokoro, check for a versioned Bazel binary.
-KOKORO_GFILE_BAZEL_BIN="bazel-5.1.1-darwin-x86_64"
+KOKORO_GFILE_BAZEL_BIN="bazel-8.0.0-darwin-x86_64"
 if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
   BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
   chmod +x ${BAZEL_BIN}
@@ -67,8 +70,9 @@
     --copt="-Wall" \
     --copt="-Werror" \
     --copt="-Wundef" \
-    --cxxopt="-std=c++14" \
+    --cxxopt="-std=c++17" \
     --define="absl=${absl}" \
+    --enable_bzlmod=true \
     --features=external_include_paths \
     --keep_going \
     --show_timestamps \
diff --git a/src/third_party/googletest/ci/windows-presubmit.bat b/src/third_party/googletest/ci/windows-presubmit.bat
index 48962eb..e2664c5 100644
--- a/src/third_party/googletest/ci/windows-presubmit.bat
+++ b/src/third_party/googletest/ci/windows-presubmit.bat
@@ -1,6 +1,6 @@
 SETLOCAL ENABLEDELAYEDEXPANSION
 
-SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-5.1.1-windows-x86_64.exe
+SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-8.0.0-windows-x86_64.exe
 
 SET PATH=C:\Python34;%PATH%
 SET BAZEL_PYTHON=C:\python34\python.exe
@@ -11,21 +11,18 @@
 SET CMAKE_BUILD_PARALLEL_LEVEL=16
 SET CTEST_PARALLEL_LEVEL=16
 
-IF EXIST git\googletest (
-  CD git\googletest
-) ELSE IF EXIST github\googletest (
-  CD github\googletest
-)
-
+SET GTEST_ROOT=%~dp0\..
 IF %errorlevel% neq 0 EXIT /B 1
 
 :: ----------------------------------------------------------------------------
 :: CMake
-MKDIR cmake_msvc2022
-CD cmake_msvc2022
+SET CMAKE_BUILD_PATH=cmake_msvc2022
+MKDIR %CMAKE_BUILD_PATH%
+CD %CMAKE_BUILD_PATH%
 
-%CMAKE_BIN% .. ^
+%CMAKE_BIN% %GTEST_ROOT% ^
   -G "Visual Studio 17 2022" ^
+  -DCMAKE_CXX_STANDARD=17 ^
   -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
   -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
   -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
@@ -40,18 +37,38 @@
 %CTEST_BIN% -C Debug --timeout 600
 IF %errorlevel% neq 0 EXIT /B 1
 
-CD ..
-RMDIR /S /Q cmake_msvc2022
+CD %GTEST_ROOT%
+RMDIR /S /Q %CMAKE_BUILD_PATH%
 
 :: ----------------------------------------------------------------------------
 :: Bazel
 
+:: The default home directory on Kokoro is a long path which causes errors
+:: because of Windows limitations on path length.
+:: --output_user_root=C:\tmp causes Bazel to use a shorter path.
 SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
-%BAZEL_EXE% test ... ^
+
+:: C++17
+%BAZEL_EXE% ^
+  --output_user_root=C:\tmp ^
+  test ... ^
   --compilation_mode=dbg ^
-  --copt=/std:c++14 ^
+  --copt=/std:c++17 ^
   --copt=/WX ^
-  --features=external_include_paths ^
+  --enable_bzlmod=true ^
+  --keep_going ^
+  --test_output=errors ^
+  --test_tag_filters=-no_test_msvc2017
+IF %errorlevel% neq 0 EXIT /B 1
+
+:: C++20
+%BAZEL_EXE% ^
+  --output_user_root=C:\tmp ^
+  test ... ^
+  --compilation_mode=dbg ^
+  --copt=/std:c++20 ^
+  --copt=/WX ^
+  --enable_bzlmod=true ^
   --keep_going ^
   --test_output=errors ^
   --test_tag_filters=-no_test_msvc2017
diff --git a/src/third_party/googletest/docs/advanced.md b/src/third_party/googletest/docs/advanced.md
index 0e1f812..9b1220a 100644
--- a/src/third_party/googletest/docs/advanced.md
+++ b/src/third_party/googletest/docs/advanced.md
@@ -286,7 +286,7 @@
 ```c++
 TEST(SkipTest, DoesSkip) {
   GTEST_SKIP() << "Skipping single test";
-  EXPECT_EQ(0, 1);  // Won't fail; it won't be executed
+  FAIL();  // Won't fail; it won't be executed
 }
 
 class SkipFixture : public ::testing::Test {
@@ -298,7 +298,7 @@
 
 // Tests for SkipFixture won't be executed.
 TEST_F(SkipFixture, SkipsOneTest) {
-  EXPECT_EQ(5, 7);  // Won't fail
+  FAIL();  // Won't fail; it won't be executed
 }
 ```
 
@@ -405,6 +405,51 @@
 For more details regarding `AbslStringify()` and its integration with other
 libraries, see go/abslstringify.
 
+## Regular Expression Syntax
+
+When built with Bazel and using Abseil, GoogleTest uses the
+[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
+systems (Linux, Cygwin, Mac), GoogleTest uses the
+[POSIX extended regular expression](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax. To learn about POSIX syntax, you may want to read this
+[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
+
+On Windows, GoogleTest uses its own simple regular expression implementation. It
+lacks many features. For example, we don't support union (`"x|y"`), grouping
+(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
+others. Below is what we do support (`A` denotes a literal character, period
+(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
+expressions.):
+
+Expression | Meaning
+---------- | --------------------------------------------------------------
+`c`        | matches any literal character `c`
+`\\d`      | matches any decimal digit
+`\\D`      | matches any character that's not a decimal digit
+`\\f`      | matches `\f`
+`\\n`      | matches `\n`
+`\\r`      | matches `\r`
+`\\s`      | matches any ASCII whitespace, including `\n`
+`\\S`      | matches any character that's not a whitespace
+`\\t`      | matches `\t`
+`\\v`      | matches `\v`
+`\\w`      | matches any letter, `_`, or decimal digit
+`\\W`      | matches any character that `\\w` doesn't match
+`\\c`      | matches any literal character `c`, which must be a punctuation
+`.`        | matches any single character except `\n`
+`A?`       | matches 0 or 1 occurrences of `A`
+`A*`       | matches 0 or many occurrences of `A`
+`A+`       | matches 1 or many occurrences of `A`
+`^`        | matches the beginning of a string (not that of each line)
+`$`        | matches the end of a string (not that of each line)
+`xy`       | matches `x` followed by `y`
+
+To help you determine which capability is available on your system, GoogleTest
+defines macros to govern which regular expression it is using. The macros are:
+`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
+tests to work in all cases, you can either `#if` on these macros or use the more
+limited syntax only.
+
 ## Death Tests
 
 In many applications, there are assertions that can cause application failure if
@@ -416,7 +461,7 @@
 such assertion statements work as expected.
 
 Since these precondition checks cause the processes to die, we call such tests
-_death tests_. More generally, any test that checks that a program terminates
+*death tests*. More generally, any test that checks that a program terminates
 (except by throwing an exception) in an expected fashion is also a death test.
 
 Note that if a piece of code throws an exception, we don't consider it "death"
@@ -462,6 +507,12 @@
     exit with exit code 0, and
 *   calling `KillProcess()` kills the process with signal `SIGKILL`.
 
+{: .callout .warning}
+Warning: If your death test contains mocks and is expecting a specific exit
+code, then you must allow the mock objects to be leaked via `Mock::AllowLeak`.
+This is because the mock leak detector will exit with its own error code if it
+detects a leak.
+
 The test function body may contain other assertions and statements as well, if
 necessary.
 
@@ -503,51 +554,6 @@
 }
 ```
 
-### Regular Expression Syntax
-
-When built with Bazel and using Abseil, GoogleTest uses the
-[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
-systems (Linux, Cygwin, Mac), GoogleTest uses the
-[POSIX extended regular expression](https://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
-syntax. To learn about POSIX syntax, you may want to read this
-[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
-
-On Windows, GoogleTest uses its own simple regular expression implementation. It
-lacks many features. For example, we don't support union (`"x|y"`), grouping
-(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
-others. Below is what we do support (`A` denotes a literal character, period
-(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
-expressions.):
-
-Expression | Meaning
----------- | --------------------------------------------------------------
-`c`        | matches any literal character `c`
-`\\d`      | matches any decimal digit
-`\\D`      | matches any character that's not a decimal digit
-`\\f`      | matches `\f`
-`\\n`      | matches `\n`
-`\\r`      | matches `\r`
-`\\s`      | matches any ASCII whitespace, including `\n`
-`\\S`      | matches any character that's not a whitespace
-`\\t`      | matches `\t`
-`\\v`      | matches `\v`
-`\\w`      | matches any letter, `_`, or decimal digit
-`\\W`      | matches any character that `\\w` doesn't match
-`\\c`      | matches any literal character `c`, which must be a punctuation
-`.`        | matches any single character except `\n`
-`A?`       | matches 0 or 1 occurrences of `A`
-`A*`       | matches 0 or many occurrences of `A`
-`A+`       | matches 1 or many occurrences of `A`
-`^`        | matches the beginning of a string (not that of each line)
-`$`        | matches the end of a string (not that of each line)
-`xy`       | matches `x` followed by `y`
-
-To help you determine which capability is available on your system, GoogleTest
-defines macros to govern which regular expression it is using. The macros are:
-`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
-tests to work in all cases, you can either `#if` on these macros or use the more
-limited syntax only.
-
 ### How It Works
 
 See [Death Assertions](reference/assertions.md#death) in the Assertions
@@ -727,7 +733,7 @@
 ### Propagating Fatal Failures
 
 A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
-when they fail they only abort the _current function_, not the entire test. For
+when they fail they only abort the *current function*, not the entire test. For
 example, the following test will segfault:
 
 ```c++
@@ -1004,11 +1010,21 @@
 Environment* AddGlobalTestEnvironment(Environment* env);
 ```
 
-Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
-each environment object, then runs the tests if none of the environments
-reported fatal failures and `GTEST_SKIP()` was not called. `RUN_ALL_TESTS()`
-always calls `TearDown()` with each environment object, regardless of whether or
-not the tests were run.
+Now, when `RUN_ALL_TESTS()` is invoked, it first calls the `SetUp()` method. The
+tests are then executed, provided that none of the environments have reported
+fatal failures and `GTEST_SKIP()` has not been invoked. Finally, `TearDown()` is
+called.
+
+Note that `SetUp()` and `TearDown()` are only invoked if there is at least one
+test to be performed. Importantly, `TearDown()` is executed even if the test is
+not run due to a fatal failure or `GTEST_SKIP()`.
+
+Calling `SetUp()` and `TearDown()` for each iteration depends on the flag
+`gtest_recreate_environments_when_repeating`. `SetUp()` and `TearDown()` are
+called for each environment object when the object is recreated for each
+iteration. However, if test environments are not recreated for each iteration,
+`SetUp()` is called only on the first iteration, and `TearDown()` is called only
+on the last iteration.
 
 It's OK to register multiple environment objects. In this suite, their `SetUp()`
 will be called in the order they are registered, and their `TearDown()` will be
@@ -1804,7 +1820,7 @@
 `::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
 
 To see a list of supported flags and their usage, please run your test program
-with the `--help` flag. You can also use `-h`, `-?`, or `/?` for short.
+with the `--help` flag.
 
 If an option is specified both by an environment variable and by a flag, the
 latter takes precedence.
@@ -1913,6 +1929,20 @@
 You can combine this with the `--gtest_filter` flag to further select which
 disabled tests to run.
 
+### Enforcing Having At Least One Test Case
+
+A not uncommon programmer mistake is to write a test program that has no test
+case linked in. This can happen, for example, when you put test case definitions
+in a library and the library is not marked as "always link".
+
+To catch such mistakes, run the test program with the
+`--gtest_fail_if_no_test_linked` flag or set the `GTEST_FAIL_IF_NO_TEST_LINKED`
+environment variable to a value other than `0`. Now the program will fail if no
+test case is linked in.
+
+Note that *any* test case linked in makes the program valid for the purpose of
+this check. In particular, even a disabled test case suffices.
+
 ### Repeating the Tests
 
 Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
@@ -2372,7 +2402,7 @@
 
 #### Detecting Test Premature Exit
 
-Google Test implements the _premature-exit-file_ protocol for test runners to
+Google Test implements the *premature-exit-file* protocol for test runners to
 catch any kind of unexpected exits of test programs. Upon start, Google Test
 creates the file which will be automatically deleted after all work has been
 finished. Then, the test runner can check if this file exists. In case the file
diff --git a/src/third_party/googletest/docs/faq.md b/src/third_party/googletest/docs/faq.md
index 90c2497..c7d10b5 100644
--- a/src/third_party/googletest/docs/faq.md
+++ b/src/third_party/googletest/docs/faq.md
@@ -3,7 +3,7 @@
 ## Why should test suite names and test names not contain underscore?
 
 {: .callout .note}
-Note: GoogleTest reserves underscore (`_`) for special purpose keywords, such as
+Note: GoogleTest reserves underscore (`_`) for special-purpose keywords, such as
 [the `DISABLED_` prefix](advanced.md#temporarily-disabling-tests), in addition
 to the following rationale.
 
@@ -33,9 +33,9 @@
     `TestSuiteName_Bar__Test`, which is invalid.
 
 So clearly `TestSuiteName` and `TestName` cannot start or end with `_`
-(Actually, `TestSuiteName` can start with `_` -- as long as the `_` isn't
-followed by an upper-case letter. But that's getting complicated. So for
-simplicity we just say that it cannot start with `_`.).
+(Actually, `TestSuiteName` can start with `_`—as long as the `_` isn't followed
+by an upper-case letter. But that's getting complicated. So for simplicity we
+just say that it cannot start with `_`.).
 
 It may seem fine for `TestSuiteName` and `TestName` to contain `_` in the
 middle. However, consider this:
@@ -128,30 +128,9 @@
 differences between the two tools. Once you have some concrete experience, you
 can much more easily decide which one to use the next time.
 
-## I got some run-time errors about invalid proto descriptors when using `ProtocolMessageEquals`. Help!
-
-{: .callout .note}
-**Note:** `ProtocolMessageEquals` and `ProtocolMessageEquiv` are *deprecated*
-now. Please use `EqualsProto`, etc instead.
-
-`ProtocolMessageEquals` and `ProtocolMessageEquiv` were redefined recently and
-are now less tolerant of invalid protocol buffer definitions. In particular, if
-you have a `foo.proto` that doesn't fully qualify the type of a protocol message
-it references (e.g. `message<Bar>` where it should be `message<blah.Bar>`), you
-will now get run-time errors like:
-
-```
-... descriptor.cc:...] Invalid proto descriptor for file "path/to/foo.proto":
-... descriptor.cc:...]  blah.MyMessage.my_field: ".Bar" is not defined.
-```
-
-If you see this, your `.proto` file is broken and needs to be fixed by making
-the types fully qualified. The new definition of `ProtocolMessageEquals` and
-`ProtocolMessageEquiv` just happen to reveal your bug.
-
 ## My death test modifies some state, but the change seems lost after the death test finishes. Why?
 
-Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
+Death tests (`EXPECT_DEATH`, etc.) are executed in a sub-process s.t. the
 expected crash won't kill the test program (i.e. the parent process). As a
 result, any in-memory side effects they incur are observable in their respective
 sub-processes, but not in the parent process. You can think of them as running
@@ -192,16 +171,16 @@
 };
 ```
 
-You also need to define it *outside* of the class body in `foo.cc`:
+you also need to define it *outside* of the class body in `foo.cc`:
 
 ```c++
 const int Foo::kBar;  // No initializer here.
 ```
 
 Otherwise your code is **invalid C++**, and may break in unexpected ways. In
-particular, using it in GoogleTest comparison assertions (`EXPECT_EQ`, etc) will
-generate an "undefined reference" linker error. The fact that "it used to work"
-doesn't mean it's valid. It just means that you were lucky. :-)
+particular, using it in GoogleTest comparison assertions (`EXPECT_EQ`, etc.)
+will generate an "undefined reference" linker error. The fact that "it used to
+work" doesn't mean it's valid. It just means that you were lucky. :-)
 
 If the declaration of the static data member is `constexpr` then it is
 implicitly an `inline` definition, and a separate definition in `foo.cc` is not
@@ -311,7 +290,7 @@
 call `TearDown()`, and then delete the test fixture object.
 
 When you need to write per-test set-up and tear-down logic, you have the choice
-between using the test fixture constructor/destructor or `SetUp()/TearDown()`.
+between using the test fixture constructor/destructor or `SetUp()`/`TearDown()`.
 The former is usually preferred, as it has the following benefits:
 
 *   By initializing a member variable in the constructor, we have the option to
@@ -352,7 +331,7 @@
     GoogleTest assertions in a destructor if your code could run on such a
     platform.
 
-## The compiler complains "no matching function to call" when I use ASSERT_PRED*. How do I fix it?
+## The compiler complains "no matching function to call" when I use `ASSERT_PRED*`. How do I fix it?
 
 See details for [`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the
 Assertions Reference.
@@ -410,7 +389,7 @@
 Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and
 wonder why it's never called.
 
-## I have several test suites which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious.
+## I have several test suites which share the same test fixture logic; do I have to define a new test fixture class for each of them? This seems pretty tedious.
 
 You don't have to. Instead of
 
@@ -545,7 +524,7 @@
 create a manager thread. However, if you don't control which machine your test
 runs on, you shouldn't depend on this.
 
-## Why does GoogleTest require the entire test suite, instead of individual tests, to be named *DeathTest when it uses ASSERT_DEATH?
+## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`?
 
 GoogleTest does not interleave tests from different test suites. That is, it
 runs all tests in one test suite first, and then runs all tests in the next test
@@ -570,7 +549,7 @@
 `FooTest` case before running any test in the `BarTest` case. This contradicts
 with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
 
-## But I don't like calling my entire test suite \*DeathTest when it contains both death tests and non-death tests. What do I do?
+## But I don't like calling my entire test suite `*DeathTest` when it contains both death tests and non-death tests. What do I do?
 
 You don't have to, but if you like, you may split up the test suite into
 `FooTest` and `FooDeathTest`, where the names make it clear that they are
@@ -654,7 +633,7 @@
 Yes.
 
 The rule is **all test methods in the same test suite must use the same fixture
-class.** This means that the following is **allowed** because both tests use the
+class**. This means that the following is **allowed** because both tests use the
 same fixture class (`::testing::Test`).
 
 ```c++
diff --git a/src/third_party/googletest/docs/gmock_cook_book.md b/src/third_party/googletest/docs/gmock_cook_book.md
index da10918..633dbc3 100644
--- a/src/third_party/googletest/docs/gmock_cook_book.md
+++ b/src/third_party/googletest/docs/gmock_cook_book.md
@@ -177,7 +177,7 @@
 template <typename Elem>
 class MockStack : public StackInterface<Elem> {
   ...
-  MOCK_METHOD(int, GetSize, (), (override));
+  MOCK_METHOD(int, GetSize, (), (const, override));
   MOCK_METHOD(void, Push, (const Elem& x), (override));
 };
 ```
@@ -936,8 +936,8 @@
     floating-point numbers), the conversion from `T` to `U` is not lossy (in
     other words, any value representable by `T` can also be represented by `U`);
     and
-3.  When `U` is a reference, `T` must also be a reference (as the underlying
-    matcher may be interested in the address of the `U` value).
+3.  When `U` is a non-const reference, `T` must also be a reference (as the
+    underlying matcher may be interested in the address of the `U` value).
 
 The code won't compile if any of these conditions isn't met.
 
@@ -1927,6 +1927,12 @@
                       action_n));
 ```
 
+The return value of the last action **must** match the return type of the mocked
+method. In the example above, `action_n` could be `Return(true)`, or a lambda
+that returns a `bool`, but not `SaveArg`, which returns `void`. Otherwise the
+signature of `DoAll` would not match the signature expected by `WillOnce`, which
+is the signature of the mocked method, and it wouldn't compile.
+
 ### Verifying Complex Arguments {#SaveArgVerify}
 
 If you want to verify that a method is called with a particular argument but the
@@ -3306,7 +3312,7 @@
 case gMock will use the sequence of words in the matcher name as the
 description.
 
-For example:
+#### Basic Example
 
 ```cpp
 MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
@@ -3344,6 +3350,8 @@
 where the descriptions `"is divisible by 7"` and `"not (is divisible by 7)"` are
 automatically calculated from the matcher name `IsDivisibleBy7`.
 
+#### Adding Custom Failure Messages
+
 As you may have noticed, the auto-generated descriptions (especially those for
 the negation) may not be so great. You can always override them with a `string`
 expression of your own:
@@ -3377,21 +3385,48 @@
     Actual: 27 (the remainder is 6)
 ```
 
+#### Using EXPECT_ Statements in Matchers
+
+You can also use `EXPECT_...` statements inside custom matcher definitions. In
+many cases, this allows you to write your matcher more concisely while still
+providing an informative error message. For example:
+
+```cpp
+MATCHER(IsDivisibleBy7, "") {
+  const auto remainder = arg % 7;
+  EXPECT_EQ(remainder, 0);
+  return true;
+}
+```
+
+If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`,
+you will get an error something like the following:
+
+```shell
+Expected equality of these values:
+  remainder
+    Which is: 6
+  0
+```
+
+#### `MatchAndExplain`
+
 You should let `MatchAndExplain()` print *any additional information* that can
 help a user understand the match result. Note that it should explain why the
 match succeeds in case of a success (unless it's obvious) - this is useful when
 the matcher is used inside `Not()`. There is no need to print the argument value
 itself, as gMock already prints it for you.
 
-{: .callout .note}
-NOTE: The type of the value being matched (`arg_type`) is determined by the
-context in which you use the matcher and is supplied to you by the compiler, so
-you don't need to worry about declaring it (nor can you). This allows the
-matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match
-any type where the value of `(arg % 7) == 0` can be implicitly converted to a
-`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an
-`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will
-be `unsigned long`; and so on.
+#### Argument Types
+
+The type of the value being matched (`arg_type`) is determined by the context in
+which you use the matcher and is supplied to you by the compiler, so you don't
+need to worry about declaring it (nor can you). This allows the matcher to be
+polymorphic. For example, `IsDivisibleBy7()` can be used to match any type where
+the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
+`Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`,
+`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
+`unsigned long`; and so on.
 
 ### Writing New Parameterized Matchers Quickly
 
diff --git a/src/third_party/googletest/docs/gmock_for_dummies.md b/src/third_party/googletest/docs/gmock_for_dummies.md
index 9f24dca..ed2297c 100644
--- a/src/third_party/googletest/docs/gmock_for_dummies.md
+++ b/src/third_party/googletest/docs/gmock_for_dummies.md
@@ -261,6 +261,8 @@
 when you allocate mocks on the heap. You get that automatically if you use the
 `gtest_main` library already.
 
+###### Expectation Ordering
+
 **Important note:** gMock requires expectations to be set **before** the mock
 functions are called, otherwise the behavior is **undefined**. Do not alternate
 between calls to `EXPECT_CALL()` and calls to the mock functions, and do not set
diff --git a/src/third_party/googletest/docs/primer.md b/src/third_party/googletest/docs/primer.md
index 4901e1a..69d6c6d 100644
--- a/src/third_party/googletest/docs/primer.md
+++ b/src/third_party/googletest/docs/primer.md
@@ -73,8 +73,8 @@
 Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
 
 
-[istqb test case]: https://glossary.istqb.org/en/search/test%20case
-[istqb test suite]: https://glossary.istqb.org/en/search/test%20suite
+[istqb test case]: https://glossary.istqb.org/en_US/term/test-case
+[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite
 
 ## Basic Concepts
 
@@ -210,7 +210,7 @@
 
 To create a fixture:
 
-1.  Derive a class from `::testing::Test` . Start its body with `protected:`, as
+1.  Derive a class from `testing::Test` . Start its body with `protected:`, as
     we'll want to access fixture members from sub-classes.
 2.  Inside the class, declare any objects you plan to use.
 3.  If necessary, write a default constructor or `SetUp()` function to prepare
@@ -271,16 +271,16 @@
 `FooTest` where `Foo` is the class being tested.
 
 ```c++
-class QueueTest : public ::testing::Test {
+class QueueTest : public testing::Test {
  protected:
-  void SetUp() override {
+  QueueTest() {
      // q0_ remains empty
      q1_.Enqueue(1);
      q2_.Enqueue(2);
      q2_.Enqueue(3);
   }
 
-  // void TearDown() override {}
+  // ~QueueTest() override = default;
 
   Queue<int> q0_;
   Queue<int> q1_;
@@ -288,8 +288,9 @@
 };
 ```
 
-In this case, `TearDown()` is not needed since we don't have to clean up after
-each test, other than what's already done by the destructor.
+In this case, we don't need to define a destructor or a `TearDown()` method,
+because the implicit destructor generated by the compiler will perform all of
+the necessary cleanup.
 
 Now we'll write tests using `TEST_F()` and this fixture.
 
@@ -326,11 +327,9 @@
 When these tests run, the following happens:
 
 1.  GoogleTest constructs a `QueueTest` object (let's call it `t1`).
-2.  `t1.SetUp()` initializes `t1`.
-3.  The first test (`IsEmptyInitially`) runs on `t1`.
-4.  `t1.TearDown()` cleans up after the test finishes.
-5.  `t1` is destructed.
-6.  The above steps are repeated on another `QueueTest` object, this time
+2.  The first test (`IsEmptyInitially`) runs on `t1`.
+3.  `t1` is destructed.
+4.  The above steps are repeated on another `QueueTest` object, this time
     running the `DequeueWorks` test.
 
 **Availability**: Linux, Windows, Mac.
@@ -402,7 +401,7 @@
 namespace {
 
 // The fixture for testing class Foo.
-class FooTest : public ::testing::Test {
+class FooTest : public testing::Test {
  protected:
   // You can remove any or all of the following functions if their bodies would
   // be empty.
@@ -450,14 +449,14 @@
 }  // namespace my
 
 int main(int argc, char **argv) {
-  ::testing::InitGoogleTest(&argc, argv);
+  testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
 }
 ```
 
-The `::testing::InitGoogleTest()` function parses the command line for
-GoogleTest flags, and removes all recognized flags. This allows the user to
-control a test program's behavior via various flags, which we'll cover in the
+The `testing::InitGoogleTest()` function parses the command line for GoogleTest
+flags, and removes all recognized flags. This allows the user to control a test
+program's behavior via various flags, which we'll cover in the
 [AdvancedGuide](advanced.md). You **must** call this function before calling
 `RUN_ALL_TESTS()`, or the flags won't be properly initialized.
 
diff --git a/src/third_party/googletest/docs/quickstart-bazel.md b/src/third_party/googletest/docs/quickstart-bazel.md
index 4f693db..5750f02 100644
--- a/src/third_party/googletest/docs/quickstart-bazel.md
+++ b/src/third_party/googletest/docs/quickstart-bazel.md
@@ -10,8 +10,8 @@
 
 *   A compatible operating system (e.g. Linux, macOS, Windows).
 *   A compatible C++ compiler that supports at least C++14.
-*   [Bazel](https://bazel.build/), the preferred build system used by the
-    GoogleTest team.
+*   [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
+    by the GoogleTest team.
 
 See [Supported Platforms](platforms.md) for more information about platforms
 compatible with GoogleTest.
@@ -28,7 +28,7 @@
 [Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace)
 is a directory on your filesystem that you use to manage source files for the
 software you want to build. Each workspace directory has a text file named
-`WORKSPACE` which may be empty, or may contain references to external
+`MODULE.bazel` which may be empty, or may contain references to external
 dependencies required to build the outputs.
 
 First, create a directory for your workspace:
@@ -37,30 +37,20 @@
 $ mkdir my_workspace && cd my_workspace
 ```
 
-Next, you’ll create the `WORKSPACE` file to specify dependencies. A common and
-recommended way to depend on GoogleTest is to use a
-[Bazel external dependency](https://docs.bazel.build/versions/main/external.html)
-via the
-[`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive).
-To do this, in the root directory of your workspace (`my_workspace/`), create a
-file named `WORKSPACE` with the following contents:
+Next, you’ll create the `MODULE.bazel` file to specify dependencies. As of Bazel
+7.0, the recommended way to consume GoogleTest is through the
+[Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do
+this, create a `MODULE.bazel` file in the root directory of your Bazel workspace
+with the following content:
 
 ```
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+# MODULE.bazel
 
-http_archive(
-  name = "com_google_googletest",
-  urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"],
-  strip_prefix = "googletest-5ab508a01f9eb089207ee87fd547d290da39d015",
-)
+# Choose the most recent version available at
+# https://registry.bazel.build/modules/googletest
+bazel_dep(name = "googletest", version = "1.15.2")
 ```
 
-The above configuration declares a dependency on GoogleTest which is downloaded
-as a ZIP archive from GitHub. In the above example,
-`5ab508a01f9eb089207ee87fd547d290da39d015` is the Git commit hash of the
-GoogleTest version to use; we recommend updating the hash often to point to the
-latest version. Use a recent hash on the `main` branch.
-
 Now you're ready to build C++ code that uses GoogleTest.
 
 ## Create and run a binary
@@ -92,17 +82,20 @@
 
 ```
 cc_test(
-  name = "hello_test",
-  size = "small",
-  srcs = ["hello_test.cc"],
-  deps = ["@com_google_googletest//:gtest_main"],
+    name = "hello_test",
+    size = "small",
+    srcs = ["hello_test.cc"],
+    deps = [
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
 )
 ```
 
 This `cc_test` rule declares the C++ test binary you want to build, and links to
-GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE`
-file (`@com_google_googletest`). For more information about Bazel `BUILD` files,
-see the
+the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()`
+function (`@googletest//:gtest_main`). For more information about Bazel `BUILD`
+files, see the
 [Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
 
 {: .callout .note}
@@ -115,7 +108,7 @@
 Now you can build and run your test:
 
 <pre>
-<strong>my_workspace$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
+<strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
 INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
 INFO: Found 1 test target...
 INFO: From Testing //:hello_test:
diff --git a/src/third_party/googletest/docs/reference/actions.md b/src/third_party/googletest/docs/reference/actions.md
index ab81a12..0ebdc1e 100644
--- a/src/third_party/googletest/docs/reference/actions.md
+++ b/src/third_party/googletest/docs/reference/actions.md
@@ -24,7 +24,8 @@
 | :--------------------------------- | :-------------------------------------- |
 | `Assign(&variable, value)` | Assign `value` to variable. |
 | `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
-| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by copy-assignment. |
+| `SaveArgByMove<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by move-assignment. |
 | `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
 | `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. |
 | `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
diff --git a/src/third_party/googletest/docs/reference/assertions.md b/src/third_party/googletest/docs/reference/assertions.md
index 492ff5e..eeec4a0 100644
--- a/src/third_party/googletest/docs/reference/assertions.md
+++ b/src/third_party/googletest/docs/reference/assertions.md
@@ -276,7 +276,8 @@
 `ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
 
 Verifies that the two `float` values *`val1`* and *`val2`* are approximately
-equal, to within 4 ULPs from each other.
+equal, to within 4 ULPs from each other. Infinity and the largest finite float
+value are considered to be one ULP apart.
 
 ### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
 
@@ -284,7 +285,8 @@
 `ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
 
 Verifies that the two `double` values *`val1`* and *`val2`* are approximately
-equal, to within 4 ULPs from each other.
+equal, to within 4 ULPs from each other. Infinity and the largest finite double
+value are considered to be one ULP apart.
 
 ### EXPECT_NEAR {#EXPECT_NEAR}
 
@@ -294,6 +296,11 @@
 Verifies that the difference between *`val1`* and *`val2`* does not exceed the
 absolute error bound *`abs_error`*.
 
+If *`val`* and *`val2`* are both infinity of the same sign, the difference is
+considered to be 0. Otherwise, if either value is infinity, the difference is
+considered to be infinity. All non-NaN values (including infinity) are
+considered to not exceed an *`abs_error`* of infinity.
+
 ## Exception Assertions {#exceptions}
 
 The following assertions verify that a piece of code throws, or does not throw,
diff --git a/src/third_party/googletest/docs/reference/matchers.md b/src/third_party/googletest/docs/reference/matchers.md
index 243e3f9..16397ef 100644
--- a/src/third_party/googletest/docs/reference/matchers.md
+++ b/src/third_party/googletest/docs/reference/matchers.md
@@ -171,6 +171,11 @@
 | `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. |
 | `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message.
 
+{: .callout .warning}
+Warning: Don't use `Property()` against member functions that you do not own,
+because taking addresses of functions is fragile and generally not part of the
+contract of the function.
+
 **Notes:**
 
 *   You can use `FieldsAre()` to match any type that supports structured
@@ -189,10 +194,6 @@
     EXPECT_THAT(s, FieldsAre(42, "aloha"));
     ```
 
-*   Don't use `Property()` against member functions that you do not own, because
-    taking addresses of functions is fragile and generally not part of the
-    contract of the function.
-
 ## Matching the Result of a Function, Functor, or Callback
 
 | Matcher          | Description                                       |
diff --git a/src/third_party/googletest/docs/reference/testing.md b/src/third_party/googletest/docs/reference/testing.md
index ead66b3..3ed5211 100644
--- a/src/third_party/googletest/docs/reference/testing.md
+++ b/src/third_party/googletest/docs/reference/testing.md
@@ -94,7 +94,8 @@
 The argument *`InstantiationName`* is a unique name for the instantiation of the
 test suite, to distinguish between multiple instantiations. In test output, the
 instantiation name is added as a prefix to the test suite name
-*`TestSuiteName`*.
+*`TestSuiteName`*. If *`InstantiationName`* is empty
+(`INSTANTIATE_TEST_SUITE_P(, ...)`), no prefix is added.
 
 The argument *`param_generator`* is one of the following GoogleTest-provided
 functions that generate the test parameters, all defined in the `::testing`
@@ -139,6 +140,7 @@
 ### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
 
 `TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
+`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`,`*`NameGenerator`*`)`
 
 Defines a typed test suite based on the test fixture *`TestFixtureName`*. The
 test suite name is *`TestFixtureName`*.
@@ -168,6 +170,22 @@
 The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE`
 macro to parse correctly.
 
+The optional third argument *`NameGenerator`* allows specifying a class that
+exposes a templated static function `GetName(int)`. For example:
+
+```cpp
+class NameGenerator {
+ public:
+  template <typename T>
+  static std::string GetName(int) {
+    if constexpr (std::is_same_v<T, char>) return "char";
+    if constexpr (std::is_same_v<T, int>) return "int";
+    if constexpr (std::is_same_v<T, unsigned int>) return "unsignedInt";
+  }
+};
+TYPED_TEST_SUITE(MyFixture, MyTypes, NameGenerator);
+```
+
 See also [`TYPED_TEST`](#TYPED_TEST) and
 [Typed Tests](../advanced.md#typed-tests) for more information.
 
@@ -277,7 +295,8 @@
 The argument *`InstantiationName`* is a unique name for the instantiation of the
 test suite, to distinguish between multiple instantiations. In test output, the
 instantiation name is added as a prefix to the test suite name
-*`TestSuiteName`*.
+*`TestSuiteName`*. If *`InstantiationName`* is empty
+(`INSTANTIATE_TYPED_TEST_SUITE_P(, ...)`), no prefix is added.
 
 The argument *`Types`* is a [`Types`](#Types) object representing the list of
 types to run the tests on, for example:
@@ -1317,7 +1336,9 @@
 Initializes GoogleTest. This must be called before calling
 [`RUN_ALL_TESTS()`](#RUN_ALL_TESTS). In particular, it parses the command line
 for the flags that GoogleTest recognizes. Whenever a GoogleTest flag is seen, it
-is removed from `argv`, and `*argc` is decremented.
+is removed from `argv`, and `*argc` is decremented. Keep in mind that `argv`
+must terminate with a `NULL` pointer (i.e. `argv[argc]` is `NULL`), which is
+already the case with the default `argv` passed to `main`.
 
 No value is returned. Instead, the GoogleTest flag variables are updated.
 
diff --git a/src/third_party/googletest/fake_fuchsia_sdk.bzl b/src/third_party/googletest/fake_fuchsia_sdk.bzl
new file mode 100644
index 0000000..bc5b927
--- /dev/null
+++ b/src/third_party/googletest/fake_fuchsia_sdk.bzl
@@ -0,0 +1,61 @@
+"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
+
+GoogleTest can be used with the [Fuchsia](https://fuchsia.dev/) SDK. However,
+because the Fuchsia SDK does not yet support bzlmod, GoogleTest's `MODULE.bazel`
+file by default provides a "fake" Fuchsia SDK.
+
+To override this and use the real Fuchsia SDK, you can add the following to your
+project's `MODULE.bazel` file:
+
+    fake_fuchsia_sdk_extension =
+    use_extension("@com_google_googletest//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
+    override_repo(fake_fuchsia_sdk_extension, "fuchsia_sdk")
+
+NOTE: The `override_repo` built-in is only available in Bazel 8.0 and higher.
+
+See https://github.com/google/googletest/issues/4472 for more details of why the
+fake Fuchsia SDK is needed.
+"""
+
+def _fake_fuchsia_sdk_impl(repo_ctx):
+    for stub_target in repo_ctx.attr._stub_build_targets:
+        stub_package = stub_target
+        stub_target_name = stub_target.split("/")[-1]
+        repo_ctx.file("%s/BUILD.bazel" % stub_package, """
+filegroup(
+    name = "%s",
+)
+""" % stub_target_name)
+
+fake_fuchsia_sdk = repository_rule(
+    doc = "Used to create a fake @fuchsia_sdk repository with stub build targets.",
+    implementation = _fake_fuchsia_sdk_impl,
+    attrs = {
+        "_stub_build_targets": attr.string_list(
+            doc = "The stub build targets to initialize.",
+            default = [
+                "pkg/fdio",
+                "pkg/syslog",
+                "pkg/zx",
+            ],
+        ),
+    },
+)
+
+_create_fake = tag_class()
+
+def _fuchsia_sdk_impl(module_ctx):
+    create_fake_sdk = False
+    for mod in module_ctx.modules:
+        for _ in mod.tags.create_fake:
+            create_fake_sdk = True
+
+    if create_fake_sdk:
+        fake_fuchsia_sdk(name = "fuchsia_sdk")
+
+    return module_ctx.extension_metadata(reproducible = True)
+
+fuchsia_sdk = module_extension(
+    implementation = _fuchsia_sdk_impl,
+    tag_classes = {"create_fake": _create_fake},
+)
diff --git a/src/third_party/googletest/googlemock/CMakeLists.txt b/src/third_party/googletest/googlemock/CMakeLists.txt
index a9aa072..99b2411 100644
--- a/src/third_party/googletest/googlemock/CMakeLists.txt
+++ b/src/third_party/googletest/googlemock/CMakeLists.txt
@@ -5,7 +5,7 @@
 # CMake build script for Google Mock.
 #
 # To run the tests for Google Mock itself on Linux, use 'make test' or
-# ctest.  You can select which tests to run using 'ctest -R regex'.
+# ctest. You can select which tests to run using 'ctest -R regex'.
 # For more options, run 'ctest --help'.
 
 option(gmock_build_tests "Build all of Google Mock's own tests." OFF)
@@ -44,7 +44,7 @@
 endif()
 
 # Instructs CMake to process Google Test's CMakeLists.txt and add its
-# targets to the current scope.  We are placing Google Test's binary
+# targets to the current scope. We are placing Google Test's binary
 # directory in a subdirectory of our own as VC compilation may break
 # if they are the same (the default).
 add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/${gtest_dir}")
@@ -60,25 +60,26 @@
 endif()
 
 # Although Google Test's CMakeLists.txt calls this function, the
-# changes there don't affect the current scope.  Therefore we have to
+# changes there don't affect the current scope. Therefore we have to
 # call it again here.
-config_compiler_and_linker()  # from ${gtest_dir}/cmake/internal_utils.cmake
+config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
 
 # Adds Google Mock's and Google Test's header directories to the search path.
+# Get Google Test's include dirs from the target, gtest_SOURCE_DIR is broken
+# when using fetch-content with the name "GTest".
+get_target_property(gtest_include_dirs gtest INCLUDE_DIRECTORIES)
 set(gmock_build_include_dirs
   "${gmock_SOURCE_DIR}/include"
   "${gmock_SOURCE_DIR}"
-  "${gtest_SOURCE_DIR}/include"
-  # This directory is needed to build directly from Google Test sources.
-  "${gtest_SOURCE_DIR}")
+  "${gtest_include_dirs}")
 include_directories(${gmock_build_include_dirs})
 
 ########################################################################
 #
-# Defines the gmock & gmock_main libraries.  User tests should link
+# Defines the gmock & gmock_main libraries. User tests should link
 # with one of them.
 
-# Google Mock libraries.  We build them using more strict warnings than what
+# Google Mock libraries. We build them using more strict warnings than what
 # are used for other targets, to ensure that Google Mock can be compiled by
 # a user aggressive about warnings.
 if (MSVC)
@@ -111,7 +112,7 @@
 
 ########################################################################
 #
-# Install rules
+# Install rules.
 install_project(gmock gmock_main)
 
 ########################################################################
@@ -121,8 +122,8 @@
 # You can skip this section if you aren't interested in testing
 # Google Mock itself.
 #
-# The tests are not built by default.  To build them, set the
-# gmock_build_tests option to ON.  You can do it by running ccmake
+# The tests are not built by default. To build them, set the
+# gmock_build_tests option to ON. You can do it by running ccmake
 # or specifying the -Dgmock_build_tests=ON flag when running cmake.
 
 if (gmock_build_tests)
@@ -187,7 +188,7 @@
   cxx_shared_library(shared_gmock_main "${cxx_default}"
     "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
 
-  # Tests that a binary can be built with Google Mock as a shared library.  On
+  # Tests that a binary can be built with Google Mock as a shared library. On
   # some system configurations, it may not possible to run the binary without
   # knowing more details about the system configurations. We do not try to run
   # this binary. To get a more robust shared library coverage, configure with
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock-actions.h b/src/third_party/googletest/googlemock/include/gmock/gmock-actions.h
index f20258b..040e702 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock-actions.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock-actions.h
@@ -135,6 +135,7 @@
 #endif
 
 #include <algorithm>
+#include <exception>
 #include <functional>
 #include <memory>
 #include <string>
@@ -1492,6 +1493,7 @@
   // providing a call operator because even with a particular set of arguments
   // they don't have a fixed return type.
 
+  // We support conversion to OnceAction whenever the sub-action does.
   template <typename R, typename... Args,
             typename std::enable_if<
                 std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value,
@@ -1500,6 +1502,21 @@
     return std::move(final_action_);
   }
 
+  // We also support conversion to OnceAction whenever the sub-action supports
+  // conversion to Action (since any Action can also be a OnceAction).
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<
+              negation<
+                  std::is_convertible<FinalAction, OnceAction<R(Args...)>>>,
+              std::is_convertible<FinalAction, Action<R(Args...)>>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    return Action<R(Args...)>(std::move(final_action_));
+  }
+
+  // We support conversion to Action whenever the sub-action does.
   template <
       typename R, typename... Args,
       typename std::enable_if<
@@ -1579,16 +1596,16 @@
       : Base({}, std::forward<U>(other_actions)...),
         initial_action_(std::forward<T>(initial_action)) {}
 
-  template <typename R, typename... Args,
-            typename std::enable_if<
-                conjunction<
-                    // Both the initial action and the rest must support
-                    // conversion to OnceAction.
-                    std::is_convertible<
-                        InitialAction,
-                        OnceAction<void(InitialActionArgType<Args>...)>>,
-                    std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
-                int>::type = 0>
+  // We support conversion to OnceAction whenever both the initial action and
+  // the rest support conversion to OnceAction.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<std::is_convertible<
+                          InitialAction,
+                          OnceAction<void(InitialActionArgType<Args>...)>>,
+                      std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
+          int>::type = 0>
   operator OnceAction<R(Args...)>() && {  // NOLINT
     // Return an action that first calls the initial action with arguments
     // filtered through InitialActionArgType, then forwards arguments directly
@@ -1611,12 +1628,34 @@
     };
   }
 
+  // We also support conversion to OnceAction whenever the initial action
+  // supports conversion to Action (since any Action can also be a OnceAction).
+  //
+  // The remaining sub-actions must also be compatible, but we don't need to
+  // special case them because the base class deals with them.
   template <
       typename R, typename... Args,
       typename std::enable_if<
           conjunction<
-              // Both the initial action and the rest must support conversion to
-              // Action.
+              negation<std::is_convertible<
+                  InitialAction,
+                  OnceAction<void(InitialActionArgType<Args>...)>>>,
+              std::is_convertible<InitialAction,
+                                  Action<void(InitialActionArgType<Args>...)>>,
+              std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
+          int>::type = 0>
+  operator OnceAction<R(Args...)>() && {  // NOLINT
+    return DoAll(
+        Action<void(InitialActionArgType<Args>...)>(std::move(initial_action_)),
+        std::move(static_cast<Base&>(*this)));
+  }
+
+  // We support conversion to Action whenever both the initial action and the
+  // rest support conversion to Action.
+  template <
+      typename R, typename... Args,
+      typename std::enable_if<
+          conjunction<
               std::is_convertible<const InitialAction&,
                                   Action<void(InitialActionArgType<Args>...)>>,
               std::is_convertible<const Base&, Action<R(Args...)>>>::value,
@@ -1664,8 +1703,9 @@
 struct ReturnArgAction {
   template <typename... Args,
             typename = typename std::enable_if<(k < sizeof...(Args))>::type>
-  auto operator()(Args&&... args) const -> decltype(std::get<k>(
-      std::forward_as_tuple(std::forward<Args>(args)...))) {
+  auto operator()(Args&&... args) const
+      -> decltype(std::get<k>(
+          std::forward_as_tuple(std::forward<Args>(args)...))) {
     return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
   }
 };
@@ -1681,6 +1721,16 @@
 };
 
 template <size_t k, typename Ptr>
+struct SaveArgByMoveAction {
+  Ptr pointer;
+
+  template <typename... Args>
+  void operator()(Args&&... args) const {
+    *pointer = std::move(std::get<k>(std::tie(args...)));
+  }
+};
+
+template <size_t k, typename Ptr>
 struct SaveArgPointeeAction {
   Ptr pointer;
 
@@ -1746,6 +1796,13 @@
     return [copy](Args...) -> R { throw copy; };
   }
 };
+struct RethrowAction {
+  std::exception_ptr exception;
+  template <typename R, typename... Args>
+  operator Action<R(Args...)>() const {  // NOLINT
+    return [ex = exception](Args...) -> R { std::rethrow_exception(ex); };
+  }
+};
 #endif  // GTEST_HAS_EXCEPTIONS
 
 }  // namespace internal
@@ -2023,6 +2080,13 @@
   return {pointer};
 }
 
+// Action SaveArgByMove<k>(pointer) moves the k-th (0-based) argument of the
+// mock function into *pointer.
+template <size_t k, typename Ptr>
+internal::SaveArgByMoveAction<k, Ptr> SaveArgByMove(Ptr pointer) {
+  return {pointer};
+}
+
 // Action SaveArgPointee<k>(pointer) saves the value pointed to
 // by the k-th (0-based) argument of the mock function to *pointer.
 template <size_t k, typename Ptr>
@@ -2062,13 +2126,23 @@
   return {pointer};
 }
 
-// Action Throw(exception) can be used in a mock function of any type
-// to throw the given exception.  Any copyable value can be thrown.
 #if GTEST_HAS_EXCEPTIONS
+// Action Throw(exception) can be used in a mock function of any type
+// to throw the given exception.  Any copyable value can be thrown,
+// except for std::exception_ptr, which is likely a mistake if
+// thrown directly.
 template <typename T>
-internal::ThrowAction<typename std::decay<T>::type> Throw(T&& exception) {
+typename std::enable_if<
+    !std::is_base_of<std::exception_ptr, typename std::decay<T>::type>::value,
+    internal::ThrowAction<typename std::decay<T>::type>>::type
+Throw(T&& exception) {
   return {std::forward<T>(exception)};
 }
+// Action Rethrow(exception_ptr) can be used in a mock function of any type
+// to rethrow any exception_ptr. Note that the same object is thrown each time.
+inline internal::RethrowAction Rethrow(std::exception_ptr exception) {
+  return {std::move(exception)};
+}
 #endif  // GTEST_HAS_EXCEPTIONS
 
 namespace internal {
@@ -2117,13 +2191,13 @@
   R operator()(Args&&... arg) const {
     static constexpr size_t kMaxArgs =
         sizeof...(Args) <= 10 ? sizeof...(Args) : 10;
-    return Apply(MakeIndexSequence<kMaxArgs>{},
-                 MakeIndexSequence<10 - kMaxArgs>{},
+    return Apply(std::make_index_sequence<kMaxArgs>{},
+                 std::make_index_sequence<10 - kMaxArgs>{},
                  args_type{std::forward<Args>(arg)...});
   }
 
   template <std::size_t... arg_id, std::size_t... excess_id>
-  R Apply(IndexSequence<arg_id...>, IndexSequence<excess_id...>,
+  R Apply(std::index_sequence<arg_id...>, std::index_sequence<excess_id...>,
           const args_type& args) const {
     // Impl need not be specific to the signature of action being implemented;
     // only the implementing function body needs to have all of the specific
@@ -2156,9 +2230,9 @@
 }
 
 #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
-  , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_
-#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_                 \
-  const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \
+  , [[maybe_unused]] const arg##i##_type& arg##i
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_          \
+  [[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \
       GMOCK_INTERNAL_ARG_UNUSED, , 10)
 
 #define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
@@ -2223,8 +2297,8 @@
     std::shared_ptr<const gmock_Impl> impl_;                                   \
   };                                                                           \
   template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
-  inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name(                    \
-      GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_;        \
+  [[nodiscard]] inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name(      \
+      GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params));                               \
   template <GMOCK_ACTION_TYPENAME_PARAMS_(params)>                             \
   inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name(                    \
       GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) {                              \
@@ -2259,7 +2333,7 @@
       return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
     };                                                                        \
   };                                                                          \
-  inline name##Action name() GTEST_MUST_USE_RESULT_;                          \
+  [[nodiscard]] inline name##Action name();                                   \
   inline name##Action name() { return name##Action(); }                       \
   template <typename function_type, typename return_type, typename args_type, \
             GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>                                \
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h b/src/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h
index 1a1f126..d2cb13c 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h
@@ -37,6 +37,7 @@
 #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
 #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
 
+#include <cstddef>
 #include <type_traits>  // IWYU pragma: keep
 #include <utility>      // IWYU pragma: keep
 
@@ -69,22 +70,22 @@
   return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1));
 }
 
-template <int N, int M>
+template <size_t N, size_t M>
 constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) {
   return N <= M && internal::PrefixOf(prefix, str);
 }
 
-template <int N, int M>
+template <size_t N, size_t M>
 constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) {
   return N <= M && internal::PrefixOf(suffix, str + M - N);
 }
 
-template <int N, int M>
+template <size_t N, size_t M>
 constexpr bool Equals(const char (&a)[N], const char (&b)[M]) {
   return N == M && internal::PrefixOf(a, b);
 }
 
-template <int N>
+template <size_t N>
 constexpr bool ValidateSpec(const char (&spec)[N]) {
   return internal::Equals("const", spec) ||
          internal::Equals("override", spec) ||
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock-matchers.h b/src/third_party/googletest/googlemock/include/gmock/gmock-matchers.h
index 0f67713..8903c7a 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock-matchers.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock-matchers.h
@@ -408,13 +408,22 @@
   }
 
  private:
-  class Impl : public MatcherInterface<T> {
+  // If it's possible to implicitly convert a `const T&` to U, then `Impl` can
+  // take that as input to avoid a copy. Otherwise, such as when `T` is a
+  // non-const reference type or a type explicitly constructible only from a
+  // non-const reference, then `Impl` must use `T` as-is (potentially copying).
+  using ImplArgT =
+      typename std::conditional<std::is_convertible<const T&, const U&>::value,
+                                const T&, T>::type;
+
+  class Impl : public MatcherInterface<ImplArgT> {
    public:
     explicit Impl(const Matcher<U>& source_matcher)
         : source_matcher_(source_matcher) {}
 
     // We delegate the matching logic to the source matcher.
-    bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+    bool MatchAndExplain(ImplArgT x,
+                         MatchResultListener* listener) const override {
       using FromType = typename std::remove_cv<typename std::remove_pointer<
           typename std::remove_reference<T>::type>::type>::type;
       using ToType = typename std::remove_cv<typename std::remove_pointer<
@@ -431,9 +440,8 @@
 
       // Do the cast to `U` explicitly if necessary.
       // Otherwise, let implicit conversions do the trick.
-      using CastType =
-          typename std::conditional<std::is_convertible<T&, const U&>::value,
-                                    T&, U>::type;
+      using CastType = typename std::conditional<
+          std::is_convertible<ImplArgT&, const U&>::value, ImplArgT&, U>::type;
 
       return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
                                              listener);
@@ -490,12 +498,12 @@
 
   template <typename F>
   operator ::testing::Matcher<F>() const {  // NOLINT(runtime/explicit)
-    return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{});
+    return Apply<F>(std::make_index_sequence<sizeof...(Ts)>{});
   }
 
  private:
   template <typename F, std::size_t... tuple_ids>
-  ::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const {
+  ::testing::Matcher<F> Apply(std::index_sequence<tuple_ids...>) const {
     return ::testing::Matcher<F>(
         new typename Derived<Ts...>::template gmock_Impl<F>(
             std::get<tuple_ids>(params_)...));
@@ -528,18 +536,16 @@
 // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
 // contravariant): just keep a copy of the original Matcher<U>, convert the
 // argument from type T to U, and then pass it to the underlying Matcher<U>.
-// The only exception is when U is a reference and T is not, as the
+// The only exception is when U is a non-const reference and T is not, as the
 // underlying Matcher<U> may be interested in the argument's address, which
-// is not preserved in the conversion from T to U.
+// cannot be preserved in the conversion from T to U (since a copy of the input
+// T argument would be required to provide a non-const reference U).
 template <typename T, typename U>
 inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
   // Enforce that T can be implicitly converted to U.
   static_assert(std::is_convertible<const T&, const U&>::value,
-                "T must be implicitly convertible to U");
-  // Enforce that we are not converting a non-reference type T to a reference
-  // type U.
-  static_assert(std::is_reference<T>::value || !std::is_reference<U>::value,
-                "cannot convert non reference arg to reference");
+                "T must be implicitly convertible to U (and T must be a "
+                "non-const reference if U is a non-const reference)");
   // In case both T and U are arithmetic types, enforce that the
   // conversion is not lossy.
   typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
@@ -561,6 +567,11 @@
 // and MUST NOT BE USED IN USER CODE!!!
 namespace internal {
 
+// Used per go/ranked-overloads for dispatching.
+struct Rank0 {};
+struct Rank1 : Rank0 {};
+using HighestRank = Rank1;
+
 // If the explanation is not empty, prints it to the ostream.
 inline void PrintIfNotEmpty(const std::string& explanation,
                             ::std::ostream* os) {
@@ -1048,7 +1059,7 @@
   template <typename MatcheeStringType>
   bool MatchAndExplain(const MatcheeStringType& s,
                        MatchResultListener* /* listener */) const {
-    const StringType& s2(s);
+    const StringType s2(s);
     return s2.length() >= prefix_.length() &&
            s2.substr(0, prefix_.length()) == prefix_;
   }
@@ -1102,7 +1113,7 @@
   template <typename MatcheeStringType>
   bool MatchAndExplain(const MatcheeStringType& s,
                        MatchResultListener* /* listener */) const {
-    const StringType& s2(s);
+    const StringType s2(s);
     return s2.length() >= suffix_.length() &&
            s2.substr(s2.length() - suffix_.length()) == suffix_;
   }
@@ -1300,34 +1311,48 @@
 
   bool MatchAndExplain(const T& x,
                        MatchResultListener* listener) const override {
-    // If either matcher1_ or matcher2_ doesn't match x, we only need
-    // to explain why one of them fails.
+    // This method uses matcher's explanation when explaining the result.
+    // However, if matcher doesn't provide one, this method uses matcher's
+    // description.
     std::string all_match_result;
-
-    for (size_t i = 0; i < matchers_.size(); ++i) {
+    for (const Matcher<T>& matcher : matchers_) {
       StringMatchResultListener slistener;
-      if (matchers_[i].MatchAndExplain(x, &slistener)) {
-        if (all_match_result.empty()) {
-          all_match_result = slistener.str();
+      // Return explanation for first failed matcher.
+      if (!matcher.MatchAndExplain(x, &slistener)) {
+        const std::string explanation = slistener.str();
+        if (!explanation.empty()) {
+          *listener << explanation;
         } else {
-          std::string result = slistener.str();
-          if (!result.empty()) {
-            all_match_result += ", and ";
-            all_match_result += result;
-          }
+          *listener << "which doesn't match (" << Describe(matcher) << ")";
         }
-      } else {
-        *listener << slistener.str();
         return false;
       }
+      // Keep track of explanations in case all matchers succeed.
+      std::string explanation = slistener.str();
+      if (explanation.empty()) {
+        explanation = Describe(matcher);
+      }
+      if (all_match_result.empty()) {
+        all_match_result = explanation;
+      } else {
+        if (!explanation.empty()) {
+          all_match_result += ", and ";
+          all_match_result += explanation;
+        }
+      }
     }
 
-    // Otherwise we need to explain why *both* of them match.
     *listener << all_match_result;
     return true;
   }
 
  private:
+  // Returns matcher description as a string.
+  std::string Describe(const Matcher<T>& matcher) const {
+    StringMatchResultListener listener;
+    matcher.DescribeTo(listener.stream());
+    return listener.str();
+  }
   const std::vector<Matcher<T>> matchers_;
 };
 
@@ -1405,34 +1430,55 @@
 
   bool MatchAndExplain(const T& x,
                        MatchResultListener* listener) const override {
+    // This method uses matcher's explanation when explaining the result.
+    // However, if matcher doesn't provide one, this method uses matcher's
+    // description.
     std::string no_match_result;
-
-    // If either matcher1_ or matcher2_ matches x, we just need to
-    // explain why *one* of them matches.
-    for (size_t i = 0; i < matchers_.size(); ++i) {
+    for (const Matcher<T>& matcher : matchers_) {
       StringMatchResultListener slistener;
-      if (matchers_[i].MatchAndExplain(x, &slistener)) {
-        *listener << slistener.str();
-        return true;
-      } else {
-        if (no_match_result.empty()) {
-          no_match_result = slistener.str();
+      // Return explanation for first match.
+      if (matcher.MatchAndExplain(x, &slistener)) {
+        const std::string explanation = slistener.str();
+        if (!explanation.empty()) {
+          *listener << explanation;
         } else {
-          std::string result = slistener.str();
-          if (!result.empty()) {
-            no_match_result += ", and ";
-            no_match_result += result;
-          }
+          *listener << "which matches (" << Describe(matcher) << ")";
+        }
+        return true;
+      }
+      // Keep track of explanations in case there is no match.
+      std::string explanation = slistener.str();
+      if (explanation.empty()) {
+        explanation = DescribeNegation(matcher);
+      }
+      if (no_match_result.empty()) {
+        no_match_result = explanation;
+      } else {
+        if (!explanation.empty()) {
+          no_match_result += ", and ";
+          no_match_result += explanation;
         }
       }
     }
 
-    // Otherwise we need to explain why *both* of them fail.
     *listener << no_match_result;
     return false;
   }
 
  private:
+  // Returns matcher description as a string.
+  std::string Describe(const Matcher<T>& matcher) const {
+    StringMatchResultListener listener;
+    matcher.DescribeTo(listener.stream());
+    return listener.str();
+  }
+
+  std::string DescribeNegation(const Matcher<T>& matcher) const {
+    StringMatchResultListener listener;
+    matcher.DescribeNegationTo(listener.stream());
+    return listener.str();
+  }
+
   const std::vector<Matcher<T>> matchers_;
 };
 
@@ -1483,7 +1529,7 @@
   }
 
  private:
-  const ::std::vector<T> matchers_;
+  const std::vector<std::remove_const_t<T>> matchers_;
 };
 
 template <typename T>
@@ -2235,6 +2281,9 @@
   class Impl : public MatcherInterface<T> {
     using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
         std::declval<CallableStorageType>(), std::declval<T>()));
+    using InnerType = std::conditional_t<
+        std::is_lvalue_reference<ResultType>::value,
+        const typename std::remove_reference<ResultType>::type&, ResultType>;
 
    public:
     template <typename M>
@@ -2242,7 +2291,7 @@
          const CallableStorageType& callable, const M& matcher)
         : result_description_(result_description),
           callable_(callable),
-          matcher_(MatcherCast<ResultType>(matcher)) {}
+          matcher_(MatcherCast<InnerType>(matcher)) {}
 
     void DescribeTo(::std::ostream* os) const override {
       if (result_description_.empty()) {
@@ -2272,7 +2321,7 @@
       // takes a non-const reference as argument.
       // Also, specifying template argument explicitly is needed because T could
       // be a non-const reference (e.g. Matcher<Uncopyable&>).
-      ResultType result =
+      InnerType result =
           CallableTraits<Callable>::template Invoke<T>(callable_, obj);
       return MatchPrintAndExplain(result, matcher_, listener);
     }
@@ -2285,7 +2334,7 @@
     // use stateful callables with ResultOf(), which doesn't guarantee
     // how many times the callable will be invoked.
     mutable CallableStorageType callable_;
-    const Matcher<ResultType> matcher_;
+    const Matcher<InnerType> matcher_;
   };  // class Impl
 
   const std::string result_description_;
@@ -2920,26 +2969,23 @@
   const M inner_matcher_;
 };
 
-struct Rank1 {};
-struct Rank0 : Rank1 {};
-
 namespace pair_getters {
 using std::get;
 template <typename T>
-auto First(T& x, Rank1) -> decltype(get<0>(x)) {  // NOLINT
+auto First(T& x, Rank0) -> decltype(get<0>(x)) {  // NOLINT
   return get<0>(x);
 }
 template <typename T>
-auto First(T& x, Rank0) -> decltype((x.first)) {  // NOLINT
+auto First(T& x, Rank1) -> decltype((x.first)) {  // NOLINT
   return x.first;
 }
 
 template <typename T>
-auto Second(T& x, Rank1) -> decltype(get<1>(x)) {  // NOLINT
+auto Second(T& x, Rank0) -> decltype(get<1>(x)) {  // NOLINT
   return get<1>(x);
 }
 template <typename T>
-auto Second(T& x, Rank0) -> decltype((x.second)) {  // NOLINT
+auto Second(T& x, Rank1) -> decltype((x.second)) {  // NOLINT
   return x.second;
 }
 }  // namespace pair_getters
@@ -2965,7 +3011,7 @@
                        MatchResultListener* listener) const override {
     StringMatchResultListener inner_listener;
     const bool match = inner_matcher_.MatchAndExplain(
-        pair_getters::First(key_value, Rank0()), &inner_listener);
+        pair_getters::First(key_value, Rank1()), &inner_listener);
     const std::string explanation = inner_listener.str();
     if (!explanation.empty()) {
       *listener << "whose first field is a value " << explanation;
@@ -3087,18 +3133,18 @@
     if (!listener->IsInterested()) {
       // If the listener is not interested, we don't need to construct the
       // explanation.
-      return first_matcher_.Matches(pair_getters::First(a_pair, Rank0())) &&
-             second_matcher_.Matches(pair_getters::Second(a_pair, Rank0()));
+      return first_matcher_.Matches(pair_getters::First(a_pair, Rank1())) &&
+             second_matcher_.Matches(pair_getters::Second(a_pair, Rank1()));
     }
     StringMatchResultListener first_inner_listener;
-    if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank0()),
+    if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank1()),
                                         &first_inner_listener)) {
       *listener << "whose first field does not match";
       PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
       return false;
     }
     StringMatchResultListener second_inner_listener;
-    if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank0()),
+    if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank1()),
                                          &second_inner_listener)) {
       *listener << "whose second field does not match";
       PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
@@ -3151,8 +3197,8 @@
 };
 
 template <typename T, size_t... I>
-auto UnpackStructImpl(const T& t, IndexSequence<I...>, int)
-    -> decltype(std::tie(get<I>(t)...)) {
+auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
+                      int) -> decltype(std::tie(get<I>(t)...)) {
   static_assert(std::tuple_size<T>::value == sizeof...(I),
                 "Number of arguments doesn't match the number of fields.");
   return std::tie(get<I>(t)...);
@@ -3160,106 +3206,111 @@
 
 #if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<1>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<1>, char) {
   const auto& [a] = t;
   return std::tie(a);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<2>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<2>, char) {
   const auto& [a, b] = t;
   return std::tie(a, b);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<3>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<3>, char) {
   const auto& [a, b, c] = t;
   return std::tie(a, b, c);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<4>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<4>, char) {
   const auto& [a, b, c, d] = t;
   return std::tie(a, b, c, d);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<5>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<5>, char) {
   const auto& [a, b, c, d, e] = t;
   return std::tie(a, b, c, d, e);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<6>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<6>, char) {
   const auto& [a, b, c, d, e, f] = t;
   return std::tie(a, b, c, d, e, f);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<7>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<7>, char) {
   const auto& [a, b, c, d, e, f, g] = t;
   return std::tie(a, b, c, d, e, f, g);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<8>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<8>, char) {
   const auto& [a, b, c, d, e, f, g, h] = t;
   return std::tie(a, b, c, d, e, f, g, h);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<9>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<9>, char) {
   const auto& [a, b, c, d, e, f, g, h, i] = t;
   return std::tie(a, b, c, d, e, f, g, h, i);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<10>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<10>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<11>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<11>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<12>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<12>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<13>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<13>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<14>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<14>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<15>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<15>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<16>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<16>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<17>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<17>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<18>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<18>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
 }
 template <typename T>
-auto UnpackStructImpl(const T& t, MakeIndexSequence<19>, char) {
+auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
   const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
   return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
 }
+template <typename T>
+auto UnpackStructImpl(const T& u, std::make_index_sequence<20>, char) {
+  const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = u;
+  return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
+}
 #endif  // defined(__cpp_structured_bindings)
 
 template <size_t I, typename T>
 auto UnpackStruct(const T& t)
-    -> decltype((UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0)) {
-  return (UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0);
+    -> decltype((UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0)) {
+  return (UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0);
 }
 
 // Helper function to do comma folding in C++11.
@@ -3272,7 +3323,7 @@
 class FieldsAreMatcherImpl;
 
 template <typename Struct, size_t... I>
-class FieldsAreMatcherImpl<Struct, IndexSequence<I...>>
+class FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
     : public MatcherInterface<Struct> {
   using UnpackedType =
       decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>()));
@@ -3354,8 +3405,8 @@
   template <typename Struct>
   operator Matcher<Struct>() const {  // NOLINT
     return Matcher<Struct>(
-        new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>(
-            matchers_));
+        new FieldsAreMatcherImpl<const Struct&,
+                                 std::index_sequence_for<Inner...>>(matchers_));
   }
 
  private:
@@ -3768,7 +3819,7 @@
 
  private:
   UnorderedMatcherRequire::Flags match_flags_;
-  ::std::vector<T> matchers_;
+  std::vector<std::remove_const_t<T>> matchers_;
 };
 
 // Implements ElementsAreArray().
@@ -3789,7 +3840,7 @@
   }
 
  private:
-  const ::std::vector<T> matchers_;
+  const std::vector<std::remove_const_t<T>> matchers_;
 };
 
 // Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
@@ -3876,6 +3927,21 @@
     bool negation, const char* matcher_name,
     const std::vector<const char*>& param_names, const Strings& param_values);
 
+// Overloads to support `OptionalMatcher` being used with a type that either
+// supports implicit conversion to bool or a `has_value()` method.
+template <typename Optional>
+auto IsOptionalEngaged(const Optional& optional,
+                       Rank1) -> decltype(!!optional) {
+  // The use of double-negation here is to preserve historical behavior where
+  // the matcher used `operator!` rather than directly using `operator bool`.
+  return !static_cast<bool>(!optional);
+}
+template <typename Optional>
+auto IsOptionalEngaged(const Optional& optional,
+                       Rank0) -> decltype(!optional.has_value()) {
+  return optional.has_value();
+}
+
 // Implements a matcher that checks the value of a optional<> type variable.
 template <typename ValueMatcher>
 class OptionalMatcher {
@@ -3908,7 +3974,7 @@
 
     bool MatchAndExplain(Optional optional,
                          MatchResultListener* listener) const override {
-      if (!optional) {
+      if (!IsOptionalEngaged(optional, HighestRank())) {
         *listener << "which is not engaged";
         return false;
       }
@@ -4387,6 +4453,10 @@
 // matches 'matcher'.  For example,
 //   Property(&Foo::str, StartsWith("hi"))
 // matches a Foo object x if and only if x.str() starts with "hi".
+//
+// Warning: Don't use `Property()` against member functions that you do not
+// own, because taking addresses of functions is fragile and generally not part
+// of the contract of the function.
 template <typename Class, typename PropertyType, typename PropertyMatcher>
 inline PolymorphicMatcher<internal::PropertyMatcher<
     Class, PropertyType, PropertyType (Class::*)() const>>
@@ -4741,9 +4811,10 @@
 
 // Supports the Pointwise(m, {a, b, c}) syntax.
 template <typename TupleMatcher, typename T>
-inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise(
-    const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
-  return Pointwise(tuple_matcher, std::vector<T>(rhs));
+inline internal::PointwiseMatcher<TupleMatcher,
+                                  std::vector<std::remove_const_t<T>>>
+Pointwise(const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
+  return Pointwise(tuple_matcher, std::vector<std::remove_const_t<T>>(rhs));
 }
 
 // UnorderedPointwise(pair_matcher, rhs) matches an STL-style
@@ -4905,7 +4976,7 @@
 // - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
 // - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
 //   matches Lt(0).
-// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
+// - {1, 2} doesn't match IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
 //   match Gt(0). The reason is that different matchers must be used for
 //   elements in different slots of the container.
 //
@@ -5230,9 +5301,10 @@
 }
 
 // Returns a matcher that matches the value of an optional<> type variable.
-// The matcher implementation only uses '!arg' and requires that the optional<>
-// type has a 'value_type' member type and that '*arg' is of type 'value_type'
-// and is printable using 'PrintToString'. It is compatible with
+// The matcher implementation only uses '!arg' (or 'arg.has_value()' if '!arg`
+// isn't a valid expression) and requires that the optional<> type has a
+// 'value_type' member type and that '*arg' is of type 'value_type' and is
+// printable using 'PrintToString'. It is compatible with
 // std::optional/std::experimental::optional.
 // Note that to compare an optional type variable against nullopt you should
 // use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the
@@ -5444,47 +5516,46 @@
       ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
 
 // MATCHER* macros itself are listed below.
-#define MATCHER(name, description)                                             \
-  class name##Matcher                                                          \
-      : public ::testing::internal::MatcherBaseImpl<name##Matcher> {           \
-   public:                                                                     \
-    template <typename arg_type>                                               \
-    class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> {   \
-     public:                                                                   \
-      gmock_Impl() {}                                                          \
-      bool MatchAndExplain(                                                    \
-          const arg_type& arg,                                                 \
-          ::testing::MatchResultListener* result_listener) const override;     \
-      void DescribeTo(::std::ostream* gmock_os) const override {               \
-        *gmock_os << FormatDescription(false);                                 \
-      }                                                                        \
-      void DescribeNegationTo(::std::ostream* gmock_os) const override {       \
-        *gmock_os << FormatDescription(true);                                  \
-      }                                                                        \
-                                                                               \
-     private:                                                                  \
-      ::std::string FormatDescription(bool negation) const {                   \
-        /* NOLINTNEXTLINE readability-redundant-string-init */                 \
-        ::std::string gmock_description = (description);                       \
-        if (!gmock_description.empty()) {                                      \
-          return gmock_description;                                            \
-        }                                                                      \
-        return ::testing::internal::FormatMatcherDescription(negation, #name,  \
-                                                             {}, {});          \
-      }                                                                        \
-    };                                                                         \
-  };                                                                           \
-  inline name##Matcher GMOCK_INTERNAL_WARNING_PUSH()                           \
-      GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-function")               \
-          GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function")    \
-              name GMOCK_INTERNAL_WARNING_POP()() {                            \
-    return {};                                                                 \
-  }                                                                            \
-  template <typename arg_type>                                                 \
-  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(                   \
-      const arg_type& arg,                                                     \
-      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \
-      const
+#define MATCHER(name, description)                                            \
+  class name##Matcher                                                         \
+      : public ::testing::internal::MatcherBaseImpl<name##Matcher> {          \
+   public:                                                                    \
+    template <typename arg_type>                                              \
+    class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> {  \
+     public:                                                                  \
+      gmock_Impl() {}                                                         \
+      bool MatchAndExplain(                                                   \
+          const arg_type& arg,                                                \
+          ::testing::MatchResultListener* result_listener) const override;    \
+      void DescribeTo(::std::ostream* gmock_os) const override {              \
+        *gmock_os << FormatDescription(false);                                \
+      }                                                                       \
+      void DescribeNegationTo(::std::ostream* gmock_os) const override {      \
+        *gmock_os << FormatDescription(true);                                 \
+      }                                                                       \
+                                                                              \
+     private:                                                                 \
+      ::std::string FormatDescription(bool negation) const {                  \
+        /* NOLINTNEXTLINE readability-redundant-string-init */                \
+        ::std::string gmock_description = (description);                      \
+        if (!gmock_description.empty()) {                                     \
+          return gmock_description;                                           \
+        }                                                                     \
+        return ::testing::internal::FormatMatcherDescription(negation, #name, \
+                                                             {}, {});         \
+      }                                                                       \
+    };                                                                        \
+  };                                                                          \
+  inline name##Matcher GMOCK_INTERNAL_WARNING_PUSH()                          \
+      GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-function")              \
+          GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function")   \
+              name GMOCK_INTERNAL_WARNING_POP()() {                           \
+    return {};                                                                \
+  }                                                                           \
+  template <typename arg_type>                                                \
+  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(                  \
+      const arg_type& arg,                                                    \
+      [[maybe_unused]] ::testing::MatchResultListener* result_listener) const
 
 #define MATCHER_P(name, p0, description) \
   GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
@@ -5566,11 +5637,11 @@
   }                                                                            \
   template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)>                      \
   template <typename arg_type>                                                 \
-  bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::gmock_Impl<        \
-      arg_type>::MatchAndExplain(const arg_type& arg,                          \
-                                 ::testing::MatchResultListener*               \
-                                     result_listener GTEST_ATTRIBUTE_UNUSED_)  \
-      const
+  bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::                   \
+      gmock_Impl<arg_type>::MatchAndExplain(                                   \
+          const arg_type& arg,                                                 \
+          [[maybe_unused]] ::testing::MatchResultListener* result_listener)    \
+          const
 
 #define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
   GMOCK_PP_TAIL(                                     \
@@ -5605,8 +5676,8 @@
 
 #define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \
   GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args))
-#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg_unused) \
-  , gmock_p##i
+#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg) \
+  , ::std::forward<arg##_type>(gmock_p##i)
 
 // To prevent ADL on certain functions we put them on a separate namespace.
 using namespace no_adl;  // NOLINT
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h b/src/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h
index 4030076..eacfdcd 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h
@@ -521,9 +521,8 @@
         GMOCK_INTERNAL_DECL_##value_params)                                    \
         GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params),    \
                     = default;                                                 \
-                    ,                                                          \
-                    : impl_(std::make_shared<gmock_Impl>(                      \
-                        GMOCK_INTERNAL_LIST_##value_params)){})                \
+                    , : impl_(std::make_shared<gmock_Impl>(                    \
+                          GMOCK_INTERNAL_LIST_##value_params)){})              \
             GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
                 name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_      \
         ##value_params                                                         \
@@ -551,10 +550,10 @@
   };                                                                           \
   template <GMOCK_INTERNAL_DECL_##template_params                              \
                 GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
-  GMOCK_ACTION_CLASS_(                                                         \
+  [[nodiscard]] GMOCK_ACTION_CLASS_(                                           \
       name, value_params)<GMOCK_INTERNAL_LIST_##template_params                \
                               GMOCK_INTERNAL_LIST_TYPE_##value_params>         \
-      name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_;         \
+      name(GMOCK_INTERNAL_DECL_##value_params);                                \
   template <GMOCK_INTERNAL_DECL_##template_params                              \
                 GMOCK_INTERNAL_DECL_TYPE_##value_params>                       \
   inline GMOCK_ACTION_CLASS_(                                                  \
@@ -592,21 +591,23 @@
 // Overloads for other custom-callables are provided in the
 // internal/custom/gmock-generated-actions.h header.
 template <typename F, typename... Args>
-auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
-  return f(args...);
+auto InvokeArgument(F &&f,
+                    Args... args) -> decltype(std::forward<F>(f)(args...)) {
+  return std::forward<F>(f)(args...);
 }
 
 template <std::size_t index, typename... Params>
 struct InvokeArgumentAction {
   template <typename... Args,
             typename = typename std::enable_if<(index < sizeof...(Args))>::type>
-  auto operator()(Args &&...args) const -> decltype(internal::InvokeArgument(
-      std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
-      std::declval<const Params &>()...)) {
+  auto operator()(Args &&...args) const
+      -> decltype(internal::InvokeArgument(
+          std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
+          std::declval<const Params &>()...)) {
     internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
                                                std::forward<Args>(args)...);
     return params.Apply([&](const Params &...unpacked_params) {
-      auto &&callable = args_tuple.template Get<index>();
+      auto &&callable = std::move(args_tuple.template Get<index>());
       return internal::InvokeArgument(
           std::forward<decltype(callable)>(callable), unpacked_params...);
     });
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h b/src/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h
index 78ca15d..c4c42b7 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h
@@ -868,7 +868,7 @@
   Clause last_clause_;
   mutable bool action_count_checked_;  // Under mutex_.
   mutable Mutex mutex_;                // Protects action_count_checked_.
-};                                     // class ExpectationBase
+};  // class ExpectationBase
 
 template <typename F>
 class TypedExpectation;
@@ -1838,9 +1838,8 @@
     // Doing so slows down compilation dramatically because the *constructor* of
     // std::function<T> is re-instantiated with different template
     // parameters each time.
-    const UninterestingCallCleanupHandler report_uninteresting_call = {
-        reaction, ss
-    };
+    const UninterestingCallCleanupHandler report_uninteresting_call = {reaction,
+                                                                       ss};
 
     return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
   }
@@ -1890,8 +1889,7 @@
   // std::function<T> is re-instantiated with different template
   // parameters each time.
   const FailureCleanupHandler handle_failures = {
-      ss, why, loc, untyped_expectation, found, is_excessive
-  };
+      ss, why, loc, untyped_expectation, found, is_excessive};
 
   return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
                                      ss);
diff --git a/src/third_party/googletest/googlemock/include/gmock/gmock.h b/src/third_party/googletest/googlemock/include/gmock/gmock.h
index 568c8c7..c78fb8e 100644
--- a/src/third_party/googletest/googlemock/include/gmock/gmock.h
+++ b/src/third_party/googletest/googlemock/include/gmock/gmock.h
@@ -53,13 +53,14 @@
 //
 // where all clauses are optional and WillOnce() can be repeated.
 
-#include "gmock/gmock-actions.h"
-#include "gmock/gmock-cardinalities.h"
-#include "gmock/gmock-function-mocker.h"
-#include "gmock/gmock-matchers.h"
-#include "gmock/gmock-more-actions.h"
-#include "gmock/gmock-more-matchers.h"
-#include "gmock/gmock-nice-strict.h"
+#include "gmock/gmock-actions.h"  // IWYU pragma: export
+#include "gmock/gmock-cardinalities.h"  // IWYU pragma: export
+#include "gmock/gmock-function-mocker.h"  // IWYU pragma: export
+#include "gmock/gmock-matchers.h"  // IWYU pragma: export
+#include "gmock/gmock-more-actions.h"  // IWYU pragma: export
+#include "gmock/gmock-more-matchers.h"  // IWYU pragma: export
+#include "gmock/gmock-nice-strict.h"  // IWYU pragma: export
+#include "gmock/gmock-spec-builders.h"  // IWYU pragma: export
 #include "gmock/internal/gmock-internal-utils.h"
 #include "gmock/internal/gmock-port.h"
 
diff --git a/src/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h b/src/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
index ead6d7c..8fc1ddc 100644
--- a/src/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
+++ b/src/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -44,6 +44,7 @@
 #include <ostream>  // NOLINT
 #include <string>
 #include <type_traits>
+#include <utility>
 #include <vector>
 
 #include "gmock/internal/gmock-port.h"
@@ -420,7 +421,7 @@
 GTEST_API_ void IllegalDoDefault(const char* file, int line);
 
 template <typename F, typename Tuple, size_t... Idx>
-auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>)
+auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence<Idx...>)
     -> decltype(std::forward<F>(f)(
         std::get<Idx>(std::forward<Tuple>(args))...)) {
   return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
@@ -428,12 +429,13 @@
 
 // Apply the function to a tuple of arguments.
 template <typename F, typename Tuple>
-auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl(
-    std::forward<F>(f), std::forward<Tuple>(args),
-    MakeIndexSequence<std::tuple_size<
-        typename std::remove_reference<Tuple>::type>::value>())) {
+auto Apply(F&& f, Tuple&& args)
+    -> decltype(ApplyImpl(
+        std::forward<F>(f), std::forward<Tuple>(args),
+        std::make_index_sequence<std::tuple_size<
+            typename std::remove_reference<Tuple>::type>::value>())) {
   return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
-                   MakeIndexSequence<std::tuple_size<
+                   std::make_index_sequence<std::tuple_size<
                        typename std::remove_reference<Tuple>::type>::value>());
 }
 
@@ -465,11 +467,6 @@
   using MakeResultIgnoredValue = IgnoredValue(Args...);
 };
 
-#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename R, typename... Args>
-constexpr size_t Function<R(Args...)>::ArgumentCount;
-#endif
-
 // Workaround for MSVC error C2039: 'type': is not a member of 'std'
 // when std::tuple_element is used.
 // See: https://github.com/google/googletest/issues/3931
diff --git a/src/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h b/src/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h
index 55ddfb6..42d36d2 100644
--- a/src/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h
+++ b/src/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h
@@ -42,6 +42,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+
 #include <cstdint>
 #include <iostream>
 
@@ -56,7 +57,7 @@
 #include "gmock/internal/custom/gmock-port.h"
 #include "gtest/internal/gtest-port.h"
 
-#ifdef GTEST_HAS_ABSL
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
 #include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #endif
@@ -73,7 +74,7 @@
 #define GMOCK_FLAG(name) FLAGS_gmock_##name
 
 // Pick a command line flags implementation.
-#ifdef GTEST_HAS_ABSL
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
 
 // Macros for defining flags.
 #define GMOCK_DEFINE_bool_(name, default_val, doc) \
@@ -95,7 +96,7 @@
 #define GMOCK_FLAG_SET(name, value) \
   (void)(::absl::SetFlag(&GMOCK_FLAG(name), value))
 
-#else  // GTEST_HAS_ABSL
+#else  // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
 
 // Macros for defining flags.
 #define GMOCK_DEFINE_bool_(name, default_val, doc)  \
@@ -134,6 +135,6 @@
 #define GMOCK_FLAG_GET(name) ::testing::GMOCK_FLAG(name)
 #define GMOCK_FLAG_SET(name, value) (void)(::testing::GMOCK_FLAG(name) = value)
 
-#endif  // GTEST_HAS_ABSL
+#endif  // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
 
 #endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
diff --git a/src/third_party/googletest/googlemock/src/gmock-cardinalities.cc b/src/third_party/googletest/googlemock/src/gmock-cardinalities.cc
index 92cde34..a7283aa 100644
--- a/src/third_party/googletest/googlemock/src/gmock-cardinalities.cc
+++ b/src/third_party/googletest/googlemock/src/gmock-cardinalities.cc
@@ -53,12 +53,12 @@
       : min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) {
     std::stringstream ss;
     if (min < 0) {
-      ss << "The invocation lower bound must be >= 0, "
-         << "but is actually " << min << ".";
+      ss << "The invocation lower bound must be >= 0, " << "but is actually "
+         << min << ".";
       internal::Expect(false, __FILE__, __LINE__, ss.str());
     } else if (max < 0) {
-      ss << "The invocation upper bound must be >= 0, "
-         << "but is actually " << max << ".";
+      ss << "The invocation upper bound must be >= 0, " << "but is actually "
+         << max << ".";
       internal::Expect(false, __FILE__, __LINE__, ss.str());
     } else if (min > max) {
       ss << "The invocation upper bound (" << max
diff --git a/src/third_party/googletest/googlemock/src/gmock-internal-utils.cc b/src/third_party/googletest/googlemock/src/gmock-internal-utils.cc
index 5c2ce0d..96c7e30 100644
--- a/src/third_party/googletest/googlemock/src/gmock-internal-utils.cc
+++ b/src/third_party/googletest/googlemock/src/gmock-internal-utils.cc
@@ -44,6 +44,7 @@
 #include <iostream>
 #include <ostream>  // NOLINT
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "gmock/gmock.h"
@@ -211,14 +212,14 @@
 }
 
 template <size_t... I>
-constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>,
+constexpr std::array<char, 256> UnBase64Impl(std::index_sequence<I...>,
                                              const char* const base64) {
   return {
       {UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};
 }
 
 constexpr std::array<char, 256> UnBase64(const char* const base64) {
-  return UnBase64Impl(MakeIndexSequence<256>{}, base64);
+  return UnBase64Impl(std::make_index_sequence<256>{}, base64);
 }
 
 static constexpr char kBase64[] =
diff --git a/src/third_party/googletest/googlemock/src/gmock-matchers.cc b/src/third_party/googletest/googlemock/src/gmock-matchers.cc
index 81a5b7e..277add6 100644
--- a/src/third_party/googletest/googlemock/src/gmock-matchers.cc
+++ b/src/third_party/googletest/googlemock/src/gmock-matchers.cc
@@ -236,9 +236,8 @@
   os << "{";
   const char* sep = "";
   for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
-    os << sep << "\n  ("
-       << "element #" << it->first << ", "
-       << "matcher #" << it->second << ")";
+    os << sep << "\n  (" << "element #" << it->first << ", " << "matcher #"
+       << it->second << ")";
     sep = ",";
   }
   os << "\n}";
@@ -374,20 +373,20 @@
     return true;
   }
 
-  if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
-    if (matrix.LhsSize() != matrix.RhsSize()) {
-      // The element count doesn't match.  If the container is empty,
-      // there's no need to explain anything as Google Mock already
-      // prints the empty container. Otherwise we just need to show
-      // how many elements there actually are.
-      if (matrix.LhsSize() != 0 && listener->IsInterested()) {
-        *listener << "which has " << Elements(matrix.LhsSize());
-      }
-      return false;
+  const bool is_exact_match_with_size_discrepency =
+      match_flags() == UnorderedMatcherRequire::ExactMatch &&
+      matrix.LhsSize() != matrix.RhsSize();
+  if (is_exact_match_with_size_discrepency) {
+    // The element count doesn't match.  If the container is empty,
+    // there's no need to explain anything as Google Mock already
+    // prints the empty container. Otherwise we just need to show
+    // how many elements there actually are.
+    if (matrix.LhsSize() != 0 && listener->IsInterested()) {
+      *listener << "which has " << Elements(matrix.LhsSize()) << "\n";
     }
   }
 
-  bool result = true;
+  bool result = !is_exact_match_with_size_discrepency;
   ::std::vector<char> element_matched(matrix.LhsSize(), 0);
   ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
 
diff --git a/src/third_party/googletest/googlemock/src/gmock-spec-builders.cc b/src/third_party/googletest/googlemock/src/gmock-spec-builders.cc
index de89471..ffdf03d 100644
--- a/src/third_party/googletest/googlemock/src/gmock-spec-builders.cc
+++ b/src/third_party/googletest/googlemock/src/gmock-spec-builders.cc
@@ -490,6 +490,7 @@
   // failure, unless the user explicitly asked us to ignore it.
   ~MockObjectRegistry() {
     if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return;
+    internal::MutexLock l(&internal::g_gmock_mutex);
 
     int leaked_count = 0;
     for (StateMap::const_iterator it = states_.begin(); it != states_.end();
@@ -530,7 +531,7 @@
 #ifdef GTEST_OS_QURT
       qurt_exception_raise_fatal();
 #else
-      _exit(1);  // We cannot call exit() as it is not reentrant and
+      _Exit(1);  // We cannot call exit() as it is not reentrant and
                  // may already have been called.
 #endif
     }
diff --git a/src/third_party/googletest/googlemock/test/gmock-actions_test.cc b/src/third_party/googletest/googlemock/test/gmock-actions_test.cc
index da1675c..84db511 100644
--- a/src/third_party/googletest/googlemock/test/gmock-actions_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-actions_test.cc
@@ -222,8 +222,8 @@
   // In C++17 and above, where it's guaranteed that functions can return
   // non-moveable objects, everything should work fine for non-moveable rsult
   // types too.
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
-    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+  // TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
   {
     struct NonMoveable {
       NonMoveable() = default;
@@ -244,7 +244,7 @@
     static_assert(!internal::is_callable_r<int, Callable>::value);
     static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
   }
-#endif  // C++17 and above
+#endif  // _MSC_VER
 
   // Nothing should choke when we try to call other arguments besides directly
   // callable objects, but they should not show up as callable.
@@ -441,8 +441,8 @@
 
   EXPECT_EQ(0, DefaultValue<int>::Get());
 
-  EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
-                            "");
+  EXPECT_DEATH_IF_SUPPORTED(
+      { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
 }
 
 TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
@@ -505,8 +505,8 @@
   EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
 
   EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
-  EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
-                            "");
+  EXPECT_DEATH_IF_SUPPORTED(
+      { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
 }
 
 // Tests that ActionInterface can be implemented by defining the
@@ -1477,6 +1477,54 @@
   }
 }
 
+// A DoAll action should be convertible to a OnceAction, even when its component
+// sub-actions are user-provided types that define only an Action conversion
+// operator. If they supposed being called more than once then they also support
+// being called at most once.
+TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
+  // Simplest case: only one sub-action.
+  struct CustomFinal final {
+    operator Action<int()>() {  // NOLINT
+      return Return(17);
+    }
+
+    operator Action<int(int, char)>() {  // NOLINT
+      return Return(19);
+    }
+  };
+
+  {
+    OnceAction<int()> action = DoAll(CustomFinal{});
+    EXPECT_EQ(17, std::move(action).Call());
+  }
+
+  {
+    OnceAction<int(int, char)> action = DoAll(CustomFinal{});
+    EXPECT_EQ(19, std::move(action).Call(0, 0));
+  }
+
+  // It should also work with multiple sub-actions.
+  struct CustomInitial final {
+    operator Action<void()>() {  // NOLINT
+      return [] {};
+    }
+
+    operator Action<void(int, char)>() {  // NOLINT
+      return [] {};
+    }
+  };
+
+  {
+    OnceAction<int()> action = DoAll(CustomInitial{}, CustomFinal{});
+    EXPECT_EQ(17, std::move(action).Call());
+  }
+
+  {
+    OnceAction<int(int, char)> action = DoAll(CustomInitial{}, CustomFinal{});
+    EXPECT_EQ(19, std::move(action).Call(0, 0));
+  }
+}
+
 // Tests using WithArgs and with an action that takes 1 argument.
 TEST(WithArgsTest, OneArg) {
   Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary));  // NOLINT
diff --git a/src/third_party/googletest/googlemock/test/gmock-function-mocker_test.cc b/src/third_party/googletest/googlemock/test/gmock-function-mocker_test.cc
index f7b31ae..cdac79b 100644
--- a/src/third_party/googletest/googlemock/test/gmock-function-mocker_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-function-mocker_test.cc
@@ -325,8 +325,8 @@
 
 // Tests mocking a decimal function.
 TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
-  EXPECT_CALL(this->mock_foo_,
-              Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
+  EXPECT_CALL(this->mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100),
+                                       5U, nullptr, "hi"))
       .WillOnce(Return(5));
 
   EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
diff --git a/src/third_party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc b/src/third_party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc
index f176962..06b0b47 100644
--- a/src/third_party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-matchers-arithmetic_test.cc
@@ -36,7 +36,9 @@
 #include <memory>
 #include <string>
 
+#include "gmock/gmock.h"
 #include "test/gmock-matchers_test.h"
+#include "gtest/gtest.h"
 
 // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
 // possible loss of data and C4100, unreferenced local parameter
@@ -559,10 +561,9 @@
   Matcher<int> m;
 
   // Successful match.  Both matchers need to explain.  The second
-  // matcher doesn't give an explanation, so only the first matcher's
-  // explanation is printed.
+  // matcher doesn't give an explanation, so the matcher description is used.
   m = AllOf(GreaterThan(10), Lt(30));
-  EXPECT_EQ("which is 15 more than 10", Explain(m, 25));
+  EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25));
 
   // Successful match.  Both matchers need to explain.
   m = AllOf(GreaterThan(10), GreaterThan(20));
@@ -572,8 +573,9 @@
   // Successful match.  All matchers need to explain.  The second
   // matcher doesn't given an explanation.
   m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
-  EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20",
-            Explain(m, 25));
+  EXPECT_EQ(
+      "which is 15 more than 10, and is < 30, and which is 5 more than 20",
+      Explain(m, 25));
 
   // Successful match.  All matchers need to explain.
   m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
@@ -588,10 +590,10 @@
   EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
 
   // Failed match.  The second matcher, which failed, needs to
-  // explain.  Since it doesn't given an explanation, nothing is
+  // explain.  Since it doesn't given an explanation, the matcher text is
   // printed.
   m = AllOf(GreaterThan(10), Lt(30));
-  EXPECT_EQ("", Explain(m, 40));
+  EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40));
 
   // Failed match.  The second matcher, which failed, needs to
   // explain.
@@ -774,45 +776,43 @@
 TEST_P(AnyOfTestP, ExplainsResult) {
   Matcher<int> m;
 
-  // Failed match.  Both matchers need to explain.  The second
-  // matcher doesn't give an explanation, so only the first matcher's
-  // explanation is printed.
+  // Failed match. The second matcher have no explanation (description is used).
   m = AnyOf(GreaterThan(10), Lt(0));
-  EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+  EXPECT_EQ("which is 5 less than 10, and isn't < 0", Explain(m, 5));
 
-  // Failed match.  Both matchers need to explain.
+  // Failed match. Both matchers have explanations.
   m = AnyOf(GreaterThan(10), GreaterThan(20));
   EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
             Explain(m, 5));
 
-  // Failed match.  All matchers need to explain.  The second
-  // matcher doesn't given an explanation.
+  // Failed match. The middle matcher have no explanation.
   m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
-  EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
-            Explain(m, 5));
+  EXPECT_EQ(
+      "which is 5 less than 10, and isn't > 20, and which is 25 less than 30",
+      Explain(m, 5));
 
-  // Failed match.  All matchers need to explain.
+  // Failed match. All three matchers have explanations.
   m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
   EXPECT_EQ(
       "which is 5 less than 10, and which is 15 less than 20, "
       "and which is 25 less than 30",
       Explain(m, 5));
 
-  // Successful match.  The first matcher, which succeeded, needs to
-  // explain.
+  // Successful match. The first macher succeeded and has explanation.
   m = AnyOf(GreaterThan(10), GreaterThan(20));
   EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
 
-  // Successful match.  The second matcher, which succeeded, needs to
-  // explain.  Since it doesn't given an explanation, nothing is
-  // printed.
-  m = AnyOf(GreaterThan(10), Lt(30));
-  EXPECT_EQ("", Explain(m, 0));
-
-  // Successful match.  The second matcher, which succeeded, needs to
-  // explain.
+  // Successful match. The second matcher succeeded and has explanation.
   m = AnyOf(GreaterThan(30), GreaterThan(20));
   EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
+
+  // Successful match. The first matcher succeeded and has no explanation.
+  m = AnyOf(Gt(10), Lt(20));
+  EXPECT_EQ("which matches (is > 10)", Explain(m, 15));
+
+  // Successful match. The second matcher succeeded and has no explanation.
+  m = AnyOf(Gt(30), Gt(20));
+  EXPECT_EQ("which matches (is > 20)", Explain(m, 25));
 }
 
 // The following predicate function and predicate functor are for
diff --git a/src/third_party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc b/src/third_party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc
index b2ce99e..a331aec 100644
--- a/src/third_party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-matchers-comparisons_test.cc
@@ -37,13 +37,14 @@
 #include <tuple>
 #include <vector>
 
+#include "gmock/gmock.h"
 #include "test/gmock-matchers_test.h"
+#include "gtest/gtest.h"
 
 // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
 // possible loss of data and C4100, unreferenced local parameter
 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
 
-
 namespace testing {
 namespace gmock_matchers_test {
 namespace {
@@ -410,9 +411,27 @@
   int value_;
 };
 
+// For testing casting matchers between compatible types. This is similar to
+// IntValue, but takes a non-const reference to the value, showing MatcherCast
+// works with such types (and doesn't, for example, use a const ref internally).
+class MutableIntView {
+ public:
+  // An int& can be statically (although not implicitly) cast to a
+  // MutableIntView.
+  explicit MutableIntView(int& a_value) : value_(a_value) {}
+
+  int& value() const { return value_; }
+
+ private:
+  int& value_;
+};
+
 // For testing casting matchers between compatible types.
 bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
 
+// For testing casting matchers between compatible types.
+bool IsPositiveMutableIntView(MutableIntView foo) { return foo.value() > 0; }
+
 // Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
 // can be statically converted to U.
 TEST(MatcherCastTest, FromCompatibleType) {
@@ -428,14 +447,34 @@
   // predicate.
   EXPECT_TRUE(m4.Matches(1));
   EXPECT_FALSE(m4.Matches(0));
+
+  Matcher<MutableIntView> m5 = Truly(IsPositiveMutableIntView);
+  Matcher<int> m6 = MatcherCast<int>(m5);
+  // In the following, the arguments 1 and 0 are statically converted to
+  // MutableIntView objects, and then tested by the IsPositiveMutableIntView()
+  // predicate.
+  EXPECT_TRUE(m6.Matches(1));
+  EXPECT_FALSE(m6.Matches(0));
 }
 
 // Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
 TEST(MatcherCastTest, FromConstReferenceToNonReference) {
-  Matcher<const int&> m1 = Eq(0);
+  int n = 0;
+  Matcher<const int&> m1 = Ref(n);
   Matcher<int> m2 = MatcherCast<int>(m1);
-  EXPECT_TRUE(m2.Matches(0));
-  EXPECT_FALSE(m2.Matches(1));
+  int n1 = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  EXPECT_FALSE(m2.Matches(n1));
+}
+
+// Tests that MatcherCast<T&>(m) works when m is a Matcher<const T&>.
+TEST(MatcherCastTest, FromConstReferenceToReference) {
+  int n = 0;
+  Matcher<const int&> m1 = Ref(n);
+  Matcher<int&> m2 = MatcherCast<int&>(m1);
+  int n1 = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  EXPECT_FALSE(m2.Matches(n1));
 }
 
 // Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
@@ -444,6 +483,12 @@
   Matcher<int> m2 = MatcherCast<int>(m1);
   EXPECT_TRUE(m2.Matches(0));
   EXPECT_FALSE(m2.Matches(1));
+
+  // Of course, reference identity isn't preserved since a copy is required.
+  int n = 0;
+  Matcher<int&> m3 = Ref(n);
+  Matcher<int> m4 = MatcherCast<int>(m3);
+  EXPECT_FALSE(m4.Matches(n));
 }
 
 // Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
@@ -648,6 +693,16 @@
   EXPECT_FALSE(m4.Matches(d2));
 }
 
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<const T&>.
+TEST(SafeMatcherCastTest, FromConstReferenceToNonReference) {
+  int n = 0;
+  Matcher<const int&> m1 = Ref(n);
+  Matcher<int> m2 = SafeMatcherCast<int>(m1);
+  int n1 = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  EXPECT_FALSE(m2.Matches(n1));
+}
+
 // Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
 TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
   int n = 0;
@@ -1769,6 +1824,15 @@
   EXPECT_EQ("starts with \"Hi\"", Describe(m));
 }
 
+TEST(StartsWithTest, WorksWithStringMatcherOnStringViewMatchee) {
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  EXPECT_THAT(internal::StringView("talk to me goose"),
+              StartsWith(std::string("talk")));
+#else
+  GTEST_SKIP() << "Not applicable without internal::StringView.";
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+}
+
 // Tests EndsWith(s).
 
 TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
@@ -2325,9 +2389,11 @@
   EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
 }
 
+// Tests that when AllOf() succeeds, but matchers have no explanation,
+// the matcher description is used.
 TEST(ExplainMatchResultTest, AllOf_True_True_2) {
   const Matcher<int> m = AllOf(Ge(2), Le(3));
-  EXPECT_EQ("", Explain(m, 2));
+  EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
 }
 
 INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
diff --git a/src/third_party/googletest/googlemock/test/gmock-matchers-containers_test.cc b/src/third_party/googletest/googlemock/test/gmock-matchers-containers_test.cc
index 38fd9a5..751fb60 100644
--- a/src/third_party/googletest/googlemock/test/gmock-matchers-containers_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-matchers-containers_test.cc
@@ -43,14 +43,14 @@
 #include <tuple>
 #include <vector>
 
+#include "gmock/gmock.h"
+#include "test/gmock-matchers_test.h"
 #include "gtest/gtest.h"
 
 // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
 // possible loss of data and C4100, unreferenced local parameter
 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
 
-#include "test/gmock-matchers_test.h"
-
 namespace testing {
 namespace gmock_matchers_test {
 namespace {
@@ -1204,13 +1204,16 @@
   vector<int> container;
   EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
   EXPECT_EQ("whose size 0 matches", Explain(m2, container));
-  EXPECT_EQ("whose size 0 matches", Explain(m3, container));
+  EXPECT_EQ("whose size 0 matches, which matches (is equal to 0)",
+            Explain(m3, container));
   EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
   container.push_back(0);
   container.push_back(0);
   EXPECT_EQ("whose size 2 matches", Explain(m1, container));
   EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
-  EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
+  EXPECT_EQ(
+      "whose size 2 doesn't match, isn't equal to 0, and isn't equal to 3",
+      Explain(m3, container));
   EXPECT_EQ("whose size 2 matches", Explain(m4, container));
 }
 
@@ -1475,8 +1478,10 @@
             Explain(m1, container));
   EXPECT_EQ("whose distance between begin() and end() 0 matches",
             Explain(m2, container));
-  EXPECT_EQ("whose distance between begin() and end() 0 matches",
-            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 0 matches, which matches (is "
+      "equal to 0)",
+      Explain(m3, container));
   EXPECT_EQ(
       "whose distance between begin() and end() 0 doesn't match, which is 1 "
       "less than 1",
@@ -1487,8 +1492,10 @@
             Explain(m1, container));
   EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
             Explain(m2, container));
-  EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
-            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 2 doesn't match, isn't equal "
+      "to 0, and isn't equal to 3",
+      Explain(m3, container));
   EXPECT_EQ(
       "whose distance between begin() and end() 2 matches, which is 1 more "
       "than 1",
@@ -2014,7 +2021,14 @@
   StringMatchResultListener listener;
   EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), v, &listener))
       << listener.str();
-  EXPECT_THAT(listener.str(), Eq("which has 1 element"));
+  EXPECT_THAT(listener.str(),
+              Eq("which has 1 element\n"
+                 "where the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1,\n"
+                 "matcher #1: is equal to 2,\n"
+                 "matcher #2: is equal to 3\n"
+                 "and where the following elements don't match any matchers:\n"
+                 "element #0: 4"));
 }
 
 TEST_F(UnorderedElementsAreTest, FailMessageCountWrongZero) {
@@ -2022,7 +2036,11 @@
   StringMatchResultListener listener;
   EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), v, &listener))
       << listener.str();
-  EXPECT_THAT(listener.str(), Eq(""));
+  EXPECT_THAT(listener.str(),
+              Eq("where the following matchers don't match any elements:\n"
+                 "matcher #0: is equal to 1,\n"
+                 "matcher #1: is equal to 2,\n"
+                 "matcher #2: is equal to 3"));
 }
 
 TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedMatchers) {
@@ -2438,7 +2456,7 @@
   const double lhs[2] = {1, 2};
   const int rhs[1] = {0};
   EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
-  EXPECT_EQ("which has 2 elements",
+  EXPECT_EQ("which has 2 elements\n",
             Explain(UnorderedPointwise(Gt(), rhs), lhs));
 
   const int rhs2[3] = {0, 1, 2};
diff --git a/src/third_party/googletest/googlemock/test/gmock-matchers-misc_test.cc b/src/third_party/googletest/googlemock/test/gmock-matchers-misc_test.cc
index b8f6458..de8b76c 100644
--- a/src/third_party/googletest/googlemock/test/gmock-matchers-misc_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-matchers-misc_test.cc
@@ -32,6 +32,7 @@
 // This file tests some commonly used argument matchers.
 
 #include <array>
+#include <cstdint>
 #include <memory>
 #include <ostream>
 #include <string>
@@ -39,14 +40,14 @@
 #include <utility>
 #include <vector>
 
+#include "gmock/gmock.h"
+#include "test/gmock-matchers_test.h"
 #include "gtest/gtest.h"
 
 // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
 // possible loss of data and C4100, unreferenced local parameter
 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
 
-#include "test/gmock-matchers_test.h"
-
 namespace testing {
 namespace gmock_matchers_test {
 namespace {
@@ -674,6 +675,8 @@
                    // explanation.
 }
 
+#if GTEST_HAS_TYPED_TEST
+
 // Sample optional type implementation with minimal requirements for use with
 // Optional matcher.
 template <typename T>
@@ -691,38 +694,94 @@
   bool has_value_;
 };
 
-TEST(OptionalTest, DescribesSelf) {
-  const Matcher<SampleOptional<int>> m = Optional(Eq(1));
+// Sample optional type implementation with alternative minimal requirements for
+// use with Optional matcher. In particular, while it doesn't have a bool
+// conversion operator, it does have a has_value() method.
+template <typename T>
+class SampleOptionalWithoutBoolConversion {
+ public:
+  using value_type = T;
+  explicit SampleOptionalWithoutBoolConversion(T value)
+      : value_(std::move(value)), has_value_(true) {}
+  SampleOptionalWithoutBoolConversion() : value_(), has_value_(false) {}
+  bool has_value() const { return has_value_; }
+  const T& operator*() const { return value_; }
+
+ private:
+  T value_;
+  bool has_value_;
+};
+
+template <typename T>
+class OptionalTest : public testing::Test {};
+
+using OptionalTestTypes =
+    testing::Types<SampleOptional<int>,
+                   SampleOptionalWithoutBoolConversion<int>>;
+
+TYPED_TEST_SUITE(OptionalTest, OptionalTestTypes);
+
+TYPED_TEST(OptionalTest, DescribesSelf) {
+  const Matcher<TypeParam> m = Optional(Eq(1));
   EXPECT_EQ("value is equal to 1", Describe(m));
 }
 
-TEST(OptionalTest, ExplainsSelf) {
-  const Matcher<SampleOptional<int>> m = Optional(Eq(1));
-  EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1)));
-  EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2)));
+TYPED_TEST(OptionalTest, ExplainsSelf) {
+  const Matcher<TypeParam> m = Optional(Eq(1));
+  EXPECT_EQ("whose value 1 matches", Explain(m, TypeParam(1)));
+  EXPECT_EQ("whose value 2 doesn't match", Explain(m, TypeParam(2)));
 }
 
-TEST(OptionalTest, MatchesNonEmptyOptional) {
-  const Matcher<SampleOptional<int>> m1 = Optional(1);
-  const Matcher<SampleOptional<int>> m2 = Optional(Eq(2));
-  const Matcher<SampleOptional<int>> m3 = Optional(Lt(3));
-  SampleOptional<int> opt(1);
+TYPED_TEST(OptionalTest, MatchesNonEmptyOptional) {
+  const Matcher<TypeParam> m1 = Optional(1);
+  const Matcher<TypeParam> m2 = Optional(Eq(2));
+  const Matcher<TypeParam> m3 = Optional(Lt(3));
+  TypeParam opt(1);
   EXPECT_TRUE(m1.Matches(opt));
   EXPECT_FALSE(m2.Matches(opt));
   EXPECT_TRUE(m3.Matches(opt));
 }
 
-TEST(OptionalTest, DoesNotMatchNullopt) {
-  const Matcher<SampleOptional<int>> m = Optional(1);
-  SampleOptional<int> empty;
+TYPED_TEST(OptionalTest, DoesNotMatchNullopt) {
+  const Matcher<TypeParam> m = Optional(1);
+  TypeParam empty;
   EXPECT_FALSE(m.Matches(empty));
 }
 
-TEST(OptionalTest, WorksWithMoveOnly) {
-  Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr));
-  EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr)));
+TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersTakingReferences) {
+  const Matcher<const int&> eq1 = Eq(1);
+  const Matcher<const int&> eq2 = Eq(2);
+  TypeParam opt(1);
+  EXPECT_THAT(opt, Optional(eq1));
+  EXPECT_THAT(opt, Optional(Not(eq2)));
+  EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
 }
 
+TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersRequiringConversion) {
+  const Matcher<int64_t> eq1 = Eq(1);
+  const Matcher<int64_t> eq2 = Eq(2);
+  TypeParam opt(1);
+  EXPECT_THAT(opt, Optional(eq1));
+  EXPECT_THAT(opt, Optional(Not(eq2)));
+  EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
+}
+
+template <typename T>
+class MoveOnlyOptionalTest : public testing::Test {};
+
+using MoveOnlyOptionalTestTypes =
+    testing::Types<SampleOptional<std::unique_ptr<int>>,
+                   SampleOptionalWithoutBoolConversion<std::unique_ptr<int>>>;
+
+TYPED_TEST_SUITE(MoveOnlyOptionalTest, MoveOnlyOptionalTestTypes);
+
+TYPED_TEST(MoveOnlyOptionalTest, WorksWithMoveOnly) {
+  Matcher<TypeParam> m = Optional(Eq(nullptr));
+  EXPECT_TRUE(m.Matches(TypeParam(nullptr)));
+}
+
+#endif  // GTEST_HAS_TYPED_TEST
+
 class SampleVariantIntString {
  public:
   SampleVariantIntString(int i) : i_(i), has_int_(true) {}
@@ -1576,10 +1635,10 @@
   const Matcher<int> m1 = AnyOfArray(v1);
   const Matcher<int> m2 = AnyOfArray(v2);
   EXPECT_EQ("", Explain(m0, 0));
-  EXPECT_EQ("", Explain(m1, 1));
-  EXPECT_EQ("", Explain(m1, 2));
-  EXPECT_EQ("", Explain(m2, 3));
-  EXPECT_EQ("", Explain(m2, 4));
+  EXPECT_EQ("which matches (is equal to 1)", Explain(m1, 1));
+  EXPECT_EQ("isn't equal to 1", Explain(m1, 2));
+  EXPECT_EQ("which matches (is equal to 3)", Explain(m2, 3));
+  EXPECT_EQ("isn't equal to 2, and isn't equal to 3", Explain(m2, 4));
   EXPECT_EQ("()", Describe(m0));
   EXPECT_EQ("(is equal to 1)", Describe(m1));
   EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));
diff --git a/src/third_party/googletest/googlemock/test/gmock-more-actions_test.cc b/src/third_party/googletest/googlemock/test/gmock-more-actions_test.cc
index 9980f3b..5b8b566 100644
--- a/src/third_party/googletest/googlemock/test/gmock-more-actions_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-more-actions_test.cc
@@ -59,6 +59,7 @@
 using testing::ReturnArg;
 using testing::ReturnPointee;
 using testing::SaveArg;
+using testing::SaveArgByMove;
 using testing::SaveArgPointee;
 using testing::SetArgReferee;
 using testing::Unused;
@@ -85,6 +86,16 @@
   int operator()(bool x) { return x ? 1 : -1; }
 };
 
+struct UnaryMoveOnlyFunctor : UnaryFunctor {
+  UnaryMoveOnlyFunctor() = default;
+  UnaryMoveOnlyFunctor(const UnaryMoveOnlyFunctor&) = delete;
+  UnaryMoveOnlyFunctor(UnaryMoveOnlyFunctor&&) = default;
+};
+
+struct OneShotUnaryFunctor {
+  int operator()(bool x) && { return x ? 1 : -1; }
+};
+
 const char* Binary(const char* input, short n) { return input + n; }  // NOLINT
 
 int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT
@@ -482,6 +493,34 @@
   EXPECT_EQ('a', result);
 }
 
+struct MoveOnly {
+  explicit MoveOnly(int v) : i(v) {}
+  MoveOnly(MoveOnly&& o) {
+    i = o.i;
+    o.i = -1;
+  }
+  MoveOnly& operator=(MoveOnly&& o) {
+    i = o.i;
+    o.i = -1;
+    return *this;
+  }
+  int i;
+};
+
+TEST(SaveArgByMoveActionTest, WorksForSameType) {
+  MoveOnly result{0};
+  const Action<void(MoveOnly v)> a1 = SaveArgByMove<0>(&result);
+  a1.Perform(std::make_tuple(MoveOnly{5}));
+  EXPECT_EQ(5, result.i);
+}
+
+TEST(SaveArgByMoveActionTest, WorksForCompatibleType) {
+  MoveOnly result{0};
+  const Action<void(bool, MoveOnly)> a1 = SaveArgByMove<1>(&result);
+  a1.Perform(std::make_tuple(true, MoveOnly{7}));
+  EXPECT_EQ(7, result.i);
+}
+
 TEST(SaveArgPointeeActionTest, WorksForSameType) {
   int result = 0;
   const int value = 5;
@@ -698,12 +737,24 @@
   EXPECT_EQ(1, a.Perform(std::make_tuple(2, &Nullary)));
 }
 
-// Tests using InvokeArgument with a unary function.
+// Tests using InvokeArgument with a unary functor.
 TEST(InvokeArgumentTest, Functor1) {
   Action<int(UnaryFunctor)> a = InvokeArgument<0>(true);  // NOLINT
   EXPECT_EQ(1, a.Perform(std::make_tuple(UnaryFunctor())));
 }
 
+// Tests using InvokeArgument with a unary move-only functor.
+TEST(InvokeArgumentTest, Functor1MoveOnly) {
+  Action<int(UnaryMoveOnlyFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(UnaryMoveOnlyFunctor())));
+}
+
+// Tests using InvokeArgument with a one-shot unary functor.
+TEST(InvokeArgumentTest, OneShotFunctor1) {
+  Action<int(OneShotUnaryFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(std::make_tuple(OneShotUnaryFunctor())));
+}
+
 // Tests using InvokeArgument with a 5-ary function.
 TEST(InvokeArgumentTest, Function5) {
   Action<int(int (*)(int, int, int, int, int))> a =  // NOLINT
@@ -734,34 +785,34 @@
 
 // Tests using InvokeArgument with a 7-ary function.
 TEST(InvokeArgumentTest, Function7) {
-  Action<std::string(std::string(*)(const char*, const char*, const char*,
-                                    const char*, const char*, const char*,
-                                    const char*))>
+  Action<std::string(std::string (*)(const char*, const char*, const char*,
+                                     const char*, const char*, const char*,
+                                     const char*))>
       a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
   EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
 }
 
 // Tests using InvokeArgument with a 8-ary function.
 TEST(InvokeArgumentTest, Function8) {
-  Action<std::string(std::string(*)(const char*, const char*, const char*,
-                                    const char*, const char*, const char*,
-                                    const char*, const char*))>
+  Action<std::string(std::string (*)(const char*, const char*, const char*,
+                                     const char*, const char*, const char*,
+                                     const char*, const char*))>
       a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
   EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
 }
 
 // Tests using InvokeArgument with a 9-ary function.
 TEST(InvokeArgumentTest, Function9) {
-  Action<std::string(std::string(*)(const char*, const char*, const char*,
-                                    const char*, const char*, const char*,
-                                    const char*, const char*, const char*))>
+  Action<std::string(std::string (*)(const char*, const char*, const char*,
+                                     const char*, const char*, const char*,
+                                     const char*, const char*, const char*))>
       a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
   EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
 }
 
 // Tests using InvokeArgument with a 10-ary function.
 TEST(InvokeArgumentTest, Function10) {
-  Action<std::string(std::string(*)(
+  Action<std::string(std::string (*)(
       const char*, const char*, const char*, const char*, const char*,
       const char*, const char*, const char*, const char*, const char*))>
       a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
@@ -806,6 +857,22 @@
   EXPECT_FALSE(a.Perform(std::make_tuple(&ReferencesGlobalDouble)));
 }
 
+TEST(InvokeArgumentTest, MoveOnlyType) {
+  struct Marker {};
+  struct {
+    // Method takes a unique_ptr (to a type we don't care about), and an
+    // invocable type.
+    MOCK_METHOD(bool, MockMethod,
+                (std::unique_ptr<Marker>, std::function<int()>), ());
+  } mock;
+
+  ON_CALL(mock, MockMethod(_, _)).WillByDefault(InvokeArgument<1>());
+
+  // This compiles, but is a little opaque as a workaround:
+  ON_CALL(mock, MockMethod(_, _))
+      .WillByDefault(WithArg<1>(InvokeArgument<0>()));
+}
+
 // Tests DoAll(a1, a2).
 TEST(DoAllTest, TwoActions) {
   int n = 0;
diff --git a/src/third_party/googletest/googlemock/test/gmock-pp_test.cc b/src/third_party/googletest/googlemock/test/gmock-pp_test.cc
index 5d1566e..e447f76 100644
--- a/src/third_party/googletest/googlemock/test/gmock-pp_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-pp_test.cc
@@ -70,7 +70,7 @@
 static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
 static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
 
-// TODO(iserna): The following asserts fail in --config=lexan.
+// TODO(iserna): The following asserts fail in --config=windows.
 #define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
 static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
 static_assert(GMOCK_PP_IS_EMPTY(), "");
diff --git a/src/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc b/src/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc
index aaf88d7..9e68aa0 100644
--- a/src/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc
+++ b/src/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc
@@ -804,9 +804,8 @@
       "to be called at least once");
 }
 
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
-    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
+// TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
 // It should be possible to return a non-moveable type from a mock action in
 // C++17 and above, where it's guaranteed that such a type can be initialized
 // from a prvalue returned from a function.
@@ -847,7 +846,7 @@
   EXPECT_EQ(17, mock.AsStdFunction()().x);
 }
 
-#endif  // C++17 and above
+#endif  // _MSC_VER
 
 // Tests that the n-th action is taken for the n-th matching
 // invocation.
diff --git a/src/third_party/googletest/googlemock/test/gmock_link_test.h b/src/third_party/googletest/googlemock/test/gmock_link_test.h
index db11c2d..cb5179b 100644
--- a/src/third_party/googletest/googlemock/test/gmock_link_test.h
+++ b/src/third_party/googletest/googlemock/test/gmock_link_test.h
@@ -186,6 +186,7 @@
 #endif
 
 #if GTEST_HAS_EXCEPTIONS
+using testing::Rethrow;
 using testing::Throw;
 #endif
 
@@ -416,6 +417,14 @@
   EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Throw(42));
   EXPECT_THROW(mock.VoidFromString(nullptr), int);
 }
+// Tests the linkage of the Rethrow action.
+TEST(LinkTest, TestRethrow) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(Rethrow(std::make_exception_ptr(42)));
+  EXPECT_THROW(mock.VoidFromString(nullptr), int);
+}
 #endif  // GTEST_HAS_EXCEPTIONS
 
 // The ACTION*() macros trigger warning C4100 (unreferenced formal
diff --git a/src/third_party/googletest/googletest/CMakeLists.txt b/src/third_party/googletest/googletest/CMakeLists.txt
index caafa8c..dce6a7c 100644
--- a/src/third_party/googletest/googletest/CMakeLists.txt
+++ b/src/third_party/googletest/googletest/CMakeLists.txt
@@ -5,7 +5,7 @@
 # CMake build script for Google Test.
 #
 # To run the tests for Google Test itself on Linux, use 'make test' or
-# ctest.  You can select which tests to run using 'ctest -R regex'.
+# ctest. You can select which tests to run using 'ctest -R regex'.
 # For more options, run 'ctest --help'.
 
 # When other libraries are using a shared version of runtime libraries,
@@ -35,7 +35,7 @@
 
 ########################################################################
 #
-# Project-wide settings
+# Project-wide settings.
 
 # Name of the project.
 #
@@ -44,7 +44,7 @@
 # ${gtest_BINARY_DIR}.
 # Language "C" is required for find_package(Threads).
 
-# Project version:
+# Project version.
 
 cmake_minimum_required(VERSION 3.13)
 project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
@@ -53,7 +53,7 @@
   set_up_hermetic_build()
 endif()
 
-# These commands only run if this is the main project
+# These commands only run if this is the main project.
 if(CMAKE_PROJECT_NAME STREQUAL "gtest" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution")
 
   # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
@@ -83,7 +83,7 @@
 config_compiler_and_linker()  # Defined in internal_utils.cmake.
 
 # Needed to set the namespace for both the export targets and the
-# alias libraries
+# alias libraries.
 set(cmake_package_name GTest CACHE INTERNAL "")
 
 # Create the CMake package file descriptors.
@@ -114,10 +114,10 @@
 
 ########################################################################
 #
-# Defines the gtest & gtest_main libraries.  User tests should link
+# Defines the gtest & gtest_main libraries. User tests should link
 # with one of them.
 
-# Google Test libraries.  We build them using more strict warnings than what
+# Google Test libraries. We build them using more strict warnings than what
 # are used for other targets, to ensure that gtest can be compiled by a user
 # aggressive about warnings.
 cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
@@ -147,22 +147,22 @@
 target_include_directories(gtest_main SYSTEM INTERFACE
   "$<BUILD_INTERFACE:${dirs}>"
   "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
-if(CMAKE_SYSTEM_NAME MATCHES "QNX")
+if(CMAKE_SYSTEM_NAME MATCHES "QNX" AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 7.1)
   target_link_libraries(gtest PUBLIC regex)
 endif()
 target_link_libraries(gtest_main PUBLIC gtest)
 
 ########################################################################
 #
-# Install rules
+# Install rules.
 install_project(gtest gtest_main)
 
 ########################################################################
 #
 # Samples on how to link user tests with gtest or gtest_main.
 #
-# They are not built by default.  To build them, set the
-# gtest_build_samples option to ON.  You can do it by running ccmake
+# They are not built by default. To build them, set the
+# gtest_build_samples option to ON. You can do it by running ccmake
 # or specifying the -Dgtest_build_samples=ON flag when running cmake.
 
 if (gtest_build_samples)
@@ -185,8 +185,8 @@
 # You can skip this section if you aren't interested in testing
 # Google Test itself.
 #
-# The tests are not built by default.  To build them, set the
-# gtest_build_tests option to ON.  You can do it by running ccmake
+# The tests are not built by default. To build them, set the
+# gtest_build_tests option to ON. You can do it by running ccmake
 # or specifying the -Dgtest_build_tests=ON flag when running cmake.
 
 if (gtest_build_tests)
@@ -268,7 +268,7 @@
   py_test(gtest_skip_environment_check_output_test)
 
   # Visual Studio .NET 2003 does not support STL with exceptions disabled.
-  if (NOT MSVC OR MSVC_VERSION GREATER 1310)  # 1310 is Visual Studio .NET 2003
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310) # 1310 is Visual Studio .NET 2003
     cxx_executable_with_flags(
       googletest-catch-exceptions-no-ex-test_
       "${cxx_no_exception}"
diff --git a/src/third_party/googletest/googletest/README.md b/src/third_party/googletest/googletest/README.md
index 44fd69b..5de23c5 100644
--- a/src/third_party/googletest/googletest/README.md
+++ b/src/third_party/googletest/googletest/README.md
@@ -25,7 +25,7 @@
 with
 
 ```
-git clone https://github.com/google/googletest.git -b v1.14.0
+git clone https://github.com/google/googletest.git -b v1.16.0
 cd googletest        # Main directory of the cloned repository.
 mkdir build          # Create a directory to hold the build output.
 cd build
diff --git a/src/third_party/googletest/googletest/cmake/Config.cmake.in b/src/third_party/googletest/googletest/cmake/Config.cmake.in
index 12be449..3f70661 100644
--- a/src/third_party/googletest/googletest/cmake/Config.cmake.in
+++ b/src/third_party/googletest/googletest/cmake/Config.cmake.in
@@ -4,6 +4,10 @@
   set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)
   find_dependency(Threads)
 endif()
+if (@GTEST_HAS_ABSL@)
+  find_dependency(absl)
+  find_dependency(re2)
+endif()
 
 include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
 check_required_components("@project_name@")
diff --git a/src/third_party/googletest/googletest/cmake/internal_utils.cmake b/src/third_party/googletest/googletest/cmake/internal_utils.cmake
index d4f67f4..7ca256a 100644
--- a/src/third_party/googletest/googletest/cmake/internal_utils.cmake
+++ b/src/third_party/googletest/googletest/cmake/internal_utils.cmake
@@ -29,7 +29,7 @@
              CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
       if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
         # When Google Test is built as a shared library, it should also use
-        # shared runtime libraries.  Otherwise, it may end up with multiple
+        # shared runtime libraries. Otherwise, it may end up with multiple
         # copies of runtime library data in different modules, resulting in
         # hard-to-find crashes. When it is built as a static library, it is
         # preferable to use CRT as static libraries, as we don't have to rely
@@ -55,11 +55,11 @@
 endmacro()
 
 # Defines the compiler/linker flags used to build Google Test and
-# Google Mock.  You can tweak these definitions to suit your need.  A
+# Google Mock. You can tweak these definitions to suit your need. A
 # variable's value is empty before it's explicitly assigned to.
 macro(config_compiler_and_linker)
   # Note: pthreads on MinGW is not supported, even if available
-  # instead, we use windows threading primitives
+  # instead, we use windows threading primitives.
   unset(GTEST_HAS_PTHREAD)
   if (NOT gtest_disable_pthreads AND NOT MINGW)
     # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
@@ -79,7 +79,7 @@
     set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
     set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")
     set(cxx_no_rtti_flags "-GR-")
-    # Suppress "unreachable code" warning
+    # Suppress "unreachable code" warning,
     # https://stackoverflow.com/questions/3232669 explains the issue.
     set(cxx_base_flags "${cxx_base_flags} -wd4702")
     # Ensure MSVC treats source files as UTF-8 encoded.
@@ -110,7 +110,7 @@
     set(cxx_exception_flags "-fexceptions")
     set(cxx_no_exception_flags "-fno-exceptions")
     # Until version 4.3.2, GCC doesn't define a macro to indicate
-    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
     # explicitly.
     set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
     set(cxx_strict_flags
@@ -127,7 +127,7 @@
     set(cxx_exception_flags "-qeh")
     set(cxx_no_exception_flags "-qnoeh")
     # Until version 9.0, Visual Age doesn't define a macro to indicate
-    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
     # explicitly.
     set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
   elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
@@ -157,7 +157,7 @@
   set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
 endmacro()
 
-# Defines the gtest & gtest_main libraries.  User tests should link
+# Defines the gtest & gtest_main libraries. User tests should link
 # with one of them.
 function(cxx_library_with_type name type cxx_flags)
   # type can be either STATIC or SHARED to denote a static or shared library.
@@ -167,7 +167,7 @@
   set_target_properties(${name}
     PROPERTIES
     COMPILE_FLAGS "${cxx_flags}")
-  # Set the output directory for build artifacts
+  # Set the output directory for build artifacts.
   set_target_properties(${name}
     PROPERTIES
     RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
@@ -175,7 +175,7 @@
     ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
     PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
     COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
-  # make PDBs match library name
+  # Make PDBs match library name.
   get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX)
   set_target_properties(${name}
     PROPERTIES
@@ -195,7 +195,7 @@
     target_link_libraries(${name} PUBLIC Threads::Threads)
   endif()
 
-  target_compile_features(${name} PUBLIC cxx_std_14)
+  target_compile_features(${name} PUBLIC cxx_std_17)
 endfunction()
 
 ########################################################################
@@ -212,7 +212,7 @@
 
 # cxx_executable_with_flags(name cxx_flags libs srcs...)
 #
-# creates a named C++ executable that depends on the given libraries and
+# Creates a named C++ executable that depends on the given libraries and
 # is built from the given source files with the given compiler flags.
 function(cxx_executable_with_flags name cxx_flags libs)
   add_executable(${name} ${ARGN})
@@ -239,19 +239,21 @@
 
 # cxx_executable(name dir lib srcs...)
 #
-# creates a named target that depends on the given libs and is built
-# from the given source files.  dir/name.cc is implicitly included in
+# Creates a named target that depends on the given libs and is built
+# from the given source files. dir/name.cc is implicitly included in
 # the source file list.
 function(cxx_executable name dir libs)
   cxx_executable_with_flags(
     ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
 endfunction()
 
-find_package(Python3)
+if(gtest_build_tests)
+  find_package(Python3)
+endif()
 
 # cxx_test_with_flags(name cxx_flags libs srcs...)
 #
-# creates a named C++ test that depends on the given libs and is built
+# Creates a named C++ test that depends on the given libs and is built
 # from the given source files with the given compiler flags.
 function(cxx_test_with_flags name cxx_flags libs)
   cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
@@ -260,8 +262,8 @@
 
 # cxx_test(name libs srcs...)
 #
-# creates a named test target that depends on the given libs and is
-# built from the given source files.  Unlike cxx_test_with_flags,
+# Creates a named test target that depends on the given libs and is
+# built from the given source files. Unlike cxx_test_with_flags,
 # test/name.cc is already implicitly included in the source file list.
 function(cxx_test name libs)
   cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
@@ -270,8 +272,8 @@
 
 # py_test(name)
 #
-# creates a Python test with the given name whose main module is in
-# test/name.py.  It does nothing if Python is not installed.
+# Creates a Python test with the given name whose main module is in
+# test/name.py. It does nothing if Python is not installed.
 function(py_test name)
   if (NOT Python3_Interpreter_FOUND)
     return()
@@ -307,7 +309,7 @@
       ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
       LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
     if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
-      # Install PDBs
+      # Install PDBs.
       foreach(t ${ARGN})
         get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME)
         get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG)
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-assertion-result.h b/src/third_party/googletest/googletest/include/gtest/gtest-assertion-result.h
index 56fe128..954e7c4 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-assertion-result.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-assertion-result.h
@@ -130,6 +130,13 @@
 //   Expected: Foo() is even
 //     Actual: it's 5
 //
+
+// Returned AssertionResult objects may not be ignored.
+// Note: Disabled for SWIG as it doesn't parse attributes correctly.
+#if !defined(SWIG)
+class [[nodiscard]] AssertionResult;
+#endif  // !SWIG
+
 class GTEST_API_ AssertionResult {
  public:
   // Copy constructor.
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-death-test.h b/src/third_party/googletest/googletest/include/gtest/gtest-death-test.h
index 08fef8c..3c61909 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-death-test.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-death-test.h
@@ -293,8 +293,8 @@
 //                statement is compiled but not executed, to ensure that
 //                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
 //                parameter if and only if EXPECT_DEATH compiles with it.
-//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
-//                the output of statement.  This parameter has to be
+//   regex_or_matcher -  A regex that a macro such as EXPECT_DEATH would use
+//                to test the output of statement.  This parameter has to be
 //                compiled but not evaluated by this macro, to ensure that
 //                this macro only accepts expressions that a macro such as
 //                EXPECT_DEATH would accept.
@@ -311,13 +311,13 @@
 //  statement unconditionally returns or throws. The Message constructor at
 //  the end allows the syntax of streaming additional messages into the
 //  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
-#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator)             \
+#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex_or_matcher, terminator)  \
   GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
   if (::testing::internal::AlwaysTrue()) {                                     \
     GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
                         << "Statement '" #statement "' cannot be verified.";   \
   } else if (::testing::internal::AlwaysFalse()) {                             \
-    ::testing::internal::RE::PartialMatch(".*", (regex));                      \
+    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher);               \
     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);                 \
     terminator;                                                                \
   } else                                                                       \
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-matchers.h b/src/third_party/googletest/googletest/include/gtest/gtest-matchers.h
index eae210e..78160f0 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-matchers.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-matchers.h
@@ -67,10 +67,10 @@
 // To implement a matcher Foo for type T, define:
 //   1. a class FooMatcherMatcher that implements the matcher interface:
 //     using is_gtest_matcher = void;
-//     bool MatchAndExplain(const T&, std::ostream*);
+//     bool MatchAndExplain(const T&, std::ostream*) const;
 //       (MatchResultListener* can also be used instead of std::ostream*)
-//     void DescribeTo(std::ostream*);
-//     void DescribeNegationTo(std::ostream*);
+//     void DescribeTo(std::ostream*) const;
+//     void DescribeNegationTo(std::ostream*) const;
 //
 //   2. a factory function that creates a Matcher<T> object from a
 //      FooMatcherMatcher.
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-message.h b/src/third_party/googletest/googletest/include/gtest/gtest-message.h
index 59b805e..448ac6b 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-message.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-message.h
@@ -59,7 +59,7 @@
 #ifdef GTEST_HAS_ABSL
 #include <type_traits>
 
-#include "absl/strings/internal/has_absl_stringify.h"
+#include "absl/strings/has_absl_stringify.h"
 #include "absl/strings/str_cat.h"
 #endif  // GTEST_HAS_ABSL
 
@@ -121,14 +121,14 @@
   // Streams a non-pointer value to this object. If building a version of
   // GoogleTest with ABSL, this overload is only enabled if the value does not
   // have an AbslStringify definition.
-  template <typename T
+  template <
+      typename T
 #ifdef GTEST_HAS_ABSL
-            ,
-            typename std::enable_if<
-                !absl::strings_internal::HasAbslStringify<T>::value,  // NOLINT
-                int>::type = 0
+      ,
+      typename std::enable_if<!absl::HasAbslStringify<T>::value,  // NOLINT
+                              int>::type = 0
 #endif  // GTEST_HAS_ABSL
-            >
+      >
   inline Message& operator<<(const T& val) {
         // Some libraries overload << for STL containers.  These
     // overloads are defined in the global namespace instead of ::std.
@@ -153,9 +153,8 @@
   // Streams a non-pointer value with an AbslStringify definition to this
   // object.
   template <typename T,
-            typename std::enable_if<
-                absl::strings_internal::HasAbslStringify<T>::value,  // NOLINT
-                int>::type = 0>
+            typename std::enable_if<absl::HasAbslStringify<T>::value,  // NOLINT
+                                    int>::type = 0>
   inline Message& operator<<(const T& val) {
     // ::operator<< is needed here for a similar reason as with the non-Abseil
     // version above
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-param-test.h b/src/third_party/googletest/googletest/include/gtest/gtest-param-test.h
index 49a47ea..dbfc5c8 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-param-test.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-param-test.h
@@ -178,7 +178,7 @@
 #include <utility>
 
 #include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util.h"  // IWYU pragma: export
 #include "gtest/internal/gtest-port.h"
 
 namespace testing {
@@ -469,7 +469,7 @@
               ::testing::internal::CodeLocation(__FILE__, __LINE__));          \
       return 0;                                                                \
     }                                                                          \
-    static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_;               \
+    [[maybe_unused]] static int gtest_registering_dummy_;                      \
   };                                                                           \
   int GTEST_TEST_CLASS_NAME_(test_suite_name,                                  \
                              test_name)::gtest_registering_dummy_ =            \
@@ -493,39 +493,38 @@
 #define GTEST_GET_FIRST_(first, ...) first
 #define GTEST_GET_SECOND_(first, second, ...) second
 
-#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...)               \
-  static ::testing::internal::ParamGenerator<test_suite_name::ParamType>     \
-      gtest_##prefix##test_suite_name##_EvalGenerator_() {                   \
-    return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_));       \
-  }                                                                          \
-  static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_(  \
-      const ::testing::TestParamInfo<test_suite_name::ParamType>& info) {    \
-    if (::testing::internal::AlwaysFalse()) {                                \
-      ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_(     \
-          __VA_ARGS__,                                                       \
-          ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
-          DUMMY_PARAM_)));                                                   \
-      auto t = std::make_tuple(__VA_ARGS__);                                 \
-      static_assert(std::tuple_size<decltype(t)>::value <= 2,                \
-                    "Too Many Args!");                                       \
-    }                                                                        \
-    return ((GTEST_EXPAND_(GTEST_GET_SECOND_(                                \
-        __VA_ARGS__,                                                         \
-        ::testing::internal::DefaultParamName<test_suite_name::ParamType>,   \
-        DUMMY_PARAM_))))(info);                                              \
-  }                                                                          \
-  static int gtest_##prefix##test_suite_name##_dummy_                        \
-      GTEST_ATTRIBUTE_UNUSED_ =                                              \
-          ::testing::UnitTest::GetInstance()                                 \
-              ->parameterized_test_registry()                                \
-              .GetTestSuitePatternHolder<test_suite_name>(                   \
-                  GTEST_STRINGIFY_(test_suite_name),                         \
-                  ::testing::internal::CodeLocation(__FILE__, __LINE__))     \
-              ->AddTestSuiteInstantiation(                                   \
-                  GTEST_STRINGIFY_(prefix),                                  \
-                  &gtest_##prefix##test_suite_name##_EvalGenerator_,         \
-                  &gtest_##prefix##test_suite_name##_EvalGenerateName_,      \
-                  __FILE__, __LINE__)
+#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...)                \
+  static ::testing::internal::ParamGenerator<test_suite_name::ParamType>      \
+      gtest_##prefix##test_suite_name##_EvalGenerator_() {                    \
+    return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_));        \
+  }                                                                           \
+  static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_(   \
+      const ::testing::TestParamInfo<test_suite_name::ParamType>& info) {     \
+    if (::testing::internal::AlwaysFalse()) {                                 \
+      ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_(      \
+          __VA_ARGS__,                                                        \
+          ::testing::internal::DefaultParamName<test_suite_name::ParamType>,  \
+          DUMMY_PARAM_)));                                                    \
+      auto t = std::make_tuple(__VA_ARGS__);                                  \
+      static_assert(std::tuple_size<decltype(t)>::value <= 2,                 \
+                    "Too Many Args!");                                        \
+    }                                                                         \
+    return ((GTEST_EXPAND_(GTEST_GET_SECOND_(                                 \
+        __VA_ARGS__,                                                          \
+        ::testing::internal::DefaultParamName<test_suite_name::ParamType>,    \
+        DUMMY_PARAM_))))(info);                                               \
+  }                                                                           \
+  [[maybe_unused]] static int gtest_##prefix##test_suite_name##_dummy_ =      \
+      ::testing::UnitTest::GetInstance()                                      \
+          ->parameterized_test_registry()                                     \
+          .GetTestSuitePatternHolder<test_suite_name>(                        \
+              GTEST_STRINGIFY_(test_suite_name),                              \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__))          \
+          ->AddTestSuiteInstantiation(                                        \
+              GTEST_STRINGIFY_(prefix),                                       \
+              &gtest_##prefix##test_suite_name##_EvalGenerator_,              \
+              &gtest_##prefix##test_suite_name##_EvalGenerateName_, __FILE__, \
+              __LINE__)
 
 // Allow Marking a Parameterized test class as not needing to be instantiated.
 #define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T)                  \
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-printers.h b/src/third_party/googletest/googletest/include/gtest/gtest-printers.h
index 9ccbff7..198a769 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-printers.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-printers.h
@@ -116,7 +116,7 @@
 #include <vector>
 
 #ifdef GTEST_HAS_ABSL
-#include "absl/strings/internal/has_absl_stringify.h"
+#include "absl/strings/has_absl_stringify.h"
 #include "absl/strings/str_cat.h"
 #endif  // GTEST_HAS_ABSL
 #include "gtest/internal/gtest-internal.h"
@@ -124,7 +124,11 @@
 
 #if GTEST_INTERNAL_HAS_STD_SPAN
 #include <span>  // NOLINT
-#endif  // GTEST_INTERNAL_HAS_STD_SPAN
+#endif           // GTEST_INTERNAL_HAS_STD_SPAN
+
+#if GTEST_INTERNAL_HAS_COMPARE_LIB
+#include <compare>  // NOLINT
+#endif              // GTEST_INTERNAL_HAS_COMPARE_LIB
 
 namespace testing {
 
@@ -241,8 +245,8 @@
   // ADL (possibly involving implicit conversions).
   // (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name
   // lookup properly when we do it in the template parameter list.)
-  static auto PrintValue(const T& value, ::std::ostream* os)
-      -> decltype((void)(*os << value)) {
+  static auto PrintValue(const T& value,
+                         ::std::ostream* os) -> decltype((void)(*os << value)) {
     // Call streaming operator found by ADL, possibly with implicit conversions
     // of the arguments.
     *os << value;
@@ -292,10 +296,9 @@
 
 #ifdef GTEST_HAS_ABSL
 struct ConvertibleToAbslStringifyPrinter {
-  template <
-      typename T,
-      typename = typename std::enable_if<
-          absl::strings_internal::HasAbslStringify<T>::value>::type>  // NOLINT
+  template <typename T,
+            typename = typename std::enable_if<
+                absl::HasAbslStringify<T>::value>::type>  // NOLINT
   static void PrintValue(const T& value, ::std::ostream* os) {
     *os << absl::StrCat(value);
   }
@@ -553,49 +556,63 @@
   int full = std::numeric_limits<FloatType>::max_digits10;
   if (val < 0) val = -val;
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
   if (val < 1000000) {
     FloatType mulfor6 = 1e10;
-    if (val >= 100000.0) {  // 100,000 to 999,999
+    // Without these static casts, the template instantiation for float would
+    // fail to compile when -Wdouble-promotion is enabled, as the arithmetic and
+    // comparison logic would promote floats to doubles.
+    if (val >= static_cast<FloatType>(100000.0)) {  // 100,000 to 999,999
       mulfor6 = 1.0;
-    } else if (val >= 10000.0) {
+    } else if (val >= static_cast<FloatType>(10000.0)) {
       mulfor6 = 1e1;
-    } else if (val >= 1000.0) {
+    } else if (val >= static_cast<FloatType>(1000.0)) {
       mulfor6 = 1e2;
-    } else if (val >= 100.0) {
+    } else if (val >= static_cast<FloatType>(100.0)) {
       mulfor6 = 1e3;
-    } else if (val >= 10.0) {
+    } else if (val >= static_cast<FloatType>(10.0)) {
       mulfor6 = 1e4;
-    } else if (val >= 1.0) {
+    } else if (val >= static_cast<FloatType>(1.0)) {
       mulfor6 = 1e5;
-    } else if (val >= 0.1) {
+    } else if (val >= static_cast<FloatType>(0.1)) {
       mulfor6 = 1e6;
-    } else if (val >= 0.01) {
+    } else if (val >= static_cast<FloatType>(0.01)) {
       mulfor6 = 1e7;
-    } else if (val >= 0.001) {
+    } else if (val >= static_cast<FloatType>(0.001)) {
       mulfor6 = 1e8;
-    } else if (val >= 0.0001) {
+    } else if (val >= static_cast<FloatType>(0.0001)) {
       mulfor6 = 1e9;
     }
-    if (static_cast<FloatType>(static_cast<int32_t>(val * mulfor6 + 0.5)) /
+    if (static_cast<FloatType>(static_cast<int32_t>(
+            val * mulfor6 + (static_cast<FloatType>(0.5)))) /
             mulfor6 ==
         val)
       return 6;
-  } else if (val < 1e10) {
-    FloatType divfor6 = 1.0;
-    if (val >= 1e9) {  // 1,000,000,000 to 9,999,999,999
+  } else if (val < static_cast<FloatType>(1e10)) {
+    FloatType divfor6 = static_cast<FloatType>(1.0);
+    if (val >= static_cast<FloatType>(1e9)) {  // 1,000,000,000 to 9,999,999,999
       divfor6 = 10000;
-    } else if (val >= 1e8) {  // 100,000,000 to 999,999,999
+    } else if (val >=
+               static_cast<FloatType>(1e8)) {  // 100,000,000 to 999,999,999
       divfor6 = 1000;
-    } else if (val >= 1e7) {  // 10,000,000 to 99,999,999
+    } else if (val >=
+               static_cast<FloatType>(1e7)) {  // 10,000,000 to 99,999,999
       divfor6 = 100;
-    } else if (val >= 1e6) {  // 1,000,000 to 9,999,999
+    } else if (val >= static_cast<FloatType>(1e6)) {  // 1,000,000 to 9,999,999
       divfor6 = 10;
     }
-    if (static_cast<FloatType>(static_cast<int32_t>(val / divfor6 + 0.5)) *
+    if (static_cast<FloatType>(static_cast<int32_t>(
+            val / divfor6 + (static_cast<FloatType>(0.5)))) *
             divfor6 ==
         val)
       return 6;
   }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
   return full;
 }
 
@@ -769,6 +786,41 @@
   (PrintSmartPointer<T>)(ptr, os, 0);
 }
 
+#if GTEST_INTERNAL_HAS_COMPARE_LIB
+template <typename T>
+void PrintOrderingHelper(T ordering, std::ostream* os) {
+  if (ordering == T::less) {
+    *os << "(less)";
+  } else if (ordering == T::greater) {
+    *os << "(greater)";
+  } else if (ordering == T::equivalent) {
+    *os << "(equivalent)";
+  } else {
+    *os << "(unknown ordering)";
+  }
+}
+
+inline void PrintTo(std::strong_ordering ordering, std::ostream* os) {
+  if (ordering == std::strong_ordering::equal) {
+    *os << "(equal)";
+  } else {
+    PrintOrderingHelper(ordering, os);
+  }
+}
+
+inline void PrintTo(std::partial_ordering ordering, std::ostream* os) {
+  if (ordering == std::partial_ordering::unordered) {
+    *os << "(unordered)";
+  } else {
+    PrintOrderingHelper(ordering, os);
+  }
+}
+
+inline void PrintTo(std::weak_ordering ordering, std::ostream* os) {
+  PrintOrderingHelper(ordering, os);
+}
+#endif
+
 // Helper function for printing a tuple.  T must be instantiated with
 // a tuple type.
 template <typename T>
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest-typed-test.h b/src/third_party/googletest/googletest/include/gtest/gtest-typed-test.h
index 72de536..442e00b 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest-typed-test.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest-typed-test.h
@@ -205,8 +205,8 @@
     typedef gtest_TypeParam_ TypeParam;                                       \
     void TestBody() override;                                                 \
   };                                                                          \
-  static bool gtest_##CaseName##_##TestName##_registered_                     \
-      GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest<   \
+  [[maybe_unused]] static bool gtest_##CaseName##_##TestName##_registered_ =  \
+      ::testing::internal::TypeParameterizedTest<                             \
           CaseName,                                                           \
           ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName,   \
                                                                   TestName)>, \
@@ -267,22 +267,22 @@
   TYPED_TEST_SUITE_P
 #endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
 
-#define TYPED_TEST_P(SuiteName, TestName)                           \
-  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                     \
-  template <typename gtest_TypeParam_>                              \
-  class TestName : public SuiteName<gtest_TypeParam_> {             \
-   private:                                                         \
-    typedef SuiteName<gtest_TypeParam_> TestFixture;                \
-    typedef gtest_TypeParam_ TypeParam;                             \
-    void TestBody() override;                                       \
-  };                                                                \
-  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
-      GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName(       \
-          __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName),          \
-          GTEST_STRINGIFY_(TestName));                              \
-  }                                                                 \
-  template <typename gtest_TypeParam_>                              \
-  void GTEST_SUITE_NAMESPACE_(                                      \
+#define TYPED_TEST_P(SuiteName, TestName)                     \
+  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {               \
+  template <typename gtest_TypeParam_>                        \
+  class TestName : public SuiteName<gtest_TypeParam_> {       \
+   private:                                                   \
+    typedef SuiteName<gtest_TypeParam_> TestFixture;          \
+    typedef gtest_TypeParam_ TypeParam;                       \
+    void TestBody() override;                                 \
+  };                                                          \
+  [[maybe_unused]] static bool gtest_##TestName##_defined_ =  \
+      GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
+          __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName),    \
+          GTEST_STRINGIFY_(TestName));                        \
+  }                                                           \
+  template <typename gtest_TypeParam_>                        \
+  void GTEST_SUITE_NAMESPACE_(                                \
       SuiteName)::TestName<gtest_TypeParam_>::TestBody()
 
 // Note: this won't work correctly if the trailing arguments are macros.
@@ -290,8 +290,8 @@
   namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                             \
   typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_;      \
   }                                                                         \
-  static const char* const GTEST_REGISTERED_TEST_NAMES_(                    \
-      SuiteName) GTEST_ATTRIBUTE_UNUSED_ =                                  \
+  [[maybe_unused]] static const char* const GTEST_REGISTERED_TEST_NAMES_(   \
+      SuiteName) =                                                          \
       GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
           GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
 
@@ -306,7 +306,7 @@
 #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...)     \
   static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1,                     \
                 "test-suit-prefix must not be empty");                    \
-  static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ =      \
+  [[maybe_unused]] static bool gtest_##Prefix##_##SuiteName =             \
       ::testing::internal::TypeParameterizedTestSuite<                    \
           SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_,  \
           ::testing::internal::GenerateTypeList<Types>::type>::           \
diff --git a/src/third_party/googletest/googletest/include/gtest/gtest.h b/src/third_party/googletest/googletest/include/gtest/gtest.h
index a932e68..7be0caa 100644
--- a/src/third_party/googletest/googletest/include/gtest/gtest.h
+++ b/src/third_party/googletest/googletest/include/gtest/gtest.h
@@ -60,16 +60,16 @@
 #include <type_traits>
 #include <vector>
 
-#include "gtest/gtest-assertion-result.h"
-#include "gtest/gtest-death-test.h"
-#include "gtest/gtest-matchers.h"
-#include "gtest/gtest-message.h"
-#include "gtest/gtest-param-test.h"
-#include "gtest/gtest-printers.h"
-#include "gtest/gtest-test-part.h"
-#include "gtest/gtest-typed-test.h"
-#include "gtest/gtest_pred_impl.h"
-#include "gtest/gtest_prod.h"
+#include "gtest/gtest-assertion-result.h"  // IWYU pragma: export
+#include "gtest/gtest-death-test.h"  // IWYU pragma: export
+#include "gtest/gtest-matchers.h"  // IWYU pragma: export
+#include "gtest/gtest-message.h"  // IWYU pragma: export
+#include "gtest/gtest-param-test.h"  // IWYU pragma: export
+#include "gtest/gtest-printers.h"  // IWYU pragma: export
+#include "gtest/gtest-test-part.h"  // IWYU pragma: export
+#include "gtest/gtest-typed-test.h"  // IWYU pragma: export
+#include "gtest/gtest_pred_impl.h"  // IWYU pragma: export
+#include "gtest/gtest_prod.h"  // IWYU pragma: export
 #include "gtest/internal/gtest-internal.h"
 #include "gtest/internal/gtest-string.h"
 
@@ -607,7 +607,7 @@
   friend class internal::UnitTestImpl;
   friend class internal::StreamingListenerTest;
   friend TestInfo* internal::MakeAndRegisterTestInfo(
-      const char* test_suite_name, const char* name, const char* type_param,
+      std::string test_suite_name, const char* name, const char* type_param,
       const char* value_param, internal::CodeLocation code_location,
       internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
       internal::TearDownTestSuiteFunc tear_down_tc,
@@ -615,7 +615,7 @@
 
   // Constructs a TestInfo object. The newly constructed instance assumes
   // ownership of the factory object.
-  TestInfo(const std::string& test_suite_name, const std::string& name,
+  TestInfo(std::string test_suite_name, std::string name,
            const char* a_type_param,   // NULL if not a type-parameterized test
            const char* a_value_param,  // NULL if not a value-parameterized test
            internal::CodeLocation a_code_location,
@@ -683,7 +683,7 @@
   //                 this is not a type-parameterized test.
   //   set_up_tc:    pointer to the function that sets up the test suite
   //   tear_down_tc: pointer to the function that tears down the test suite
-  TestSuite(const char* name, const char* a_type_param,
+  TestSuite(const std::string& name, const char* a_type_param,
             internal::SetUpTestSuiteFunc set_up_tc,
             internal::TearDownTestSuiteFunc tear_down_tc);
 
@@ -1123,7 +1123,7 @@
   // This method can only be called from the main thread.
   //
   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-  int Run() GTEST_MUST_USE_RESULT_;
+  [[nodiscard]] int Run();
 
   // Returns the working directory when the first TEST() or TEST_F()
   // was executed.  The UnitTest object owns the string.
@@ -1262,6 +1262,20 @@
   // total_test_suite_count() - 1. If i is not in that range, returns NULL.
   TestSuite* GetMutableTestSuite(int i);
 
+  // Invokes OsStackTrackGetterInterface::UponLeavingGTest. UponLeavingGTest()
+  // should be called immediately before Google Test calls user code. It saves
+  // some information about the current stack that CurrentStackTrace() will use
+  // to find and hide Google Test stack frames.
+  void UponLeavingGTest();
+
+  // Sets the TestSuite object for the test that's currently running.
+  void set_current_test_suite(TestSuite* a_current_test_suite)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Sets the TestInfo object for the test that's currently running.
+  void set_current_test_info(TestInfo* a_current_test_info)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
   // Accessors for the implementation object.
   internal::UnitTestImpl* impl() { return impl_; }
   const internal::UnitTestImpl* impl() const { return impl_; }
@@ -1270,6 +1284,8 @@
   // members of UnitTest.
   friend class ScopedTrace;
   friend class Test;
+  friend class TestInfo;
+  friend class TestSuite;
   friend class internal::AssertHelper;
   friend class internal::StreamingListenerTest;
   friend class internal::UnitTestRecordPropertyTestHelper;
@@ -1751,6 +1767,7 @@
 // generic name and clashes with some other libraries.
 #if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
 #define FAIL() GTEST_FAIL()
+#define FAIL_AT(file, line) GTEST_FAIL_AT(file, line)
 #endif
 
 // Generates a success with a generic message.
@@ -2307,11 +2324,12 @@
 // tests are successful, or 1 otherwise.
 //
 // RUN_ALL_TESTS() should be invoked after the command line has been
-// parsed by InitGoogleTest().
+// parsed by InitGoogleTest(). RUN_ALL_TESTS will tear down and delete any
+// installed environments and should only be called once per binary.
 //
 // This function was formerly a macro; thus, it is in the global
 // namespace and has an all-caps name.
-int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+[[nodiscard]] int RUN_ALL_TESTS();
 
 inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
 
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
index 8e9c988..b363259 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -46,17 +46,38 @@
 
 #include "gtest/gtest-matchers.h"
 #include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
 
 GTEST_DECLARE_string_(internal_run_death_test);
 
 namespace testing {
 namespace internal {
 
-// Names of the flags (needed for parsing Google Test flags).
-const char kDeathTestStyleFlag[] = "death_test_style";
-const char kDeathTestUseFork[] = "death_test_use_fork";
+// Name of the flag (needed for parsing Google Test flag).
 const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
 
+// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
+// and interpreted as a regex (rather than an Eq matcher) for legacy
+// compatibility.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    ::testing::internal::RE regex) {
+  return ContainsRegex(regex.pattern());
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
+  return ContainsRegex(regex);
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    const ::std::string& regex) {
+  return ContainsRegex(regex);
+}
+
+// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
+// used directly.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    Matcher<const ::std::string&> matcher) {
+  return matcher;
+}
+
 #ifdef GTEST_HAS_DEATH_TEST
 
 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
@@ -73,7 +94,7 @@
 //
 // exit status:  The integer exit information in the format specified
 //               by wait(2)
-// exit code:    The integer code passed to exit(3), _exit(2), or
+// exit code:    The integer code passed to exit(3), _Exit(2), or
 //               returned from main()
 class GTEST_API_ DeathTest {
  public:
@@ -170,28 +191,6 @@
 // by a signal, or exited normally with a nonzero exit code.
 GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
 
-// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
-// and interpreted as a regex (rather than an Eq matcher) for legacy
-// compatibility.
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
-    ::testing::internal::RE regex) {
-  return ContainsRegex(regex.pattern());
-}
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
-  return ContainsRegex(regex);
-}
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
-    const ::std::string& regex) {
-  return ContainsRegex(regex);
-}
-
-// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
-// used directly.
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
-    Matcher<const ::std::string&> matcher) {
-  return matcher;
-}
-
 // Traps C++ exceptions escaping statement and reports them as test
 // failures. Note that trapping SEH exceptions is not implemented here.
 #if GTEST_HAS_EXCEPTIONS
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h
index 5189c81..6dc47be 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h
@@ -43,6 +43,7 @@
 #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
 
 #include <string>
+#include <utility>
 
 #include "gtest/internal/gtest-port.h"
 #include "gtest/internal/gtest-string.h"
@@ -70,8 +71,9 @@
  public:
   FilePath() : pathname_("") {}
   FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
+  FilePath(FilePath&& rhs) noexcept : pathname_(std::move(rhs.pathname_)) {}
 
-  explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+  explicit FilePath(std::string pathname) : pathname_(std::move(pathname)) {
     Normalize();
   }
 
@@ -79,6 +81,10 @@
     Set(rhs);
     return *this;
   }
+  FilePath& operator=(FilePath&& rhs) noexcept {
+    pathname_ = std::move(rhs.pathname_);
+    return *this;
+  }
 
   void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }
 
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h
index 4f077fc..dcab397 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h
@@ -474,8 +474,8 @@
 using TearDownTestSuiteFunc = void (*)();
 
 struct CodeLocation {
-  CodeLocation(const std::string& a_file, int a_line)
-      : file(a_file), line(a_line) {}
+  CodeLocation(std::string a_file, int a_line)
+      : file(std::move(a_file)), line(a_line) {}
 
   std::string file;
   int line;
@@ -555,7 +555,7 @@
 //   type_param:       the name of the test's type parameter, or NULL if
 //                     this is not a typed or a type-parameterized test.
 //   value_param:      text representation of the test's value parameter,
-//                     or NULL if this is not a type-parameterized test.
+//                     or NULL if this is not a value-parameterized test.
 //   code_location:    code location where the test is defined
 //   fixture_class_id: ID of the test fixture class
 //   set_up_tc:        pointer to the function that sets up the test suite
@@ -564,7 +564,7 @@
 //                     The newly created TestInfo instance will assume
 //                     ownership of the factory object.
 GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
-    const char* test_suite_name, const char* name, const char* type_param,
+    std::string test_suite_name, const char* name, const char* type_param,
     const char* value_param, CodeLocation code_location,
     TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
     TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
@@ -595,8 +595,7 @@
       fflush(stderr);
       posix::Abort();
     }
-    registered_tests_.insert(
-        ::std::make_pair(test_name, CodeLocation(file, line)));
+    registered_tests_.emplace(test_name, CodeLocation(file, line));
     return true;
   }
 
@@ -700,7 +699,7 @@
   // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
   // Types).  Valid values for 'index' are [0, N - 1] where N is the
   // length of Types.
-  static bool Register(const char* prefix, const CodeLocation& code_location,
+  static bool Register(const char* prefix, CodeLocation code_location,
                        const char* case_name, const char* test_names, int index,
                        const std::vector<std::string>& type_names =
                            GenerateNames<DefaultNameGenerator, Types>()) {
@@ -712,8 +711,7 @@
     // list.
     MakeAndRegisterTestInfo(
         (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
-         "/" + type_names[static_cast<size_t>(index)])
-            .c_str(),
+         "/" + type_names[static_cast<size_t>(index)]),
         StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
         GetTypeName<Type>().c_str(),
         nullptr,  // No value parameter.
@@ -725,13 +723,9 @@
         new TestFactoryImpl<TestClass>);
 
     // Next, recurses (at compile time) with the tail of the type list.
-    return TypeParameterizedTest<Fixture, TestSel,
-                                 typename Types::Tail>::Register(prefix,
-                                                                 code_location,
-                                                                 case_name,
-                                                                 test_names,
-                                                                 index + 1,
-                                                                 type_names);
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>::
+        Register(prefix, std::move(code_location), case_name, test_names,
+                 index + 1, type_names);
   }
 };
 
@@ -739,7 +733,7 @@
 template <GTEST_TEMPLATE_ Fixture, class TestSel>
 class TypeParameterizedTest<Fixture, TestSel, internal::None> {
  public:
-  static bool Register(const char* /*prefix*/, const CodeLocation&,
+  static bool Register(const char* /*prefix*/, CodeLocation,
                        const char* /*case_name*/, const char* /*test_names*/,
                        int /*index*/,
                        const std::vector<std::string>& =
@@ -786,7 +780,8 @@
 
     // Next, recurses (at compile time) with the tail of the test list.
     return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
-                                      Types>::Register(prefix, code_location,
+                                      Types>::Register(prefix,
+                                                       std::move(code_location),
                                                        state, case_name,
                                                        SkipComma(test_names),
                                                        type_names);
@@ -899,11 +894,6 @@
       HasDebugStringType::value && HasShortDebugStringType::value;
 };
 
-#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename T>
-constexpr bool HasDebugStringAndShortDebugString<T>::value;
-#endif
-
 // When the compiler sees expression IsContainerTest<C>(0), if C is an
 // STL-style container class, the first overload of IsContainerTest
 // will be viable (since both C::iterator* and C::const_iterator* are
@@ -1142,40 +1132,6 @@
   void (NativeArray::*clone_)(const Element*, size_t);
 };
 
-// Backport of std::index_sequence.
-template <size_t... Is>
-struct IndexSequence {
-  using type = IndexSequence;
-};
-
-// Double the IndexSequence, and one if plus_one is true.
-template <bool plus_one, typename T, size_t sizeofT>
-struct DoubleSequence;
-template <size_t... I, size_t sizeofT>
-struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
-  using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
-};
-template <size_t... I, size_t sizeofT>
-struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
-  using type = IndexSequence<I..., (sizeofT + I)...>;
-};
-
-// Backport of std::make_index_sequence.
-// It uses O(ln(N)) instantiation depth.
-template <size_t N>
-struct MakeIndexSequenceImpl
-    : DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type,
-                     N / 2>::type {};
-
-template <>
-struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
-
-template <size_t N>
-using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type;
-
-template <typename... T>
-using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type;
-
 template <size_t>
 struct Ignore {
   Ignore(...);  // NOLINT
@@ -1184,7 +1140,7 @@
 template <typename>
 struct ElemFromListImpl;
 template <size_t... I>
-struct ElemFromListImpl<IndexSequence<I...>> {
+struct ElemFromListImpl<std::index_sequence<I...>> {
   // We make Ignore a template to solve a problem with MSVC.
   // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
   // MSVC doesn't understand how to deal with that pack expansion.
@@ -1195,9 +1151,8 @@
 
 template <size_t N, typename... T>
 struct ElemFromList {
-  using type =
-      decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
-          static_cast<T (*)()>(nullptr)...));
+  using type = decltype(ElemFromListImpl<std::make_index_sequence<N>>::Apply(
+      static_cast<T (*)()>(nullptr)...));
 };
 
 struct FlatTupleConstructTag {};
@@ -1222,9 +1177,9 @@
 struct FlatTupleBase;
 
 template <size_t... Idx, typename... T>
-struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
+struct FlatTupleBase<FlatTuple<T...>, std::index_sequence<Idx...>>
     : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
-  using Indices = IndexSequence<Idx...>;
+  using Indices = std::index_sequence<Idx...>;
   FlatTupleBase() = default;
   template <typename... Args>
   explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
@@ -1259,14 +1214,15 @@
 // implementations.
 // FlatTuple and ElemFromList are not recursive and have a fixed depth
 // regardless of T...
-// MakeIndexSequence, on the other hand, it is recursive but with an
+// std::make_index_sequence, on the other hand, it is recursive but with an
 // instantiation depth of O(ln(N)).
 template <typename... T>
 class FlatTuple
     : private FlatTupleBase<FlatTuple<T...>,
-                            typename MakeIndexSequence<sizeof...(T)>::type> {
-  using Indices = typename FlatTupleBase<
-      FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices;
+                            std::make_index_sequence<sizeof...(T)>> {
+  using Indices =
+      typename FlatTupleBase<FlatTuple<T...>,
+                             std::make_index_sequence<sizeof...(T)>>::Indices;
 
  public:
   FlatTuple() = default;
@@ -1280,30 +1236,40 @@
 
 // Utility functions to be called with static_assert to induce deprecation
 // warnings.
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
     "INSTANTIATE_TEST_CASE_P is deprecated, please use "
-    "INSTANTIATE_TEST_SUITE_P")
-constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
+    "INSTANTIATE_TEST_SUITE_P")]]
+constexpr bool InstantiateTestCase_P_IsDeprecated() {
+  return true;
+}
 
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
     "TYPED_TEST_CASE_P is deprecated, please use "
-    "TYPED_TEST_SUITE_P")
-constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
+    "TYPED_TEST_SUITE_P")]]
+constexpr bool TypedTestCase_P_IsDeprecated() {
+  return true;
+}
 
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
     "TYPED_TEST_CASE is deprecated, please use "
-    "TYPED_TEST_SUITE")
-constexpr bool TypedTestCaseIsDeprecated() { return true; }
+    "TYPED_TEST_SUITE")]]
+constexpr bool TypedTestCaseIsDeprecated() {
+  return true;
+}
 
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
     "REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
-    "REGISTER_TYPED_TEST_SUITE_P")
-constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
+    "REGISTER_TYPED_TEST_SUITE_P")]]
+constexpr bool RegisterTypedTestCase_P_IsDeprecated() {
+  return true;
+}
 
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
     "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
-    "INSTANTIATE_TYPED_TEST_SUITE_P")
-constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
+    "INSTANTIATE_TYPED_TEST_SUITE_P")]]
+constexpr bool InstantiateTypedTestCase_P_IsDeprecated() {
+  return true;
+}
 
 }  // namespace internal
 }  // namespace testing
@@ -1540,7 +1506,7 @@
                                                                                \
    private:                                                                    \
     void TestBody() override;                                                  \
-    static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;      \
+    [[maybe_unused]] static ::testing::TestInfo* const test_info_;             \
   };                                                                           \
                                                                                \
   ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,           \
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h
index dd39e98..cc7ea53 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h
@@ -47,6 +47,7 @@
 #include <string>
 #include <tuple>
 #include <type_traits>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -85,7 +86,7 @@
 // TEST_P macro is used to define two tests with the same name
 // but in different namespaces.
 GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
-                                           CodeLocation code_location);
+                                           const CodeLocation& code_location);
 
 template <typename>
 class ParamGeneratorInterface;
@@ -379,9 +380,7 @@
 // integer test parameter index.
 template <class ParamType>
 std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
-  Message name_stream;
-  name_stream << info.index;
-  return name_stream.GetString();
+  return std::to_string(info.index);
 }
 
 template <typename T = int>
@@ -513,9 +512,10 @@
   typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
   using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
 
-  explicit ParameterizedTestSuiteInfo(const char* name,
+  explicit ParameterizedTestSuiteInfo(std::string name,
                                       CodeLocation code_location)
-      : test_suite_name_(name), code_location_(code_location) {}
+      : test_suite_name_(std::move(name)),
+        code_location_(std::move(code_location)) {}
 
   // Test suite base name for display purposes.
   const std::string& GetTestSuiteName() const override {
@@ -529,20 +529,21 @@
   // prefix). test_base_name is the name of an individual test without
   // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
   // test suite base name and DoBar is test base name.
-  void AddTestPattern(const char* test_suite_name, const char* test_base_name,
+  void AddTestPattern(const char*,
+                      const char* test_base_name,
                       TestMetaFactoryBase<ParamType>* meta_factory,
                       CodeLocation code_location) {
-    tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
-        test_suite_name, test_base_name, meta_factory, code_location)));
+    tests_.emplace_back(
+        new TestInfo(test_base_name, meta_factory, std::move(code_location)));
   }
   // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
   // about a generator.
-  int AddTestSuiteInstantiation(const std::string& instantiation_name,
+  int AddTestSuiteInstantiation(std::string instantiation_name,
                                 GeneratorCreationFunc* func,
                                 ParamNameGeneratorFunc* name_func,
                                 const char* file, int line) {
-    instantiations_.push_back(
-        InstantiationInfo(instantiation_name, func, name_func, file, line));
+    instantiations_.emplace_back(std::move(instantiation_name), func, name_func,
+                                 file, line);
     return 0;  // Return value used only to run this method in namespace scope.
   }
   // UnitTest class invokes this method to register tests in this test suite
@@ -553,62 +554,61 @@
   void RegisterTests() override {
     bool generated_instantiations = false;
 
-    for (typename TestInfoContainer::iterator test_it = tests_.begin();
-         test_it != tests_.end(); ++test_it) {
-      std::shared_ptr<TestInfo> test_info = *test_it;
-      for (typename InstantiationContainer::iterator gen_it =
-               instantiations_.begin();
-           gen_it != instantiations_.end(); ++gen_it) {
-        const std::string& instantiation_name = gen_it->name;
-        ParamGenerator<ParamType> generator((*gen_it->generator)());
-        ParamNameGeneratorFunc* name_func = gen_it->name_func;
-        const char* file = gen_it->file;
-        int line = gen_it->line;
+    std::string test_suite_name;
+    std::string test_name;
+    for (const std::shared_ptr<TestInfo>& test_info : tests_) {
+      for (const InstantiationInfo& instantiation : instantiations_) {
+        const std::string& instantiation_name = instantiation.name;
+        ParamGenerator<ParamType> generator((*instantiation.generator)());
+        ParamNameGeneratorFunc* name_func = instantiation.name_func;
+        const char* file = instantiation.file;
+        int line = instantiation.line;
 
-        std::string test_suite_name;
         if (!instantiation_name.empty())
           test_suite_name = instantiation_name + "/";
-        test_suite_name += test_info->test_suite_base_name;
+        else
+          test_suite_name.clear();
+        test_suite_name += test_suite_name_;
 
         size_t i = 0;
         std::set<std::string> test_param_names;
-        for (typename ParamGenerator<ParamType>::iterator param_it =
-                 generator.begin();
-             param_it != generator.end(); ++param_it, ++i) {
+        for (const auto& param : generator) {
           generated_instantiations = true;
 
-          Message test_name_stream;
+          test_name.clear();
 
           std::string param_name =
-              name_func(TestParamInfo<ParamType>(*param_it, i));
+              name_func(TestParamInfo<ParamType>(param, i));
 
           GTEST_CHECK_(IsValidParamName(param_name))
               << "Parameterized test name '" << param_name
-              << "' is invalid (contains spaces, dashes, underscores, or "
-                 "non-alphanumeric characters), in "
+              << "' is invalid (contains spaces, dashes, or any "
+                 "non-alphanumeric characters other than underscores), in "
               << file << " line " << line << "" << std::endl;
 
           GTEST_CHECK_(test_param_names.count(param_name) == 0)
               << "Duplicate parameterized test name '" << param_name << "', in "
               << file << " line " << line << std::endl;
 
-          test_param_names.insert(param_name);
-
           if (!test_info->test_base_name.empty()) {
-            test_name_stream << test_info->test_base_name << "/";
+            test_name.append(test_info->test_base_name).append("/");
           }
-          test_name_stream << param_name;
+          test_name += param_name;
+
+          test_param_names.insert(std::move(param_name));
+
           MakeAndRegisterTestInfo(
-              test_suite_name.c_str(), test_name_stream.GetString().c_str(),
+              test_suite_name, test_name.c_str(),
               nullptr,  // No type parameter.
-              PrintToString(*param_it).c_str(), test_info->code_location,
+              PrintToString(param).c_str(), test_info->code_location,
               GetTestSuiteTypeId(),
               SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
               SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
-              test_info->test_meta_factory->CreateTestFactory(*param_it));
-        }  // for param_it
-      }    // for gen_it
-    }      // for test_it
+              test_info->test_meta_factory->CreateTestFactory(param));
+          ++i;
+        }  // for param
+      }  // for instantiation
+    }  // for test_info
 
     if (!generated_instantiations) {
       // There are no generaotrs, or they all generate nothing ...
@@ -621,15 +621,13 @@
   // LocalTestInfo structure keeps information about a single test registered
   // with TEST_P macro.
   struct TestInfo {
-    TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
+    TestInfo(const char* a_test_base_name,
              TestMetaFactoryBase<ParamType>* a_test_meta_factory,
              CodeLocation a_code_location)
-        : test_suite_base_name(a_test_suite_base_name),
-          test_base_name(a_test_base_name),
+        : test_base_name(a_test_base_name),
           test_meta_factory(a_test_meta_factory),
-          code_location(a_code_location) {}
+          code_location(std::move(a_code_location)) {}
 
-    const std::string test_suite_base_name;
     const std::string test_base_name;
     const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
     const CodeLocation code_location;
@@ -639,11 +637,10 @@
   //  <Instantiation name, Sequence generator creation function,
   //     Name generator function, Source file, Source line>
   struct InstantiationInfo {
-    InstantiationInfo(const std::string& name_in,
-                      GeneratorCreationFunc* generator_in,
+    InstantiationInfo(std::string name_in, GeneratorCreationFunc* generator_in,
                       ParamNameGeneratorFunc* name_func_in, const char* file_in,
                       int line_in)
-        : name(name_in),
+        : name(std::move(name_in)),
           generator(generator_in),
           name_func(name_func_in),
           file(file_in),
@@ -704,29 +701,32 @@
   // tests and instantiations of a particular test suite.
   template <class TestSuite>
   ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
-      const char* test_suite_name, CodeLocation code_location) {
+      std::string test_suite_name, CodeLocation code_location) {
     ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
-    for (auto& test_suite_info : test_suite_infos_) {
-      if (test_suite_info->GetTestSuiteName() == test_suite_name) {
-        if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
-          // Complain about incorrect usage of Google Test facilities
-          // and terminate the program since we cannot guaranty correct
-          // test suite setup and tear-down in this case.
-          ReportInvalidTestSuiteType(test_suite_name, code_location);
-          posix::Abort();
-        } else {
-          // At this point we are sure that the object we found is of the same
-          // type we are looking for, so we downcast it to that type
-          // without further checks.
-          typed_test_info = CheckedDowncastToActualType<
-              ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info);
-        }
-        break;
+
+    auto item_it = suite_name_to_info_index_.find(test_suite_name);
+    if (item_it != suite_name_to_info_index_.end()) {
+      auto* test_suite_info = test_suite_infos_[item_it->second];
+      if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
+        // Complain about incorrect usage of Google Test facilities
+        // and terminate the program since we cannot guaranty correct
+        // test suite setup and tear-down in this case.
+        ReportInvalidTestSuiteType(test_suite_name.c_str(), code_location);
+        posix::Abort();
+      } else {
+        // At this point we are sure that the object we found is of the same
+        // type we are looking for, so we downcast it to that type
+        // without further checks.
+        typed_test_info =
+            CheckedDowncastToActualType<ParameterizedTestSuiteInfo<TestSuite>>(
+                test_suite_info);
       }
     }
     if (typed_test_info == nullptr) {
       typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
-          test_suite_name, code_location);
+          test_suite_name, std::move(code_location));
+      suite_name_to_info_index_.emplace(std::move(test_suite_name),
+                                        test_suite_infos_.size());
       test_suite_infos_.push_back(typed_test_info);
     }
     return typed_test_info;
@@ -740,8 +740,9 @@
 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
   template <class TestCase>
   ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
-      const char* test_case_name, CodeLocation code_location) {
-    return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
+      std::string test_case_name, CodeLocation code_location) {
+    return GetTestSuitePatternHolder<TestCase>(std::move(test_case_name),
+                                               std::move(code_location));
   }
 
 #endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
@@ -750,6 +751,7 @@
   using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
 
   TestSuiteInfoContainer test_suite_infos_;
+  ::std::unordered_map<std::string, size_t> suite_name_to_info_index_;
 
   ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
       delete;
@@ -776,7 +778,7 @@
  private:
   struct TypeParameterizedTestSuiteInfo {
     explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
-        : code_location(c), instantiated(false) {}
+        : code_location(std::move(c)), instantiated(false) {}
 
     CodeLocation code_location;
     bool instantiated;
@@ -805,12 +807,12 @@
 
   template <typename T>
   operator ParamGenerator<T>() const {  // NOLINT
-    return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
+    return ValuesIn(MakeVector<T>(std::make_index_sequence<sizeof...(Ts)>()));
   }
 
  private:
   template <typename T, size_t... I>
-  std::vector<T> MakeVector(IndexSequence<I...>) const {
+  std::vector<T> MakeVector(std::index_sequence<I...>) const {
     return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
   }
 
@@ -840,7 +842,7 @@
   template <class I>
   class IteratorImpl;
   template <size_t... I>
-  class IteratorImpl<IndexSequence<I...>>
+  class IteratorImpl<std::index_sequence<I...>>
       : public ParamIteratorInterface<ParamType> {
    public:
     IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
@@ -931,7 +933,7 @@
     std::shared_ptr<ParamType> current_value_;
   };
 
-  using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
+  using Iterator = IteratorImpl<std::make_index_sequence<sizeof...(T)>>;
 
   std::tuple<ParamGenerator<T>...> generators_;
 };
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
index 3162f2b..7ec968f 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
@@ -56,6 +56,8 @@
 #elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
 #define GTEST_OS_WINDOWS_PHONE 1
 #define GTEST_OS_WINDOWS_TV_TITLE 1
+#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES)
+#define GTEST_OS_WINDOWS_GAMES 1
 #else
 // WINAPI_FAMILY defined but no known partition matched.
 // Default to desktop.
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-port.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-port.h
index 35544a0..4cfc16c 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-port.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-port.h
@@ -194,9 +194,6 @@
 //
 // Macros for basic C++ coding:
 //   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
-//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
-//                              variable don't have to be used.
-//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
 //   GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
 //                                        suppressed (constant conditional).
 //   GTEST_INTENTIONAL_CONST_COND_POP_  - finish code section where MSVC C4127
@@ -262,11 +259,6 @@
 //   BoolFromGTestEnv()   - parses a bool environment variable.
 //   Int32FromGTestEnv()  - parses an int32_t environment variable.
 //   StringFromGTestEnv() - parses a string environment variable.
-//
-// Deprecation warnings:
-//   GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
-//                                        deprecated; calling a marked function
-//                                        should generate a compiler warning
 
 // The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
 // potentially be used as an #include guard.
@@ -277,8 +269,24 @@
 #endif
 
 #if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
-    GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
-#error C++ versions less than C++14 are not supported.
+    GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
+#error C++ versions less than C++17 are not supported.
+#endif
+
+// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
+#ifdef __has_include
+#define GTEST_INTERNAL_HAS_INCLUDE __has_include
+#else
+#define GTEST_INTERNAL_HAS_INCLUDE(...) 0
+#endif
+
+// Detect C++ feature test macros as gracefully as possible.
+// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
+#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
+    (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
+#include <version>  // C++20 and later
+#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
+#include <ciso646>  // Pre-C++20
 #endif
 
 #include <ctype.h>   // for isspace, etc
@@ -322,7 +330,8 @@
 #define GTEST_HAS_NOTIFICATION_ 0
 #endif
 
-#ifdef GTEST_HAS_ABSL
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#define GTEST_INTERNAL_HAS_ABSL_FLAGS  // Used only in this file.
 #include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/reflection.h"
@@ -592,7 +601,8 @@
      defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) ||         \
      defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
      defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_HAIKU) ||          \
-     defined(GTEST_OS_GNU_HURD))
+     defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_SOLARIS) ||       \
+     defined(GTEST_OS_AIX) || defined(GTEST_OS_ZOS))
 #define GTEST_HAS_PTHREAD 1
 #else
 #define GTEST_HAS_PTHREAD 0
@@ -642,9 +652,9 @@
 // platforms except known mobile / embedded ones. Also, if the port doesn't have
 // a file system, stream redirection is not supported.
 #if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \
-    defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_ESP8266) ||           \
-    defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) ||                  \
-    !GTEST_HAS_FILE_SYSTEM
+    defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_WINDOWS_GAMES) ||     \
+    defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) ||               \
+    defined(GTEST_OS_QURT) || !GTEST_HAS_FILE_SYSTEM
 #define GTEST_HAS_STREAM_REDIRECTION 0
 #else
 #define GTEST_HAS_STREAM_REDIRECTION 1
@@ -654,7 +664,7 @@
 // Determines whether to support death tests.
 // pops up a dialog window that cannot be suppressed programmatically.
 #if (defined(GTEST_OS_LINUX) || defined(GTEST_OS_CYGWIN) ||           \
-     defined(GTEST_OS_SOLARIS) ||                                     \
+     defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_ZOS) ||            \
      (defined(GTEST_OS_MAC) && !defined(GTEST_OS_IOS)) ||             \
      (defined(GTEST_OS_WINDOWS_DESKTOP) && _MSC_VER) ||               \
      defined(GTEST_OS_WINDOWS_MINGW) || defined(GTEST_OS_AIX) ||      \
@@ -732,6 +742,20 @@
 #define GTEST_HAVE_ATTRIBUTE_(x) 0
 #endif
 
+// GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE
+//
+// A function-like feature checking macro that accepts C++11 style attributes.
+// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// find `__has_cpp_attribute`, will evaluate to 0.
+#if defined(__has_cpp_attribute)
+// NOTE: requiring __cplusplus above should not be necessary, but
+// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
+#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) 0
+#endif
+
 // GTEST_HAVE_FEATURE_
 //
 // A function-like feature checking macro that is a wrapper around
@@ -742,17 +766,6 @@
 #define GTEST_HAVE_FEATURE_(x) 0
 #endif
 
-// Use this annotation after a variable or parameter declaration to tell the
-// compiler the variable/parameter does not have to be used.
-// Example:
-//
-//   GTEST_ATTRIBUTE_UNUSED_ int foo = bar();
-#if GTEST_HAVE_ATTRIBUTE_(unused)
-#define GTEST_ATTRIBUTE_UNUSED_ __attribute__((unused))
-#else
-#define GTEST_ATTRIBUTE_UNUSED_
-#endif
-
 // Use this annotation before a function that takes a printf format string.
 #if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
 // MinGW has two different printf implementations. Ensure the format macro
@@ -767,17 +780,6 @@
 #define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
 #endif
 
-// Tell the compiler to warn about unused return values for functions declared
-// with this macro.  The macro should be used on function declarations
-// following the argument list:
-//
-//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
-#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
-#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
-#else
-#define GTEST_MUST_USE_RESULT_
-#endif
-
 // MS C++ compiler emits warning when a conditional expression is compile time
 // constant. In some contexts this warning is false positive and needs to be
 // suppressed. Use the following two macros in such cases:
@@ -829,9 +831,9 @@
 #ifndef GTEST_API_
 
 #ifdef _MSC_VER
-#if GTEST_LINKED_AS_SHARED_LIBRARY
+#if defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY
 #define GTEST_API_ __declspec(dllimport)
-#elif GTEST_CREATE_SHARED_LIBRARY
+#elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
 #define GTEST_API_ __declspec(dllexport)
 #endif
 #elif GTEST_HAVE_ATTRIBUTE_(visibility)
@@ -1989,7 +1991,9 @@
 namespace posix {
 
 // File system porting.
-#if GTEST_HAS_FILE_SYSTEM
+// Note: Not every I/O-related function is related to file systems, so don't
+// just disable all of them here. For example, fileno() and isatty(), etc. must
+// always be available in order to detect if a pipe points to a terminal.
 #ifdef GTEST_OS_WINDOWS
 
 typedef struct _stat StatStruct;
@@ -2000,27 +2004,32 @@
 // time and thus not defined there.
 #else
 inline int FileNo(FILE* file) { return _fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
 inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
 inline int RmDir(const char* dir) { return _rmdir(dir); }
 inline bool IsDir(const StatStruct& st) { return (_S_IFDIR & st.st_mode) != 0; }
+#endif
 #endif  // GTEST_OS_WINDOWS_MOBILE
 
 #elif defined(GTEST_OS_ESP8266)
 typedef struct stat StatStruct;
 
 inline int FileNo(FILE* file) { return fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
 inline int Stat(const char* path, StatStruct* buf) {
   // stat function not implemented on ESP8266
   return 0;
 }
 inline int RmDir(const char* dir) { return rmdir(dir); }
 inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+#endif
 
 #else
 
 typedef struct stat StatStruct;
 
 inline int FileNo(FILE* file) { return fileno(file); }
+#if GTEST_HAS_FILE_SYSTEM
 inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
 #ifdef GTEST_OS_QURT
 // QuRT doesn't support any directory functions, including rmdir
@@ -2029,9 +2038,9 @@
 inline int RmDir(const char* dir) { return rmdir(dir); }
 #endif
 inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+#endif
 
 #endif  // GTEST_OS_WINDOWS
-#endif  // GTEST_HAS_FILE_SYSTEM
 
 // Other functions with a different name on Windows.
 
@@ -2084,8 +2093,9 @@
 // defined there.
 #if GTEST_HAS_FILE_SYSTEM
 #if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
-    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_ESP8266) &&           \
-    !defined(GTEST_OS_XTENSA) && !defined(GTEST_OS_QURT)
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES) &&     \
+    !defined(GTEST_OS_ESP8266) && !defined(GTEST_OS_XTENSA) &&               \
+    !defined(GTEST_OS_QURT)
 inline int ChDir(const char* dir) { return chdir(dir); }
 #endif
 inline FILE* FOpen(const char* path, const char* mode) {
@@ -2229,7 +2239,7 @@
 #endif  // !defined(GTEST_FLAG)
 
 // Pick a command line flags implementation.
-#ifdef GTEST_HAS_ABSL
+#ifdef GTEST_INTERNAL_HAS_ABSL_FLAGS
 
 // Macros for defining flags.
 #define GTEST_DEFINE_bool_(name, default_val, doc) \
@@ -2254,7 +2264,8 @@
   (void)(::absl::SetFlag(&GTEST_FLAG(name), value))
 #define GTEST_USE_OWN_FLAGFILE_FLAG_ 0
 
-#else  // GTEST_HAS_ABSL
+#undef GTEST_INTERNAL_HAS_ABSL_FLAGS
+#else  // ndef GTEST_INTERNAL_HAS_ABSL_FLAGS
 
 // Macros for defining flags.
 #define GTEST_DEFINE_bool_(name, default_val, doc)  \
@@ -2296,7 +2307,7 @@
 #define GTEST_FLAG_SET(name, value) (void)(::testing::GTEST_FLAG(name) = value)
 #define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
 
-#endif  // GTEST_HAS_ABSL
+#endif  // GTEST_INTERNAL_HAS_ABSL_FLAGS
 
 // Thread annotations
 #if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
@@ -2320,26 +2331,6 @@
 }  // namespace internal
 }  // namespace testing
 
-#if !defined(GTEST_INTERNAL_DEPRECATED)
-
-// Internal Macro to mark an API deprecated, for googletest usage only
-// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
-// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
-// a deprecated entity will trigger a warning when compiled with
-// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
-// For msvc /W3 option will need to be used
-// Note that for 'other' compilers this macro evaluates to nothing to prevent
-// compilations errors.
-#if defined(_MSC_VER)
-#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
-#elif defined(__GNUC__)
-#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
-#else
-#define GTEST_INTERNAL_DEPRECATED(message)
-#endif
-
-#endif  // !defined(GTEST_INTERNAL_DEPRECATED)
-
 #ifdef GTEST_HAS_ABSL
 // Always use absl::any for UniversalPrinter<> specializations if googletest
 // is built with absl support.
@@ -2351,9 +2342,9 @@
 }  // namespace internal
 }  // namespace testing
 #else
-#ifdef __has_include
-#if __has_include(<any>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
-    (!defined(_MSC_VER) || GTEST_HAS_RTTI)
+#if defined(__cpp_lib_any) || (GTEST_INTERNAL_HAS_INCLUDE(<any>) &&        \
+                               GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
+                               (!defined(_MSC_VER) || GTEST_HAS_RTTI))
 // Otherwise for C++17 and higher use std::any for UniversalPrinter<>
 // specializations.
 #define GTEST_INTERNAL_HAS_ANY 1
@@ -2365,8 +2356,7 @@
 }  // namespace testing
 // The case where absl is configured NOT to alias std::any is not
 // supported.
-#endif  // __has_include(<any>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-#endif  // __has_include
+#endif  // __cpp_lib_any
 #endif  // GTEST_HAS_ABSL
 
 #ifndef GTEST_INTERNAL_HAS_ANY
@@ -2386,8 +2376,8 @@
 }  // namespace internal
 }  // namespace testing
 #else
-#ifdef __has_include
-#if __has_include(<optional>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+#if defined(__cpp_lib_optional) || (GTEST_INTERNAL_HAS_INCLUDE(<optional>) && \
+                                    GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
 // Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
 // specializations.
 #define GTEST_INTERNAL_HAS_OPTIONAL 1
@@ -2401,19 +2391,17 @@
 }  // namespace testing
 // The case where absl is configured NOT to alias std::optional is not
 // supported.
-#endif  // __has_include(<optional>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-#endif  // __has_include
+#endif  // __cpp_lib_optional
 #endif  // GTEST_HAS_ABSL
 
 #ifndef GTEST_INTERNAL_HAS_OPTIONAL
 #define GTEST_INTERNAL_HAS_OPTIONAL 0
 #endif
 
-#ifdef __has_include
-#if __has_include(<span>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
+                                GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L)
 #define GTEST_INTERNAL_HAS_STD_SPAN 1
-#endif  // __has_include(<span>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L
-#endif  // __has_include
+#endif  // __cpp_lib_span
 
 #ifndef GTEST_INTERNAL_HAS_STD_SPAN
 #define GTEST_INTERNAL_HAS_STD_SPAN 0
@@ -2430,8 +2418,9 @@
 }  // namespace internal
 }  // namespace testing
 #else
-#ifdef __has_include
-#if __has_include(<string_view>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+#if defined(__cpp_lib_string_view) ||             \
+    (GTEST_INTERNAL_HAS_INCLUDE(<string_view>) && \
+     GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
 // Otherwise for C++17 and higher use std::string_view for Matcher<>
 // specializations.
 #define GTEST_INTERNAL_HAS_STRING_VIEW 1
@@ -2443,9 +2432,7 @@
 }  // namespace testing
 // The case where absl is configured NOT to alias std::string_view is not
 // supported.
-#endif  // __has_include(<string_view>) && GTEST_INTERNAL_CPLUSPLUS_LANG >=
-        // 201703L
-#endif  // __has_include
+#endif  // __cpp_lib_string_view
 #endif  // GTEST_HAS_ABSL
 
 #ifndef GTEST_INTERNAL_HAS_STRING_VIEW
@@ -2464,8 +2451,8 @@
 }  // namespace internal
 }  // namespace testing
 #else
-#ifdef __has_include
-#if __has_include(<variant>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+#if defined(__cpp_lib_variant) || (GTEST_INTERNAL_HAS_INCLUDE(<variant>) && \
+                                   GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
 // Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
 // specializations.
 #define GTEST_INTERNAL_HAS_VARIANT 1
@@ -2477,17 +2464,19 @@
 }  // namespace internal
 }  // namespace testing
 // The case where absl is configured NOT to alias std::variant is not supported.
-#endif  // __has_include(<variant>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-#endif  // __has_include
+#endif  // __cpp_lib_variant
 #endif  // GTEST_HAS_ABSL
 
 #ifndef GTEST_INTERNAL_HAS_VARIANT
 #define GTEST_INTERNAL_HAS_VARIANT 0
 #endif
 
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
-    GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
-#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
+#if (defined(__cpp_lib_three_way_comparison) || \
+     (GTEST_INTERNAL_HAS_INCLUDE(<compare>) &&  \
+      GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
+#define GTEST_INTERNAL_HAS_COMPARE_LIB 1
+#else
+#define GTEST_INTERNAL_HAS_COMPARE_LIB 0
 #endif
 
 #endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/src/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h b/src/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h
index f94cf61..78da053 100644
--- a/src/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h
+++ b/src/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h
@@ -71,7 +71,7 @@
   // Strip redundant spaces in typename to match MSVC
   // For example, std::pair<int, bool> -> std::pair<int,bool>
   static const char to_search[] = ", ";
-  static const char replace_str[] = ",";
+  const char replace_char = ',';
   size_t pos = 0;
   while (true) {
     // Get the next occurrence from the current position
@@ -80,8 +80,8 @@
       break;
     }
     // Replace this occurrence of substring
-    s.replace(pos, strlen(to_search), replace_str);
-    pos += strlen(replace_str);
+    s.replace(pos, strlen(to_search), 1, replace_char);
+    ++pos;
   }
   return s;
 }
diff --git a/src/third_party/googletest/googletest/src/gtest-death-test.cc b/src/third_party/googletest/googletest/src/gtest-death-test.cc
index 8417a30..15472f1 100644
--- a/src/third_party/googletest/googletest/src/gtest-death-test.cc
+++ b/src/third_party/googletest/googletest/src/gtest-death-test.cc
@@ -32,6 +32,8 @@
 
 #include "gtest/gtest-death-test.h"
 
+#include <stdlib.h>
+
 #include <functional>
 #include <memory>
 #include <sstream>
@@ -115,7 +117,7 @@
 GTEST_DEFINE_bool_(
     death_test_use_fork,
     testing::internal::BoolFromGTestEnv("death_test_use_fork", false),
-    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Instructs to use fork()/_Exit() instead of clone() in death tests. "
     "Ignored and always uses fork() on POSIX systems where clone() is not "
     "implemented. Useful when running under valgrind or similar tools if "
     "those do not support clone(). Valgrind 3.3.1 will just fail if "
@@ -299,7 +301,7 @@
     fputc(kDeathTestInternalError, parent);
     fprintf(parent, "%s", message.c_str());
     fflush(parent);
-    _exit(1);
+    _Exit(1);
   } else {
     fprintf(stderr, "%s", message.c_str());
     fflush(stderr);
@@ -511,7 +513,7 @@
 // Signals that the death test code which should have exited, didn't.
 // Should be called only in a death test child process.
 // Writes a status byte to the child's status file descriptor, then
-// calls _exit(1).
+// calls _Exit(1).
 void DeathTestImpl::Abort(AbortReason reason) {
   // The parent process considers the death test to be a failure if
   // it finds any data in our pipe.  So, here we write a single flag byte
@@ -523,13 +525,13 @@
   GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
   // We are leaking the descriptor here because on some platforms (i.e.,
   // when built as Windows DLL), destructors of global objects will still
-  // run after calling _exit(). On such systems, write_fd_ will be
+  // run after calling _Exit(). On such systems, write_fd_ will be
   // indirectly closed from the destructor of UnitTestImpl, causing double
   // close if it is also closed here. On debug configurations, double close
   // may assert. As there are no in-process buffers to flush here, we are
   // relying on the OS to close the descriptor after the process terminates
   // when the destructors are not run.
-  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+  _Exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
 }
 
 // Returns an indented copy of stderr output for a death test.
@@ -628,13 +630,13 @@
 #ifndef GTEST_OS_WINDOWS
 // Note: The return value points into args, so the return value's lifetime is
 // bound to that of args.
-static std::unique_ptr<char*[]> CreateArgvFromArgs(
-    std::vector<std::string>& args) {
-  auto result = std::make_unique<char*[]>(args.size() + 1);
-  for (size_t i = 0; i < args.size(); ++i) {
-    result[i] = &args[i][0];
+static std::vector<char*> CreateArgvFromArgs(std::vector<std::string>& args) {
+  std::vector<char*> result;
+  result.reserve(args.size() + 1);
+  for (auto& arg : args) {
+    result.push_back(&arg[0]);
   }
-  result[args.size()] = nullptr;  // extra null terminator
+  result.push_back(nullptr);  // Extra null terminator.
   return result;
 }
 #endif
@@ -1034,8 +1036,8 @@
   // "Fuchsia Test Component" which contains a "Fuchsia Component Manifest")
   // Launching processes is a privileged operation in Fuchsia, and the
   // declaration indicates that the ability is required for the component.
-  std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args);
-  status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.get(),
+  std::vector<char*> argv = CreateArgvFromArgs(args);
+  status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.data(),
                           nullptr, 2, spawn_actions,
                           child_process_.reset_and_get_address(), nullptr);
   GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
@@ -1333,7 +1335,7 @@
 #endif  // GTEST_HAS_CLONE
 
   if (use_fork && (child_pid = fork()) == 0) {
-    _exit(ExecDeathTestChildMain(&args));
+    _Exit(ExecDeathTestChildMain(&args));
   }
 #endif  // GTEST_OS_QNX
 #ifdef GTEST_OS_LINUX
@@ -1386,8 +1388,8 @@
   // is necessary.
   FlushInfoLog();
 
-  std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args);
-  const pid_t child_pid = ExecDeathTestSpawnChild(argv.get(), pipe_fd[0]);
+  std::vector<char*> argv = CreateArgvFromArgs(args);
+  const pid_t child_pid = ExecDeathTestSpawnChild(argv.data(), pipe_fd[0]);
   GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
   set_child_pid(child_pid);
   set_read_fd(pipe_fd[0]);
diff --git a/src/third_party/googletest/googletest/src/gtest-filepath.cc b/src/third_party/googletest/googletest/src/gtest-filepath.cc
index 513e947..902d8c7 100644
--- a/src/third_party/googletest/googletest/src/gtest-filepath.cc
+++ b/src/third_party/googletest/googletest/src/gtest-filepath.cc
@@ -336,7 +336,7 @@
     return false;
   }
 
-  if (pathname_.length() == 0 || this->DirectoryExists()) {
+  if (pathname_.empty() || this->DirectoryExists()) {
     return true;
   }
 
diff --git a/src/third_party/googletest/googletest/src/gtest-internal-inl.h b/src/third_party/googletest/googletest/src/gtest-internal-inl.h
index 4799a1e..cc6f004 100644
--- a/src/third_party/googletest/googletest/src/gtest-internal-inl.h
+++ b/src/third_party/googletest/googletest/src/gtest-internal-inl.h
@@ -46,6 +46,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "gtest/internal/gtest-port.h"
@@ -649,13 +650,15 @@
   //                    this is not a typed or a type-parameterized test.
   //   set_up_tc:       pointer to the function that sets up the test suite
   //   tear_down_tc:    pointer to the function that tears down the test suite
-  TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
+  TestSuite* GetTestSuite(const std::string& test_suite_name,
+                          const char* type_param,
                           internal::SetUpTestSuiteFunc set_up_tc,
                           internal::TearDownTestSuiteFunc tear_down_tc);
 
 //  Legacy API is deprecated but still available
 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-  TestCase* GetTestCase(const char* test_case_name, const char* type_param,
+  TestCase* GetTestCase(const std::string& test_case_name,
+                        const char* type_param,
                         internal::SetUpTestSuiteFunc set_up_tc,
                         internal::TearDownTestSuiteFunc tear_down_tc) {
     return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
@@ -681,13 +684,13 @@
     // AddTestInfo(), which is called to register a TEST or TEST_F
     // before main() is reached.
     if (original_working_dir_.IsEmpty()) {
-      original_working_dir_.Set(FilePath::GetCurrentDir());
+      original_working_dir_ = FilePath::GetCurrentDir();
       GTEST_CHECK_(!original_working_dir_.IsEmpty())
           << "Failed to get the current working directory.";
     }
 #endif  // GTEST_HAS_FILE_SYSTEM
 
-    GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
+    GetTestSuite(test_info->test_suite_name_, test_info->type_param(),
                  set_up_tc, tear_down_tc)
         ->AddTestInfo(test_info);
   }
@@ -709,18 +712,6 @@
     return type_parameterized_test_registry_;
   }
 
-  // Sets the TestSuite object for the test that's currently running.
-  void set_current_test_suite(TestSuite* a_current_test_suite) {
-    current_test_suite_ = a_current_test_suite;
-  }
-
-  // Sets the TestInfo object for the test that's currently running.  If
-  // current_test_info is NULL, the assertion results will be stored in
-  // ad_hoc_test_result_.
-  void set_current_test_info(TestInfo* a_current_test_info) {
-    current_test_info_ = a_current_test_info;
-  }
-
   // Registers all parameterized tests defined using TEST_P and
   // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
   // combination. This method can be called more then once; it has guards
@@ -835,12 +826,30 @@
   bool catch_exceptions() const { return catch_exceptions_; }
 
  private:
+  struct CompareTestSuitesByPointer {
+    bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
+      return lhs->name_ < rhs->name_;
+    }
+  };
+
   friend class ::testing::UnitTest;
 
   // Used by UnitTest::Run() to capture the state of
   // GTEST_FLAG(catch_exceptions) at the moment it starts.
   void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
 
+  // Sets the TestSuite object for the test that's currently running.
+  void set_current_test_suite(TestSuite* a_current_test_suite) {
+    current_test_suite_ = a_current_test_suite;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
   // The UnitTest object that owns this implementation object.
   UnitTest* const parent_;
 
@@ -873,6 +882,9 @@
   // elements in the vector.
   std::vector<TestSuite*> test_suites_;
 
+  // The set of TestSuites by name.
+  std::unordered_map<std::string, TestSuite*> test_suites_by_name_;
+
   // Provides a level of indirection for the test suite list to allow
   // easy shuffling and restoring the test suite order.  The i-th
   // element of this vector is the index of the i-th test suite in the
diff --git a/src/third_party/googletest/googletest/src/gtest-port.cc b/src/third_party/googletest/googletest/src/gtest-port.cc
index 2aaf2bc..1038ad7 100644
--- a/src/third_party/googletest/googletest/src/gtest-port.cc
+++ b/src/third_party/googletest/googletest/src/gtest-port.cc
@@ -158,13 +158,13 @@
 // we cannot detect it.
 size_t GetThreadCount() {
   int mib[] = {
-    CTL_KERN,
-    KERN_PROC,
-    KERN_PROC_PID,
-    getpid(),
+      CTL_KERN,
+      KERN_PROC,
+      KERN_PROC_PID,
+      getpid(),
 #ifdef GTEST_OS_NETBSD
-    sizeof(struct kinfo_proc),
-    1,
+      sizeof(struct kinfo_proc),
+      1,
 #endif
   };
   u_int miblen = sizeof(mib) / sizeof(mib[0]);
@@ -587,9 +587,11 @@
   // thread's ID.
   typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
 
-  // Holds the thread id and thread handle that we pass from
-  // StartWatcherThreadFor to WatcherThreadFunc.
-  typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
+  struct WatcherThreadParams {
+    DWORD thread_id;
+    HANDLE handle;
+    Notification has_initialized;
+  };
 
   static void StartWatcherThreadFor(DWORD thread_id) {
     // The returned handle will be kept in thread_map and closed by
@@ -597,15 +599,20 @@
     HANDLE thread =
         ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
     GTEST_CHECK_(thread != nullptr);
+
+    WatcherThreadParams* watcher_thread_params = new WatcherThreadParams;
+    watcher_thread_params->thread_id = thread_id;
+    watcher_thread_params->handle = thread;
+
     // We need to pass a valid thread ID pointer into CreateThread for it
     // to work correctly under Win98.
     DWORD watcher_thread_id;
-    HANDLE watcher_thread = ::CreateThread(
-        nullptr,  // Default security.
-        0,        // Default stack size
-        &ThreadLocalRegistryImpl::WatcherThreadFunc,
-        reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
-        CREATE_SUSPENDED, &watcher_thread_id);
+    HANDLE watcher_thread =
+        ::CreateThread(nullptr,  // Default security.
+                       0,        // Default stack size
+                       &ThreadLocalRegistryImpl::WatcherThreadFunc,
+                       reinterpret_cast<LPVOID>(watcher_thread_params),
+                       CREATE_SUSPENDED, &watcher_thread_id);
     GTEST_CHECK_(watcher_thread != nullptr)
         << "CreateThread failed with error " << ::GetLastError() << ".";
     // Give the watcher thread the same priority as ours to avoid being
@@ -614,17 +621,25 @@
                         ::GetThreadPriority(::GetCurrentThread()));
     ::ResumeThread(watcher_thread);
     ::CloseHandle(watcher_thread);
+
+    // Wait for the watcher thread to start to avoid race conditions.
+    // One specific race condition that can happen is that we have returned
+    // from main and have started to tear down, the newly spawned watcher
+    // thread may access already-freed variables, like global shared_ptrs.
+    watcher_thread_params->has_initialized.WaitForNotification();
   }
 
   // Monitors exit from a given thread and notifies those
   // ThreadIdToThreadLocals about thread termination.
   static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
-    const ThreadIdAndHandle* tah =
-        reinterpret_cast<const ThreadIdAndHandle*>(param);
-    GTEST_CHECK_(::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
-    OnThreadExit(tah->first);
-    ::CloseHandle(tah->second);
-    delete tah;
+    WatcherThreadParams* watcher_thread_params =
+        reinterpret_cast<WatcherThreadParams*>(param);
+    watcher_thread_params->has_initialized.Notify();
+    GTEST_CHECK_(::WaitForSingleObject(watcher_thread_params->handle,
+                                       INFINITE) == WAIT_OBJECT_0);
+    OnThreadExit(watcher_thread_params->thread_id);
+    ::CloseHandle(watcher_thread_params->handle);
+    delete watcher_thread_params;
     return 0;
   }
 
@@ -697,13 +712,24 @@
 void RE::Init(const char* regex) {
   pattern_ = regex;
 
+  // NetBSD (and Android, which takes its regex implemntation from NetBSD) does
+  // not include the GNU regex extensions (such as Perl style character classes
+  // like \w) in REG_EXTENDED. REG_EXTENDED is only specified to include the
+  // [[:alpha:]] style character classes. Enable REG_GNU wherever it is defined
+  // so users can use those extensions.
+#if defined(REG_GNU)
+  constexpr int reg_flags = REG_EXTENDED | REG_GNU;
+#else
+  constexpr int reg_flags = REG_EXTENDED;
+#endif
+
   // Reserves enough bytes to hold the regular expression used for a
   // full match.
   const size_t full_regex_len = strlen(regex) + 10;
   char* const full_pattern = new char[full_regex_len];
 
   snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
-  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  is_valid_ = regcomp(&full_regex_, full_pattern, reg_flags) == 0;
   // We want to call regcomp(&partial_regex_, ...) even if the
   // previous expression returns false.  Otherwise partial_regex_ may
   // not be properly initialized can may cause trouble when it's
@@ -714,7 +740,7 @@
   // regex.  We change it to an equivalent form "()" to be safe.
   if (is_valid_) {
     const char* const partial_regex = (*regex == '\0') ? "()" : regex;
-    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, reg_flags) == 0;
   }
   EXPECT_TRUE(is_valid_)
       << "Regular expression \"" << regex
@@ -1022,11 +1048,21 @@
   }
 }
 
+#if GTEST_HAS_STREAM_REDIRECTION
+
 // Disable Microsoft deprecation warnings for POSIX functions called from
 // this class (creat, dup, dup2, and close)
 GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
 
-#if GTEST_HAS_STREAM_REDIRECTION
+namespace {
+
+#if defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_IOS)
+bool EndsWithPathSeparator(const std::string& path) {
+  return !path.empty() && path.back() == GTEST_PATH_SEP_[0];
+}
+#endif
+
+}  // namespace
 
 // Object that captures an output stream (stdout/stderr).
 class CapturedStream {
@@ -1064,7 +1100,13 @@
     // The location /data/local/tmp is directly accessible from native code.
     // '/sdcard' and other variants cannot be relied on, as they are not
     // guaranteed to be mounted, or may have a delay in mounting.
-    name_template = "/data/local/tmp/";
+    //
+    // However, prefer using the TMPDIR environment variable if set, as newer
+    // devices may have /data/local/tmp read-only.
+    name_template = TempDir();
+    if (!EndsWithPathSeparator(name_template))
+      name_template.push_back(GTEST_PATH_SEP_[0]);
+
 #elif defined(GTEST_OS_IOS)
     char user_temp_dir[PATH_MAX + 1];
 
@@ -1084,7 +1126,7 @@
     ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
 
     name_template = user_temp_dir;
-    if (name_template.back() != GTEST_PATH_SEP_[0])
+    if (!EndsWithPathSeparator(name_template))
       name_template.push_back(GTEST_PATH_SEP_[0]);
 #else
     name_template = "/tmp/";
@@ -1306,8 +1348,8 @@
   ) {
     Message msg;
     msg << "WARNING: " << src_text
-        << " is expected to be a 32-bit integer, but actually"
-        << " has value " << str << ", which overflows.\n";
+        << " is expected to be a 32-bit integer, but actually" << " has value "
+        << str << ", which overflows.\n";
     printf("%s", msg.GetString().c_str());
     fflush(stdout);
     return false;
diff --git a/src/third_party/googletest/googletest/src/gtest.cc b/src/third_party/googletest/googletest/src/gtest.cc
index 62dfef6..81096ae 100644
--- a/src/third_party/googletest/googletest/src/gtest.cc
+++ b/src/third_party/googletest/googletest/src/gtest.cc
@@ -43,6 +43,7 @@
 #include <algorithm>
 #include <chrono>  // NOLINT
 #include <cmath>
+#include <csignal>  // NOLINT: raise(3) is used on some platforms
 #include <cstdint>
 #include <cstdlib>
 #include <cstring>
@@ -161,6 +162,10 @@
 #define GTEST_HAS_BUILTIN(x) 0
 #endif  // defined(__has_builtin)
 
+#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#define GTEST_HAS_ABSL_FLAGS
+#endif
+
 namespace testing {
 
 using internal::CountIf;
@@ -254,6 +259,12 @@
     "True if and only if a test failure should stop further test execution.");
 
 GTEST_DEFINE_bool_(
+    fail_if_no_test_linked,
+    testing::internal::BoolFromGTestEnv("fail_if_no_test_linked", false),
+    "True if and only if the test should fail if no test case (including "
+    "disabled test cases) is linked.");
+
+GTEST_DEFINE_bool_(
     also_run_disabled_tests,
     testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
     "Run disabled tests too, in addition to the tests normally being run.");
@@ -374,7 +385,7 @@
     testing::internal::StringFromGTestEnv("stream_result_to", ""),
     "This flag specifies the host name and the port number on which to stream "
     "test results. Example: \"localhost:555\". The flag is effective only on "
-    "Linux.");
+    "Linux and macOS.");
 
 GTEST_DEFINE_bool_(
     throw_on_failure,
@@ -446,6 +457,19 @@
   return test_suite->should_run();
 }
 
+namespace {
+
+// Returns true if test part results of type `type` should include a stack
+// trace.
+bool ShouldEmitStackTraceForResultType(TestPartResult::Type type) {
+  // Suppress emission of the stack trace for SUCCEED() since it likely never
+  // requires investigation, and GTEST_SKIP() since skipping is an intentional
+  // act by the developer rather than a failure requiring investigation.
+  return type != TestPartResult::kSuccess && type != TestPartResult::kSkip;
+}
+
+}  // namespace
+
 // AssertHelper constructor.
 AssertHelper::AssertHelper(TestPartResult::Type type, const char* file,
                            int line, const char* message)
@@ -458,7 +482,9 @@
   UnitTest::GetInstance()->AddTestPartResult(
       data_->type, data_->file, data_->line,
       AppendUserMessage(data_->message, message),
-      UnitTest::GetInstance()->impl()->CurrentOsStackTraceExceptTop(1)
+      ShouldEmitStackTraceForResultType(data_->type)
+          ? UnitTest::GetInstance()->impl()->CurrentOsStackTraceExceptTop(1)
+          : ""
       // Skips the stack frame for this function itself.
   );  // NOLINT
 }
@@ -516,7 +542,8 @@
   if (ignored.find(name) != ignored.end()) return;
 
   const char kMissingInstantiation[] =  //
-      " is defined via TEST_P, but never instantiated. None of the test cases "
+      " is defined via TEST_P, but never instantiated. None of the test "
+      "cases "
       "will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only "
       "ones provided expand to nothing."
       "\n\n"
@@ -557,7 +584,7 @@
 void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
                                         CodeLocation code_location) {
   GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite(
-      test_suite_name, code_location);
+      test_suite_name, std::move(code_location));
 }
 
 void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
@@ -568,7 +595,7 @@
 void TypeParameterizedTestSuiteRegistry::RegisterTestSuite(
     const char* test_suite_name, CodeLocation code_location) {
   suites_.emplace(std::string(test_suite_name),
-                  TypeParameterizedTestSuiteInfo(code_location));
+                  TypeParameterizedTestSuiteInfo(std::move(code_location)));
 }
 
 void TypeParameterizedTestSuiteRegistry::RegisterInstantiation(
@@ -595,10 +622,12 @@
         "\n\n"
         "Ideally, TYPED_TEST_P definitions should only ever be included as "
         "part of binaries that intend to use them. (As opposed to, for "
-        "example, being placed in a library that may be linked in to get other "
+        "example, being placed in a library that may be linked in to get "
+        "other "
         "utilities.)"
         "\n\n"
-        "To suppress this error for this test suite, insert the following line "
+        "To suppress this error for this test suite, insert the following "
+        "line "
         "(in a non-header) in the namespace it is defined in:"
         "\n\n"
         "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" +
@@ -638,11 +667,14 @@
 FilePath GetCurrentExecutableName() {
   FilePath result;
 
+  auto args = GetArgvs();
+  if (!args.empty()) {
 #if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_OS2)
-  result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe"));
+    result.Set(FilePath(args[0]).RemoveExtension("exe"));
 #else
-  result.Set(FilePath(GetArgvs()[0]));
+    result.Set(FilePath(args[0]));
 #endif  // GTEST_OS_WINDOWS
+  }
 
   return result.RemoveDirectoryName();
 }
@@ -778,7 +810,7 @@
   // Returns true if and only if name matches at least one of the patterns in
   // the filter.
   bool MatchesName(const std::string& name) const {
-    return exact_match_patterns_.count(name) > 0 ||
+    return exact_match_patterns_.find(name) != exact_match_patterns_.end() ||
            std::any_of(glob_patterns_.begin(), glob_patterns_.end(),
                        [&name](const std::string& pattern) {
                          return PatternMatchesString(
@@ -1634,10 +1666,25 @@
   return msg.GetString();
 }
 
-// Helper function for implementing ASSERT_NEAR.
+// Helper function for implementing ASSERT_NEAR. Treats infinity as a specific
+// value, such that comparing infinity to infinity is equal, the distance
+// between -infinity and +infinity is infinity, and infinity <= infinity is
+// true.
 AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2,
                                      const char* abs_error_expr, double val1,
                                      double val2, double abs_error) {
+  // We want to return success when the two values are infinity and at least
+  // one of the following is true:
+  //  * The values are the same-signed infinity.
+  //  * The error limit itself is infinity.
+  // This is done here so that we don't end up with a NaN when calculating the
+  // difference in values.
+  if (std::isinf(val1) && std::isinf(val2) &&
+      (std::signbit(val1) == std::signbit(val2) ||
+       (abs_error > 0.0 && std::isinf(abs_error)))) {
+    return AssertionSuccess();
+  }
+
   const double diff = fabs(val1 - val2);
   if (diff <= abs_error) return AssertionSuccess();
 
@@ -2317,7 +2364,7 @@
     "type_param", "value_param", "file",   "line"};
 
 // Use a slightly different set for allowed output to ensure existing tests can
-// still RecordProperty("result") or "RecordProperty(timestamp")
+// still RecordProperty("result") or RecordProperty("timestamp")
 static const char* const kReservedOutputTestCaseAttributes[] = {
     "classname",   "name", "status", "time",   "type_param",
     "value_param", "file", "line",   "result", "timestamp"};
@@ -2717,18 +2764,16 @@
 
 // Constructs a TestInfo object. It assumes ownership of the test factory
 // object.
-TestInfo::TestInfo(const std::string& a_test_suite_name,
-                   const std::string& a_name, const char* a_type_param,
-                   const char* a_value_param,
+TestInfo::TestInfo(std::string a_test_suite_name, std::string a_name,
+                   const char* a_type_param, const char* a_value_param,
                    internal::CodeLocation a_code_location,
                    internal::TypeId fixture_class_id,
                    internal::TestFactoryBase* factory)
-    : test_suite_name_(a_test_suite_name),
-      // begin()/end() is MSVC 17.3.3 ASAN crash workaround (GitHub issue #3997)
-      name_(a_name.begin(), a_name.end()),
+    : test_suite_name_(std::move(a_test_suite_name)),
+      name_(std::move(a_name)),
       type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
       value_param_(a_value_param ? new std::string(a_value_param) : nullptr),
-      location_(a_code_location),
+      location_(std::move(a_code_location)),
       fixture_class_id_(fixture_class_id),
       should_run_(false),
       is_disabled_(false),
@@ -2761,19 +2806,19 @@
 //                     The newly created TestInfo instance will assume
 //                     ownership of the factory object.
 TestInfo* MakeAndRegisterTestInfo(
-    const char* test_suite_name, const char* name, const char* type_param,
+    std::string test_suite_name, const char* name, const char* type_param,
     const char* value_param, CodeLocation code_location,
     TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
     TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
   TestInfo* const test_info =
-      new TestInfo(test_suite_name, name, type_param, value_param,
-                   code_location, fixture_class_id, factory);
+      new TestInfo(std::move(test_suite_name), name, type_param, value_param,
+                   std::move(code_location), fixture_class_id, factory);
   GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
   return test_info;
 }
 
 void ReportInvalidTestSuiteType(const char* test_suite_name,
-                                CodeLocation code_location) {
+                                const CodeLocation& code_location) {
   Message errors;
   errors
       << "Attempted redefinition of test suite " << test_suite_name << ".\n"
@@ -2813,14 +2858,13 @@
   }
 
   // Tells UnitTest where to store test result.
-  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-  impl->set_current_test_info(this);
+  UnitTest::GetInstance()->set_current_test_info(this);
 
   // Notifies the unit test event listeners that a test is about to start.
   repeater->OnTestStart(*this);
   result_.set_start_timestamp(internal::GetTimeInMillis());
   internal::Timer timer;
-  impl->os_stack_trace_getter()->UponLeavingGTest();
+  UnitTest::GetInstance()->UponLeavingGTest();
 
   // Creates the test object.
   Test* const test = internal::HandleExceptionsInMethodIfSupported(
@@ -2838,7 +2882,7 @@
 
   if (test != nullptr) {
     // Deletes the test object.
-    impl->os_stack_trace_getter()->UponLeavingGTest();
+    UnitTest::GetInstance()->UponLeavingGTest();
     internal::HandleExceptionsInMethodIfSupported(
         test, &Test::DeleteSelf_, "the test fixture's destructor");
   }
@@ -2850,15 +2894,14 @@
 
   // Tells UnitTest to stop associating assertion results to this
   // test.
-  impl->set_current_test_info(nullptr);
+  UnitTest::GetInstance()->set_current_test_info(nullptr);
 }
 
 // Skip and records a skipped test result for this object.
 void TestInfo::Skip() {
   if (!should_run_) return;
 
-  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-  impl->set_current_test_info(this);
+  UnitTest::GetInstance()->set_current_test_info(this);
 
   TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
 
@@ -2867,12 +2910,13 @@
 
   const TestPartResult test_part_result =
       TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
-  impl->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult(
-      test_part_result);
+  internal::GetUnitTestImpl()
+      ->GetTestPartResultReporterForCurrentThread()
+      ->ReportTestPartResult(test_part_result);
 
   // Notifies the unit test event listener that a test has just finished.
   repeater->OnTestEnd(*this);
-  impl->set_current_test_info(nullptr);
+  UnitTest::GetInstance()->set_current_test_info(nullptr);
 }
 
 // class TestSuite
@@ -2926,7 +2970,7 @@
 //                 this is not a typed or a type-parameterized test suite.
 //   set_up_tc:    pointer to the function that sets up the test suite
 //   tear_down_tc: pointer to the function that tears down the test suite
-TestSuite::TestSuite(const char* a_name, const char* a_type_param,
+TestSuite::TestSuite(const std::string& a_name, const char* a_type_param,
                      internal::SetUpTestSuiteFunc set_up_tc,
                      internal::TearDownTestSuiteFunc tear_down_tc)
     : name_(a_name),
@@ -2968,8 +3012,7 @@
 void TestSuite::Run() {
   if (!should_run_) return;
 
-  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-  impl->set_current_test_suite(this);
+  UnitTest::GetInstance()->set_current_test_suite(this);
 
   TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
 
@@ -2999,7 +3042,7 @@
   repeater->OnTestCaseStart(*this);
 #endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
 
-  impl->os_stack_trace_getter()->UponLeavingGTest();
+  UnitTest::GetInstance()->UponLeavingGTest();
   internal::HandleExceptionsInMethodIfSupported(
       this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
 
@@ -3024,7 +3067,7 @@
   }
   elapsed_time_ = timer.Elapsed();
 
-  impl->os_stack_trace_getter()->UponLeavingGTest();
+  UnitTest::GetInstance()->UponLeavingGTest();
   internal::HandleExceptionsInMethodIfSupported(
       this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
 
@@ -3035,15 +3078,14 @@
   repeater->OnTestCaseEnd(*this);
 #endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
 
-  impl->set_current_test_suite(nullptr);
+  UnitTest::GetInstance()->set_current_test_suite(nullptr);
 }
 
 // Skips all tests under this TestSuite.
 void TestSuite::Skip() {
   if (!should_run_) return;
 
-  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-  impl->set_current_test_suite(this);
+  UnitTest::GetInstance()->set_current_test_suite(this);
 
   TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
 
@@ -3065,7 +3107,7 @@
   repeater->OnTestCaseEnd(*this);
 #endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
 
-  impl->set_current_test_suite(nullptr);
+  UnitTest::GetInstance()->set_current_test_suite(nullptr);
 }
 
 // Clears the results of all tests in this test suite.
@@ -3166,9 +3208,9 @@
 }
 
 // class PrettyUnitTestResultPrinter
-#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&    \
-    !defined(GTEST_OS_WINDOWS_PHONE) && !defined(GTEST_OS_WINDOWS_RT) && \
-    !defined(GTEST_OS_WINDOWS_MINGW)
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&       \
+    !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
 
 // Returns the character attribute for the given color.
 static WORD GetColorAttribute(GTestColor color) {
@@ -3252,6 +3294,7 @@
         term != nullptr && (String::CStringEquals(term, "xterm") ||
                             String::CStringEquals(term, "xterm-color") ||
                             String::CStringEquals(term, "xterm-kitty") ||
+                            String::CStringEquals(term, "alacritty") ||
                             String::CStringEquals(term, "screen") ||
                             String::CStringEquals(term, "tmux") ||
                             String::CStringEquals(term, "rxvt-unicode") ||
@@ -3282,11 +3325,9 @@
   va_start(args, fmt);
 
   static const bool in_color_mode =
-#if GTEST_HAS_FILE_SYSTEM
+      // We don't condition this on GTEST_HAS_FILE_SYSTEM because we still need
+      // to be able to detect terminal I/O regardless.
       ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
-#else
-      false;
-#endif  // GTEST_HAS_FILE_SYSTEM
 
   const bool use_color = in_color_mode && (color != GTestColor::kDefault);
 
@@ -3296,9 +3337,9 @@
     return;
   }
 
-#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&    \
-    !defined(GTEST_OS_WINDOWS_PHONE) && !defined(GTEST_OS_WINDOWS_RT) && \
-    !defined(GTEST_OS_WINDOWS_MINGW)
+#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) &&       \
+    !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
   const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
 
   // Gets the current text color.
@@ -3954,6 +3995,12 @@
   static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
                                               const TestResult& result);
 
+  // Streams a test case XML stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputXmlTestCaseForTestResult(::std::ostream* stream,
+                                             const TestResult& result);
+
   // Streams an XML representation of a TestResult object.
   static void OutputXmlTestResult(::std::ostream* stream,
                                   const TestResult& result);
@@ -3971,16 +4018,11 @@
   static void PrintXmlUnitTest(::std::ostream* stream,
                                const UnitTest& unit_test);
 
-  // Produces a string representing the test properties in a result as space
-  // delimited XML attributes based on the property key="value" pairs.
-  // When the std::string is not empty, it includes a space at the beginning,
-  // to delimit this attribute from prior attributes.
-  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
-
   // Streams an XML representation of the test properties of a TestResult
   // object.
   static void OutputXmlTestProperties(std::ostream* stream,
-                                      const TestResult& result);
+                                      const TestResult& result,
+                                      const std::string& indent);
 
   // The output file.
   const std::string output_file_;
@@ -4201,6 +4243,15 @@
       FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
   *stream << ">";
 
+  OutputXmlTestCaseForTestResult(stream, result);
+
+  // Complete the test suite.
+  *stream << "  </testsuite>\n";
+}
+
+// Streams a test case XML stanza containing the given test result.
+void XmlUnitTestResultPrinter::OutputXmlTestCaseForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
   // Output the boilerplate for a minimal test case with a single test.
   *stream << "    <testcase";
   OutputXmlAttribute(stream, "testcase", "name", "");
@@ -4215,9 +4266,6 @@
 
   // Output the actual test result.
   OutputXmlTestResult(stream, result);
-
-  // Complete the test suite.
-  *stream << "  </testsuite>\n";
 }
 
 // Prints an XML representation of a TestInfo object.
@@ -4308,7 +4356,7 @@
     if (failures == 0 && skips == 0) {
       *stream << ">\n";
     }
-    OutputXmlTestProperties(stream, result);
+    OutputXmlTestProperties(stream, result, /*indent=*/"      ");
     *stream << "    </testcase>\n";
   }
 }
@@ -4337,13 +4385,18 @@
     OutputXmlAttribute(
         stream, kTestsuite, "timestamp",
         FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
-    *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
   }
   *stream << ">\n";
+  OutputXmlTestProperties(stream, test_suite.ad_hoc_test_result(),
+                          /*indent=*/"    ");
   for (int i = 0; i < test_suite.total_test_count(); ++i) {
     if (test_suite.GetTestInfo(i)->is_reportable())
       OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
   }
+  if (test_suite.ad_hoc_test_result().Failed()) {
+    OutputXmlTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
+  }
+
   *stream << "  </" << kTestsuite << ">\n";
 }
 
@@ -4373,11 +4426,12 @@
     OutputXmlAttribute(stream, kTestsuites, "random_seed",
                        StreamableToString(unit_test.random_seed()));
   }
-  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
 
   OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
   *stream << ">\n";
 
+  OutputXmlTestProperties(stream, unit_test.ad_hoc_test_result(),
+                          /*indent=*/"  ");
   for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
     if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
       PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
@@ -4414,21 +4468,8 @@
   *stream << "</" << kTestsuites << ">\n";
 }
 
-// Produces a string representing the test properties in a result as space
-// delimited XML attributes based on the property key="value" pairs.
-std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
-    const TestResult& result) {
-  Message attributes;
-  for (int i = 0; i < result.test_property_count(); ++i) {
-    const TestProperty& property = result.GetTestProperty(i);
-    attributes << " " << property.key() << "="
-               << "\"" << EscapeXmlAttribute(property.value()) << "\"";
-  }
-  return attributes.GetString();
-}
-
 void XmlUnitTestResultPrinter::OutputXmlTestProperties(
-    std::ostream* stream, const TestResult& result) {
+    std::ostream* stream, const TestResult& result, const std::string& indent) {
   const std::string kProperties = "properties";
   const std::string kProperty = "property";
 
@@ -4436,15 +4477,15 @@
     return;
   }
 
-  *stream << "      <" << kProperties << ">\n";
+  *stream << indent << "<" << kProperties << ">\n";
   for (int i = 0; i < result.test_property_count(); ++i) {
     const TestProperty& property = result.GetTestProperty(i);
-    *stream << "        <" << kProperty;
+    *stream << indent << "  <" << kProperty;
     *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
     *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
     *stream << "/>\n";
   }
-  *stream << "      </" << kProperties << ">\n";
+  *stream << indent << "</" << kProperties << ">\n";
 }
 
 // End XmlUnitTestResultPrinter
@@ -4483,6 +4524,12 @@
   static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
                                                const TestResult& result);
 
+  // Streams a test case JSON stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputJsonTestCaseForTestResult(::std::ostream* stream,
+                                              const TestResult& result);
+
   // Streams a JSON representation of a TestResult object.
   static void OutputJsonTestResult(::std::ostream* stream,
                                    const TestResult& result);
@@ -4653,6 +4700,15 @@
   }
   *stream << Indent(6) << "\"testsuite\": [\n";
 
+  OutputJsonTestCaseForTestResult(stream, result);
+
+  // Finish the test suite.
+  *stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
+}
+
+// Streams a test case JSON stanza containing the given test result.
+void JsonUnitTestResultPrinter::OutputJsonTestCaseForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
   // Output the boilerplate for a new test case.
   *stream << Indent(8) << "{\n";
   OutputJsonKey(stream, "testcase", "name", "", Indent(10));
@@ -4669,9 +4725,6 @@
 
   // Output the actual test result.
   OutputJsonTestResult(stream, result);
-
-  // Finish the test suite.
-  *stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
 }
 
 // Prints a JSON representation of a TestInfo object.
@@ -4726,28 +4779,53 @@
                                                      const TestResult& result) {
   const std::string kIndent = Indent(10);
 
-  int failures = 0;
-  for (int i = 0; i < result.total_part_count(); ++i) {
-    const TestPartResult& part = result.GetTestPartResult(i);
-    if (part.failed()) {
-      *stream << ",\n";
-      if (++failures == 1) {
-        *stream << kIndent << "\""
-                << "failures"
-                << "\": [\n";
+  {
+    int failures = 0;
+    for (int i = 0; i < result.total_part_count(); ++i) {
+      const TestPartResult& part = result.GetTestPartResult(i);
+      if (part.failed()) {
+        *stream << ",\n";
+        if (++failures == 1) {
+          *stream << kIndent << "\"" << "failures" << "\": [\n";
+        }
+        const std::string location =
+            internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                            part.line_number());
+        const std::string message =
+            EscapeJson(location + "\n" + part.message());
+        *stream << kIndent << "  {\n"
+                << kIndent << "    \"failure\": \"" << message << "\",\n"
+                << kIndent << "    \"type\": \"\"\n"
+                << kIndent << "  }";
       }
-      const std::string location =
-          internal::FormatCompilerIndependentFileLocation(part.file_name(),
-                                                          part.line_number());
-      const std::string message = EscapeJson(location + "\n" + part.message());
-      *stream << kIndent << "  {\n"
-              << kIndent << "    \"failure\": \"" << message << "\",\n"
-              << kIndent << "    \"type\": \"\"\n"
-              << kIndent << "  }";
     }
+
+    if (failures > 0) *stream << "\n" << kIndent << "]";
   }
 
-  if (failures > 0) *stream << "\n" << kIndent << "]";
+  {
+    int skipped = 0;
+    for (int i = 0; i < result.total_part_count(); ++i) {
+      const TestPartResult& part = result.GetTestPartResult(i);
+      if (part.skipped()) {
+        *stream << ",\n";
+        if (++skipped == 1) {
+          *stream << kIndent << "\"" << "skipped" << "\": [\n";
+        }
+        const std::string location =
+            internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                            part.line_number());
+        const std::string message =
+            EscapeJson(location + "\n" + part.message());
+        *stream << kIndent << "  {\n"
+                << kIndent << "    \"message\": \"" << message << "\"\n"
+                << kIndent << "  }";
+      }
+    }
+
+    if (skipped > 0) *stream << "\n" << kIndent << "]";
+  }
+
   *stream << "\n" << Indent(8) << "}";
 }
 
@@ -4791,6 +4869,16 @@
       OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
     }
   }
+
+  // If there was a failure in the test suite setup or teardown include that in
+  // the output.
+  if (test_suite.ad_hoc_test_result().Failed()) {
+    if (comma) {
+      *stream << ",\n";
+    }
+    OutputJsonTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
+  }
+
   *stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
 }
 
@@ -4884,8 +4972,8 @@
   for (int i = 0; i < result.test_property_count(); ++i) {
     const TestProperty& property = result.GetTestProperty(i);
     attributes << ",\n"
-               << indent << "\"" << property.key() << "\": "
-               << "\"" << EscapeJson(property.value()) << "\"";
+               << indent << "\"" << property.key() << "\": " << "\""
+               << EscapeJson(property.value()) << "\"";
   }
   return attributes.GetString();
 }
@@ -5283,6 +5371,22 @@
   return impl()->GetMutableSuiteCase(i);
 }
 
+void UnitTest::UponLeavingGTest() {
+  impl()->os_stack_trace_getter()->UponLeavingGTest();
+}
+
+// Sets the TestSuite object for the test that's currently running.
+void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
+  internal::MutexLock lock(&mutex_);
+  impl_->set_current_test_suite(a_current_test_suite);
+}
+
+// Sets the TestInfo object for the test that's currently running.
+void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
+  internal::MutexLock lock(&mutex_);
+  impl_->set_current_test_info(a_current_test_info);
+}
+
 // Returns the list of event listeners that can be used to track events
 // inside Google Test.
 TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); }
@@ -5400,7 +5504,7 @@
 int UnitTest::Run() {
 #ifdef GTEST_HAS_DEATH_TEST
   const bool in_death_test_child_process =
-      GTEST_FLAG_GET(internal_run_death_test).length() > 0;
+      !GTEST_FLAG_GET(internal_run_death_test).empty();
 
   // Google Test implements this protocol for catching that a test
   // program exits before returning control to Google Test:
@@ -5442,7 +5546,7 @@
   // about crashes - they are expected.
   if (impl()->catch_exceptions() || in_death_test_child_process) {
 #if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
-    !defined(GTEST_OS_WINDOWS_RT)
+    !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES)
     // SetErrorMode doesn't exist on CE.
     SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
                  SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
@@ -5712,29 +5816,6 @@
   }
 }
 
-// A predicate that checks the name of a TestSuite against a known
-// value.
-//
-// This is used for implementation of the UnitTest class only.  We put
-// it in the anonymous namespace to prevent polluting the outer
-// namespace.
-//
-// TestSuiteNameIs is copyable.
-class TestSuiteNameIs {
- public:
-  // Constructor.
-  explicit TestSuiteNameIs(const std::string& name) : name_(name) {}
-
-  // Returns true if and only if the name of test_suite matches name_.
-  bool operator()(const TestSuite* test_suite) const {
-    return test_suite != nullptr &&
-           strcmp(test_suite->name(), name_.c_str()) == 0;
-  }
-
- private:
-  std::string name_;
-};
-
 // Finds and returns a TestSuite with the given name.  If one doesn't
 // exist, creates one and returns it.  It's the CALLER'S
 // RESPONSIBILITY to ensure that this function is only called WHEN THE
@@ -5748,19 +5829,27 @@
 //   set_up_tc:       pointer to the function that sets up the test suite
 //   tear_down_tc:    pointer to the function that tears down the test suite
 TestSuite* UnitTestImpl::GetTestSuite(
-    const char* test_suite_name, const char* type_param,
+    const std::string& test_suite_name, const char* type_param,
     internal::SetUpTestSuiteFunc set_up_tc,
     internal::TearDownTestSuiteFunc tear_down_tc) {
-  // Can we find a TestSuite with the given name?
-  const auto test_suite =
-      std::find_if(test_suites_.rbegin(), test_suites_.rend(),
-                   TestSuiteNameIs(test_suite_name));
+  // During initialization, all TestInfos for a given suite are added in
+  // sequence. To optimize this case, see if the most recently added suite is
+  // the one being requested now.
+  if (!test_suites_.empty() &&
+      (*test_suites_.rbegin())->name_ == test_suite_name) {
+    return *test_suites_.rbegin();
+  }
 
-  if (test_suite != test_suites_.rend()) return *test_suite;
+  // Fall back to searching the collection.
+  auto item_it = test_suites_by_name_.find(test_suite_name);
+  if (item_it != test_suites_by_name_.end()) {
+    return item_it->second;
+  }
 
-  // No.  Let's create one.
+  // Not found. Create a new instance.
   auto* const new_test_suite =
       new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);
+  test_suites_by_name_.emplace(test_suite_name, new_test_suite);
 
   const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter);
   // Is this a death test suite?
@@ -5807,6 +5896,14 @@
   // user didn't call InitGoogleTest.
   PostFlagParsingInit();
 
+  if (GTEST_FLAG_GET(fail_if_no_test_linked) && total_test_count() == 0) {
+    ColoredPrintf(
+        GTestColor::kRed,
+        "This test program does NOT link in any test case. This is INVALID. "
+        "Please make sure to link in at least one test case.\n");
+    return false;
+  }
+
 #if GTEST_HAS_FILE_SYSTEM
   // Even if sharding is not on, test runners may want to use the
   // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
@@ -5973,6 +6070,12 @@
   }
 
   repeater->OnTestProgramEnd(*parent_);
+  // Destroy environments in normal code, not in static teardown.
+  bool delete_environment_on_teardown = true;
+  if (delete_environment_on_teardown) {
+    ForEach(environments_, internal::Delete<Environment>);
+    environments_.clear();
+  }
 
   if (!gtest_is_initialized_before_run_all_tests) {
     ColoredPrintf(
@@ -6106,12 +6209,11 @@
   int num_runnable_tests = 0;
   int num_selected_tests = 0;
   for (auto* test_suite : test_suites_) {
-    const std::string& test_suite_name = test_suite->name();
+    const std::string& test_suite_name = test_suite->name_;
     test_suite->set_should_run(false);
 
-    for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
-      TestInfo* const test_info = test_suite->test_info_list()[j];
-      const std::string test_name(test_info->name());
+    for (TestInfo* test_info : test_suite->test_info_list()) {
+      const std::string& test_name = test_info->name_;
       // A test is disabled if test suite name or test name matches
       // kDisableTestFilter.
       const bool is_disabled =
@@ -6202,8 +6304,8 @@
 #if GTEST_HAS_FILE_SYSTEM
   const std::string& output_format = UnitTestOptions::GetOutputFormat();
   if (output_format == "xml" || output_format == "json") {
-    FILE* fileout = OpenFileForWriting(
-        UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+    FILE* fileout =
+        OpenFileForWriting(UnitTestOptions::GetAbsolutePathToOutputFile());
     std::stringstream stream;
     if (output_format == "xml") {
       XmlUnitTestResultPrinter(
@@ -6589,6 +6691,7 @@
   GTEST_INTERNAL_PARSE_FLAG(death_test_style);
   GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
   GTEST_INTERNAL_PARSE_FLAG(fail_fast);
+  GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_linked);
   GTEST_INTERNAL_PARSE_FLAG(filter);
   GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
   GTEST_INTERNAL_PARSE_FLAG(list_tests);
@@ -6652,17 +6755,17 @@
     }
 
     if (remove_flag) {
-      // Shift the remainder of the argv list left by one.  Note
-      // that argv has (*argc + 1) elements, the last one always being
-      // NULL.  The following loop moves the trailing NULL element as
-      // well.
-      for (int j = i; j != *argc; j++) {
-        argv[j] = argv[j + 1];
+      // Shift the remainder of the argv list left by one.
+      for (int j = i + 1; j < *argc; ++j) {
+        argv[j - 1] = argv[j];
       }
 
       // Decrements the argument count.
       (*argc)--;
 
+      // Terminate the array with nullptr.
+      argv[*argc] = nullptr;
+
       // We also need to decrement the iterator as we just removed
       // an element.
       i--;
@@ -6684,7 +6787,7 @@
 // remain in place. Unrecognized flags are not reported and do not cause the
 // program to exit.
 void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
-#ifdef GTEST_HAS_ABSL
+#ifdef GTEST_HAS_ABSL_FLAGS
   if (*argc <= 0) return;
 
   std::vector<char*> positional_args;
@@ -6770,11 +6873,13 @@
 #ifdef GTEST_HAS_ABSL
   absl::InitializeSymbolizer(g_argvs[0].c_str());
 
+#ifdef GTEST_HAS_ABSL_FLAGS
   // When using the Abseil Flags library, set the program usage message to the
   // help message, but remove the color-encoding from the message first.
   absl::SetProgramUsageMessage(absl::StrReplaceAll(
       kColorEncodedHelpMessage,
       {{"@D", ""}, {"@R", ""}, {"@G", ""}, {"@Y", ""}, {"@@", "@"}}));
+#endif  // GTEST_HAS_ABSL_FLAGS
 #endif  // GTEST_HAS_ABSL
 
   ParseGoogleTestFlagsOnly(argc, argv);
diff --git a/src/third_party/googletest/googletest/test/BUILD.bazel b/src/third_party/googletest/googletest/test/BUILD.bazel
index 1890b6f..c561ef8 100644
--- a/src/third_party/googletest/googletest/test/BUILD.bazel
+++ b/src/third_party/googletest/googletest/test/BUILD.bazel
@@ -45,36 +45,38 @@
             "gtest-*.cc",
             "googletest-*.cc",
             "*.h",
-            "googletest/include/gtest/**/*.h",
         ],
         exclude = [
-            "gtest-unittest-api_test.cc",
-            "googletest/src/gtest-all.cc",
-            "gtest_all_test.cc",
-            "gtest-death-test_ex_test.cc",
-            "gtest-listener_test.cc",
-            "gtest-unittest-api_test.cc",
-            "googletest-param-test-test.cc",
-            "googletest-param-test2-test.cc",
+            # go/keep-sorted start
+            "googletest-break-on-failure-unittest_.cc",
             "googletest-catch-exceptions-test_.cc",
             "googletest-color-test_.cc",
+            "googletest-death-test_ex_test.cc",
             "googletest-env-var-test_.cc",
+            "googletest-fail-if-no-test-linked-test-with-disabled-test_.cc",
+            "googletest-fail-if-no-test-linked-test-with-enabled-test_.cc",
             "googletest-failfast-unittest_.cc",
             "googletest-filter-unittest_.cc",
             "googletest-global-environment-unittest_.cc",
-            "googletest-break-on-failure-unittest_.cc",
+            "googletest-list-tests-unittest_.cc",
             "googletest-listener-test.cc",
             "googletest-message-test.cc",
             "googletest-output-test_.cc",
-            "googletest-list-tests-unittest_.cc",
-            "googletest-shuffle-test_.cc",
-            "googletest-setuptestsuite-test_.cc",
-            "googletest-uninitialized-test_.cc",
-            "googletest-death-test_ex_test.cc",
-            "googletest-param-test-test",
-            "googletest-throw-on-failure-test_.cc",
             "googletest-param-test-invalid-name1-test_.cc",
             "googletest-param-test-invalid-name2-test_.cc",
+            "googletest-param-test-test",
+            "googletest-param-test-test.cc",
+            "googletest-param-test2-test.cc",
+            "googletest-setuptestsuite-test_.cc",
+            "googletest-shuffle-test_.cc",
+            "googletest-throw-on-failure-test_.cc",
+            "googletest-uninitialized-test_.cc",
+            "googletest/src/gtest-all.cc",
+            "gtest-death-test_ex_test.cc",
+            "gtest-listener_test.cc",
+            "gtest-unittest-api_test.cc",
+            "gtest_all_test.cc",
+            # go/keep-sorted end
         ],
     ) + select({
         "//:windows": [],
@@ -324,6 +326,26 @@
     deps = ["//:gtest"],
 )
 
+cc_binary(
+    name = "googletest-fail-if-no-test-linked-test-without-test_",
+    testonly = 1,
+    deps = ["//:gtest_main"],
+)
+
+cc_binary(
+    name = "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+    testonly = 1,
+    srcs = ["googletest-fail-if-no-test-linked-test-with-disabled-test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
+cc_binary(
+    name = "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+    testonly = 1,
+    srcs = ["googletest-fail-if-no-test-linked-test-with-enabled-test_.cc"],
+    deps = ["//:gtest_main"],
+)
+
 cc_test(
     name = "gtest_skip_test",
     size = "small",
@@ -364,6 +386,18 @@
     deps = [":gtest_test_utils"],
 )
 
+py_test(
+    name = "googletest-fail-if-no-test-linked-test",
+    size = "small",
+    srcs = ["googletest-fail-if-no-test-linked-test.py"],
+    data = [
+        ":googletest-fail-if-no-test-linked-test-with-disabled-test_",
+        ":googletest-fail-if-no-test-linked-test-with-enabled-test_",
+        ":googletest-fail-if-no-test-linked-test-without-test_",
+    ],
+    deps = [":gtest_test_utils"],
+)
+
 cc_binary(
     name = "googletest-shuffle-test_",
     srcs = ["googletest-shuffle-test_.cc"],
diff --git a/src/third_party/googletest/googletest/test/googletest-color-test.py b/src/third_party/googletest/googletest/test/googletest-color-test.py
index 8926a48..8968cf1 100755
--- a/src/third_party/googletest/googletest/test/googletest-color-test.py
+++ b/src/third_party/googletest/googletest/test/googletest-color-test.py
@@ -80,6 +80,7 @@
     self.assertTrue(UsesColor('xterm', None, None))
     self.assertTrue(UsesColor('xterm-color', None, None))
     self.assertTrue(UsesColor('xterm-kitty', None, None))
+    self.assertTrue(UsesColor('alacritty', None, None))
     self.assertTrue(UsesColor('xterm-256color', None, None))
 
   def testFlagOnly(self):
diff --git a/src/third_party/googletest/googletest/test/googletest-death-test-test.cc b/src/third_party/googletest/googletest/test/googletest-death-test-test.cc
index 4cc81b7..44b8046 100644
--- a/src/third_party/googletest/googletest/test/googletest-death-test-test.cc
+++ b/src/third_party/googletest/googletest/test/googletest-death-test-test.cc
@@ -30,6 +30,8 @@
 //
 // Tests for death tests.
 
+#include <stdlib.h>
+
 #include "gtest/gtest-death-test.h"
 #include "gtest/gtest.h"
 #include "gtest/internal/gtest-filepath.h"
@@ -111,15 +113,15 @@
   fprintf(stderr, "%s", message.c_str());
   fflush(stderr);  // Make sure the text is printed before the process exits.
 
-  // We call _exit() instead of exit(), as the former is a direct
+  // We call _Exit() instead of exit(), as the former is a direct
   // system call and thus safer in the presence of threads.  exit()
   // will invoke user-defined exit-hooks, which may do dangerous
   // things that conflict with death tests.
   //
-  // Some compilers can recognize that _exit() never returns and issue the
+  // Some compilers can recognize that _Exit() never returns and issue the
   // 'unreachable code' warning for code following this function, unless
   // fooled by a fake condition.
-  if (AlwaysTrue()) _exit(1);
+  if (AlwaysTrue()) _Exit(1);
 }
 
 void DieInside(const ::std::string& function) {
@@ -238,13 +240,13 @@
 
 #else
 
-// Returns the exit status of a process that calls _exit(2) with a
+// Returns the exit status of a process that calls _Exit(2) with a
 // given exit code.  This is a helper function for the
 // ExitStatusPredicateTest test suite.
 static int NormalExitStatus(int exit_code) {
   pid_t child_pid = fork();
   if (child_pid == 0) {
-    _exit(exit_code);
+    _Exit(exit_code);
   }
   int status;
   waitpid(child_pid, &status, 0);
@@ -260,7 +262,7 @@
   pid_t child_pid = fork();
   if (child_pid == 0) {
     raise(signum);
-    _exit(1);
+    _Exit(1);
   }
   int status;
   waitpid(child_pid, &status, 0);
@@ -289,7 +291,9 @@
   const int status_kill = KilledExitStatus(SIGKILL);
   const testing::KilledBySignal pred_segv(SIGSEGV);
   const testing::KilledBySignal pred_kill(SIGKILL);
+#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 21)
   EXPECT_PRED1(pred_segv, status_segv);
+#endif
   EXPECT_PRED1(pred_kill, status_kill);
   EXPECT_FALSE(pred_segv(status_kill));
   EXPECT_FALSE(pred_kill(status_segv));
@@ -313,7 +317,7 @@
     ASSERT_DEATH(return, "");
 
   if (AlwaysTrue())
-    EXPECT_DEATH(_exit(1), "");
+    EXPECT_DEATH(_Exit(1), "");
   else
     // This empty "else" branch is meant to ensure that EXPECT_DEATH
     // doesn't expand into an "if" statement without an "else"
@@ -324,7 +328,7 @@
   if (AlwaysFalse())
     ;
   else
-    EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
+    EXPECT_DEATH(_Exit(1), "") << 1 << 2 << 3;
 }
 #ifdef __GNUC__
 #pragma GCC diagnostic pop
@@ -339,11 +343,11 @@
 
   switch (0)
   default:
-    ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
+    ASSERT_DEATH(_Exit(1), "") << "exit in default switch handler";
 
   switch (0)
   case 0:
-    EXPECT_DEATH(_exit(1), "") << "exit in switch case";
+    EXPECT_DEATH(_Exit(1), "") << "exit in switch case";
 
   GTEST_DISABLE_MSC_WARNINGS_POP_()
 }
@@ -371,10 +375,10 @@
   GTEST_FLAG_SET(death_test_style, "fast");
 
   ChangeToRootDir();
-  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
 
   ChangeToRootDir();
-  ASSERT_DEATH(_exit(1), "");
+  ASSERT_DEATH(_Exit(1), "");
 }
 
 #ifdef GTEST_OS_LINUX
@@ -416,7 +420,7 @@
 TEST_F(TestForDeathTest, FastSigprofActionSet) {
   GTEST_FLAG_SET(death_test_style, "fast");
   SetSigprofActionAndTimer();
-  EXPECT_DEATH(_exit(1), "");
+  EXPECT_DEATH(_Exit(1), "");
   struct sigaction old_signal_action;
   DisableSigprofActionAndTimer(&old_signal_action);
   EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
@@ -425,7 +429,7 @@
 TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) {
   GTEST_FLAG_SET(death_test_style, "threadsafe");
   SetSigprofActionAndTimer();
-  EXPECT_DEATH(_exit(1), "");
+  EXPECT_DEATH(_Exit(1), "");
   struct sigaction old_signal_action;
   DisableSigprofActionAndTimer(&old_signal_action);
   EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
@@ -449,24 +453,24 @@
   GTEST_FLAG_SET(death_test_style, "threadsafe");
 
   for (int i = 0; i < 3; ++i)
-    EXPECT_EXIT(_exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
+    EXPECT_EXIT(_Exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
 }
 
 TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
   GTEST_FLAG_SET(death_test_style, "threadsafe");
 
   ChangeToRootDir();
-  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
 
   ChangeToRootDir();
-  ASSERT_DEATH(_exit(1), "");
+  ASSERT_DEATH(_Exit(1), "");
 }
 
 TEST_F(TestForDeathTest, MixedStyles) {
   GTEST_FLAG_SET(death_test_style, "threadsafe");
-  EXPECT_DEATH(_exit(1), "");
+  EXPECT_DEATH(_Exit(1), "");
   GTEST_FLAG_SET(death_test_style, "fast");
-  EXPECT_DEATH(_exit(1), "");
+  EXPECT_DEATH(_Exit(1), "");
 }
 
 #if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
@@ -480,7 +484,7 @@
     GTEST_FLAG_SET(death_test_style, "threadsafe");
     pthread_flag = false;
     ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, nullptr, nullptr));
-    ASSERT_DEATH(_exit(1), "");
+    ASSERT_DEATH(_Exit(1), "");
     ASSERT_FALSE(pthread_flag);
   }
 }
@@ -805,8 +809,8 @@
 
 // Tests the *_EXIT family of macros, using a variety of predicates.
 static void TestExitMacros() {
-  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
-  ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
+  EXPECT_EXIT(_Exit(1), testing::ExitedWithCode(1), "");
+  ASSERT_EXIT(_Exit(42), testing::ExitedWithCode(42), "");
 
 #ifdef GTEST_OS_WINDOWS
 
@@ -823,7 +827,7 @@
 
   EXPECT_FATAL_FAILURE(
       {  // NOLINT
-        ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
+        ASSERT_EXIT(_Exit(0), testing::KilledBySignal(SIGSEGV), "")
             << "This failure is expected, too.";
       },
       "This failure is expected, too.");
@@ -849,7 +853,7 @@
   GTEST_FLAG_SET(death_test_style, "rococo");
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
+        EXPECT_DEATH(_Exit(0), "") << "This failure is expected.";
       },
       "This failure is expected.");
 }
@@ -1140,7 +1144,7 @@
   // This time there are two calls to Abort: one since the test didn't
   // die, and another from the ReturnSentinel when it's destroyed.  The
   // sentinel normally isn't destroyed if a test doesn't die, since
-  // _exit(2) is called in that case by ForkingDeathTest, but not by
+  // _Exit(2) is called in that case by ForkingDeathTest, but not by
   // our MockDeathTest.
   ASSERT_EQ(2U, factory_->AbortCalls());
   EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE, factory_->AbortArgument(0));
@@ -1152,21 +1156,21 @@
 // Tests that a successful death test does not register a successful
 // test part.
 TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
-  EXPECT_DEATH(_exit(1), "");
+  EXPECT_DEATH(_Exit(1), "");
   EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
 }
 
 TEST(StreamingAssertionsDeathTest, DeathTest) {
-  EXPECT_DEATH(_exit(1), "") << "unexpected failure";
-  ASSERT_DEATH(_exit(1), "") << "unexpected failure";
+  EXPECT_DEATH(_Exit(1), "") << "unexpected failure";
+  ASSERT_DEATH(_Exit(1), "") << "unexpected failure";
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        EXPECT_DEATH(_exit(0), "") << "expected failure";
+        EXPECT_DEATH(_Exit(0), "") << "expected failure";
       },
       "expected failure");
   EXPECT_FATAL_FAILURE(
       {  // NOLINT
-        ASSERT_DEATH(_exit(0), "") << "expected failure";
+        ASSERT_DEATH(_Exit(0), "") << "expected failure";
       },
       "expected failure");
 }
@@ -1330,7 +1334,7 @@
       {
         fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
         fflush(stderr);
-        _exit(1);
+        _Exit(1);
       },
       "Inside");
 }
@@ -1342,7 +1346,7 @@
       {
         fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
         fflush(stderr);
-        _exit(1);
+        _Exit(1);
       },
       "Inside");
 }
@@ -1350,7 +1354,7 @@
 void DieWithMessage(const char* message) {
   fputs(message, stderr);
   fflush(stderr);  // Make sure the text is printed before the process exits.
-  _exit(1);
+  _Exit(1);
 }
 
 TEST(MatcherDeathTest, DoesNotBreakBareRegexMatching) {
@@ -1466,7 +1470,7 @@
     ASSERT_DEATH_IF_SUPPORTED(return, "");
 
   if (AlwaysTrue())
-    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "");
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "");
   else
     // This empty "else" branch is meant to ensure that EXPECT_DEATH
     // doesn't expand into an "if" statement without an "else"
@@ -1477,7 +1481,7 @@
   if (AlwaysFalse())
     ;  // NOLINT
   else
-    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "") << 1 << 2 << 3;
 }
 #ifdef __GNUC__
 #pragma GCC diagnostic pop
@@ -1492,11 +1496,11 @@
 
   switch (0)
   default:
-    ASSERT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in default switch handler";
+    ASSERT_DEATH_IF_SUPPORTED(_Exit(1), "") << "exit in default switch handler";
 
   switch (0)
   case 0:
-    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
+    EXPECT_DEATH_IF_SUPPORTED(_Exit(1), "") << "exit in switch case";
 
   GTEST_DISABLE_MSC_WARNINGS_POP_()
 }
diff --git a/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc
new file mode 100644
index 0000000..56d2690
--- /dev/null
+++ b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc
@@ -0,0 +1,38 @@
+// Copyright 2025, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 COPYRIGHT
+// OWNER 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.
+
+// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
+//
+// This program will be invoked from a Python test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+// A dummy test that is disabled.
+TEST(SomeTest, DISABLED_Test1) {}
diff --git a/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc
new file mode 100644
index 0000000..1ed2034
--- /dev/null
+++ b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc
@@ -0,0 +1,38 @@
+// Copyright 2025, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 COPYRIGHT
+// OWNER 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.
+
+// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
+//
+// This program will be invoked from a Python test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+// A dummy test that is enabled.
+TEST(SomeTest, Test1) {}
diff --git a/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test.py b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test.py
new file mode 100755
index 0000000..3ecf208
--- /dev/null
+++ b/src/third_party/googletest/googletest/test/googletest-fail-if-no-test-linked-test.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3  # pylint: disable=g-interpreter-mismatch
+#
+# Copyright 2025, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * 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.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 COPYRIGHT
+# OWNER 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.
+
+"""Tests for Google Test's --gtest_fail_if_no_test_linked flag."""
+
+from googletest.test import gtest_test_utils
+
+# The command line flag for enabling the fail-if-no-test-linked behavior.
+FAIL_IF_NO_TEST_LINKED_FLAG = "gtest_fail_if_no_test_linked"
+
+
+class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase):
+  """Tests the --gtest_fail_if_no_test_linked flag."""
+
+  def Run(self, program_name, flag=None):
+    """Run the given program with the given flag.
+
+    Args:
+      program_name: Name of the program to run.
+      flag: The command line flag to pass to the program, or None.
+
+    Returns:
+      True if the program exits with code 0, false otherwise.
+    """
+
+    exe_path = gtest_test_utils.GetTestExecutablePath(program_name)
+    args = [exe_path]
+    if flag is not None:
+      args += [flag]
+    process = gtest_test_utils.Subprocess(args, capture_stderr=False)
+    return process.exited and process.exit_code == 0
+
+  def testSucceedsIfNoTestLinkedAndFlagNotSpecified(self):
+    """Tests the behavior of no test linked and flag not specified."""
+
+    self.assertTrue(
+        self.Run("googletest-fail-if-no-test-linked-test-without-test_")
+    )
+
+  def testFailsIfNoTestLinkedAndFlagSpecified(self):
+    """Tests the behavior of no test linked and flag specified."""
+
+    self.assertFalse(
+        self.Run(
+            "googletest-fail-if-no-test-linked-test-without-test_",
+            f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+        )
+    )
+
+  def testSucceedsIfEnabledTestLinkedAndFlagNotSpecified(self):
+    """Tests the behavior of enabled test linked and flag not specified."""
+
+    self.assertTrue(
+        self.Run("googletest-fail-if-no-test-linked-test-with-enabled-test_")
+    )
+
+  def testSucceedsIfEnabledTestLinkedAndFlagSpecified(self):
+    """Tests the behavior of enabled test linked and flag specified."""
+
+    self.assertTrue(
+        self.Run(
+            "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+            f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+        )
+    )
+
+  def testSucceedsIfDisabledTestLinkedAndFlagNotSpecified(self):
+    """Tests the behavior of disabled test linked and flag not specified."""
+
+    self.assertTrue(
+        self.Run("googletest-fail-if-no-test-linked-test-with-disabled-test_")
+    )
+
+  def testSucceedsIfDisabledTestLinkedAndFlagSpecified(self):
+    """Tests the behavior of disabled test linked and flag specified."""
+
+    self.assertTrue(
+        self.Run(
+            "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+            f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+        )
+    )
+
+
+if __name__ == "__main__":
+  gtest_test_utils.Main()
diff --git a/src/third_party/googletest/googletest/test/googletest-json-output-unittest.py b/src/third_party/googletest/googletest/test/googletest-json-output-unittest.py
index cb97694..c75051c 100644
--- a/src/third_party/googletest/googletest/test/googletest-json-output-unittest.py
+++ b/src/third_party/googletest/googletest/test/googletest-json-output-unittest.py
@@ -57,7 +57,7 @@
   STACK_TRACE_TEMPLATE = '\n'
 
 EXPECTED_NON_EMPTY = {
-    'tests': 26,
+    'tests': 28,
     'failures': 5,
     'disabled': 2,
     'errors': 0,
@@ -150,6 +150,9 @@
                     'time': '*',
                     'timestamp': '*',
                     'classname': 'SkippedTest',
+                    'skipped': [
+                        {'message': 'gtest_xml_output_unittest_.cc:*\n\n'}
+                    ],
                 },
                 {
                     'name': 'SkippedWithMessage',
@@ -160,6 +163,12 @@
                     'time': '*',
                     'timestamp': '*',
                     'classname': 'SkippedTest',
+                    'skipped': [{
+                        'message': (
+                            'gtest_xml_output_unittest_.cc:*\n'
+                            'It is good practice to tell why you skip a test.\n'
+                        )
+                    }],
                 },
                 {
                     'name': 'SkippedAfterFailure',
@@ -179,6 +188,12 @@
                         ),
                         'type': '',
                     }],
+                    'skipped': [{
+                        'message': (
+                            'gtest_xml_output_unittest_.cc:*\n'
+                            'It is good practice to tell why you skip a test.\n'
+                        )
+                    }],
                 },
             ],
         },
@@ -308,12 +323,14 @@
             'time': '*',
             'timestamp': '*',
             'SetUpTestSuite': 'yes',
+            'SetUpTestSuite (with whitespace)': 'yes and yes',
             'TearDownTestSuite': 'aye',
+            'TearDownTestSuite (with whitespace)': 'aye and aye',
             'testsuite': [
                 {
                     'name': 'OneProperty',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 121,
+                    'line': 125,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -324,7 +341,7 @@
                 {
                     'name': 'IntValuedProperty',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 125,
+                    'line': 129,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -335,7 +352,7 @@
                 {
                     'name': 'ThreeProperties',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 129,
+                    'line': 133,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -348,7 +365,7 @@
                 {
                     'name': 'TwoValuesForOneKeyUsesLastValue',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 135,
+                    'line': 139,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -370,7 +387,7 @@
                 {
                     'name': 'RecordProperty',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 140,
+                    'line': 144,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -381,7 +398,7 @@
                 {
                     'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 153,
+                    'line': 157,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -394,7 +411,7 @@
                         'ExternalUtilityThatCallsRecordStringValuedProperty'
                     ),
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 157,
+                    'line': 161,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -405,6 +422,83 @@
             ],
         },
         {
+            'name': 'SetupFailTest',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'time': '*',
+            'timestamp': '*',
+            'testsuite': [
+                {
+                    'name': 'NoopPassingTest',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 172,
+                    'status': 'RUN',
+                    'result': 'SKIPPED',
+                    'timestamp': '*',
+                    'time': '*',
+                    'classname': 'SetupFailTest',
+                    'skipped': [
+                        {'message': 'gtest_xml_output_unittest_.cc:*\n'}
+                    ],
+                },
+                {
+                    'name': '',
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'timestamp': '*',
+                    'time': '*',
+                    'classname': '',
+                    'failures': [{
+                        'failure': (
+                            'gtest_xml_output_unittest_.cc:*\nExpected equality'
+                            ' of these values:\n  1\n  2'
+                            + STACK_TRACE_TEMPLATE
+                        ),
+                        'type': '',
+                    }],
+                },
+            ],
+        },
+        {
+            'name': 'TearDownFailTest',
+            'tests': 1,
+            'failures': 0,
+            'disabled': 0,
+            'errors': 0,
+            'timestamp': '*',
+            'time': '*',
+            'testsuite': [
+                {
+                    'name': 'NoopPassingTest',
+                    'file': 'gtest_xml_output_unittest_.cc',
+                    'line': 179,
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'timestamp': '*',
+                    'time': '*',
+                    'classname': 'TearDownFailTest',
+                },
+                {
+                    'name': '',
+                    'status': 'RUN',
+                    'result': 'COMPLETED',
+                    'timestamp': '*',
+                    'time': '*',
+                    'classname': '',
+                    'failures': [{
+                        'failure': (
+                            'gtest_xml_output_unittest_.cc:*\nExpected equality'
+                            ' of these values:\n  1\n  2'
+                            + STACK_TRACE_TEMPLATE
+                        ),
+                        'type': '',
+                    }],
+                },
+            ],
+        },
+        {
             'name': 'TypedTest/0',
             'tests': 1,
             'failures': 0,
@@ -416,7 +510,7 @@
                 'name': 'HasTypeParamAttribute',
                 'type_param': 'int',
                 'file': 'gtest_xml_output_unittest_.cc',
-                'line': 173,
+                'line': 193,
                 'status': 'RUN',
                 'result': 'COMPLETED',
                 'time': '*',
@@ -436,7 +530,7 @@
                 'name': 'HasTypeParamAttribute',
                 'type_param': 'long',
                 'file': 'gtest_xml_output_unittest_.cc',
-                'line': 173,
+                'line': 193,
                 'status': 'RUN',
                 'result': 'COMPLETED',
                 'time': '*',
@@ -456,7 +550,7 @@
                 'name': 'HasTypeParamAttribute',
                 'type_param': 'int',
                 'file': 'gtest_xml_output_unittest_.cc',
-                'line': 180,
+                'line': 200,
                 'status': 'RUN',
                 'result': 'COMPLETED',
                 'time': '*',
@@ -476,7 +570,7 @@
                 'name': 'HasTypeParamAttribute',
                 'type_param': 'long',
                 'file': 'gtest_xml_output_unittest_.cc',
-                'line': 180,
+                'line': 200,
                 'status': 'RUN',
                 'result': 'COMPLETED',
                 'time': '*',
@@ -497,7 +591,7 @@
                     'name': 'HasValueParamAttribute/0',
                     'value_param': '33',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 164,
+                    'line': 184,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -508,7 +602,7 @@
                     'name': 'HasValueParamAttribute/1',
                     'value_param': '42',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 164,
+                    'line': 184,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -519,7 +613,7 @@
                     'name': 'AnotherTestThatHasValueParamAttribute/0',
                     'value_param': '33',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 165,
+                    'line': 185,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
@@ -530,7 +624,7 @@
                     'name': 'AnotherTestThatHasValueParamAttribute/1',
                     'value_param': '42',
                     'file': 'gtest_xml_output_unittest_.cc',
-                    'line': 165,
+                    'line': 185,
                     'status': 'RUN',
                     'result': 'COMPLETED',
                     'time': '*',
diff --git a/src/third_party/googletest/googletest/test/googletest-options-test.cc b/src/third_party/googletest/googletest/test/googletest-options-test.cc
index b712c06..91d06a5 100644
--- a/src/third_party/googletest/googletest/test/googletest-options-test.cc
+++ b/src/third_party/googletest/googletest/test/googletest-options-test.cc
@@ -115,11 +115,14 @@
       strcasecmp("gtest_dll_test", exe_str.c_str()) == 0;
 #elif defined(GTEST_OS_FUCHSIA)
   const bool success = exe_str == "app";
+#elif defined(__EMSCRIPTEN__)
+  const bool success = exe_str == "patched_googletest-options-test.js";
 #else
   const bool success =
       exe_str == "googletest-options-test" || exe_str == "gtest_all_test" ||
       exe_str == "lt-gtest_all_test" || exe_str == "gtest_dll_test";
-#endif  // GTEST_OS_WINDOWS
+#endif  // platform ifdefs
+
   if (!success) FAIL() << "GetCurrentExecutableName() returns " << exe_str;
 }
 
diff --git a/src/third_party/googletest/googletest/test/googletest-output-test-golden-lin.txt b/src/third_party/googletest/googletest/test/googletest-output-test-golden-lin.txt
index 6ddf822..533eb8c 100644
--- a/src/third_party/googletest/googletest/test/googletest-output-test-golden-lin.txt
+++ b/src/third_party/googletest/googletest/test/googletest-output-test-golden-lin.txt
@@ -696,7 +696,6 @@
   Actual:
 googletest-output-test_.cc:#: Success:
 Succeeded
-Stack trace: (omitted)
 
 
 Stack trace: (omitted)
@@ -733,7 +732,6 @@
   Actual:
 googletest-output-test_.cc:#: Success:
 Succeeded
-Stack trace: (omitted)
 
 
 Stack trace: (omitted)
@@ -770,7 +768,6 @@
   Actual:
 googletest-output-test_.cc:#: Success:
 Succeeded
-Stack trace: (omitted)
 
 
 Stack trace: (omitted)
@@ -807,7 +804,6 @@
   Actual:
 googletest-output-test_.cc:#: Success:
 Succeeded
-Stack trace: (omitted)
 
 
 Stack trace: (omitted)
@@ -970,7 +966,6 @@
 [----------] 1 test from TestSuiteThatSkipsInSetUp
 googletest-output-test_.cc:#: Skipped
 Skip entire test suite
-Stack trace: (omitted)
 
 [ RUN      ] TestSuiteThatSkipsInSetUp.ShouldNotRun
 googletest-output-test_.cc:#: Skipped
diff --git a/src/third_party/googletest/googletest/test/googletest-port-test.cc b/src/third_party/googletest/googletest/test/googletest-port-test.cc
index e0793ba..9f05a01 100644
--- a/src/third_party/googletest/googletest/test/googletest-port-test.cc
+++ b/src/third_party/googletest/googletest/test/googletest-port-test.cc
@@ -296,7 +296,7 @@
 TEST(GetThreadCountTest, ReturnsCorrectValue) {
   size_t starting_count;
   size_t thread_count_after_create;
-  size_t thread_count_after_join;
+  size_t thread_count_after_join = 0;
 
   // We can't guarantee that no other thread was created or destroyed between
   // any two calls to GetThreadCount(). We make multiple attempts, hoping that
@@ -316,9 +316,9 @@
       const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
       ASSERT_EQ(0, pthread_attr_destroy(&attr));
       ASSERT_EQ(0, status);
-    }
 
-    thread_count_after_create = GetThreadCount();
+      thread_count_after_create = GetThreadCount();
+    }
 
     void* dummy;
     ASSERT_EQ(0, pthread_join(thread_id, &dummy));
@@ -418,8 +418,8 @@
   const RE simple(TypeParam("hello"));
   EXPECT_STREQ("hello", simple.pattern());
 
-  const RE normal(TypeParam(".*([[:alnum:]_]+)"));
-  EXPECT_STREQ(".*([[:alnum:]_]+)", normal.pattern());
+  const RE normal(TypeParam(".*(\\w+)"));
+  EXPECT_STREQ(".*(\\w+)", normal.pattern());
 }
 
 // Tests that RE's constructors reject invalid regular expressions.
diff --git a/src/third_party/googletest/googletest/test/googletest-printers-test.cc b/src/third_party/googletest/googletest/test/googletest-printers-test.cc
index d5061be..52b2c49 100644
--- a/src/third_party/googletest/googletest/test/googletest-printers-test.cc
+++ b/src/third_party/googletest/googletest/test/googletest-printers-test.cc
@@ -64,6 +64,10 @@
 #include <span>  // NOLINT
 #endif  // GTEST_INTERNAL_HAS_STD_SPAN
 
+#if GTEST_INTERNAL_HAS_COMPARE_LIB
+#include <compare>  // NOLINT
+#endif              // GTEST_INTERNAL_HAS_COMPARE_LIB
+
 // Some user-defined types for testing the universal value printer.
 
 // An anonymous enum type.
@@ -117,6 +121,9 @@
 // A user-defined streamable type in the global namespace.
 class StreamableInGlobal {
  public:
+  StreamableInGlobal() = default;
+  StreamableInGlobal(const StreamableInGlobal&) = default;
+  StreamableInGlobal& operator=(const StreamableInGlobal&) = default;
   virtual ~StreamableInGlobal() = default;
 };
 
@@ -568,6 +575,8 @@
 }
 
 // Tests that u8 strings are escaped properly.
+// TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
 TEST(PrintU8StringTest, EscapesProperly) {
   const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
   EXPECT_EQ(PrintPointer(p) +
@@ -575,7 +584,8 @@
                 "hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
             Print(p));
 }
-#endif
+#endif  // _MSC_VER
+#endif  // __cpp_lib_char8_t
 
 // const char16_t*.
 TEST(PrintU16StringTest, Const) {
@@ -1970,6 +1980,26 @@
       PrintToString(Type(NonPrintable{})));
 }
 #endif  // GTEST_INTERNAL_HAS_VARIANT
+
+#if GTEST_INTERNAL_HAS_COMPARE_LIB
+TEST(PrintOrderingTest, Basic) {
+  EXPECT_EQ("(less)", PrintToString(std::strong_ordering::less));
+  EXPECT_EQ("(greater)", PrintToString(std::strong_ordering::greater));
+  // equal == equivalent for strong_ordering.
+  EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equivalent));
+  EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equal));
+
+  EXPECT_EQ("(less)", PrintToString(std::weak_ordering::less));
+  EXPECT_EQ("(greater)", PrintToString(std::weak_ordering::greater));
+  EXPECT_EQ("(equivalent)", PrintToString(std::weak_ordering::equivalent));
+
+  EXPECT_EQ("(less)", PrintToString(std::partial_ordering::less));
+  EXPECT_EQ("(greater)", PrintToString(std::partial_ordering::greater));
+  EXPECT_EQ("(equivalent)", PrintToString(std::partial_ordering::equivalent));
+  EXPECT_EQ("(unordered)", PrintToString(std::partial_ordering::unordered));
+}
+#endif
+
 namespace {
 class string_ref;
 
diff --git a/src/third_party/googletest/googletest/test/googletest-setuptestsuite-test_.cc b/src/third_party/googletest/googletest/test/googletest-setuptestsuite-test_.cc
index d20899f..f4c43cc 100644
--- a/src/third_party/googletest/googletest/test/googletest-setuptestsuite-test_.cc
+++ b/src/third_party/googletest/googletest/test/googletest-setuptestsuite-test_.cc
@@ -31,14 +31,14 @@
 
 class SetupFailTest : public ::testing::Test {
  protected:
-  static void SetUpTestSuite() { ASSERT_EQ("", "SET_UP_FAIL"); }
+  static void SetUpTestSuite() { ASSERT_STREQ("", "SET_UP_FAIL"); }
 };
 
 TEST_F(SetupFailTest, NoopPassingTest) {}
 
 class TearDownFailTest : public ::testing::Test {
  protected:
-  static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); }
+  static void TearDownTestSuite() { ASSERT_STREQ("", "TEAR_DOWN_FAIL"); }
 };
 
 TEST_F(TearDownFailTest, NoopPassingTest) {}
diff --git a/src/third_party/googletest/googletest/test/gtest_environment_test.cc b/src/third_party/googletest/googletest/test/gtest_environment_test.cc
index 122eaf3..03657c7 100644
--- a/src/third_party/googletest/googletest/test/gtest_environment_test.cc
+++ b/src/third_party/googletest/googletest/test/gtest_environment_test.cc
@@ -40,16 +40,21 @@
 
 enum FailureType { NO_FAILURE, NON_FATAL_FAILURE, FATAL_FAILURE };
 
+// Was SetUp run?
+bool set_up_was_run;
+// Was TearDown run?
+bool tear_down_was_run;
+// Was the TEST run?
+bool test_was_run;
+
 // For testing using global test environments.
 class MyEnvironment : public testing::Environment {
  public:
-  MyEnvironment() { Reset(); }
-
   // Depending on the value of failure_in_set_up_, SetUp() will
   // generate a non-fatal failure, generate a fatal failure, or
   // succeed.
   void SetUp() override {
-    set_up_was_run_ = true;
+    set_up_was_run = true;
 
     switch (failure_in_set_up_) {
       case NON_FATAL_FAILURE:
@@ -65,36 +70,18 @@
 
   // Generates a non-fatal failure.
   void TearDown() override {
-    tear_down_was_run_ = true;
+    tear_down_was_run = true;
     ADD_FAILURE() << "Expected non-fatal failure in global tear-down.";
   }
 
-  // Resets the state of the environment s.t. it can be reused.
-  void Reset() {
-    failure_in_set_up_ = NO_FAILURE;
-    set_up_was_run_ = false;
-    tear_down_was_run_ = false;
-  }
-
   // We call this function to set the type of failure SetUp() should
   // generate.
   void set_failure_in_set_up(FailureType type) { failure_in_set_up_ = type; }
 
-  // Was SetUp() run?
-  bool set_up_was_run() const { return set_up_was_run_; }
-
-  // Was TearDown() run?
-  bool tear_down_was_run() const { return tear_down_was_run_; }
-
  private:
   FailureType failure_in_set_up_;
-  bool set_up_was_run_;
-  bool tear_down_was_run_;
 };
 
-// Was the TEST run?
-bool test_was_run;
-
 // The sole purpose of this TEST is to enable us to check whether it
 // was run.
 TEST(FooTest, Bar) { test_was_run = true; }
@@ -112,67 +99,88 @@
 // The 'failure' parameter specifies the type of failure that should
 // be generated by the global set-up.
 int RunAllTests(MyEnvironment* env, FailureType failure) {
-  env->Reset();
-  env->set_failure_in_set_up(failure);
+  set_up_was_run = false;
+  tear_down_was_run = false;
   test_was_run = false;
+  env->set_failure_in_set_up(failure);
   testing::internal::GetUnitTestImpl()->ClearAdHocTestResult();
   return RUN_ALL_TESTS();
 }
 
+// Registers a global test environment, and verifies that the
+// registration function returns its argument.
+MyEnvironment* RegisterTestEnv() {
+  MyEnvironment* const env = new MyEnvironment;
+  Check(testing::AddGlobalTestEnvironment(env) == env,
+        "AddGlobalTestEnvironment() should return its argument.");
+  return env;
+}
+
+// Verifies that RUN_ALL_TESTS() runs the tests when the global
+// set-up is successful.
+void TestGlobalSetUp() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, NO_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
+        "should generate a failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "failure");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() runs the tests when the global
+// set-up generates no fatal failure.
+void TestTestsRun() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
+        "and the global tear-down should generate a non-fatal failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "fatal failure.");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() runs no test when the global set-up
+// generates a fatal failure.
+void TestNoTestsRunSetUpFailure() {
+  MyEnvironment* const env = RegisterTestEnv();
+  Check(RunAllTests(env, FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global set-up "
+        "should generate a fatal failure.");
+  Check(!test_was_run,
+        "The tests should not run, as the global set-up should generate "
+        "a fatal failure.");
+  Check(tear_down_was_run,
+        "The global tear-down should run, as the global set-up was run.");
+}
+
+// Verifies that RUN_ALL_TESTS() doesn't do global set-up or
+// tear-down when there is no test to run.
+void TestNoTestsSkipsSetUp() {
+  MyEnvironment* const env = RegisterTestEnv();
+  GTEST_FLAG_SET(filter, "-*");
+  Check(RunAllTests(env, NO_FAILURE) == 0,
+        "RUN_ALL_TESTS() should return zero, as there is no test to run.");
+  Check(!set_up_was_run,
+        "The global set-up should not run, as there is no test to run.");
+  Check(!tear_down_was_run,
+        "The global tear-down should not run, "
+        "as the global set-up was not run.");
+}
+
 }  // namespace
 
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
 
-  // Registers a global test environment, and verifies that the
-  // registration function returns its argument.
-  MyEnvironment* const env = new MyEnvironment;
-  Check(testing::AddGlobalTestEnvironment(env) == env,
-        "AddGlobalTestEnvironment() should return its argument.");
-
-  // Verifies that RUN_ALL_TESTS() runs the tests when the global
-  // set-up is successful.
-  Check(RunAllTests(env, NO_FAILURE) != 0,
-        "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
-        "should generate a failure.");
-  Check(test_was_run,
-        "The tests should run, as the global set-up should generate no "
-        "failure");
-  Check(env->tear_down_was_run(),
-        "The global tear-down should run, as the global set-up was run.");
-
-  // Verifies that RUN_ALL_TESTS() runs the tests when the global
-  // set-up generates no fatal failure.
-  Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
-        "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
-        "and the global tear-down should generate a non-fatal failure.");
-  Check(test_was_run,
-        "The tests should run, as the global set-up should generate no "
-        "fatal failure.");
-  Check(env->tear_down_was_run(),
-        "The global tear-down should run, as the global set-up was run.");
-
-  // Verifies that RUN_ALL_TESTS() runs no test when the global set-up
-  // generates a fatal failure.
-  Check(RunAllTests(env, FATAL_FAILURE) != 0,
-        "RUN_ALL_TESTS() should return non-zero, as the global set-up "
-        "should generate a fatal failure.");
-  Check(!test_was_run,
-        "The tests should not run, as the global set-up should generate "
-        "a fatal failure.");
-  Check(env->tear_down_was_run(),
-        "The global tear-down should run, as the global set-up was run.");
-
-  // Verifies that RUN_ALL_TESTS() doesn't do global set-up or
-  // tear-down when there is no test to run.
-  GTEST_FLAG_SET(filter, "-*");
-  Check(RunAllTests(env, NO_FAILURE) == 0,
-        "RUN_ALL_TESTS() should return zero, as there is no test to run.");
-  Check(!env->set_up_was_run(),
-        "The global set-up should not run, as there is no test to run.");
-  Check(!env->tear_down_was_run(),
-        "The global tear-down should not run, "
-        "as the global set-up was not run.");
+  TestGlobalSetUp();
+  TestTestsRun();
+  TestNoTestsRunSetUpFailure();
+  TestNoTestsSkipsSetUp();
 
   printf("PASS\n");
   return 0;
diff --git a/src/third_party/googletest/googletest/test/gtest_json_test_utils.py b/src/third_party/googletest/googletest/test/gtest_json_test_utils.py
index 86a5925..694a7a6 100644
--- a/src/third_party/googletest/googletest/test/gtest_json_test_utils.py
+++ b/src/third_party/googletest/googletest/test/gtest_json_test_utils.py
@@ -51,6 +51,9 @@
     elif key == 'failure':
       value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
       return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
+    elif key == 'message':
+      value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
+      return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
     elif key == 'file':
       return re.sub(r'^.*[/\\](.*)', '\\1', value)
     else:
diff --git a/src/third_party/googletest/googletest/test/gtest_repeat_test.cc b/src/third_party/googletest/googletest/test/gtest_repeat_test.cc
index f67b788..55103d0 100644
--- a/src/third_party/googletest/googletest/test/gtest_repeat_test.cc
+++ b/src/third_party/googletest/googletest/test/gtest_repeat_test.cc
@@ -61,7 +61,6 @@
 
 class MyEnvironment : public testing::Environment {
  public:
-  MyEnvironment() = default;
   void SetUp() override { g_environment_set_up_count++; }
   void TearDown() override { g_environment_tear_down_count++; }
 };
@@ -117,6 +116,7 @@
   g_should_pass_count = 0;
   g_death_test_count = 0;
   g_param_test_count = 0;
+  testing::AddGlobalTestEnvironment(new MyEnvironment);
 }
 
 // Checks that the count for each test is expected.
@@ -197,8 +197,6 @@
 int main(int argc, char **argv) {
   testing::InitGoogleTest(&argc, argv);
 
-  testing::AddGlobalTestEnvironment(new MyEnvironment);
-
   TestRepeatUnspecified();
   TestRepeat(0);
   TestRepeat(1);
diff --git a/src/third_party/googletest/googletest/test/gtest_unittest.cc b/src/third_party/googletest/googletest/test/gtest_unittest.cc
index 67d776e..559d34c 100644
--- a/src/third_party/googletest/googletest/test/gtest_unittest.cc
+++ b/src/third_party/googletest/googletest/test/gtest_unittest.cc
@@ -422,11 +422,14 @@
   EXPECT_EQ("-1234567.89", FormatTimeInMillisAsSeconds(-1234567890));
 }
 
+// TODO: b/287046337 - In emscripten, local time zone modification is not
+// supported.
+#if !defined(__EMSCRIPTEN__)
 // Tests FormatEpochTimeInMillisAsIso8601().  The correctness of conversion
 // for particular dates below was verified in Python using
 // datetime.datetime.fromutctimestamp(<timestamp>/1000).
 
-// FormatEpochTimeInMillisAsIso8601 depends on the current timezone, so we
+// FormatEpochTimeInMillisAsIso8601 depends on the local timezone, so we
 // have to set up a particular timezone to obtain predictable results.
 class FormatEpochTimeInMillisAsIso8601Test : public Test {
  public:
@@ -445,9 +448,8 @@
     }
     GTEST_DISABLE_MSC_DEPRECATED_POP_()
 
-    // Set up the time zone for FormatEpochTimeInMillisAsIso8601 to use.  We
-    // cannot use the local time zone because the function's output depends
-    // on the time zone.
+    // Set the local time zone for FormatEpochTimeInMillisAsIso8601 to be
+    // a fixed time zone for reproducibility purposes.
     SetTimeZone("UTC+00");
   }
 
@@ -514,6 +516,8 @@
   EXPECT_EQ("1970-01-01T00:00:00.000", FormatEpochTimeInMillisAsIso8601(0));
 }
 
+#endif  // __EMSCRIPTEN__
+
 #ifdef __BORLANDC__
 // Silences warnings: "Condition is always true", "Unreachable code"
 #pragma option push -w-ccc -w-rch
@@ -2159,7 +2163,7 @@
 };
 
 // This will test property recording outside of any test or test case.
-static Environment* record_property_env GTEST_ATTRIBUTE_UNUSED_ =
+[[maybe_unused]] static Environment* record_property_env =
     AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
 
 // This group of tests is for predicate assertions (ASSERT_PRED*, etc)
@@ -2866,6 +2870,8 @@
 // This ensures that no overflow occurs when comparing numbers whose
 // absolute value is very large.
 TEST_F(FloatTest, Infinity) {
+  EXPECT_FLOAT_EQ(values_.infinity, values_.infinity);
+  EXPECT_FLOAT_EQ(-values_.infinity, -values_.infinity);
   EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
   EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
   EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
@@ -2890,6 +2896,11 @@
   EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1");
   EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2");
   EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, 1.0f), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, v.infinity), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0f), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
+                          "v.nan1");
 
   EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity");
 }
@@ -2913,11 +2924,28 @@
 
 // Tests EXPECT_NEAR.
 TEST_F(FloatTest, EXPECT_NEAR) {
+  static const FloatTest::TestValues& v = this->values_;
+
   EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
   EXPECT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_NEAR(v.infinity, v.infinity, 0.0f);
+  EXPECT_NEAR(-v.infinity, -v.infinity, 0.0f);
+  EXPECT_NEAR(0.0f, 1.0f, v.infinity);
+  EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
+  EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
   EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f),  // NOLINT
                           "The difference between 1.0f and 1.5f is 0.5, "
                           "which exceeds 0.25f");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0f),  // NOLINT
+                          "The difference between v.infinity and -v.infinity "
+                          "is inf, which exceeds 0.0f");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0f),  // NOLINT
+                          "The difference between -v.infinity and v.infinity "
+                          "is inf, which exceeds 0.0f");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
+      "The difference between v.infinity and v.close_to_infinity is inf, which "
+      "exceeds v.further_from_infinity");
 }
 
 // Tests ASSERT_NEAR.
@@ -3024,6 +3052,8 @@
 // This ensures that no overflow occurs when comparing numbers whose
 // absolute value is very large.
 TEST_F(DoubleTest, Infinity) {
+  EXPECT_DOUBLE_EQ(values_.infinity, values_.infinity);
+  EXPECT_DOUBLE_EQ(-values_.infinity, -values_.infinity);
   EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
   EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
   EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
@@ -3043,6 +3073,12 @@
   EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1");
   EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
   EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, 1.0), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, v.infinity), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0), "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
+                          "v.nan1");
+
   EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity");
 }
 
@@ -3065,11 +3101,28 @@
 
 // Tests EXPECT_NEAR.
 TEST_F(DoubleTest, EXPECT_NEAR) {
+  static const DoubleTest::TestValues& v = this->values_;
+
   EXPECT_NEAR(-1.0, -1.1, 0.2);
   EXPECT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_NEAR(v.infinity, v.infinity, 0.0);
+  EXPECT_NEAR(-v.infinity, -v.infinity, 0.0);
+  EXPECT_NEAR(0.0, 1.0, v.infinity);
+  EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
+  EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
   EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25),  // NOLINT
                           "The difference between 1.0 and 1.5 is 0.5, "
                           "which exceeds 0.25");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0),
+                          "The difference between v.infinity and -v.infinity "
+                          "is inf, which exceeds 0.0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0),
+                          "The difference between -v.infinity and v.infinity "
+                          "is inf, which exceeds 0.0");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
+      "The difference between v.infinity and v.close_to_infinity is inf, which "
+      "exceeds v.further_from_infinity");
   // At this magnitude adjacent doubles are 512.0 apart, so this triggers a
   // slightly different failure reporting path.
   EXPECT_NONFATAL_FAILURE(
@@ -4168,8 +4221,8 @@
 #endif
 TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
   if (AlwaysFalse())
-    EXPECT_NO_FATAL_FAILURE(FAIL()) << "This should never be executed. "
-                                    << "It's a compilation test only.";
+    EXPECT_NO_FATAL_FAILURE(FAIL())
+        << "This should never be executed. " << "It's a compilation test only.";
   else
     ;  // NOLINT
 
@@ -6667,6 +6720,9 @@
   SetEnv("TERM", "xterm-kitty");      // TERM supports colors.
   EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
 
+  SetEnv("TERM", "alacritty");        // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
   SetEnv("TERM", "xterm-256color");   // TERM supports colors.
   EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
 
@@ -6691,15 +6747,15 @@
   SetEnv("TERM", "linux");            // TERM supports colors.
   EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
 
-  SetEnv("TERM", "cygwin");  // TERM supports colors.
+  SetEnv("TERM", "cygwin");           // TERM supports colors.
   EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
 #endif  // GTEST_OS_WINDOWS
 }
 
 // Verifies that StaticAssertTypeEq works in a namespace scope.
 
-static bool dummy1 GTEST_ATTRIBUTE_UNUSED_ = StaticAssertTypeEq<bool, bool>();
-static bool dummy2 GTEST_ATTRIBUTE_UNUSED_ =
+[[maybe_unused]] static bool dummy1 = StaticAssertTypeEq<bool, bool>();
+[[maybe_unused]] static bool dummy2 =
     StaticAssertTypeEq<const int, const int>();
 
 // Verifies that StaticAssertTypeEq works in a class.
@@ -7475,22 +7531,6 @@
   EXPECT_EQ(a, na.begin());
 }
 
-// IndexSequence
-TEST(IndexSequence, MakeIndexSequence) {
-  using testing::internal::IndexSequence;
-  using testing::internal::MakeIndexSequence;
-  EXPECT_TRUE(
-      (std::is_same<IndexSequence<>, MakeIndexSequence<0>::type>::value));
-  EXPECT_TRUE(
-      (std::is_same<IndexSequence<0>, MakeIndexSequence<1>::type>::value));
-  EXPECT_TRUE(
-      (std::is_same<IndexSequence<0, 1>, MakeIndexSequence<2>::type>::value));
-  EXPECT_TRUE((
-      std::is_same<IndexSequence<0, 1, 2>, MakeIndexSequence<3>::type>::value));
-  EXPECT_TRUE(
-      (std::is_base_of<IndexSequence<0, 1, 2>, MakeIndexSequence<3>>::value));
-}
-
 // ElemFromList
 TEST(ElemFromList, Basic) {
   using testing::internal::ElemFromList;
diff --git a/src/third_party/googletest/googletest/test/gtest_xml_output_unittest.py b/src/third_party/googletest/googletest/test/gtest_xml_output_unittest.py
index 422569e..87a7683 100755
--- a/src/third_party/googletest/googletest/test/gtest_xml_output_unittest.py
+++ b/src/third_party/googletest/googletest/test/gtest_xml_output_unittest.py
@@ -29,14 +29,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Unit test for the gtest_xml_output module"""
+"""Unit test for the gtest_xml_output module."""
 
 import datetime
 import errno
 import os
 import re
 import sys
-from xml.dom import minidom, Node
+from xml.dom import minidom
 
 from googletest.test import gtest_test_utils
 from googletest.test import gtest_xml_test_utils
@@ -67,7 +67,10 @@
   sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
 
 EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="26" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
+<testsuites tests="28" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests">
+  <properties>
+    <property name="ad_hoc_property" value="42"/>
+  </properties>
   <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
     <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
   </testsuite>
@@ -112,81 +115,111 @@
   </testsuite>
   <testsuite name="SkippedTest" tests="3" failures="1" disabled="0" skipped="2" errors="0" time="*" timestamp="*">
     <testcase name="Skipped" status="run" file="gtest_xml_output_unittest_.cc" line="75" result="skipped" time="*" timestamp="*" classname="SkippedTest">
-      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;%(stack_entity)s"><![CDATA[gtest_xml_output_unittest_.cc:*
-%(stack)s]]></skipped>
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+
+]]></skipped>
     </testcase>
     <testcase name="SkippedWithMessage" file="gtest_xml_output_unittest_.cc" line="79" status="run" result="skipped" time="*" timestamp="*" classname="SkippedTest">
-      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.%(stack_entity)s"><![CDATA[gtest_xml_output_unittest_.cc:*
-It is good practice to tell why you skip a test.%(stack)s]]></skipped>
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+It is good practice to tell why you skip a test.
+]]></skipped>
     </testcase>
     <testcase name="SkippedAfterFailure" file="gtest_xml_output_unittest_.cc" line="83" status="run" result="completed" time="*" timestamp="*" classname="SkippedTest">
       <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
 Expected equality of these values:
   1
   2%(stack)s]]></failure>
-      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.%(stack_entity)s"><![CDATA[gtest_xml_output_unittest_.cc:*
-It is good practice to tell why you skip a test.%(stack)s]]></skipped>
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;It is good practice to tell why you skip a test.&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+It is good practice to tell why you skip a test.
+]]></skipped>
     </testcase>
 
   </testsuite>
-  <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
-    <testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="121" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+  <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <properties>
+      <property name="SetUpTestSuite" value="yes"/>
+      <property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
+      <property name="TearDownTestSuite" value="aye"/>
+      <property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
+    </properties>
+    <testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
       <properties>
         <property name="key_1" value="1"/>
       </properties>
     </testcase>
-    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
       <properties>
         <property name="key_int" value="1"/>
       </properties>
     </testcase>
-    <testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+    <testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="133" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
       <properties>
         <property name="key_1" value="1"/>
         <property name="key_2" value="2"/>
         <property name="key_3" value="3"/>
       </properties>
     </testcase>
-    <testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="135" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+    <testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="139" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
       <properties>
         <property name="key_1" value="2"/>
       </properties>
     </testcase>
   </testsuite>
   <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-     <testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="140" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+     <testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="144" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
        <properties>
          <property name="key" value="1"/>
        </properties>
      </testcase>
-     <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="153" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+     <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
        <properties>
          <property name="key_for_utility_int" value="1"/>
        </properties>
      </testcase>
-     <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
+     <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="161" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
        <properties>
          <property name="key_for_utility_string" value="1"/>
        </properties>
      </testcase>
   </testsuite>
+  <testsuite name="SetupFailTest" tests="1" failures="0" disabled="0" skipped="1" errors="0" time="*" timestamp="*">
+    <testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="172" status="run" result="skipped" time="*" timestamp="*" classname="SetupFailTest">
+      <skipped message="gtest_xml_output_unittest_.cc:*&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
+]]></skipped>
+    </testcase>
+    <testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="TearDownFailTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="179" status="run" result="completed" time="*" timestamp="*" classname="TearDownFailTest"/>
+    <testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A;  1&#x0A;  2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Expected equality of these values:
+  1
+  2%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
   <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
-    <testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="164" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
-    <testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="165" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
-    <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="165" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="184" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="184" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="185" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="185" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
   </testsuite>
   <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
   </testsuite>
   <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
   </testsuite>
   <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
   </testsuite>
   <testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
+    <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
   </testsuite>
 </testsuites>""" % {
     'stack': STACK_TRACE_TEMPLATE,
@@ -194,8 +227,10 @@
 }
 
 EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
-            timestamp="*" name="AllTests" ad_hoc_property="42">
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <properties>
+    <property name="ad_hoc_property" value="42"/>
+  </properties>
   <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0"
              errors="0" time="*" timestamp="*">
     <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
@@ -203,19 +238,28 @@
 </testsuites>"""
 
 EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
+<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <properties>
+    <property name="ad_hoc_property" value="42"/>
+  </properties>
   <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
     <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
   </testsuite>
-  <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
-    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
+  <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <properties>
+      <property name="SetUpTestSuite" value="yes"/>
+      <property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
+      <property name="TearDownTestSuite" value="aye"/>
+      <property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
+    </properties>
+    <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
       <properties>
         <property name="key_int" value="1"/>
       </properties>
     </testcase>
   </testsuite>
-  <testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
-    <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
+  <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" file="gtest_xml_output_unittest_.cc" line="200" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
   </testsuite>
 </testsuites>"""
 
diff --git a/src/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc b/src/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc
index 0ab3302..fe196b6 100644
--- a/src/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc
+++ b/src/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc
@@ -112,8 +112,12 @@
 
 class PropertyRecordingTest : public Test {
  public:
-  static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); }
+  static void SetUpTestSuite() {
+    RecordProperty("SetUpTestSuite (with whitespace)", "yes and yes");
+    RecordProperty("SetUpTestSuite", "yes");
+  }
   static void TearDownTestSuite() {
+    RecordProperty("TearDownTestSuite (with whitespace)", "aye and aye");
     RecordProperty("TearDownTestSuite", "aye");
   }
 };
@@ -158,6 +162,22 @@
   ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
 }
 
+// Ensures that SetUpTestSuite and TearDownTestSuite failures are reported in
+// the XML output.
+class SetupFailTest : public ::testing::Test {
+ protected:
+  static void SetUpTestSuite() { ASSERT_EQ(1, 2); }
+};
+
+TEST_F(SetupFailTest, NoopPassingTest) {}
+
+class TearDownFailTest : public ::testing::Test {
+ protected:
+  static void TearDownTestSuite() { ASSERT_EQ(1, 2); }
+};
+
+TEST_F(TearDownFailTest, NoopPassingTest) {}
+
 // Verifies that the test parameter value is output in the 'value_param'
 // XML attribute for value-parameterized tests.
 class ValueParamTest : public TestWithParam<int> {};
diff --git a/src/third_party/googletest/googletest_deps.bzl b/src/third_party/googletest/googletest_deps.bzl
index e25f5a1..d3dd03e 100644
--- a/src/third_party/googletest/googletest_deps.bzl
+++ b/src/third_party/googletest/googletest_deps.bzl
@@ -1,22 +1,28 @@
 """Load dependencies needed to use the googletest library as a 3rd-party consumer."""
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
 
 def googletest_deps():
     """Loads common dependencies needed to use the googletest library."""
 
-    if not native.existing_rule("com_googlesource_code_re2"):
+    if not native.existing_rule("re2"):
         http_archive(
-            name = "com_googlesource_code_re2",  # 2023-03-17T11:36:51Z
-            sha256 = "cb8b5312a65f2598954545a76e8bce913f35fbb3a21a5c88797a4448e9f9b9d9",
-            strip_prefix = "re2-578843a516fd1da7084ae46209a75f3613b6065e",
-            urls = ["https://github.com/google/re2/archive/578843a516fd1da7084ae46209a75f3613b6065e.zip"],
+            name = "re2",
+            sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
+            strip_prefix = "re2-2024-07-02",
+            urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
         )
 
-    if not native.existing_rule("com_google_absl"):
+    if not native.existing_rule("abseil-cpp"):
         http_archive(
-            name = "com_google_absl",  # 2023-08-01T14:59:13Z
-            sha256 = "d2c09bf3b3aba57ad87a56082020bee2948445407756e92ddaf3595396086853",
-            strip_prefix = "abseil-cpp-22091f4c0d6626b3ef40446ce3d4ccab19425ca3",
-            urls = ["https://github.com/abseil/abseil-cpp/archive/22091f4c0d6626b3ef40446ce3d4ccab19425ca3.zip"],
+            name = "abseil-cpp",
+            sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8",
+            strip_prefix = "abseil-cpp-20250127.0",
+            urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"],
+        )
+
+    if not native.existing_rule("fuchsia_sdk"):
+        fake_fuchsia_sdk(
+            name = "fuchsia_sdk",
         )
diff --git a/src/third_party/wycheproof_testvectors/aes_eax_test.txt b/src/third_party/wycheproof_testvectors/aes_eax_test.txt
new file mode 100644
index 0000000..210524e
--- /dev/null
+++ b/src/third_party/wycheproof_testvectors/aes_eax_test.txt
@@ -0,0 +1,1820 @@
+# Imported from Wycheproof's third_party/wycheproof_testvectors/aes_eax_test.json.
+# This file is generated by convert_wycheproof.go. Do not edit by hand.
+#
+# Algorithm: AES-EAX
+# Generator version: 0.8r12
+
+[ivSize = 128]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 1
+# eprint.iacr.org/2003/069
+aad = 6bfb914fd07eae6b
+ct = 
+iv = 62ec67f9c3a4a407fcb2a8c49031a8b3
+key = 233952dee4d5ed5f9b9c6d6ff80ff478
+msg = 
+result = valid
+tag = e037830e8389f27b025a2d6527e79d01
+
+# tcId = 2
+# eprint.iacr.org/2003/069
+aad = fa3bfd4806eb53fa
+ct = 19dd
+iv = becaf043b0a23d843194ba972c66debd
+key = 91945d3f4dcbee0bf45ef52255f095a4
+msg = f7fb
+result = valid
+tag = 5c4c9331049d0bdab0277408f67967e5
+
+# tcId = 3
+# eprint.iacr.org/2003/069
+aad = 234a3463c1264ac6
+ct = d851d5bae0
+iv = 70c3db4f0d26368400a10ed05d2bff5e
+key = 01f74ad64077f2e704c0f60ada3dd523
+msg = 1a47cb4933
+result = valid
+tag = 3a59f238a23e39199dc9266626c40f80
+
+# tcId = 4
+# eprint.iacr.org/2003/069
+aad = 33cce2eabff5a79d
+ct = 632a9d131a
+iv = 8408dfff3c1a2b1292dc199e46b7d617
+key = d07cf6cbb7f313bdde66b727afd3c5e8
+msg = 481c9e39b1
+result = valid
+tag = d4c168a4225d8e1ff755939974a7bede
+
+# tcId = 5
+# eprint.iacr.org/2003/069
+aad = aeb96eaebe2970e9
+ct = 071dfe16c675
+iv = fdb6b06676eedc5c61d74276e1f8e816
+key = 35b6d0580005bbc12b0587124557d2c2
+msg = 40d0c07da5e4
+result = valid
+tag = cb0677e536f73afe6a14b74ee49844dd
+
+# tcId = 6
+# eprint.iacr.org/2003/069
+aad = d4482d1ca78dce0f
+ct = 835bb4f15d743e350e728414
+iv = 6eac5c93072d8e8513f750935e46da1b
+key = bd8e6e11475e60b268784c38c62feb22
+msg = 4de3b35c3fc039245bd1fb7d
+result = valid
+tag = abb8644fd6ccb86947c5e10590210a4f
+
+# tcId = 7
+# eprint.iacr.org/2003/069
+aad = 65d2017990d62528
+ct = 02083e3979da014812f59f11d52630da30
+iv = 1a8c98dcd73d38393b2bf1569deefc19
+key = 7c77d6e813bed5ac98baa417477a2e7d
+msg = 8b0a79306c9ce7ed99dae4f87f8dd61636
+result = valid
+tag = 137327d10649b0aa6e1c181db617d7f2
+
+# tcId = 8
+# eprint.iacr.org/2003/069
+aad = 54b9f04e6a09189a
+ct = 2ec47b2c4954a489afc7ba4897edcdae8cc3
+iv = dde59b97d722156d4d9aff2bc7559826
+key = 5fff20cafab119ca2fc73549e20f5b0d
+msg = 1bda122bce8a8dbaf1877d962b8592dd2d56
+result = valid
+tag = 3b60450599bd02c96382902aef7f832a
+
+# tcId = 9
+# eprint.iacr.org/2003/069
+aad = 899a175897561d7e
+ct = 0de18fd0fdd91e7af19f1d8ee8733938b1e8
+iv = b781fcf2f75fa5a8de97a9ca48e522ec
+key = a4a4782bcffd3ec5e7ef6d8c34a56123
+msg = 6cf36720872b8513f6eab1a8a44438d5ef11
+result = valid
+tag = e7f6d2231618102fdb7fe55ff1991700
+
+# tcId = 10
+# eprint.iacr.org/2003/069
+aad = 126735fcc320d25a
+ct = cb8920f87a6c75cff39627b56e3ed197c552d295a7
+iv = 22e7add93cfc6393c57ec0b3c17d6b44
+key = 8395fcf1e95bebd697bd010bc766aac3
+msg = ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7
+result = valid
+tag = cfc46afc253b4652b1af3795b124ab6e
+
+# tcId = 11
+# Initial counter value == 2^128-1
+aad = 
+ct = 3c441f32ce07822364d7a2990e50bb13d7b02a26969e4a937e5e9073b0d9c968
+iv = 3c8cc2970a008f75cc5beae2847258c2
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = db90bdb3da3d00afd0fc6a83551da95e
+flags = CounterWrap
+
+# tcId = 12
+# counter value overflows at 64-bit boundary
+aad = 
+ct = d19ac59849026a91aa1b9aec29b11a202a4d739fd86c28e3ae3d588ea21d70c6
+iv = aef03d00598494e9fb03cd7d8b590866
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = c30f6cd9202074ed6e2a2a360eac8c47
+flags = CounterWrap
+
+# tcId = 13
+# no counter overflow, but the 64 most significant bits are set.
+aad = 
+ct = 2108558ac4b2c2d5cc66cea51d6210e046177a67631cd2dd8f09469733acb517
+iv = 55d12511c696a80d0514d1ffba49cada
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = fc355e87a267be3ae3e44c0bf3f99b2b
+flags = CounterWrap
+
+# tcId = 14
+# counter value overflows at 32-bit boundary
+aad = 
+ct = 4d2c1524ca4baa4eefcce6b91b227ee83abaff8105dcafa2ab191f5df2575035
+iv = 79422ddd91c4eee2deaef1f968305304
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = e2c865ce2d7abdac024c6f991a848390
+flags = CounterWrap
+
+# tcId = 15
+# bits 32-64 and 96-128 of counter are set
+aad = 
+ct = 8eb01e62185d782eb9287a341a6862ac5257d6f9adc99ee0a24d9c22b3e9b38a
+iv = 0af5aa7a7676e28306306bcd9bf2003a
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = 39c339bc8a74c75e2c65c6119544d61e
+flags = CounterWrap
+
+# tcId = 16
+# lower bits of initial counter are 2^63-1
+aad = 
+ct = 94c5d2aca6dbbce8c24513a25e095c0e54a942860d327a222a815cc713b163b4
+iv = af5a03ae7edd73471bdcdfac5e194a60
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111
+result = valid
+tag = f50b30304e45c9d411e8df4508a98612
+flags = CounterWrap
+
+# tcId = 17
+# counter overflow
+aad = 
+ct = 3bb6173e3772d4b62eef37f9ef0781f360b6c74be3bf6b371067bc1b090d9d6622a1fbec6ac471b3349cd4277a101d40890fbf27dfdcd0b4e3781f9806daabb6
+iv = b37087680f0edd5a52228b8c7aaea664
+key = 000102030405060708090a0b0c0d0e0f
+msg = 00000000000000000000000000000000111111111111111111111111111111112222222222222222222222222222222233333333333333333333333333333333
+result = valid
+tag = a0498745e59999ddc32d5b140241124e
+flags = CounterWrap
+
+# tcId = 18
+# lower 64 bits of initial counter are 2^63-4
+aad = 
+ct = e9b0bb8857818ce3201c3690d21daa7f264fb8ee93cc7a4674ea2fc32bf182fb2a7e8ad51507ad4f31cefc2356fe7936a7f6e19f95e88fdbf17620916d3a6f3d01fc17d358672f777fd4099246e436e1
+iv = 4f802da62a384555a19bc2b382eb25af
+key = 000102030405060708090a0b0c0d0e0f
+msg = 0000000000000000000000000000000011111111111111111111111111111111222222222222222222222222222222223333333333333333333333333333333344444444444444444444444444444444
+result = valid
+tag = 67910be744b8315ae0eb6124590c5d8b
+flags = CounterWrap
+
+# tcId = 19
+aad = 
+ct = 
+iv = fa294b129972f7fc5bbd5b96bba837c9
+key = b67b1a6efdd40d37080fbe8f8047aeb9
+msg = 
+result = valid
+tag = b14b64fb589899699570cc9160e39896
+
+# tcId = 20
+aad = 
+ct = 1d
+iv = 9477849d6ccdfca112d92e53fae4a7ca
+key = 209e6dbf2ad26a105445fc0207cd9e9a
+msg = 01
+result = valid
+tag = 52a5f600fe5338026a7cb09c11640082
+
+# tcId = 21
+aad = 
+ct = d7b8a6b43d2e9f98c2b44ce5e3cfdb
+iv = 5171524568e81d97e8c4de4ba56c10a0
+key = a549442e35154032d07c8666006aa6a2
+msg = 1182e93596cac5608946400bc73f3a
+result = valid
+tag = 1bdd52fc987daf0ee19234c905ea645f
+
+# tcId = 22
+aad = 
+ct = 73e5c6f0e703a52d02f7f7faeb1b77fd4fd0cb421eaf
+iv = 0e6ec879b02c6f516976e35898428da7
+key = 958bcdb66a3952b53701582a68a0e474
+msg = 140415823ecc8932a058384b738ea6ea6d4dfe3bbeee
+result = valid
+tag = 6c154a85968edd74776575a4450bd897
+
+# tcId = 23
+aad = df10d0d212242450
+ct = 936b69b6c955adfd15539b9be4989cb6
+iv = 2e35901ae7d491eecc8838fedd631405
+key = 965b757ba5018a8d66edc78e0ceee86b
+msg = 36e57a763958b02cea9d6a676ebce81f
+result = valid
+tag = ee15a1454e88faad8e48a8df2983b425
+
+# tcId = 24
+aad = 7c571d2fbb5f62523c0eb338bef9a9
+ct = 67caac35443a3138d2cb811f0ce04dd2
+iv = 7f2985296315507aa4c0a93d5c12bd77
+key = 88d02033781c7b4164711a05420f256e
+msg = d98adc03d9d582732eb07df23d7b9f74
+result = valid
+tag = b7968e0b5640e3b236569653208b9deb
+
+# tcId = 25
+aad = 16843c091d43b0a191d0c73d15601be9
+ct = 200ac451fbeb0f6151d61583a43b7343
+iv = bf47afdfd492137a24236bc36797a88e
+key = 515840cf67d2e40eb65e54a24c72cbf2
+msg = c834588cb6daf9f06dd23519f4be9f56
+result = valid
+tag = 2ad43e4caa51983a9d4d24481bf4c839
+
+# tcId = 26
+aad = 904d86f133cec15a0c3caf14d7e029c82a07705a23f0d080
+ct = 27c6e9a653c5253ca1c5673f97b9b33e
+iv = d02bf0763a9fefbf70c33aee1e9da1d6
+key = 2e4492d444e5b6f4cec8c2d3615ac858
+msg = 9e62d6511b0bda7dd7740b614d97bae0
+result = valid
+tag = 2d581271e1fa9e3686136caa8f4d6c8e
+
+# tcId = 27
+# Flipped bit 0 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e70e7c5013a6dbf25298b1929bc356a7
+
+# tcId = 28
+# Flipped bit 1 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e40e7c5013a6dbf25298b1929bc356a7
+
+# tcId = 29
+# Flipped bit 7 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 660e7c5013a6dbf25298b1929bc356a7
+
+# tcId = 30
+# Flipped bit 8 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60f7c5013a6dbf25298b1929bc356a7
+
+# tcId = 31
+# Flipped bit 31 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7cd013a6dbf25298b1929bc356a7
+
+# tcId = 32
+# Flipped bit 32 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5012a6dbf25298b1929bc356a7
+
+# tcId = 33
+# Flipped bit 33 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5011a6dbf25298b1929bc356a7
+
+# tcId = 34
+# Flipped bit 63 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6db725298b1929bc356a7
+
+# tcId = 35
+# Flipped bit 64 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25398b1929bc356a7
+
+# tcId = 36
+# Flipped bit 71 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf2d298b1929bc356a7
+
+# tcId = 37
+# Flipped bit 77 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf252b8b1929bc356a7
+
+# tcId = 38
+# Flipped bit 80 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b0929bc356a7
+
+# tcId = 39
+# Flipped bit 96 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1929ac356a7
+
+# tcId = 40
+# Flipped bit 97 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b19299c356a7
+
+# tcId = 41
+# Flipped bit 103 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1921bc356a7
+
+# tcId = 42
+# Flipped bit 120 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1929bc356a6
+
+# tcId = 43
+# Flipped bit 121 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1929bc356a5
+
+# tcId = 44
+# Flipped bit 126 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1929bc356e7
+
+# tcId = 45
+# Flipped bit 127 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6dbf25298b1929bc35627
+
+# tcId = 46
+# Flipped bits 0 and 64 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e70e7c5013a6dbf25398b1929bc356a7
+
+# tcId = 47
+# Flipped bits 31 and 63 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7cd013a6db725298b1929bc356a7
+
+# tcId = 48
+# Flipped bits 63 and 127 in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e60e7c5013a6db725298b1929bc35627
+
+# tcId = 49
+# all bits of tag flipped
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 19f183afec59240dad674e6d643ca958
+
+# tcId = 50
+# Tag changed to all zero
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 00000000000000000000000000000000
+
+# tcId = 51
+# tag changed to all 1
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = ffffffffffffffffffffffffffffffff
+
+# tcId = 52
+# msbs changed in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 668efcd093265b72d21831121b43d627
+
+# tcId = 53
+# lsbs changed in tag
+aad = 
+ct = 29a0914fec4bef54babf6613a9f9cd70
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e70f7d5112a7daf35399b0939ac257a6
+
+[ivSize = 96]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 54
+aad = 
+ct = 
+iv = 438a547a94ea88dce46c6c85
+key = bedcfb5a011ebc84600fcb296c15af0d
+msg = 
+result = valid
+tag = 9607977cd7556b1dfedf0c73a35a5197
+
+# tcId = 55
+aad = 
+ct = 98
+iv = b30c084727ad1c592ac21d12
+key = 384ea416ac3c2f51a76e7d8226346d4e
+msg = 35
+result = valid
+tag = f5d7930952e275beecb998d804c241f0
+
+# tcId = 56
+aad = 
+ct = 7fd2878318ab0f2b
+iv = b5e006ded553110e6dc56529
+key = cae31cd9f55526eb038241fc44cac1e5
+msg = d10989f2c52e94ad
+result = valid
+tag = ab184ffde523565529a9be111b0c2d6d
+
+# tcId = 57
+aad = 
+ct = e928622d1e6e798d8665ae732c4c1e5f
+iv = 0e1666f2dc652f7708fb8f0d
+key = ffdf4228361ea1f8165852136b3480f7
+msg = 25b12e28ac0ef6ead0226a3b2288c800
+result = valid
+tag = 33ab476757ffa42c0f6c276391a46eac
+
+# tcId = 58
+aad = 
+ct = efd299a43b25ce8cc31b80e5489ef9ce7356ececa91bc7bd
+iv = fbbc04fd6e025b7193eb57f6
+key = a8ee11b26d7ceb7f17eaa1e4b83a2cf6
+msg = c08f085e6a9e0ef3636280c11ecfadf0c1e72919ffc17eaf
+result = valid
+tag = 3c33fc0bcd256b0a8a34ecc8b01e52a6
+
+# tcId = 59
+aad = 
+ct = 356bca9cddd39efd393278e43b4e80266071608036e81d6e924d4e4800fb27
+iv = 42b51388f6f9047a2a994575
+key = 1655bf662f7ee685615701fd3779d628
+msg = 857b2f6cd608c9cea0246c740caa4ca19c5f1c7d71cb9273f0d8c8bb65b70a
+result = valid
+tag = 71f02ba7c6cf3a579e56245025420071
+
+# tcId = 60
+aad = 
+ct = 9d911b934a68ce7db322410028bd31bd81bcbdadf26f15676be472bc3821fb68e4728db76930bc0958aeed6faf3e333da7af3d48c480b424ff3d6600cc56a507c8ad
+iv = 064b3cfbe04d94d4d5c19b30
+key = 42e38abef2dd7573248c5aefb3ecca54
+msg = 2c763b9ec84903bcbb8aec15e678a3a955e4870edbf62d9d3c81c4f9ed6154877875779ca33cce8f73a55ca7af1d8d817fc6baac00ef962c5a0da339ce81427a3d59
+result = valid
+tag = d679eb9e5d744b62d91dcf6fb6284f41
+
+[ivSize = 96]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 61
+aad = 
+ct = 
+iv = ff0ddb0a0d7b36d219da12b5
+key = 5019eb9fef82e5750b631758f0213e3e5fcca12748b40eb4
+msg = 
+result = valid
+tag = bce273d0e68112371745e665ececa823
+
+# tcId = 62
+aad = 
+ct = a3
+iv = 34047bc39b9c608384dff5b8
+key = 21218af790428f8024d3e7e1428c9fcf578c216636d60e73
+msg = e3
+result = valid
+tag = 54a0b780af21eb4714feeecfafbb2226
+
+# tcId = 63
+aad = 
+ct = 58a3891bbda8d0ed
+iv = 4ebc13cf4636cc7c45e560a7
+key = 3a8bf543c480925632118245bcbf5d01522b987a31a33da3
+msg = 53fc72e71b59eeb3
+result = valid
+tag = af4e86d045c2397ee273fe9d3a324656
+
+# tcId = 64
+aad = 
+ct = 586e1aa844e2fa3749e44a0aa4cb745d
+iv = be0326d23bdc2c64648d13f4
+key = bcb6bc5ee6743df1396a34639327b25809ec9c81dd6a0c0e
+msg = 80474a3a3b809560eee2ce7a7a33ea07
+result = valid
+tag = 96f41c15cddf13c4032cfdaccf1c414a
+
+# tcId = 65
+aad = 
+ct = e271d068193af63e3c604659ad0268525f78dcb8a67b0c22
+iv = b022067048505b20946216ef
+key = 7f672d85e151aa490bc0eec8f66b5e5bee74af11642be3ff
+msg = ef6412c72b03c643fa02565a0ae2378a9311c11a84065f80
+result = valid
+tag = e345fba42d860b1c1886d0cc4c5db134
+
+# tcId = 66
+aad = 
+ct = 282317a4b3dab218ab8a691d20b3849f90eed541fd28c0d575b5dc767e8fb4
+iv = 6e2ba2833c5dce6becc4f6d8
+key = f7ace6c3c10c3ff977febe7dc882b8e779ef3a17ef9324a8
+msg = 2e11e41951c20460c768b0d71ad56e77bec05e0478f99d5b62e799f732e467
+result = valid
+tag = 33d8ec06ea9751eb0ac4f8a08bbde648
+
+# tcId = 67
+aad = 
+ct = e8325d16185109f5ebde020dd4219a5c1554ee83a82c60ae3d2a018e795730ed8ef404d8ba4aba95cc8fa6e435bf8ec9e405b3525dfd66c2be91812f0008c02fceed
+iv = 14a6281a43b4eb056a67b9e6
+key = 239195b58668eb89636b1ec2b331336946369fc6c87b8849
+msg = 39d873d4cad71cb252784bd14648a494ceb517eb9e3e6f32d19bd18dfaf877c7aec22103d242993ed7bab123326110dfdb7229143a0c601e16aa4ecdde808cd83bb2
+result = valid
+tag = 72418f7d6c3770d603f5762d666af049
+
+[ivSize = 96]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 68
+aad = 
+ct = 
+iv = 4da5bf8dfd5852c1ea12379d
+key = 80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0
+msg = 
+result = valid
+tag = 4d293af9a8fe4ac034f14b14334c16ae
+
+# tcId = 69
+aad = 
+ct = 8c
+iv = 99e23ec48985bccdeeab60f1
+key = cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273
+msg = 2a
+result = valid
+tag = c460d5ff45235c3c2491c7e6a32491d6
+
+# tcId = 70
+aad = 
+ct = 6038296421fb5007
+iv = 4f07afedfdc3b6c2361823d3
+key = 51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152
+msg = be3308f72a2c6aed
+result = valid
+tag = 0a91c72219c0b9ad716accd910e04e13
+
+# tcId = 71
+aad = 
+ct = c4066e265a948f40e05e37fa400fde1b
+iv = 2fcb1b38a99e71b84740ad9b
+key = 59d4eafb4de0cfc7d3db99a8f54b15d7b39f0acc8da69763b019c1699f87674a
+msg = 549b365af913f3b081131ccb6b825588
+result = valid
+tag = 611de27128955c54edd7a4d6d23e78ee
+
+# tcId = 72
+aad = 
+ct = f64ffe52cd838cea89dd500662a2ee4b4b450eee68218e84
+iv = e6b1adf2fd58a8762c65f31b
+key = 0212a8de5007ed87b33f1a7090b6114f9e08cefd9607f2c276bdcfdbc5ce9cd7
+msg = 10f1ecf9c60584665d9ae5efe279e7f7377eea6916d2b111
+result = valid
+tag = ae1e2eda96bed82182240aae08f9fe9c
+
+# tcId = 73
+aad = 
+ct = 01f09a6a136909c158e13502ee5488f592ee24059d6da734acba8c11e9815f
+iv = 04a9be03508a5f31371a6fd2
+key = 2eb51c469aa8eb9e6c54a8349bae50a20f0e382711bba1152c424f03b6671d71
+msg = b053999286a2824f42cc8c203ab24e2c97a685adcc2ad32662558e55a5c729
+result = valid
+tag = 79e57b518fa6dabe94e0e89cae89976b
+
+# tcId = 74
+aad = 
+ct = 72356ce9f1822e30809817a3b91ea13700ab3275b6f3718a845ad0b132bf4bbbb61ee466c1b0a1cb5a26424dbcc8d1b649f22785907a9c0164a2a41a9fc477d6c4dd
+iv = ce03bbb56778f25d4528350b
+key = 95e87eda64d0dc2d4e851030c3e1b27cca2265b3464c2c572bd8fc8cfb282d1b
+msg = 2e5acc19acb9940bb74d414b45e71386a409b641490b139493d7d632cbf1674fdf2511c3fad6c27359e6137b4cd52efc4bf871e6623451517d6a3c68240f2a79916a
+result = valid
+tag = 872861d71412e15732f60a83d4b47ee1
+
+[ivSize = 128]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 75
+aad = 
+ct = 
+iv = bc28433953772d57bbd933100cd47a56
+key = fae2a14197c7d1140061fe7c3d11d9f77c79562e3593a99b
+msg = 
+result = valid
+tag = b8c26823cb288d2ddc93ea1f3c91248b
+
+# tcId = 76
+aad = 
+ct = 1d
+iv = 1e8259e0a43e571068f701cd2064fc0c
+key = cee9abbc26b63e169f0ced621fe21d95904e75b881d93e6b
+msg = 46
+result = valid
+tag = 902249b563e6a8a63bb3bb6ee7696951
+
+# tcId = 77
+aad = 
+ct = 89071306b9c39befaf1b76b5bcaeb8
+iv = c84442d6975f0359737de0fa828f958e
+key = 189f0bd390ba40632586a45c39735c2b87113329c800f394
+msg = b4bcd7b8eeca3050dd17682c6a914e
+result = valid
+tag = 76feba04f1fbe3d564728b07184e0911
+
+# tcId = 78
+aad = 
+ct = a4d87792b61883322716b345f9c29b5a12a10441d5e4
+iv = a2357e33ef9992be34144d2e7e043275
+key = 2bc95c03e9c5b4b95e30fb597f7ea6dd1e8eaa68940da236
+msg = 3aa230f4526b82ff6ebc0b3b54e61016ad459ca86899
+result = valid
+tag = 1cda87ea66dfc34a8d2558c001992863
+
+# tcId = 79
+aad = 6293808cc471bfac
+ct = 3998fa4f34537f4f1af95cea04832254
+iv = e9b33cbe2cf00e3df7a9757c26887236
+key = 2ac418c329bce760b9928bb3d9e3171e4b95a9490bff0563
+msg = 230e0d77a23c35be592aa6c612ebfe8c
+result = valid
+tag = bef5f02f0272e26effeefca831d33d0b
+
+# tcId = 80
+aad = 922dc6f1ed0da9d25500a0b7157a10
+ct = 7342838539ec975f2b4e3cf9a08c860e
+iv = ea8bc8bde29e057ebaa67e3516295d22
+key = bfe0945395ca57a1c2368f56bb6054755f1f16e6d6dce5dc
+msg = 212b0b1f685300651eb43b2ec0779126
+result = valid
+tag = 1ab9c92a3a2b2c0c7996c8a25738959c
+
+# tcId = 81
+aad = 0f1a3473ff20352972b395a2dec89d1a
+ct = b9143fec99d73850ca15adc7313dc00c
+iv = 6900b2667811f60b1170542b6d44b913
+key = b08b98d7b077662a1f6224ba91c22b95b13d0a75e54d609c
+msg = 28ccf9f4f3cb429f75144275b907d19d
+result = valid
+tag = 28dee7cedb311961f868697c91ef0729
+
+# tcId = 82
+aad = 8cdec329f05a3e2964ea9426430dfe40ce7f40a6fc429b33
+ct = e286ad3f23d2d5742b043ba2c18a73d1
+iv = 0c300db1fbf94c6ae9a36e5ae4bbb906
+key = a90bd7b87c03803fe77291483954578c07849fb273a52243
+msg = 644b8ee3162e81b0d59792d3386cc30c
+result = valid
+tag = 9252f1b2ea6946fa42b2e86cc7bd5114
+
+# tcId = 83
+# Flipped bit 0 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 99c338570bb58a2ca8f3ecaba85e9a22
+
+# tcId = 84
+# Flipped bit 1 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 9ac338570bb58a2ca8f3ecaba85e9a22
+
+# tcId = 85
+# Flipped bit 7 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 18c338570bb58a2ca8f3ecaba85e9a22
+
+# tcId = 86
+# Flipped bit 8 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c238570bb58a2ca8f3ecaba85e9a22
+
+# tcId = 87
+# Flipped bit 31 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338d70bb58a2ca8f3ecaba85e9a22
+
+# tcId = 88
+# Flipped bit 32 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570ab58a2ca8f3ecaba85e9a22
+
+# tcId = 89
+# Flipped bit 33 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c3385709b58a2ca8f3ecaba85e9a22
+
+# tcId = 90
+# Flipped bit 63 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58aaca8f3ecaba85e9a22
+
+# tcId = 91
+# Flipped bit 64 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca9f3ecaba85e9a22
+
+# tcId = 92
+# Flipped bit 71 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2c28f3ecaba85e9a22
+
+# tcId = 93
+# Flipped bit 77 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8d3ecaba85e9a22
+
+# tcId = 94
+# Flipped bit 80 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3edaba85e9a22
+
+# tcId = 95
+# Flipped bit 96 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecaba95e9a22
+
+# tcId = 96
+# Flipped bit 97 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecabaa5e9a22
+
+# tcId = 97
+# Flipped bit 103 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecab285e9a22
+
+# tcId = 98
+# Flipped bit 120 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecaba85e9a23
+
+# tcId = 99
+# Flipped bit 121 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecaba85e9a20
+
+# tcId = 100
+# Flipped bit 126 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecaba85e9a62
+
+# tcId = 101
+# Flipped bit 127 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58a2ca8f3ecaba85e9aa2
+
+# tcId = 102
+# Flipped bits 0 and 64 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 99c338570bb58a2ca9f3ecaba85e9a22
+
+# tcId = 103
+# Flipped bits 31 and 63 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338d70bb58aaca8f3ecaba85e9a22
+
+# tcId = 104
+# Flipped bits 63 and 127 in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 98c338570bb58aaca8f3ecaba85e9aa2
+
+# tcId = 105
+# all bits of tag flipped
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 673cc7a8f44a75d3570c135457a165dd
+
+# tcId = 106
+# Tag changed to all zero
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 00000000000000000000000000000000
+
+# tcId = 107
+# tag changed to all 1
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = ffffffffffffffffffffffffffffffff
+
+# tcId = 108
+# msbs changed in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 1843b8d78b350aac28736c2b28de1aa2
+
+# tcId = 109
+# lsbs changed in tag
+aad = 
+ct = 8bec36e347b5df50a5fb5c6b25189fdc
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f1011121314151617
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 99c239560ab48b2da9f2edaaa95f9b23
+
+[ivSize = 128]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 110
+aad = 
+ct = 
+iv = 00c49f4ebb07393f07ebc3825f7b0830
+key = b4cd11db0b3e0b9b34eafd9fe027746976379155e76116afde1b96d21298e34f
+msg = 
+result = valid
+tag = 80d821cde2d6c523b718597b11dd0fa8
+
+# tcId = 111
+aad = 
+ct = 25
+iv = 0ad570d8863918fe89124e09d125a271
+key = b7797eb0c1a6089ad5452d81fdb14828c040ddc4589c32b565aad8cb4de3e4a0
+msg = ed
+result = valid
+tag = 4fef9ec45255dbba5631105d00a55767
+
+# tcId = 112
+aad = 
+ct = cbfcaa3634d6cff5656bc6bda6ab5f
+iv = 2a55caa137c5b0b66cf3809eb8f730c4
+key = 4c010d9561c7234c308c01cea3040c925a9f324dc958ff904ae39b37e60e1e03
+msg = 2a093c9ed72b8ff4994201e9f9e010
+result = valid
+tag = 0144be0643b036a8147e19f4ea9e7af2
+
+# tcId = 113
+aad = 
+ct = f531097aa1bb35d9f401d459340afbd27f9bdf72c537
+iv = 21cbeff0b123799da74f4daff2e279c5
+key = 2f6cfb7a215a7bafb607c273f7e66f9a6d51d57f9c29422ec64699bad0c6f33b
+msg = 39dbc71f6838ed6c6e582137436e1c61bbbfb80531f4
+result = valid
+tag = e4e18170dce4e1af90b15eae64355331
+
+# tcId = 114
+aad = e9ee894ad5b0781d
+ct = 0b70b24253b2e1c3ef1165925b5c5e57
+iv = 42f82085c08afd5b19a9491a79cd8119
+key = 7517c973a9de3614431e3198f4ddc0f8dc33862654649e9ff7838635bb278231
+msg = d17fbed25ad5f72477580b9e82a7b883
+result = valid
+tag = 45009a2a101877ed70e58f2e5910004f
+
+# tcId = 115
+aad = 813399ff1e1ef0b58bb2be130ce5d4
+ct = 65019212ccbbd4cd2f995cc59d46fd27
+iv = d4df79c69f73b26a13598af07eed6a77
+key = 9f5c60fb5df5cf2b1b39254c3fa80e51d30d64e344b3aba59574305b4d2212ad
+msg = a3ca2ef9bd1fdbaa83db4c7eae6de94e
+result = valid
+tag = 4026c486430a1ae2a5fc4081cd665468
+
+# tcId = 116
+aad = d1544013b885a7083abece9e31d98ebc
+ct = 91b9f4424b68b4af839ce553d10b7dbc
+iv = 7078c9239650b8a1a8cf031d460e51c1
+key = 38f3d880ed6cd605f2eab88027c9a1c21d13e3de1af50ac884723bcf2b70f495
+msg = 52609620d7f572aa9267565e459ae419
+result = valid
+tag = 0541b1a518f4bb585a594f3eab5535c3
+
+# tcId = 117
+aad = d28d5811d4168a08da54b97831b59200041adb0e2891ea91
+ct = e42b53912ce21a3ee7a1fb51194d6fe3
+iv = 1ec1d18c96ca6cad66690e60b91cf222
+key = ec88cec13d8ebae7d62f60197e5486d61c33ee5a50b19f197c1348fbc9e27e8e
+msg = 658c6c7d8ea64a48375d69d9a405095a
+result = valid
+tag = 2bc8cc7f42cac1a121fd9ddff4f2073c
+
+# tcId = 118
+# Flipped bit 0 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e976fdd461c0a0a49971db8d9678acb8
+
+# tcId = 119
+# Flipped bit 1 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = ea76fdd461c0a0a49971db8d9678acb8
+
+# tcId = 120
+# Flipped bit 7 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 6876fdd461c0a0a49971db8d9678acb8
+
+# tcId = 121
+# Flipped bit 8 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e877fdd461c0a0a49971db8d9678acb8
+
+# tcId = 122
+# Flipped bit 31 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fd5461c0a0a49971db8d9678acb8
+
+# tcId = 123
+# Flipped bit 32 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd460c0a0a49971db8d9678acb8
+
+# tcId = 124
+# Flipped bit 33 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd463c0a0a49971db8d9678acb8
+
+# tcId = 125
+# Flipped bit 63 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0249971db8d9678acb8
+
+# tcId = 126
+# Flipped bit 64 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49871db8d9678acb8
+
+# tcId = 127
+# Flipped bit 71 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a41971db8d9678acb8
+
+# tcId = 128
+# Flipped bit 77 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49951db8d9678acb8
+
+# tcId = 129
+# Flipped bit 80 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971da8d9678acb8
+
+# tcId = 130
+# Flipped bit 96 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9778acb8
+
+# tcId = 131
+# Flipped bit 97 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9478acb8
+
+# tcId = 132
+# Flipped bit 103 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d1678acb8
+
+# tcId = 133
+# Flipped bit 120 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9678acb9
+
+# tcId = 134
+# Flipped bit 121 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9678acba
+
+# tcId = 135
+# Flipped bit 126 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9678acf8
+
+# tcId = 136
+# Flipped bit 127 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0a49971db8d9678ac38
+
+# tcId = 137
+# Flipped bits 0 and 64 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e976fdd461c0a0a49871db8d9678acb8
+
+# tcId = 138
+# Flipped bits 31 and 63 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fd5461c0a0249971db8d9678acb8
+
+# tcId = 139
+# Flipped bits 63 and 127 in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e876fdd461c0a0249971db8d9678ac38
+
+# tcId = 140
+# all bits of tag flipped
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 1789022b9e3f5f5b668e247269875347
+
+# tcId = 141
+# Tag changed to all zero
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 00000000000000000000000000000000
+
+# tcId = 142
+# tag changed to all 1
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = ffffffffffffffffffffffffffffffff
+
+# tcId = 143
+# msbs changed in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = 68f67d54e140202419f15b0d16f82c38
+
+# tcId = 144
+# lsbs changed in tag
+aad = 
+ct = 059e01599f94b38f2435b47a0c7b5c59
+iv = 505152535455565758595a5b5c5d5e5f
+key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+msg = 202122232425262728292a2b2c2d2e2f
+result = invalid
+tag = e977fcd560c1a1a59870da8c9779adb9
+
+[ivSize = 160]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 145
+# large IV size
+aad = 
+ct = 298e86436ead703a38f869690f020d4c
+iv = ef4886c4fe8b26f045e09ac925ccbbad42d70347
+key = 7edabee31897bf9b29394aeca84c4dcc
+msg = 52583c7b11de051c2e5c2114ee20527b
+result = valid
+tag = f20d2f2d170ebbe1d0ec718eefe632e4
+
+[ivSize = 256]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 146
+# large IV size
+aad = 
+ct = 487e94228d338acee8e9f5c07e22fb06
+iv = f23a924d75c57fee8e75defd97be48e8cf3202cd658add0a4f50b24b5af9f013
+key = e071a62bcde9ee648118ed3b1c629c20
+msg = a0650c4299cf63ec5e28104e9064247f
+result = valid
+tag = 72c99b644664378c88fd1f4ecfd80f76
+
+[ivSize = 160]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 147
+# large IV size
+aad = 
+ct = 3ac1c21a7d7d60973c6c12d58c59ec1e
+iv = d6b33e2be9eeb8bcb33f1291c728699276781f29
+key = f9aced074bde719edba80bc8ad475f7ebd3ba6e98a4c0f96
+msg = 4487fc05e84d49e94d38b733ce063a75
+result = valid
+tag = 3ff9167a5afb0bb09fc5c10136a6d37c
+
+[ivSize = 256]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 148
+# large IV size
+aad = 
+ct = 199f609949240ce2a65bf1b492f17afe
+iv = 4683f07aafca7f952acedc57c45315307593f52a7b405bf2ebcd19d18098ac04
+key = 94ffb2d57189012cbbe314e4e36dec0dd9e2b9c88b53bbae
+msg = 10e1e492691ebb658324f1982168073e
+result = valid
+tag = 7cd958a59d5706b396d219a2936be571
+
+[ivSize = 160]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 149
+# large IV size
+aad = 
+ct = 5cceb0253bcbd6800d3b316af3a56937
+iv = 989f015e6ab79d5e43eca8364a38c9f6b381dda1
+key = 1739fd2876258457e3e4c323dbabd85edda8ecad83a7496d8feb0b88aeab2e74
+msg = d1b13ceacedad362851dc876d8b1dd20
+result = valid
+tag = 15186910a0f2a2bc41d32e7fe687f17c
+
+[ivSize = 256]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 150
+# large IV size
+aad = 
+ct = 1a288496f909036b35f3604b3ecd3493
+iv = e1ed38af5753851b79175e4ae11fd6cf80033f81aec484ecd0448c5e7cc0a27e
+key = aa5429fd3f178b3885f2c696975e88890102455b5d9e42766429e80d4889672a
+msg = 7aa8919ebb950f34690acb98651854cb
+result = valid
+tag = 62eb49550cbee8c3cf88302c826690a2
+
+[ivSize = 32]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 151
+# small IV size
+aad = 
+ct = d324ca1530c68ed86c775ed9bb1d8490
+iv = 7b5faeb2
+key = d83c1d7a97c43f182409a4aa5609c1b1
+msg = c8f07ba1d65554a9bd40390c30c5529c
+result = acceptable
+tag = 30062eb9cedbaddf36f93e4219620afa
+flags = SmallIv
+
+[ivSize = 64]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 152
+# small IV size
+aad = 
+ct = 3064cf4883703f170bf01e6c2d67259f
+iv = d084547de55bbc15
+key = deb62233559b57476602b5adac57c77f
+msg = d8986df0241ed3297582c0c239c724cb
+result = acceptable
+tag = 09471c09f897d46216fbb52436e3c4fc
+flags = SmallIv
+
+[ivSize = 32]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 153
+# small IV size
+aad = 
+ct = bc3c8eb10b6cfa8fa1758ce9358753fe
+iv = bb9d2aa3
+key = 834d0bb601170865a78139428a1503695a6a291ebd747cd1
+msg = 6f79e18b4acd5a03d3a5f7e1a8d0f183
+result = acceptable
+tag = db1ae0ef0315046b5358bff4629880c5
+flags = SmallIv
+
+[ivSize = 64]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 154
+# small IV size
+aad = 
+ct = 33ca3171ec118e72cc29950f6c129227
+iv = 8f075cbcda9831c3
+key = 0b177198c8b419bf74acc3bc65b5fb3d09a915ff71add754
+msg = c4b1e05ca3d591f9543e64de3fc682ac
+result = acceptable
+tag = 737967a2501f14ce84d9981c89be1785
+flags = SmallIv
+
+[ivSize = 32]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 155
+# small IV size
+aad = 
+ct = 5aca28621e2bd92d7f182ff653b1e8eb
+iv = 5110604c
+key = 093eb12343537ee8e91c1f715b862603f8daf9d4e1d7d67212a9d68e5aac9358
+msg = 33efb58c91e8c70271870ec00fe2e202
+result = acceptable
+tag = 8a89a0db74a55f907f8ba115e2e15853
+flags = SmallIv
+
+[ivSize = 64]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 156
+# small IV size
+aad = 
+ct = df32c13a2278326a3c966dee321a42f6
+iv = 04102199ef21e1df
+key = 115884f693b155563e9bfb3b07cacb2f7f7caa9bfe51f89e23feb5a9468bfdd0
+msg = 82e3e604d2be8fcab74f638d1e70f24c
+result = acceptable
+tag = b1798b8e4b95df6c620a5cbcbe1238d1
+flags = SmallIv
+
+[ivSize = 0]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 157
+# IV size = 0
+aad = 
+ct = 
+iv = 
+key = 8f3f52e3c75c58f5cb261f518f4ad30a
+msg = 
+result = acceptable
+tag = 5adbeefc8fa9cae2b9a6db3f5f6c82e9
+flags = SmallIv
+
+# tcId = 158
+# IV size = 0
+aad = 
+ct = 73b4716f7e44f3bb22a2648069ebbc1e
+iv = 
+key = 2a4bf90e56b70fdd8649d775c089de3b
+msg = 324ced6cd15ecc5b3741541e22c18ad9
+result = acceptable
+tag = 3f6ac9672db499324ead0c234b544054
+flags = SmallIv
+
+[ivSize = 0]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 159
+# IV size = 0
+aad = 
+ct = 
+iv = 
+key = 0b18d21337035c7baa08211b702fa780ac7c09be8f9ed11f
+msg = 
+result = acceptable
+tag = 1bd7ab03a24e07b57f9d173c8e6d57a1
+flags = SmallIv
+
+# tcId = 160
+# IV size = 0
+aad = 
+ct = 87ac7db89a1f4bf772534003ad82d75d
+iv = 
+key = ba76d594a6df915bb7ab7e6d1a8d024b2796336c1b8328a9
+msg = d62f302742d61d823ea991b93430d589
+result = acceptable
+tag = b6974b88fb44fabe8c10c693f788a068
+flags = SmallIv
+
+[ivSize = 0]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 161
+# IV size = 0
+aad = 
+ct = 
+iv = 
+key = 3f8ca47b9a940582644e8ecf9c2d44e8138377a8379c5c11aafe7fec19856cf1
+msg = 
+result = acceptable
+tag = b17f6100882e6b419d9fed0c8b7c8d9a
+flags = SmallIv
+
+# tcId = 162
+# IV size = 0
+aad = 
+ct = 8187621069d3c07b7861bb40e8a56b3a
+iv = 
+key = 7660d10966c6503903a552dde2a809ede9da490e5e5cc3e349da999671809883
+msg = c314235341debfafa1526bb61044a7f1
+result = acceptable
+tag = c1f0897558300e979ba29b36336a0d06
+flags = SmallIv
+
+[ivSize = 512]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 163
+# very large IV size
+aad = 
+ct = 51cf50ea2d71d0efd3a9ddc3092f9b8b
+iv = fa3ef369cf29e9e088393c357ff160cbdb8fd97b7ea2b11fe3df763c5e928b6b5f6e87625bf7c88a56154474defdb61f71b12f7bc0169857f5964b8ef162ba25
+key = 228437ab28e69a4319f2d6d505c9a411
+msg = dc0583f633b1e1ce666c2ccfb6dc084f
+result = valid
+tag = 2ee385a31b716f325d3b59f67eab2cbb
+flags = LongIv
+
+[ivSize = 1024]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 164
+# very large IV size
+aad = 
+ct = 60388395837d5ded6b6bcc0223738340
+iv = 731258b46c074a64b3cfff5a2a411a98a46a1dcfde32e01268ca5542951289f1882462d9bdfc0f887ec797b6268cd97086cb847e332719a18e81fe2bc53e82d878971b1c1bedfb6d31f97fe9d3fb7f7d0f639fb4877fa191ea39bfbf6d474a82611beae9889fbc3f1c85a8aefdea3bc83ac5b44a997e53b934bd29dd8a3ef873
+key = 21a7eb9f06bfa7cbb42726569f70eaeb
+msg = 47e162ce2c3bfd85fa1b8e1fae5215ed
+result = valid
+tag = 3a9806509e47a57429e37410f6baaf69
+flags = LongIv
+
+[ivSize = 2056]
+[keySize = 128]
+[tagSize = 128]
+
+# tcId = 165
+# very large IV size
+aad = 
+ct = 8156f78835c1168440e211718a704e36
+iv = 39480a40a8af403e7cd81f5d7e2f522f7dd2a111ca300d118e6950cba47bdda5afe4defc0c81e09cea24f7013f9d9fdee8a3df58632c25d0abeed9b6245043f992f3b915449ca4c92325b91307e0b3e99ff9cb79de06e8a376c5cd85640c75bd5bed56381097c4219f38268b7f0e12746f09d88d1b113ca9b6bc28c6b9af60bc9648ed311f290a496575dbc8233bfb429df3847cc146b4cf5b721fc0c72185ad90f5543bb63799d29b4e3f07324569c791202e4a50afa4e2cb4cd6ba5bad0b6c3ea216737b3de6b74a17d68b46d63e9574a5c3a872128e73dae8331d0eb4cdec38a602f9d662ce42256a4379ec2543e17c562ade2af57255a28874918a4dfe6f5a
+key = 5700338fcb7c61bfc8ad8b15cbe66104
+msg = d30598f6680810efc94ea10d0c079203
+result = valid
+tag = b9e93a071921e0e91d098bcb41744dc8
+flags = LongIv
+
+[ivSize = 512]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 166
+# very large IV size
+aad = 
+ct = be9ada6a7f996d98cb97970c1a072133
+iv = 8880fc62c2b96aa6ed7459661d5ab48ce2c06e3f2d00c943edfd7b703842f98ade9cab33f4deb269e2d3b92cdae369a7584b80ebbae91ebd42be789d5bae2afd
+key = b8dc7be3ca28f7a81ea63d47d305dcb984e40fbb9b31be2a
+msg = 59ed5441aae067b2b27d2ff62a0bea11
+result = valid
+tag = f8ce4f9c5ddacbd2eae3bc1c69554363
+flags = LongIv
+
+[ivSize = 1024]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 167
+# very large IV size
+aad = 
+ct = cbf7d083fa4f22e3ce887ee08f2ae9f9
+iv = 23943437572aa0b193774b3604e8007143de793cad75b76dec8da9200c087d03ced977405b188e373de32b5046b7d1b9a61c21d94a3fa609a183ce74fbdd4da4b647708ee72ddb4aa306a40278ba705aa4021abdef36ea609b2380446c211cf49747c72b6738d6edc9f2c9a9dec940febdb275c02295f40de1621006f1025604
+key = 10944c59fda6a9087b1af7b8afaedf78b190c1ef7854e3db
+msg = 091ecded07b8f7d35ad122bced57cae7
+result = valid
+tag = 57abc1d1b5f0be8962a346696a1e43ac
+flags = LongIv
+
+[ivSize = 2056]
+[keySize = 192]
+[tagSize = 128]
+
+# tcId = 168
+# very large IV size
+aad = 
+ct = 280fdd4ae81fe81775efc2c835079a1b
+iv = cf0e233cbc2a2267f67e51c629d1ec1e9278c56737980be7aa58c61b9b995a13be21e686842e2cedf6bf19f7067140f3d276e7b227993832639459400c6a651b1ba326d003351d0f21bc28e54ba68e3e03d16196efbab5cf487a57670e6af785025b08e2d2b710cdfa277c80d5a0f6b88a809b708e26e2d68eacdf190a0e84213b9fcb72d619f2976850bdaa1a7fe6a53d581472ed77f333fe32dda9917bc1c8e3a4e963930a60b2d336433c85bab9d5c6d8e7dd857c75516cc64a0ad9c3006576da7694a7f37c80cc803adf8b8884b4133b2478f78157578da088ca1a010aa21d2c67aed174943bdba2e90c748726bb3d1642939cc22157102e4ea4441c39ff09
+key = 2e5faa81df5196d2185db4ca51bf96222062163ad60d6f3f
+msg = eb4d8ea0c45eb5af2958965bf1c687a3
+result = valid
+tag = 25a97647be49ace070733aecc9aad041
+flags = LongIv
+
+[ivSize = 512]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 169
+# very large IV size
+aad = 
+ct = 6726cff4f3fd9adc019b622b2eb66ee8
+iv = e04e25476d6cd5193094c5812e50ca0cf61430ae52d50637ab78e97b37bb652e79db4319747eba111fabb26737061ab837f4e54c860c74dcefa9f1d8ffec8e0c
+key = 37a2093a9f4418787905d53b7eb8e0c8d6d0a3c00417bd57ab12aad04fafc438
+msg = 7229459dcc3c431339a4347bcb5e0c76
+result = valid
+tag = 73eea2d201558afd2302183d2dbd33e4
+flags = LongIv
+
+[ivSize = 1024]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 170
+# very large IV size
+aad = 
+ct = 63e20d0f564d87952fca8a8e00d29616
+iv = aded3859f2705fbe7ea4baf459d4fe6d5f852f858e0b357fddf53eca1fe1ab25c39bef65dd901ac029c4d190cebfaea9045dc24a53f4f8a50f5eea70af1633eac6c2bd4a2cc9f8118dfa60b2b09a192ed33f2cb100401bac924e5bdc8ca14fa72c549f340e7afd4aab34059c03887e0c02bdba17d822be775cae0d22a1a5c453
+key = 32954d52a3dce6483c65090e74186e8223491872fd8a5bd36301d3a430228840
+msg = f36a508e286787ea108dc01340de0351
+result = valid
+tag = 33ccd9822664234c7c7954ba585a08cf
+flags = LongIv
+
+[ivSize = 2056]
+[keySize = 256]
+[tagSize = 128]
+
+# tcId = 171
+# very large IV size
+aad = 
+ct = 523697a212c183f2c6873baff910229f
+iv = b08c7387cfce5f892357b91653cfc73330cee7bd0aad33f3276b015e035ee543e8edfea70074ffeced2459d8acfc765c7f65fdec8f5c44480ae388d3afe42915c94363690ff20625f81ddffeceb9f95984824256a4ce4ce482a3e0234d111ec95162f80f6c0285d56de68a8c114df82b9742e9b2e2603967a44ec1d9bd64758cea894dd9d6fb8a8421853ad06579e1f4ab615215f39d6e35f0bda6e1ab0a587cec79be65e56557b160f879e58105e5e19b47d8848fd953ad0cfa1c7b116cf5fcab3981cb23846ab9f6eb4172e6706ec0d37e2a4f7dab02c1795b6dc79c78fdb964dd336e4b05243feb56fece8c01def9542205fadc977eb4861ea384235628e992
+key = f386e46fec6925e4344f03147f04fbcba04a27ae8f8cb552ab0ff5c8658ddcd2
+msg = 5bfb8243b2c0bc1101180d58f7647ad1
+result = valid
+tag = 3cce18521559d42c0527be6d49ef6d77
+flags = LongIv
+
diff --git a/src/tool/client.cc b/src/tool/client.cc
index ed9b5bd..0839d48 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -19,9 +19,7 @@
 #if !defined(OPENSSL_WINDOWS)
 #include <sys/select.h>
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/err.h>
diff --git a/src/tool/digest.cc b/src/tool/digest.cc
index b3b2ffd..008e8f5 100644
--- a/src/tool/digest.cc
+++ b/src/tool/digest.cc
@@ -32,9 +32,7 @@
 #define O_BINARY 0
 #endif
 #else
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #include <io.h>
 #if !defined(PATH_MAX)
 #define PATH_MAX MAX_PATH
diff --git a/src/tool/internal.h b/src/tool/internal.h
index 2c02a74..739b518 100644
--- a/src/tool/internal.h
+++ b/src/tool/internal.h
@@ -18,18 +18,11 @@
 #include <openssl/base.h>
 #include <openssl/span.h>
 
+#include <map>
 #include <string>
 #include <utility>
 #include <vector>
 
-// MSVC issues warning C4702 for unreachable code in its xtree header when
-// compiling with -D_HAS_EXCEPTIONS=0. See
-// https://connect.microsoft.com/VisualStudio/feedback/details/809962
-OPENSSL_MSVC_PRAGMA(warning(push))
-OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
-#include <map>
-OPENSSL_MSVC_PRAGMA(warning(pop))
-
 struct FileCloser {
   void operator()(FILE *file) {
     fclose(file);
diff --git a/src/tool/speed.cc b/src/tool/speed.cc
index 8bc3eef..b9bca8e 100644
--- a/src/tool/speed.cc
+++ b/src/tool/speed.cc
@@ -52,9 +52,7 @@
 #include <openssl/trust_token.h>
 
 #if defined(OPENSSL_WINDOWS)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 #elif defined(OPENSSL_APPLE)
 #include <sys/time.h>
 #else
diff --git a/src/tool/transport_common.cc b/src/tool/transport_common.cc
index 264db13..141cf36 100644
--- a/src/tool/transport_common.cc
+++ b/src/tool/transport_common.cc
@@ -50,10 +50,8 @@
 #include <utility>
 
 #include <io.h>
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
 
 OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
diff --git a/src/util/bot/DEPS b/src/util/bot/DEPS
index bb5fc34..6414e75 100644
--- a/src/util/bot/DEPS
+++ b/src/util/bot/DEPS
@@ -25,7 +25,6 @@
   'checkout_nasm': False,
   'checkout_libcxx': False,
   'checkout_riscv64': False,
-  'vs_version': '2022',
 
   # Run the following command to see the latest builds in CIPD:
   #  cipd describe PACKAGE_NAME -version latest
@@ -34,26 +33,29 @@
   # Keep this in sync with .bazelversion.
   'bazel_version': 'version:3@7.5.0.chromium.1',
   # infra/3pp/tools/cmake/linux-amd64
-  'cmake_version': 'version:3@3.31.5.chromium.8',
+  'cmake_version': 'version:3@3.31.7.chromium.8',
   # infra/3pp/tools/go/linux-amd64
-  'go_version': 'version:3@1.24.0',
+  'go_version': 'version:3@1.24.2',
   # infra/3pp/tools/perl/windows-amd64
-  'perl_version': 'version:2@5.32.1.1',
+  'perl_version': 'version:3@5.38.2.2',
+  # chrome_internal/third_party/sdk/windows, but if an update switches this to a
+  # new major VS release, keep some bots at the older version.
+  'windows_sdk_version': 'uploaded:2024-01-11',
 
   # Update the following from
   # https://chromium.googlesource.com/chromium/src/+/main/DEPS
-  'android_sdk_platform-tools_version': 'WihaseZR6cojZbkzIqwGhpTp92ztaGfqq8njBU8eTXYC',
+  'android_sdk_platform-tools_version': 'mjFmRj7k_XR9yj60pYbr9mG38FyEbU5oWdU56bZQ5cwC',
   'libfuzzer_revision': 'e31b99917861f891308269c36a32363b120126bb',
-  'libcxx_revision': '61c68567ca977656440757c3effe124057509e8f',
-  'libcxxabi_revision': '634228a732a1d9ae1a6d459556e8fc58707cf961',
-  'llvm_libc_revision': '5333472378a666cca9d0fcf6551b4d768c70a55c',
+  'libcxx_revision': 'bf30ab1b37bc976f82a46fa7f15e30235c4a1a49',
+  'libcxxabi_revision': 'e01dce316dd430f006c8af7d1179f83270236e24',
+  'llvm_libc_revision': 'f86693f91c5aa0566fa403f4189c943744155ca6',
   'ninja_version': 'version:2@1.12.1.chromium.4',
 
   # Update to the latest revision of
   # https://chromium.googlesource.com/chromium/src/tools/clang
-  'tools_clang_revision': '2ca96532f8f3dfc83e43070fca2549ed6393699d',
+  'tools_clang_revision': 'a7f7a7df1c3b38293f869dbdc74d494cb962bda7',
 
-  # The Android NDK cannot be updated until https://crbug.com/boringssl/454 is fixed.
+  # The Android NDK cannot be updated until https://crbug.com/42290318 is fixed.
   # We rely on an older NDK to test building without NEON instructions as the baseline.
   'android_ndk_revision': 'U0e8L6l52ySjBrUBB82Vdyhsg60vVMqH0ItTW3TRHAQC',
   'qemu_static_version': 'gYNEUqCr-Tu1C_vBu68YFtN31hjjLe61dnI2AtuyEsYC',
@@ -150,6 +152,15 @@
       'dep_type': 'cipd',
   },
 
+  'boringssl/util/bot/windows_sdk': {
+    'packages': [{
+      'package': 'chrome_internal/third_party/sdk/windows',
+      'version': Var('windows_sdk_version'),
+    }],
+    'condition': 'host_os == "win"',
+    'dep_type': 'cipd',
+  },
+
   'boringssl/util/bot/tools/clang': {
     'url': Var('chromium_git') + '/chromium/src/tools/clang.git' + '@' + Var('tools_clang_revision'),
     'condition': 'checkout_clang',
@@ -175,16 +186,6 @@
     ],
   },
   {
-    'name': 'win_toolchain',
-    'pattern': '.',
-    'condition': 'host_os == "win"',
-    'action': [ 'python3',
-                'boringssl/util/bot/vs_toolchain.py',
-                'update',
-                Var('vs_version'),
-    ],
-  },
-  {
     'name': 'clang',
     'pattern': '.',
     'condition': 'checkout_clang',
diff --git a/src/util/bot/UPDATING b/src/util/bot/UPDATING
index 5a97e48..8c0c635 100644
--- a/src/util/bot/UPDATING
+++ b/src/util/bot/UPDATING
@@ -10,11 +10,6 @@
 
 DEPS: Update the variables as described in the comments.
 
-vs_toolchain.py: Update _GetDesiredVsToolchainHashes from Chromium, found at
-    https://chromium.googlesource.com/chromium/src/+/main/build/vs_toolchain.py
-    This may require taking other updates to that file. (Don't remove MSVC
-    versions if BoringSSL still needs to support them.)
-
 The .sha1 files correspond to files downloaded from Google Cloud Storage. To
 update, place the updated files in their intended location and run:
 
diff --git a/src/util/bot/sde-linux64.tar.xz.sha1 b/src/util/bot/sde-linux64.tar.xz.sha1
index c0f0b03..51e1aaf 100644
--- a/src/util/bot/sde-linux64.tar.xz.sha1
+++ b/src/util/bot/sde-linux64.tar.xz.sha1
@@ -1 +1 @@
-e63579d20a25860a7963e5e93011c1e3ba914d09
\ No newline at end of file
+b0266ba3d880bece6c189a4fa56347f4c96a33ae
\ No newline at end of file
diff --git a/src/util/bot/sde-win32.tar.xz.sha1 b/src/util/bot/sde-win32.tar.xz.sha1
index 1907b25..878abc9 100644
--- a/src/util/bot/sde-win32.tar.xz.sha1
+++ b/src/util/bot/sde-win32.tar.xz.sha1
@@ -1 +1 @@
-532993ce76008b0b235a6eed69aeacde9e30facf
\ No newline at end of file
+a7e6913d232fb616f28a0106c279dc25777851be
\ No newline at end of file
diff --git a/src/util/bot/vs_env.py b/src/util/bot/vs_env.py
index 47f975a..b650795 100644
--- a/src/util/bot/vs_env.py
+++ b/src/util/bot/vs_env.py
@@ -12,12 +12,47 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
+import json
+import os
+import os.path
 import subprocess
 import sys
 
-import vs_toolchain
+script_dir = os.path.dirname(os.path.realpath(__file__))
+sdk_root = os.path.join(script_dir, 'windows_sdk')
+
+def SetEnvironmentForCPU(cpu):
+  """Sets the environment to build with the selected toolchain for |cpu|."""
+  assert cpu in ('x86', 'x64', 'arm', 'arm64')
+  sdk_dir = os.path.join(sdk_root, 'Windows Kits', '10')
+  os.environ['WINDOWSSDKDIR'] = sdk_dir
+  # Include the VS runtime in the PATH in case it's not machine-installed.
+  runtime_dirs = \
+      [os.path.join(sdk_root, d) for d in ['sys64', 'sys32', 'sysarm64']]
+  os.environ['PATH'] = \
+      os.pathsep.join(runtime_dirs) + os.pathsep + os.environ['PATH']
+
+  # Set up the architecture-specific environment from the SetEnv files. See
+  # _LoadToolchainEnv() from setup_toolchain.py in Chromium.
+  with open(os.path.join(sdk_dir, 'bin', 'SetEnv.%s.json' % cpu)) as f:
+    env = json.load(f)['env']
+  if env['VSINSTALLDIR'] == [["..", "..\\"]]:
+    # Old-style paths were relative to the win_sdk\bin directory.
+    json_relative_dir = os.path.join(sdk_dir, 'bin')
+  else:
+    # New-style paths are relative to the toolchain directory.
+    json_relative_dir = sdk_root
+  for k in env:
+    entries = [os.path.join(*([json_relative_dir] + e)) for e in env[k]]
+    # clang-cl wants INCLUDE to be ;-separated even on non-Windows,
+    # lld-link wants LIB to be ;-separated even on non-Windows.  Path gets :.
+    sep = os.pathsep if k == 'PATH' else ';'
+    env[k] = sep.join(entries)
+  # PATH is a bit of a special case, it's in addition to the current PATH.
+  env['PATH'] = env['PATH'] + os.pathsep + os.environ['PATH']
+
+  for k, v in env.items():
+    os.environ[k] = v
 
 if len(sys.argv) < 2:
   print("Usage: vs_env.py TARGET_ARCH CMD...", file=sys.stderr)
@@ -26,5 +61,5 @@
 target_arch = sys.argv[1]
 cmd = sys.argv[2:]
 
-vs_toolchain.SetEnvironmentForCPU(target_arch)
+SetEnvironmentForCPU(target_arch)
 sys.exit(subprocess.call(cmd))
diff --git a/src/util/bot/vs_toolchain.py b/src/util/bot/vs_toolchain.py
deleted file mode 100644
index 4fb70ea..0000000
--- a/src/util/bot/vs_toolchain.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from __future__ import print_function
-
-import json
-import os
-import os.path
-import subprocess
-import sys
-
-
-script_dir = os.path.dirname(os.path.realpath(__file__))
-toolchain_dir = os.path.join(script_dir, 'win_toolchain')
-json_data_file = os.path.join(script_dir, 'win_toolchain.json')
-
-
-def SetEnvironmentForCPU(cpu):
-  """Sets the environment to build with the selected toolchain for |cpu|."""
-  with open(json_data_file, 'r') as tempf:
-    toolchain_data = json.load(tempf)
-  sdk_dir = toolchain_data['win_sdk']
-  os.environ['WINDOWSSDKDIR'] = sdk_dir
-  os.environ['WDK_DIR'] = toolchain_data['wdk']
-  # Include the VS runtime in the PATH in case it's not machine-installed.
-  vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
-  runtime_path = os.pathsep.join(vs_runtime_dll_dirs)
-  os.environ['PATH'] = runtime_path + os.pathsep + os.environ['PATH']
-
-  # Set up the architecture-specific environment from the SetEnv files. See
-  # _LoadToolchainEnv() from setup_toolchain.py in Chromium.
-  assert cpu in ('x86', 'x64', 'arm', 'arm64')
-  with open(os.path.join(sdk_dir, 'bin', 'SetEnv.%s.json' % cpu)) as f:
-    env = json.load(f)['env']
-  if env['VSINSTALLDIR'] == [["..", "..\\"]]:
-    # Old-style paths were relative to the win_sdk\bin directory.
-    json_relative_dir = os.path.join(sdk_dir, 'bin')
-  else:
-    # New-style paths are relative to the toolchain directory.
-    json_relative_dir = toolchain_data['path']
-  for k in env:
-    entries = [os.path.join(*([json_relative_dir] + e)) for e in env[k]]
-    # clang-cl wants INCLUDE to be ;-separated even on non-Windows,
-    # lld-link wants LIB to be ;-separated even on non-Windows.  Path gets :.
-    sep = os.pathsep if k == 'PATH' else ';'
-    env[k] = sep.join(entries)
-  # PATH is a bit of a special case, it's in addition to the current PATH.
-  env['PATH'] = env['PATH'] + os.pathsep + os.environ['PATH']
-
-  for k, v in env.items():
-    os.environ[k] = v
-
-
-def FindDepotTools():
-  """Returns the path to depot_tools in $PATH."""
-  for path in os.environ['PATH'].split(os.pathsep):
-    if os.path.isfile(os.path.join(path, 'gclient.py')):
-      return path
-  raise Exception("depot_tools not found!")
-
-
-def _GetDesiredVsToolchainHashes(version):
-  """Load a list of SHA1s corresponding to the toolchains that we want installed
-  to build with."""
-  if version == '2022':
-    # VS 2022 17.9.2 with 10.0.22621.2428 SDK with ARM64 libraries and UWP
-    # support.
-    return ['7393122652']
-  raise Exception('Unsupported VS version %s' % version)
-
-
-def Update(version):
-  """Requests an update of the toolchain to the specific hashes we have at
-  this revision. The update outputs a .json of the various configuration
-  information required to pass to vs_env.py which we use in
-  |SetEnvironmentForCPU()|.
-  """
-  depot_tools_path = FindDepotTools()
-  get_toolchain_args = [
-      sys.executable,
-      os.path.join(depot_tools_path,
-                  'win_toolchain',
-                  'get_toolchain_if_necessary.py'),
-      '--output-json', json_data_file,
-      '--toolchain-dir', toolchain_dir,
-    ] + _GetDesiredVsToolchainHashes(version)
-  subprocess.check_call(get_toolchain_args)
-  return 0
-
-
-def main():
-  if not sys.platform.startswith(('win32', 'cygwin')):
-    return 0
-  commands = {
-      'update': Update,
-  }
-  if len(sys.argv) < 2 or sys.argv[1] not in commands:
-    print('Expected one of: %s' % ', '.join(commands), file=sys.stderr)
-    return 1
-  return commands[sys.argv[1]](*sys.argv[2:])
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/src/util/convert_wycheproof/convert_wycheproof.go b/src/util/convert_wycheproof/convert_wycheproof.go
index cfc5add..67ae738 100644
--- a/src/util/convert_wycheproof/convert_wycheproof.go
+++ b/src/util/convert_wycheproof/convert_wycheproof.go
@@ -26,10 +26,10 @@
 )
 
 type wycheproofTest struct {
-	Algorithm        string            `json:"algorithm"`
-	GeneratorVersion string            `json:"generatorVersion"`
-	NumberOfTests    int               `json:"numberOfTests"`
-	Header           []string          `json:"header"`
+	Algorithm        string   `json:"algorithm"`
+	GeneratorVersion string   `json:"generatorVersion"`
+	NumberOfTests    int      `json:"numberOfTests"`
+	Header           []string `json:"header"`
 	// encoding/json does not support collecting unused keys, so we leave
 	// everything past this point as generic.
 	TestGroups []map[string]any `json:"testGroups"`
@@ -195,6 +195,7 @@
 var defaultInputs = []string{
 	"aes_cbc_pkcs5_test.json",
 	"aes_cmac_test.json",
+	"aes_eax_test.json",
 	"aes_gcm_siv_test.json",
 	"aes_gcm_test.json",
 	"chacha20_poly1305_test.json",
diff --git a/src/util/doc.go b/src/util/doc.go
index 1de7064..fed939f 100644
--- a/src/util/doc.go
+++ b/src/util/doc.go
@@ -676,41 +676,42 @@
 }
 
 // markupPipeWords converts |s| into an HTML string, safe to be included outside
-// a tag, while also marking up words surrounded by |.
+// a tag, while also marking up words surrounded by | or `.
 func markupPipeWords(allDecls map[string]string, s string, linkDecls bool) template.HTML {
-	// It is safe to look for '|' in the HTML-escaped version of |s|
-	// below. The escaped version cannot include '|' instead tags because
+	// It is safe to look for '|' and '`' in the HTML-escaped version of |s|
+	// below. The escaped version cannot include '|' or '`' inside tags because
 	// there are no tags by construction.
 	s = template.HTMLEscapeString(s)
-	ret := ""
+	var ret strings.Builder
 
 	for {
-		i := strings.Index(s, "|")
+		i := strings.IndexAny(s, "|`")
 		if i == -1 {
-			ret += s
+			ret.WriteString(s)
 			break
 		}
-		ret += s[:i]
+		c := s[i]
+		ret.WriteString(s[:i])
 		s = s[i+1:]
 
-		i = strings.Index(s, "|")
+		i = strings.IndexByte(s, c)
 		j := strings.Index(s, " ")
 		if i > 0 && (j == -1 || j > i) {
-			ret += "<tt>"
+			ret.WriteString("<tt>")
 			anchor, isLink := allDecls[s[:i]]
 			if linkDecls && isLink {
-				ret += fmt.Sprintf("<a href=\"%s\">%s</a>", template.HTMLEscapeString(anchor), s[:i])
+				fmt.Fprintf(&ret, "<a href=\"%s\">%s</a>", template.HTMLEscapeString(anchor), s[:i])
 			} else {
-				ret += s[:i]
+				ret.WriteString(s[:i])
 			}
-			ret += "</tt>"
+			ret.WriteString("</tt>")
 			s = s[i+1:]
 		} else {
-			ret += "|"
+			ret.WriteByte(c)
 		}
 	}
 
-	return template.HTML(ret)
+	return template.HTML(ret.String())
 }
 
 func markupFirstWord(s template.HTML) template.HTML {
diff --git a/src/util/fipstools/CMakeLists.txt b/src/util/fipstools/CMakeLists.txt
deleted file mode 100644
index ff33b4f..0000000
--- a/src/util/fipstools/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-add_executable(
-  test_fips
-
-  test_fips.cc
-)
-target_link_libraries(test_fips crypto)
diff --git a/src/util/fipstools/acvp/acvptool/acvp.go b/src/util/fipstools/acvp/acvptool/acvp.go
index 3a089ae..7a5c43c 100644
--- a/src/util/fipstools/acvp/acvptool/acvp.go
+++ b/src/util/fipstools/acvp/acvptool/acvp.go
@@ -29,7 +29,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	neturl "net/url"
@@ -52,7 +51,7 @@
 	runFlag         = flag.String("run", "", "Name of primitive to run tests for")
 	fetchFlag       = flag.String("fetch", "", "Name of primitive to fetch vectors for")
 	expectedOutFlag = flag.String("expected-out", "", "Name of a file to write the expected results to")
-	wrapperPath     = flag.String("wrapper", "../../../../build/util/fipstools/acvp/modulewrapper/modulewrapper", "Path to the wrapper binary")
+	wrapperPath     = flag.String("wrapper", "../../../../build/modulewrapper", "Path to the wrapper binary")
 )
 
 type Config struct {
@@ -183,6 +182,13 @@
 	return s
 }
 
+func addTrailingSlash(s string) string {
+	if !strings.HasSuffix(s, "/") {
+		s += "/"
+	}
+	return s
+}
+
 // looksLikeVectorSetHeader returns true iff element looks like it's a
 // vectorSetHeader, not a test. Some ACVP files contain a header as the first
 // element that should be duplicated into the response, and some don't. If the
@@ -496,9 +502,9 @@
 // Vector Test Result files are JSON formatted with various objects and keys.
 // Define structs to read and process the files.
 type vectorResult struct {
-	Version    string      `json:"acvVersion,omitempty"`
-	Algorithm  string      `json:"algorithm,omitempty"`
-	ID         int         `json:"vsId,omitempty"`
+	Version   string `json:"acvVersion,omitempty"`
+	Algorithm string `json:"algorithm,omitempty"`
+	ID        int    `json:"vsId,omitempty"`
 	// Objects under testGroups can have various keys so use an empty interface.
 	Tests []map[string]interface{} `json:"testGroups,omitempty"`
 }
@@ -539,6 +545,35 @@
 	JSONResult []byte
 }
 
+// Processes test result and returns them in format to be uploaded.
+func processResultContent(previousResults []nistUploadResult, result []byte, sessionID string, filename string) []nistUploadResult {
+	var data []vectorResult
+	if err := json.Unmarshal(result, &data); err != nil {
+		// Assume file is not JSON. Log and continue to next file.
+		log.Printf("Failed to parse %q: %s", filename, err)
+		return previousResults
+	}
+
+	vectorSetID, err := getVectorSetID(data)
+	if err != nil {
+		log.Fatalf("failed to get VectorSetID: %s", err)
+	}
+	// uploadResult() uses acvp.Server whose write() function takes the
+	// JSON *object* payload and turns it into a JSON *array* adding
+	// {"acvVersion":"1.0"} as a top-level object. Since the result file is
+	// already in this format, the JSON provided to uploadResult() must be
+	// modified to have those aspects removed. In other words, only store only
+	// the vector test result JSON object (do not store a JSON array or
+	// acvVersion object).
+	vectorTestResult, err := getVectorResult(data)
+	if err != nil {
+		log.Fatalf("failed to get VectorResult: %s", err)
+	}
+	requestPath := fmt.Sprintf("/acvp/v1/testSessions/%s/vectorSets/%d", sessionID, vectorSetID)
+	newResult := nistUploadResult{URLPath: requestPath, JSONResult: vectorTestResult}
+	return append(previousResults, newResult)
+}
+
 // Uploads a results directory based on the directory name being the session id.
 // Non-JSON files are ignored and JSON files are assumed to be test results.
 // The vectorSetId is retrieved from the test result file.
@@ -551,7 +586,7 @@
 
 	var results []nistUploadResult
 	// Read directory, identify, and process all files.
-	files, err := ioutil.ReadDir(directory)
+	files, err := os.ReadDir(directory)
 	if err != nil {
 		log.Fatalf("Unable to read directory: %s", err)
 	}
@@ -559,36 +594,12 @@
 	for _, file := range files {
 		// Add contents of the result file to results.
 		filePath := filepath.Join(directory, file.Name())
-		in, err := ioutil.ReadFile(filePath)
+		content, err := os.ReadFile(filePath)
 		if err != nil {
 			log.Fatalf("Cannot open input: %s", err)
 		}
 
-		var data []vectorResult
-		if err := json.Unmarshal(in, &data); err != nil {
-			// Assume file is not JSON. Log and continue to next file.
-			log.Printf("Failed to parse %q: %s", filePath, err)
-			continue
-		}
-
-		vectorSetID, err := getVectorSetID(data)
-		if err != nil {
-			log.Fatalf("Failed to get VectorSetId: %s", err)
-		}
-		// uploadResult() uses acvp.Server whose write() function takes the
-		// JSON *object* payload and turns it into a JSON *array* adding
-		// {"acvVersion":"1.0"} as a top-level object. Since the result file is
-		// already in this format, the JSON provided to uploadResult() must be
-		// modified to have those aspects removed. In other words, only store only
-		// the vector test result JSON object (do not store a JSON array or
-		// acvVersion object).
-		vectorTestResult, err := getVectorResult(data)
-		if err != nil {
-			log.Fatalf("Failed to get VectorResult: %s", err)
-		}
-		requestPath := fmt.Sprintf("/acvp/v1/testSessions/%s/vectorSets/%d", sessionID, vectorSetID)
-		newResult := nistUploadResult{URLPath: requestPath, JSONResult: vectorTestResult}
-		results = append(results, newResult)
+		results = processResultContent(results, content, sessionID, filePath)
 	}
 
 	uploadResults(results, sessionID, config, sessionTokensCacheDir)
@@ -656,18 +667,18 @@
 		}
 	}
 	if resultFlagCount > 1 {
-		log.Fatalf("only one submit result action (-upload, -directory) is allowed at a time")
+		log.Fatalf("only one submit result action (-upload, -directory, -gcs) is allowed at a time")
 	} else if resultFlagCount == 1 {
 		if len(*jsonInputFile) > 0 {
-			log.Fatalf("submit result action (-upload, -directory) cannot be used with -json")
+			log.Fatalf("submit result action (-upload, -directory, -gcs) cannot be used with -json")
 		} else if len(*runFlag) > 0 {
-			log.Fatalf("submit result action (-upload, -directory) cannot be used with -run")
+			log.Fatalf("submit result action (-upload, -directory, -gcs) cannot be used with -run")
 		} else if len(*fetchFlag) > 0 {
-			log.Fatalf("submit result action (-upload, -directory) cannot be used with -fetch")
+			log.Fatalf("submit result action (-upload, -directory, -gcs) cannot be used with -fetch")
 		} else if len(*expectedOutFlag) > 0 {
-			log.Fatalf("submit result action (-upload, -directory) cannot be used with -expected-out")
+			log.Fatalf("submit result action (-upload, -directory, -gcs) cannot be used with -expected-out")
 		} else if *dumpRegcap {
-			log.Fatalf("submit result action (-upload, -directory) cannot be used with -regcap")
+			log.Fatalf("submit result action (-upload, -directory, -gcs) cannot be used with -regcap")
 		}
 	}
 
@@ -813,6 +824,9 @@
 		uploadResultsDirectory(*uploadDirectory, &config, sessionTokensCacheDir)
 		return
 	}
+	if handleGCSFlag(&config, sessionTokensCacheDir) {
+		return
+	}
 
 	server, err := connect(&config, sessionTokensCacheDir)
 	if err != nil {
diff --git a/src/util/fipstools/acvp/acvptool/gcs.go b/src/util/fipstools/acvp/acvptool/gcs.go
new file mode 100644
index 0000000..e010216
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/gcs.go
@@ -0,0 +1,99 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build gcs
+
+package main
+
+import (
+	"context"
+	"flag"
+	"io"
+	"log"
+	neturl "net/url"
+	"time"
+
+	"cloud.google.com/go/storage"
+	"google.golang.org/api/iterator"
+)
+
+var uploadGCSDirectory = flag.String("gcs", "", "GCS path to folder where result files to be uploaded are")
+
+// Uploads results directory from GCS.
+// Similar to uploadResultsDirectory().
+func uploadResultsFromGCS(gcsBucket string, config *Config, sessionTokensCacheDir string) {
+	u, err := neturl.Parse(gcsBucket)
+	if err != nil {
+		log.Fatal(err)
+	}
+	bucket := u.Host
+	folder := trimLeadingSlash(addTrailingSlash(u.Path))
+	sessionID, err := getLastDigitDir(folder)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	ctx := context.Background()
+	client, err := storage.NewClient(ctx)
+	if err != nil {
+		log.Fatalf("Failed to create client: %v", err)
+	}
+	defer client.Close()
+	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
+	defer cancel()
+
+	// Access bucket and identify all objects.
+	// Objects include the folder.
+	it := client.Bucket(bucket).Objects(ctx, &storage.Query{
+		Prefix:    folder,
+		Delimiter: "/",
+	})
+
+	var results []nistUploadResult
+	// Go through each object (noting GCS stores objects, not files)
+	for {
+		attrs, err := it.Next()
+		if err == iterator.Done {
+			break
+		} else if err != nil {
+			log.Fatalf("Unable to read bucket: %s", err)
+		}
+		rc, err := client.Bucket(bucket).Object(attrs.Name).NewReader(ctx)
+		if err != nil {
+			log.Fatalf("unable to open object from bucket %q, object %q: %v", bucket, attrs.Name, err)
+			return
+		}
+		defer rc.Close()
+		content, err := io.ReadAll(rc)
+		if err != nil {
+			log.Fatalf("unable to read contents of object %q: %v", attrs.Name, err)
+		}
+		if len(content) == 0 {
+			log.Printf("object (gs://%s/%s) is a \"folder\" or empty.", bucket, attrs.Name)
+			continue
+		}
+
+		results = processResultContent(results, content, sessionID, attrs.Name)
+	}
+
+	uploadResults(results, sessionID, config, sessionTokensCacheDir)
+}
+
+func handleGCSFlag(config *Config, sessionTokensCacheDir string) bool {
+	if len(*uploadGCSDirectory) > 0 {
+		uploadResultsFromGCS(*uploadGCSDirectory, config, sessionTokensCacheDir)
+		return true
+	}
+	return false
+}
diff --git a/src/util/fipstools/acvp/acvptool/interactive.go b/src/util/fipstools/acvp/acvptool/interactive.go
index d3c83a3..68b00a2 100644
--- a/src/util/fipstools/acvp/acvptool/interactive.go
+++ b/src/util/fipstools/acvp/acvptool/interactive.go
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 //go:build interactive
-// +build interactive
 
 package main
 
diff --git a/src/util/fipstools/acvp/acvptool/nogcs.go b/src/util/fipstools/acvp/acvptool/nogcs.go
new file mode 100644
index 0000000..b081351
--- /dev/null
+++ b/src/util/fipstools/acvp/acvptool/nogcs.go
@@ -0,0 +1,19 @@
+// Copyright 2025 The BoringSSL Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build !gcs
+
+package main
+
+func handleGCSFlag(config *Config, sessionTokensCacheDir string) bool { return false }
diff --git a/src/util/fipstools/acvp/acvptool/nointeractive.go b/src/util/fipstools/acvp/acvptool/nointeractive.go
index 53d2a28..23caed7 100644
--- a/src/util/fipstools/acvp/acvptool/nointeractive.go
+++ b/src/util/fipstools/acvp/acvptool/nointeractive.go
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 //go:build !interactive
-// +build !interactive
 
 package main
 
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/hmac.go b/src/util/fipstools/acvp/acvptool/subprocess/hmac.go
index 3273f3c..e4d5e40 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/hmac.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/hmac.go
@@ -119,14 +119,14 @@
 			}
 
 			m.TransactAsync(h.algo, 1, [][]byte{msg, key}, func(result [][]byte) error {
-				if l := len(result[0]); l < outBytes {
-					return fmt.Errorf("HMAC result too short: %d bytes but wanted %d", l, outBytes)
+				if l := len(result[0]); l != outBytes {
+					return fmt.Errorf("incorrect HMAC length: %d bytes but wanted %d", l, outBytes)
 				}
 
 				// https://pages.nist.gov/ACVP/draft-fussell-acvp-mac.html#name-test-vectors
 				response.Tests = append(response.Tests, hmacTestResponse{
 					ID:     test.ID,
-					MACHex: hex.EncodeToString(result[0][:outBytes]),
+					MACHex: hex.EncodeToString(result[0]),
 				})
 				return nil
 			})
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/mldsa.go b/src/util/fipstools/acvp/acvptool/subprocess/mldsa.go
index d248ff6..b7cde7d 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/mldsa.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/mldsa.go
@@ -92,12 +92,12 @@
 	ID           uint64            `json:"tgId"`
 	TestType     string            `json:"testType"`
 	ParameterSet string            `json:"parameterSet"`
-	PublicKey    string            `json:"pk"`
 	Tests        []mldsaSigVerTest `json:"tests"`
 }
 
 type mldsaSigVerTest struct {
 	ID        uint64 `json:"tcId"`
+	PublicKey string `json:"pk"`
 	Message   string `json:"message"`
 	Signature string `json:"signature"`
 }
@@ -254,13 +254,13 @@
 		}
 		cmdName := group.ParameterSet + "/sigVer"
 
-		pk, err := hex.DecodeString(group.PublicKey)
-		if err != nil {
-			return nil, fmt.Errorf("failed to decode public key in group %d: %s",
-				group.ID, err)
-		}
-
 		for _, test := range group.Tests {
+			pk, err := hex.DecodeString(test.PublicKey)
+			if err != nil || len(pk) == 0 {
+				return nil, fmt.Errorf("failed to decode public key in test case %d/%d: %s",
+					group.ID, test.ID, err)
+			}
+
 			msg, err := hex.DecodeString(test.Message)
 			if err != nil {
 				return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s",
diff --git a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
index f550cf0..78e69ce 100644
--- a/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
+++ b/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
@@ -371,8 +371,6 @@
 					m.supportsFlush = true
 				}
 			}
-		} else if _, ok := m.primitives[algo.Algorithm]; !ok {
-			return nil, fmt.Errorf("wrapper config advertises support for unknown algorithm %q", algo.Algorithm)
 		}
 	}
 
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/CMAC-AES.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/CMAC-AES.bz2
index f80e502..5c71478 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/CMAC-AES.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/CMAC-AES.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA-1.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA-1.bz2
index a95786d..de6c60f 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA-1.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA-1.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-224.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-224.bz2
index c8ab1f9..8a14531 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-224.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-224.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-256.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-256.bz2
index 1090835..6639cf0 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-256.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-256.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-384.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-384.bz2
index 5b445a5..8d799b7 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-384.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-384.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512-256.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512-256.bz2
index 1fdfa42..5f869cd 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512-256.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512-256.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512.bz2
index 3e46724..a1b2fd4 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/HMAC-SHA2-512.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/expected/ML-DSA.bz2 b/src/util/fipstools/acvp/acvptool/test/expected/ML-DSA.bz2
index 77290c1..cf13292 100644
--- a/src/util/fipstools/acvp/acvptool/test/expected/ML-DSA.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/expected/ML-DSA.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/trim_vectors.go b/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
index 33dc947..59e5791 100644
--- a/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
+++ b/src/util/fipstools/acvp/acvptool/test/trim_vectors.go
@@ -15,11 +15,13 @@
 //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.
+// from each test group, and also discards any test that serializes to more than
+// 4096 bytes. This hope is that this achieves good coverage without having to
+// check in megabytes worth of JSON files.
 package main
 
 import (
+	"bytes"
 	"encoding/json"
 	"os"
 )
@@ -39,12 +41,22 @@
 			testGroup := testGroupInterface.(map[string]any)
 			tests := testGroup["tests"].([]any)
 
-			keepIndex := 10
-			if keepIndex >= len(tests) {
-				keepIndex = len(tests) - 1
+			var keptTests []any
+			for _, test := range tests {
+				var b bytes.Buffer
+				encoder := json.NewEncoder(&b)
+				if err := encoder.Encode(test); err != nil {
+					panic(err)
+				}
+				if b.Len() <= 4096 {
+					keptTests = append(keptTests, test)
+				}
+				// We only keep the first test that meets the size criteria.
+				if len(keptTests) >= 1 {
+					break
+				}
 			}
-
-			testGroup["tests"] = []any{tests[keepIndex]}
+			testGroup["tests"] = keptTests
 		}
 	}
 
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/CMAC-AES.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/CMAC-AES.bz2
index ff34573..f38d822 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/CMAC-AES.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/CMAC-AES.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA-1.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA-1.bz2
index d427f2e..b379dee 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA-1.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA-1.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-224.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-224.bz2
index dd67b61..62b52d4 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-224.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-224.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-256.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-256.bz2
index b137466..5cb072a 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-256.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-256.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-384.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-384.bz2
index 2c1b317..6d1eb6d 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-384.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-384.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512-256.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512-256.bz2
index d981300..68b34e0 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512-256.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512-256.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512.bz2
index a3ffe61..5ce2742 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/HMAC-SHA2-512.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/acvptool/test/vectors/ML-DSA.bz2 b/src/util/fipstools/acvp/acvptool/test/vectors/ML-DSA.bz2
index e4bcaa1..317dfec 100644
--- a/src/util/fipstools/acvp/acvptool/test/vectors/ML-DSA.bz2
+++ b/src/util/fipstools/acvp/acvptool/test/vectors/ML-DSA.bz2
Binary files differ
diff --git a/src/util/fipstools/acvp/modulewrapper/CMakeLists.txt b/src/util/fipstools/acvp/modulewrapper/CMakeLists.txt
deleted file mode 100644
index 7938d39..0000000
--- a/src/util/fipstools/acvp/modulewrapper/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-if(FIPS)
-  add_executable(
-    modulewrapper
-
-    main.cc
-    modulewrapper.cc
-  )
-  target_link_libraries(modulewrapper crypto)
-endif()
diff --git a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
index d862f87..018aceb 100644
--- a/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
+++ b/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
@@ -442,9 +442,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 160, "increment": 8
-        }]
+        "macLen": [160]
       },
       {
         "algorithm": "HMAC-SHA2-224",
@@ -452,9 +450,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 224, "increment": 8
-        }]
+        "macLen": [224]
       },
       {
         "algorithm": "HMAC-SHA2-256",
@@ -462,9 +458,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 256, "increment": 8
-        }]
+        "macLen": [256]
       },
       {
         "algorithm": "HMAC-SHA2-384",
@@ -472,9 +466,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 384, "increment": 8
-        }]
+        "macLen": [384]
       },
       {
         "algorithm": "HMAC-SHA2-512",
@@ -482,9 +474,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 512, "increment": 8
-        }]
+        "macLen": [512]
       },
       {
         "algorithm": "HMAC-SHA2-512/256",
@@ -492,9 +482,7 @@
         "keyLen": [{
           "min": 8, "max": 524288, "increment": 8
         }],
-        "macLen": [{
-          "min": 32, "max": 256, "increment": 8
-        }]
+        "macLen": [256]
       },
       {
         "algorithm": "ctrDRBG",
@@ -848,11 +836,7 @@
             "increment": 8
           }],
           "keyLen": [128, 256],
-          "macLen": [{
-            "min": 8,
-            "max": 128,
-            "increment": 8
-          }]
+          "macLen": [128]
         }]
       },
       {
@@ -959,30 +943,42 @@
         "algorithm": "ML-DSA",
         "mode": "sigGen",
         "revision": "FIPS204",
-        "parameterSets": [
-          "ML-DSA-65",
-          "ML-DSA-87"
-        ],
+        "signatureInterfaces": ["internal"],
         "deterministic": [
           true,
           false
         ],
-        "messageLength": [
-          {
+        "externalMu": [
+          false
+        ],
+        "capabilities": [{
+          "parameterSets": [
+            "ML-DSA-65",
+            "ML-DSA-87"
+          ],
+          "messageLength": [{
             "min": 8,
             "max": 65536,
             "increment": 8
-          }
-        ]
+          }]
+        }]
       },
       {
         "algorithm": "ML-DSA",
         "mode": "sigVer",
         "revision": "FIPS204",
-        "parameterSets": [
-          "ML-DSA-65",
-          "ML-DSA-87"
-        ]
+        "signatureInterfaces": ["internal"],
+        "capabilities": [{
+          "messageLength": [{
+            "min": 8,
+            "max": 65536,
+            "increment": 8
+          }],
+          "parameterSets": [
+            "ML-DSA-65",
+            "ML-DSA-87"
+          ]
+        }]
       },
       {
         "algorithm": "ML-KEM",
@@ -1022,6 +1018,7 @@
           true,
           false
         ],
+        "signatureInterfaces": [ "internal" ],
         "capabilities": [
           {
             "parameterSets": [
@@ -1041,6 +1038,7 @@
         "algorithm": "SLH-DSA",
         "mode": "sigVer",
         "revision": "FIPS205",
+        "signatureInterfaces": [ "internal" ],
         "deterministic": [
           true,
           false
@@ -1952,11 +1950,11 @@
     return false;
   }
   memcpy(&mac_len, args[0].data(), sizeof(mac_len));
-  if (mac_len > sizeof(mac)) {
+  if (mac_len != sizeof(mac)) {
     return false;
   }
 
-  return write_reply({Span<const uint8_t>(mac, mac_len)});
+  return write_reply({Span<const uint8_t>(mac, sizeof(mac))});
 }
 
 static bool CMAC_AESVerify(const Span<const uint8_t> args[],
@@ -2573,11 +2571,11 @@
     {"FFDH", 6, FFDH},
     {"ML-DSA-65/keyGen", 1,
      MLDSAKeyGen<BCM_mldsa65_private_key, BCM_MLDSA65_PUBLIC_KEY_BYTES,
-                 BCM_mldsa65_generate_key_external_entropy,
+                 BCM_mldsa65_generate_key_external_entropy_fips,
                  BCM_mldsa65_marshal_private_key>},
     {"ML-DSA-87/keyGen", 1,
      MLDSAKeyGen<BCM_mldsa87_private_key, BCM_MLDSA87_PUBLIC_KEY_BYTES,
-                 BCM_mldsa87_generate_key_external_entropy,
+                 BCM_mldsa87_generate_key_external_entropy_fips,
                  BCM_mldsa87_marshal_private_key>},
     {"ML-DSA-65/sigGen", 3,
      MLDSASigGen<BCM_mldsa65_private_key, BCM_MLDSA65_SIGNATURE_BYTES,
diff --git a/src/util/fipstools/break-kat.go b/src/util/fipstools/break-kat.go
index aafd1c3..3304e9e 100644
--- a/src/util/fipstools/break-kat.go
+++ b/src/util/fipstools/break-kat.go
@@ -38,9 +38,18 @@
 		"DRBG":            "c4da0740d505f1ee280b95e58c4931ac6de846a0152fbb4a3f174cf4787a4f1a40c2b50babe14aae530be5886d910a27",
 		"DRBG-reseed":     "c7161ca36c2309b716e9859bb96c6d49bdc8352103a18cd24ef42ec97ef46bf446eb1a4576c186e9351803763a7912fe",
 		"HKDF":            "68678504b9b3add17d5967a1a7bd37993fd8a33ce7303071f39c096d1635b3c9",
+		"MLDSA-keygen":    "0c6f387d2ab43387f021b0da816c71f0bc815ef0b16af1124f354c273eedb42fe54a019a",
+		"MLDSA-sign":      "f8c725848b39d9d980f02ff7a02419087065e2c80ac4d3d5974931ea7bd664b66e6bf3c7",
+		"MLDSA-verify":    "4923cea1293b2400ccc3b19f1e803ed85a0d6e0ba64f35f845f420d848e1858205883fdd",
+		"MLKEM-keygen":    "d8c9397c3130d8ecb411a68efcc89a553cb7e6817e0288bd0691609bf5",
+		"MLKEM-encap":     "7d9f1cb4ae04d75fa6575ae0e429b573a974b7",
+		"MLKEM-decap":     "a3192a8c88fc996d2df9858d2c55363993f0494d7ec0be5a567b8a4243a5745d",
 		"SHA-1":           "132fd9bad5c1826263bafbb699f707a5",
 		"SHA-256":         "ff3b857da7236a2baa0f396b51522217",
 		"SHA-512":         "212512f8d2ad8322781c6c4d69a9daa1",
+		"SLHDSA-keygen":   "be6bd7e8e198eaf62d572f13fc79f26f",
+		"SLHDSA-sign":     "82d409744d97ae305318469f7b857b91d4e33310b709b550a7c48a46094ec9d4",
+		"SLHDSA-verify":   "3fd69193ee9708bdea110ba29f235ff2ec9888d12761f84dc6e3f0d7eb48d05cacf6e87f",
 		"TLS10-KDF":       "abc3657b094c7628a0b282996fe75a75f4984fd94d4ecc2fcf53a2c469a3f731",
 		"TLS12-KDF":       "c5438ee26fd4acbd259fc91855dc69bf884ee29322fcbfd2966a4623d42ec781",
 		"TLS13-KDF":       "024a0d80f357f2499a1244dac26dab66fc13ed85fca71dace146211119525874",
@@ -88,6 +97,8 @@
 	}
 
 	for _, test := range sortedKATs() {
+		fmt.Printf("\n### Running test for %q\n\n", test)
+
 		const outFile = "test_fips_broken"
 		output, err := os.OpenFile(outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0755)
 		if err != nil {
@@ -96,7 +107,6 @@
 		breakBinary(binaryContents, test, output)
 		output.Close()
 
-		fmt.Printf("\n### Running test for %q\n\n", test)
 		cmd := exec.Command("./" + outFile)
 		cmd.Stdout = os.Stdout
 		cmd.Stderr = os.Stdout
@@ -108,7 +118,7 @@
 		os.Remove(outFile)
 	}
 
-	for _, test := range []string{"ECDSA_PWCT", "RSA_PWCT", "CRNG"} {
+	for _, test := range []string{"ECDSA_PWCT", "RSA_PWCT", "MLDSA_PWCT", "MLKEM_PWCT", "SLHDSA_PWCT", "CRNG"} {
 		fmt.Printf("\n### Running test for %q\n\n", test)
 
 		cmd := exec.Command("./" + inPath)
@@ -129,24 +139,28 @@
 		panic("invalid KAT data: " + err.Error())
 	}
 
-	i := bytes.Index(binaryContents, testInputValue)
-	if i < 0 {
-		fmt.Fprintln(os.Stderr, "Expected test input value for", test, "was not found in binary.")
-		os.Exit(3)
-	}
-
 	brokenContents := make([]byte, len(binaryContents))
 	copy(brokenContents, binaryContents)
 
-	// Zero out the entire value because the compiler may produce code
-	// where parts of the value are embedded in the instructions.
-	for j := range testInputValue {
-		brokenContents[i+j] = 0
+	found := false
+	for {
+		i := bytes.Index(brokenContents, testInputValue)
+		if i < 0 {
+			break
+		}
+		found = true
+
+		// Zero out the entire value because the compiler may produce code
+		// where parts of the value are embedded in the instructions.
+		// See crbug.com/399818730
+		for j := range testInputValue {
+			brokenContents[i+j] = 0
+		}
 	}
 
-	if bytes.Index(brokenContents, testInputValue) >= 0 {
-		fmt.Fprintln(os.Stderr, "Test input value was still found after erasing it. Second copy?")
-		os.Exit(4)
+	if !found {
+		fmt.Fprintln(os.Stderr, "Expected test input value for", test, "was not found in binary.")
+		os.Exit(3)
 	}
 
 	if n, err := output.Write(brokenContents); err != nil || n != len(brokenContents) {
diff --git a/src/util/fipstools/break-tests.sh b/src/util/fipstools/break-tests.sh
index e056e8f..111f120 100644
--- a/src/util/fipstools/break-tests.sh
+++ b/src/util/fipstools/break-tests.sh
@@ -128,7 +128,7 @@
 }
 
 if [ "$MODE" = "local" ]; then
-  TEST_FIPS_BIN=${TEST_FIPS_BIN:-build/util/fipstools/test_fips}
+  TEST_FIPS_BIN=${TEST_FIPS_BIN:-build/test_fips}
   TEST_FIPS_BREAK_BIN=${TEST_FIPS_BREAK_BIN:-./test_fips_break}
   check_file "$TEST_FIPS_BIN"
   check_file "$TEST_FIPS_BREAK_BIN"
diff --git a/src/util/fipstools/delocate/delocate.go b/src/util/fipstools/delocate/delocate.go
index a1107f1..0252781 100644
--- a/src/util/fipstools/delocate/delocate.go
+++ b/src/util/fipstools/delocate/delocate.go
@@ -21,6 +21,7 @@
 	"errors"
 	"flag"
 	"fmt"
+	"io"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -48,6 +49,7 @@
 }
 
 type stringWriter interface {
+	io.Writer
 	WriteString(string) (int, error)
 }
 
@@ -145,6 +147,8 @@
 			statement, err = d.processDirective(statement, node.up)
 		case ruleLabelContainingDirective:
 			statement, err = d.processLabelContainingDirective(statement, node.up)
+		case ruleSymbolDefiningDirective:
+			statement, err = d.processSymbolDefiningDirective(statement, node.up)
 		case ruleLabel:
 			statement, err = d.processLabel(statement, node.up)
 		case ruleInstruction:
@@ -195,7 +199,7 @@
 		if len(args) < 1 {
 			return nil, errors.New("comm directive has no arguments")
 		}
-		d.bssAccessorsNeeded[demangle(args[0])] = args[0]
+		d.bssAccessorsNeeded[args[0]] = args[0]
 		d.writeNode(statement)
 
 	case "data":
@@ -204,6 +208,10 @@
 		// will have to work around this in the future.
 		return nil, errors.New(".data section found in module")
 
+	case "bss":
+		d.writeNode(statement)
+		return d.handleBSS(statement)
+
 	case "section":
 		section := args[0]
 
@@ -339,6 +347,45 @@
 	return statement, nil
 }
 
+func (d *delocation) processSymbolDefiningDirective(statement, directive *node32) (*node32, error) {
+	changed := false
+	assertNodeType(directive, ruleSymbolDefiningDirectiveName)
+	name := d.contents(directive)
+
+	node := directive.next
+	assertNodeType(node, ruleWS)
+
+	node = node.next
+	symbol := d.contents(node)
+	isLocal := node.pegRule == ruleLocalSymbol
+	if isLocal {
+		symbol = d.mapLocalSymbol(symbol)
+		changed = true
+	} else {
+		assertNodeType(node, ruleSymbolName)
+	}
+
+	node = skipWS(node.next)
+	assertNodeType(node, ruleSymbolArg)
+	assertNodeType(node.up, ruleSymbolExpr)
+	var b strings.Builder
+	changed = d.processSymbolExpr(node.up, &b) || changed
+	arg := b.String()
+
+	if !changed {
+		d.writeNode(statement)
+	} else {
+		d.writeCommentedNode(statement)
+		fmt.Fprintf(d.output, "\t%s\t%s, %s\n", name, symbol, arg)
+	}
+
+	if !isLocal {
+		fmt.Fprintf(d.output, "\t%s\t%s, %s\n", name, localTargetName(symbol), arg)
+	}
+
+	return statement, nil
+}
+
 func (d *delocation) processLabel(statement, label *node32) (*node32, error) {
 	symbol := d.contents(label)
 
@@ -411,18 +458,13 @@
 		panic("non-zero offset for helper-based reference")
 	}
 
-	var helperFunc string
-	if symbol == "OPENSSL_armcap_P" {
-		helperFunc = ".LOPENSSL_armcap_P_addr"
-	} else {
-		// GOT helpers also dereference the GOT entry, thus the subsequent ldr
-		// instruction, which would normally do the dereferencing, needs to be
-		// dropped. GOT helpers have to include the dereference because the
-		// assembler doesn't support ":got_lo12:foo" offsets except in an ldr
-		// instruction.
-		d.gotExternalsNeeded[symbol] = struct{}{}
-		helperFunc = gotHelperName(symbol)
-	}
+	// GOT helpers also dereference the GOT entry, thus the subsequent ldr
+	// instruction, which would normally do the dereferencing, needs to be
+	// dropped. GOT helpers have to include the dereference because the
+	// assembler doesn't support ":got_lo12:foo" offsets except in an ldr
+	// instruction.
+	d.gotExternalsNeeded[symbol] = struct{}{}
+	helperFunc := gotHelperName(symbol)
 
 	// Clear the red-zone. I can't find a definitive answer about whether Linux
 	// Aarch64 includes a red-zone, but Microsoft has a 16-byte one and Apple a
@@ -969,37 +1011,6 @@
 			symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up)
 			changed = didChange
 
-			if symbol == "OPENSSL_ia32cap_P" && section == "" {
-				if instructionName != "leaq" {
-					return nil, fmt.Errorf("non-leaq instruction %q referenced OPENSSL_ia32cap_P directly", instructionName)
-				}
-
-				if i != 0 || len(argNodes) != 2 || !d.isRIPRelative(memRef) || len(offset) > 0 {
-					return nil, fmt.Errorf("invalid OPENSSL_ia32cap_P reference in instruction %q", instructionName)
-				}
-
-				target := argNodes[1]
-				assertNodeType(target, ruleRegisterOrConstant)
-				reg := d.contents(target)
-
-				if !strings.HasPrefix(reg, "%r") {
-					return nil, fmt.Errorf("tried to load OPENSSL_ia32cap_P into %q, which is not a standard register.", reg)
-				}
-
-				changed = true
-
-				// Flag-altering instructions (i.e. addq) are going to be used so the
-				// flags need to be preserved.
-				wrappers = append(wrappers, saveFlags(d.output, false /* Red Zone not yet cleared */))
-
-				wrappers = append(wrappers, func(k func()) {
-					d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + reg + "\n")
-					d.output.WriteString("\taddq\t(" + reg + "), " + reg + "\n")
-				})
-
-				break Args
-			}
-
 			switch section {
 			case "":
 				if _, knownSymbol := d.symbols[symbol]; knownSymbol {
@@ -1142,15 +1153,7 @@
 					redzoneCleared = true
 				}
 
-				if symbol == "OPENSSL_ia32cap_P" {
-					// Flag-altering instructions (i.e. addq) are going to be used so the
-					// flags need to be preserved.
-					wrappers = append(wrappers, saveFlags(d.output, redzoneCleared))
-					wrappers = append(wrappers, func(k func()) {
-						d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + targetReg + "\n")
-						d.output.WriteString("\taddq\t(" + targetReg + "), " + targetReg + "\n")
-					})
-				} else if useGOT {
+				if useGOT {
 					wrappers = append(wrappers, d.loadFromGOT(d.output, targetReg, symbol, section, redzoneCleared))
 				} else {
 					wrappers = append(wrappers, func(k func()) {
@@ -1180,6 +1183,10 @@
 				argStr += d.contents(memRef)
 			}
 
+			for suffix := arg.next; suffix != nil; suffix = suffix.next {
+				argStr += d.contents(suffix)
+			}
+
 			args = append(args, argStr)
 
 		case ruleGOTAddress:
@@ -1189,6 +1196,9 @@
 			if i != 0 || len(argNodes) != 2 {
 				return nil, fmt.Errorf("Load of _GLOBAL_OFFSET_TABLE_ address didn't have expected form")
 			}
+			if arg.next != nil {
+				return nil, fmt.Errorf("unexpected argument suffix")
+			}
 			d.gotDeltaNeeded = true
 			changed = true
 			targetReg := d.contents(argNodes[1])
@@ -1205,6 +1215,9 @@
 			if i != 0 || len(argNodes) != 2 {
 				return nil, fmt.Errorf("movabs of _GLOBAL_OFFSET_TABLE_ didn't expected form")
 			}
+			if arg.next != nil {
+				return nil, fmt.Errorf("unexpected argument suffix")
+			}
 
 			d.gotDeltaNeeded = true
 			changed = true
@@ -1225,6 +1238,9 @@
 			if i != 0 || len(argNodes) != 2 {
 				return nil, fmt.Errorf("movabs of _GLOBAL_OFFSET_TABLE_ offset didn't have expected form")
 			}
+			if arg.next != nil {
+				return nil, fmt.Errorf("unexpected argument suffix")
+			}
 
 			assertNodeType(arg.up, ruleSymbolName)
 			symbol := d.contents(arg.up)
@@ -1303,7 +1319,7 @@
 				localSymbol := localTargetName(symbol)
 				d.output.WriteString(fmt.Sprintf("\n%s:\n", localSymbol))
 
-				d.bssAccessorsNeeded[demangle(symbol)] = localSymbol
+				d.bssAccessorsNeeded[symbol] = localSymbol
 			}
 
 		case ruleLabelContainingDirective:
@@ -1313,6 +1329,13 @@
 				return nil, err
 			}
 
+		case ruleSymbolDefiningDirective:
+			var err error
+			statement, err = d.processSymbolDefiningDirective(statement, node.up)
+			if err != nil {
+				return nil, err
+			}
+
 		default:
 			return nil, fmt.Errorf("unknown BSS statement type %q in %q", rul3s[node.pegRule], d.contents(statement))
 		}
@@ -1355,9 +1378,6 @@
 	// to match that behaviour otherwise warnings result.
 	fileDirectivesContainMD5 := false
 
-	// OPENSSL_ia32cap_get will be synthesized by this script.
-	symbols["OPENSSL_ia32cap_get"] = struct{}{}
-
 	for _, input := range inputs {
 		forEachPath(input.ast.up, func(node *node32) {
 			symbol := input.contents[node.begin:node.end]
@@ -1367,6 +1387,18 @@
 			symbols[symbol] = struct{}{}
 		}, ruleStatement, ruleLabel, ruleSymbolName)
 
+		// Some directives also define symbols.
+		forEachPath(input.ast.up, func(node *node32) {
+			node = skipWS(node.next)
+			if node.pegRule == ruleLocalSymbol {
+				return
+			}
+			assertNodeType(node, ruleSymbolName)
+			symbol := input.contents[node.begin:node.end]
+			// Allow duplicates. A symbol may be set multiple times with .set.
+			symbols[symbol] = struct{}{}
+		}, ruleStatement, ruleSymbolDefiningDirective, ruleSymbolDefiningDirectiveName)
+
 		forEachPath(input.ast.up, func(node *node32) {
 			assertNodeType(node, ruleLocationDirective)
 			directive := input.contents[node.begin:node.end]
@@ -1503,12 +1535,6 @@
 			})
 		}
 
-		writeAarch64Function(w, ".LOPENSSL_armcap_P_addr", func(w stringWriter) {
-			w.WriteString("\tadrp x0, OPENSSL_armcap_P\n")
-			w.WriteString("\tadd x0, x0, :lo12:OPENSSL_armcap_P\n")
-			w.WriteString("\tret\n")
-		})
-
 	case x86_64:
 		externalNames := sortedSet(d.gotExternalsNeeded)
 		for _, name := range externalNames {
@@ -1525,19 +1551,6 @@
 			w.WriteString("\t.long 0\n")
 		}
 
-		w.WriteString(".type OPENSSL_ia32cap_get, @function\n")
-		w.WriteString(".globl OPENSSL_ia32cap_get\n")
-		w.WriteString(localTargetName("OPENSSL_ia32cap_get") + ":\n")
-		w.WriteString("OPENSSL_ia32cap_get:\n")
-		w.WriteString("\tleaq OPENSSL_ia32cap_P(%rip), %rax\n")
-		w.WriteString("\tret\n")
-
-		w.WriteString(".extern OPENSSL_ia32cap_P\n")
-		w.WriteString(".type OPENSSL_ia32cap_addr_delta, @object\n")
-		w.WriteString(".size OPENSSL_ia32cap_addr_delta, 8\n")
-		w.WriteString("OPENSSL_ia32cap_addr_delta:\n")
-		w.WriteString(".quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta\n")
-
 		if d.gotDeltaNeeded {
 			w.WriteString(".Lboringssl_got_delta:\n")
 			w.WriteString("\t.quad _GLOBAL_OFFSET_TABLE_-.Lboringssl_got_delta\n")
@@ -1805,7 +1818,6 @@
 
 func isSynthesized(symbol string) bool {
 	return strings.HasSuffix(symbol, "_bss_get") ||
-		symbol == "OPENSSL_ia32cap_get" ||
 		strings.HasPrefix(symbol, "BORINGSSL_bcm_text_")
 }
 
@@ -1813,42 +1825,6 @@
 	return "bcm_redirector_" + symbol
 }
 
-// Optionally demangle C++ local variable names.
-func demangle(symbol string) string {
-	if !strings.HasPrefix(symbol, "_Z") {
-		return symbol
-	}
-
-	// The names must have the form "_ZL", followed by the length of the name
-	// in base 10, followed by the name.
-	if !strings.HasPrefix(symbol, "_ZL") {
-		panic("malformed symbol: starts with _Z but not _ZL")
-	}
-
-	if len(symbol) < 4 {
-		panic("malformed symbol: too short")
-	}
-
-	pos := 3
-	for pos < len(symbol) && '0' <= symbol[pos] && symbol[pos] <= '9' {
-		pos++
-	}
-	if pos == 3 {
-		panic("malformed symbol: no length digits")
-	}
-
-	length, err := strconv.Atoi(symbol[3:pos])
-	if err != nil {
-		panic("malformed symbol: invalid length")
-	}
-
-	if len(symbol[pos:]) != length {
-		panic("malformed symbol: length mismatch")
-	}
-
-	return symbol[pos:]
-}
-
 // sectionType returns the type of a section. I.e. a section called “.text.foo”
 // is a “.text” section.
 func sectionType(section string) (string, bool) {
diff --git a/src/util/fipstools/delocate/delocate.peg b/src/util/fipstools/delocate/delocate.peg
index 79dbe7f..078972e 100644
--- a/src/util/fipstools/delocate/delocate.peg
+++ b/src/util/fipstools/delocate/delocate.peg
@@ -30,6 +30,7 @@
 AsmFile <- Statement* !.
 Statement <- WS? (Label / ((GlobalDirective /
                             LocationDirective /
+                            SymbolDefiningDirective /
                             LabelContainingDirective /
                             Instruction /
                             Directive /
@@ -41,11 +42,13 @@
 FileDirective <- ".file" WS [^#\n]+
 LocDirective <- ".loc" WS [^#/\n]+
 Args <- Arg ((WS? ',' WS?) Arg)*
-Arg <- QuotedArg / [[0-9a-z%+\-*_@.]]*
+Arg <- QuotedArg / [[0-9a-z%+\-*_@.$]]*
 QuotedArg <- '"' QuotedText '"'
 QuotedText <- (EscapedChar / [^"])*
+SymbolDefiningDirective <- SymbolDefiningDirectiveName WS (LocalSymbol / SymbolName) WS? ',' WS? SymbolArg
+SymbolDefiningDirectiveName <- ".equiv" / ".equ" / ".set"
 LabelContainingDirective <- LabelContainingDirectiveName WS SymbolArgs
-LabelContainingDirectiveName <- ".xword" / ".word" / ".hword" / ".long" / ".set" / ".byte" / ".8byte" / ".4byte" / ".quad" / ".tc" / ".localentry" / ".size" / ".type" / ".uleb128" / ".sleb128"
+LabelContainingDirectiveName <- ".xword" / ".word" / ".hword" / ".long" / ".byte" / ".8byte" / ".4byte" / ".quad" / ".tc" / ".localentry" / ".size" / ".type" / ".uleb128" / ".sleb128"
 SymbolArgs <- SymbolArg ((WS? ',' WS?) SymbolArg)*
 
 SymbolArg <- SymbolExpr
@@ -85,7 +88,7 @@
                        ('#' '~'? '(' [0-9] WS? "<<" WS? [0-9] ')' ) /
                        ARMRegister)
                       ![fb:(+\-]
-ARMConstantTweak <- ((([us] "xt" [xwhb]) / "lsl" / "lsr" / "ror" / "asr") (WS '#' Offset)?) /
+ARMConstantTweak <- ((([us] "xt" [xwhb]) / "lsl" / "lsr" / "ror" / "asr" / "msl") (WS '#' Offset)?) /
                     "mul vl"  / # multiply offset by the hardware's vector length
                     "mul #" [0-9]
 ARMRegister <- "sp" /
diff --git a/src/util/fipstools/delocate/delocate.peg.go b/src/util/fipstools/delocate/delocate.peg.go
index 7baa0e7..0ff918c 100644
--- a/src/util/fipstools/delocate/delocate.peg.go
+++ b/src/util/fipstools/delocate/delocate.peg.go
@@ -30,6 +30,8 @@
 	ruleArg
 	ruleQuotedArg
 	ruleQuotedText
+	ruleSymbolDefiningDirective
+	ruleSymbolDefiningDirectiveName
 	ruleLabelContainingDirective
 	ruleLabelContainingDirectiveName
 	ruleSymbolArgs
@@ -95,6 +97,8 @@
 	"Arg",
 	"QuotedArg",
 	"QuotedText",
+	"SymbolDefiningDirective",
+	"SymbolDefiningDirectiveName",
 	"LabelContainingDirective",
 	"LabelContainingDirectiveName",
 	"SymbolArgs",
@@ -258,7 +262,7 @@
 type Asm struct {
 	Buffer string
 	buffer []rune
-	rules  [62]func() bool
+	rules  [64]func() bool
 	parse  func(rule ...int) error
 	reset  func()
 	Pretty bool
@@ -469,7 +473,7 @@
 			position, tokenIndex = position0, tokenIndex0
 			return false
 		},
-		/* 1 Statement <- <(WS? (Label / ((GlobalDirective / LocationDirective / LabelContainingDirective / Instruction / Directive / Comment / ) WS? ((Comment? '\n') / ';'))))> */
+		/* 1 Statement <- <(WS? (Label / ((GlobalDirective / LocationDirective / SymbolDefiningDirective / LabelContainingDirective / Instruction / Directive / Comment / ) WS? ((Comment? '\n') / ';'))))> */
 		func() bool {
 			position5, tokenIndex5 := position, tokenIndex
 			{
@@ -506,67 +510,73 @@
 						goto l11
 					l13:
 						position, tokenIndex = position11, tokenIndex11
-						if !_rules[ruleLabelContainingDirective]() {
+						if !_rules[ruleSymbolDefiningDirective]() {
 							goto l14
 						}
 						goto l11
 					l14:
 						position, tokenIndex = position11, tokenIndex11
-						if !_rules[ruleInstruction]() {
+						if !_rules[ruleLabelContainingDirective]() {
 							goto l15
 						}
 						goto l11
 					l15:
 						position, tokenIndex = position11, tokenIndex11
-						if !_rules[ruleDirective]() {
+						if !_rules[ruleInstruction]() {
 							goto l16
 						}
 						goto l11
 					l16:
 						position, tokenIndex = position11, tokenIndex11
-						if !_rules[ruleComment]() {
+						if !_rules[ruleDirective]() {
 							goto l17
 						}
 						goto l11
 					l17:
 						position, tokenIndex = position11, tokenIndex11
+						if !_rules[ruleComment]() {
+							goto l18
+						}
+						goto l11
+					l18:
+						position, tokenIndex = position11, tokenIndex11
 					}
 				l11:
 					{
-						position18, tokenIndex18 := position, tokenIndex
+						position19, tokenIndex19 := position, tokenIndex
 						if !_rules[ruleWS]() {
-							goto l18
+							goto l19
 						}
-						goto l19
-					l18:
-						position, tokenIndex = position18, tokenIndex18
+						goto l20
+					l19:
+						position, tokenIndex = position19, tokenIndex19
 					}
-				l19:
+				l20:
 					{
-						position20, tokenIndex20 := position, tokenIndex
+						position21, tokenIndex21 := position, tokenIndex
 						{
-							position22, tokenIndex22 := position, tokenIndex
+							position23, tokenIndex23 := position, tokenIndex
 							if !_rules[ruleComment]() {
-								goto l22
+								goto l23
 							}
-							goto l23
-						l22:
-							position, tokenIndex = position22, tokenIndex22
+							goto l24
+						l23:
+							position, tokenIndex = position23, tokenIndex23
 						}
-					l23:
+					l24:
 						if buffer[position] != rune('\n') {
-							goto l21
+							goto l22
 						}
 						position++
-						goto l20
-					l21:
-						position, tokenIndex = position20, tokenIndex20
+						goto l21
+					l22:
+						position, tokenIndex = position21, tokenIndex21
 						if buffer[position] != rune(';') {
 							goto l5
 						}
 						position++
 					}
-				l20:
+				l21:
 				}
 			l9:
 				add(ruleStatement, position6)
@@ -578,1771 +588,1759 @@
 		},
 		/* 2 GlobalDirective <- <((('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('a' / 'A') ('l' / 'L')) / ('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('l' / 'L'))) WS SymbolName)> */
 		func() bool {
-			position24, tokenIndex24 := position, tokenIndex
+			position25, tokenIndex25 := position, tokenIndex
 			{
-				position25 := position
+				position26 := position
 				{
-					position26, tokenIndex26 := position, tokenIndex
+					position27, tokenIndex27 := position, tokenIndex
 					if buffer[position] != rune('.') {
-						goto l27
-					}
-					position++
-					{
-						position28, tokenIndex28 := position, tokenIndex
-						if buffer[position] != rune('g') {
-							goto l29
-						}
-						position++
 						goto l28
-					l29:
-						position, tokenIndex = position28, tokenIndex28
-						if buffer[position] != rune('G') {
-							goto l27
-						}
-						position++
-					}
-				l28:
-					{
-						position30, tokenIndex30 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l31
-						}
-						position++
-						goto l30
-					l31:
-						position, tokenIndex = position30, tokenIndex30
-						if buffer[position] != rune('L') {
-							goto l27
-						}
-						position++
-					}
-				l30:
-					{
-						position32, tokenIndex32 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l33
-						}
-						position++
-						goto l32
-					l33:
-						position, tokenIndex = position32, tokenIndex32
-						if buffer[position] != rune('O') {
-							goto l27
-						}
-						position++
-					}
-				l32:
-					{
-						position34, tokenIndex34 := position, tokenIndex
-						if buffer[position] != rune('b') {
-							goto l35
-						}
-						position++
-						goto l34
-					l35:
-						position, tokenIndex = position34, tokenIndex34
-						if buffer[position] != rune('B') {
-							goto l27
-						}
-						position++
-					}
-				l34:
-					{
-						position36, tokenIndex36 := position, tokenIndex
-						if buffer[position] != rune('a') {
-							goto l37
-						}
-						position++
-						goto l36
-					l37:
-						position, tokenIndex = position36, tokenIndex36
-						if buffer[position] != rune('A') {
-							goto l27
-						}
-						position++
-					}
-				l36:
-					{
-						position38, tokenIndex38 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l39
-						}
-						position++
-						goto l38
-					l39:
-						position, tokenIndex = position38, tokenIndex38
-						if buffer[position] != rune('L') {
-							goto l27
-						}
-						position++
-					}
-				l38:
-					goto l26
-				l27:
-					position, tokenIndex = position26, tokenIndex26
-					if buffer[position] != rune('.') {
-						goto l24
 					}
 					position++
 					{
-						position40, tokenIndex40 := position, tokenIndex
+						position29, tokenIndex29 := position, tokenIndex
 						if buffer[position] != rune('g') {
-							goto l41
+							goto l30
 						}
 						position++
-						goto l40
-					l41:
-						position, tokenIndex = position40, tokenIndex40
+						goto l29
+					l30:
+						position, tokenIndex = position29, tokenIndex29
 						if buffer[position] != rune('G') {
-							goto l24
+							goto l28
 						}
 						position++
 					}
-				l40:
+				l29:
 					{
-						position42, tokenIndex42 := position, tokenIndex
+						position31, tokenIndex31 := position, tokenIndex
 						if buffer[position] != rune('l') {
-							goto l43
+							goto l32
 						}
 						position++
-						goto l42
-					l43:
-						position, tokenIndex = position42, tokenIndex42
+						goto l31
+					l32:
+						position, tokenIndex = position31, tokenIndex31
 						if buffer[position] != rune('L') {
-							goto l24
+							goto l28
 						}
 						position++
 					}
-				l42:
+				l31:
 					{
-						position44, tokenIndex44 := position, tokenIndex
+						position33, tokenIndex33 := position, tokenIndex
 						if buffer[position] != rune('o') {
-							goto l45
+							goto l34
 						}
 						position++
-						goto l44
-					l45:
-						position, tokenIndex = position44, tokenIndex44
+						goto l33
+					l34:
+						position, tokenIndex = position33, tokenIndex33
 						if buffer[position] != rune('O') {
-							goto l24
+							goto l28
 						}
 						position++
 					}
-				l44:
+				l33:
 					{
-						position46, tokenIndex46 := position, tokenIndex
+						position35, tokenIndex35 := position, tokenIndex
 						if buffer[position] != rune('b') {
-							goto l47
+							goto l36
 						}
 						position++
-						goto l46
-					l47:
-						position, tokenIndex = position46, tokenIndex46
+						goto l35
+					l36:
+						position, tokenIndex = position35, tokenIndex35
 						if buffer[position] != rune('B') {
-							goto l24
+							goto l28
 						}
 						position++
 					}
-				l46:
+				l35:
 					{
-						position48, tokenIndex48 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l49
+						position37, tokenIndex37 := position, tokenIndex
+						if buffer[position] != rune('a') {
+							goto l38
 						}
 						position++
-						goto l48
-					l49:
-						position, tokenIndex = position48, tokenIndex48
-						if buffer[position] != rune('L') {
-							goto l24
+						goto l37
+					l38:
+						position, tokenIndex = position37, tokenIndex37
+						if buffer[position] != rune('A') {
+							goto l28
 						}
 						position++
 					}
-				l48:
+				l37:
+					{
+						position39, tokenIndex39 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l40
+						}
+						position++
+						goto l39
+					l40:
+						position, tokenIndex = position39, tokenIndex39
+						if buffer[position] != rune('L') {
+							goto l28
+						}
+						position++
+					}
+				l39:
+					goto l27
+				l28:
+					position, tokenIndex = position27, tokenIndex27
+					if buffer[position] != rune('.') {
+						goto l25
+					}
+					position++
+					{
+						position41, tokenIndex41 := position, tokenIndex
+						if buffer[position] != rune('g') {
+							goto l42
+						}
+						position++
+						goto l41
+					l42:
+						position, tokenIndex = position41, tokenIndex41
+						if buffer[position] != rune('G') {
+							goto l25
+						}
+						position++
+					}
+				l41:
+					{
+						position43, tokenIndex43 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l44
+						}
+						position++
+						goto l43
+					l44:
+						position, tokenIndex = position43, tokenIndex43
+						if buffer[position] != rune('L') {
+							goto l25
+						}
+						position++
+					}
+				l43:
+					{
+						position45, tokenIndex45 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l46
+						}
+						position++
+						goto l45
+					l46:
+						position, tokenIndex = position45, tokenIndex45
+						if buffer[position] != rune('O') {
+							goto l25
+						}
+						position++
+					}
+				l45:
+					{
+						position47, tokenIndex47 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l48
+						}
+						position++
+						goto l47
+					l48:
+						position, tokenIndex = position47, tokenIndex47
+						if buffer[position] != rune('B') {
+							goto l25
+						}
+						position++
+					}
+				l47:
+					{
+						position49, tokenIndex49 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l50
+						}
+						position++
+						goto l49
+					l50:
+						position, tokenIndex = position49, tokenIndex49
+						if buffer[position] != rune('L') {
+							goto l25
+						}
+						position++
+					}
+				l49:
 				}
-			l26:
+			l27:
 				if !_rules[ruleWS]() {
-					goto l24
+					goto l25
 				}
 				if !_rules[ruleSymbolName]() {
-					goto l24
+					goto l25
 				}
-				add(ruleGlobalDirective, position25)
+				add(ruleGlobalDirective, position26)
 			}
 			return true
-		l24:
-			position, tokenIndex = position24, tokenIndex24
+		l25:
+			position, tokenIndex = position25, tokenIndex25
 			return false
 		},
 		/* 3 Directive <- <('.' DirectiveName (WS Args)?)> */
 		func() bool {
-			position50, tokenIndex50 := position, tokenIndex
+			position51, tokenIndex51 := position, tokenIndex
 			{
-				position51 := position
+				position52 := position
 				if buffer[position] != rune('.') {
-					goto l50
+					goto l51
 				}
 				position++
 				if !_rules[ruleDirectiveName]() {
-					goto l50
+					goto l51
 				}
 				{
-					position52, tokenIndex52 := position, tokenIndex
+					position53, tokenIndex53 := position, tokenIndex
 					if !_rules[ruleWS]() {
-						goto l52
+						goto l53
 					}
 					if !_rules[ruleArgs]() {
-						goto l52
+						goto l53
 					}
-					goto l53
-				l52:
-					position, tokenIndex = position52, tokenIndex52
+					goto l54
+				l53:
+					position, tokenIndex = position53, tokenIndex53
 				}
-			l53:
-				add(ruleDirective, position51)
+			l54:
+				add(ruleDirective, position52)
 			}
 			return true
-		l50:
-			position, tokenIndex = position50, tokenIndex50
+		l51:
+			position, tokenIndex = position51, tokenIndex51
 			return false
 		},
 		/* 4 DirectiveName <- <([a-z] / [A-Z] / ([0-9] / [0-9]) / '_')+> */
 		func() bool {
-			position54, tokenIndex54 := position, tokenIndex
+			position55, tokenIndex55 := position, tokenIndex
 			{
-				position55 := position
+				position56 := position
 				{
-					position58, tokenIndex58 := position, tokenIndex
+					position59, tokenIndex59 := position, tokenIndex
 					if c := buffer[position]; c < rune('a') || c > rune('z') {
-						goto l59
-					}
-					position++
-					goto l58
-				l59:
-					position, tokenIndex = position58, tokenIndex58
-					if c := buffer[position]; c < rune('A') || c > rune('Z') {
 						goto l60
 					}
 					position++
-					goto l58
+					goto l59
 				l60:
-					position, tokenIndex = position58, tokenIndex58
+					position, tokenIndex = position59, tokenIndex59
+					if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						goto l61
+					}
+					position++
+					goto l59
+				l61:
+					position, tokenIndex = position59, tokenIndex59
 					{
-						position62, tokenIndex62 := position, tokenIndex
+						position63, tokenIndex63 := position, tokenIndex
 						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l63
+							goto l64
 						}
 						position++
-						goto l62
-					l63:
-						position, tokenIndex = position62, tokenIndex62
+						goto l63
+					l64:
+						position, tokenIndex = position63, tokenIndex63
 						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l61
+							goto l62
 						}
 						position++
 					}
+				l63:
+					goto l59
 				l62:
-					goto l58
-				l61:
-					position, tokenIndex = position58, tokenIndex58
+					position, tokenIndex = position59, tokenIndex59
 					if buffer[position] != rune('_') {
-						goto l54
+						goto l55
 					}
 					position++
 				}
-			l58:
-			l56:
+			l59:
+			l57:
 				{
-					position57, tokenIndex57 := position, tokenIndex
+					position58, tokenIndex58 := position, tokenIndex
 					{
-						position64, tokenIndex64 := position, tokenIndex
+						position65, tokenIndex65 := position, tokenIndex
 						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l65
-						}
-						position++
-						goto l64
-					l65:
-						position, tokenIndex = position64, tokenIndex64
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
 							goto l66
 						}
 						position++
-						goto l64
+						goto l65
 					l66:
-						position, tokenIndex = position64, tokenIndex64
+						position, tokenIndex = position65, tokenIndex65
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l67
+						}
+						position++
+						goto l65
+					l67:
+						position, tokenIndex = position65, tokenIndex65
 						{
-							position68, tokenIndex68 := position, tokenIndex
+							position69, tokenIndex69 := position, tokenIndex
 							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l69
+								goto l70
 							}
 							position++
-							goto l68
-						l69:
-							position, tokenIndex = position68, tokenIndex68
+							goto l69
+						l70:
+							position, tokenIndex = position69, tokenIndex69
 							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l67
+								goto l68
 							}
 							position++
 						}
+					l69:
+						goto l65
 					l68:
-						goto l64
-					l67:
-						position, tokenIndex = position64, tokenIndex64
+						position, tokenIndex = position65, tokenIndex65
 						if buffer[position] != rune('_') {
-							goto l57
+							goto l58
 						}
 						position++
 					}
-				l64:
-					goto l56
-				l57:
-					position, tokenIndex = position57, tokenIndex57
+				l65:
+					goto l57
+				l58:
+					position, tokenIndex = position58, tokenIndex58
 				}
-				add(ruleDirectiveName, position55)
+				add(ruleDirectiveName, position56)
 			}
 			return true
-		l54:
-			position, tokenIndex = position54, tokenIndex54
+		l55:
+			position, tokenIndex = position55, tokenIndex55
 			return false
 		},
 		/* 5 LocationDirective <- <(FileDirective / LocDirective)> */
 		func() bool {
-			position70, tokenIndex70 := position, tokenIndex
+			position71, tokenIndex71 := position, tokenIndex
 			{
-				position71 := position
+				position72 := position
 				{
-					position72, tokenIndex72 := position, tokenIndex
+					position73, tokenIndex73 := position, tokenIndex
 					if !_rules[ruleFileDirective]() {
-						goto l73
+						goto l74
 					}
-					goto l72
-				l73:
-					position, tokenIndex = position72, tokenIndex72
+					goto l73
+				l74:
+					position, tokenIndex = position73, tokenIndex73
 					if !_rules[ruleLocDirective]() {
-						goto l70
+						goto l71
 					}
 				}
-			l72:
-				add(ruleLocationDirective, position71)
+			l73:
+				add(ruleLocationDirective, position72)
 			}
 			return true
-		l70:
-			position, tokenIndex = position70, tokenIndex70
+		l71:
+			position, tokenIndex = position71, tokenIndex71
 			return false
 		},
 		/* 6 FileDirective <- <('.' ('f' / 'F') ('i' / 'I') ('l' / 'L') ('e' / 'E') WS (!('#' / '\n') .)+)> */
 		func() bool {
-			position74, tokenIndex74 := position, tokenIndex
+			position75, tokenIndex75 := position, tokenIndex
 			{
-				position75 := position
+				position76 := position
 				if buffer[position] != rune('.') {
-					goto l74
+					goto l75
 				}
 				position++
 				{
-					position76, tokenIndex76 := position, tokenIndex
+					position77, tokenIndex77 := position, tokenIndex
 					if buffer[position] != rune('f') {
-						goto l77
+						goto l78
 					}
 					position++
-					goto l76
-				l77:
-					position, tokenIndex = position76, tokenIndex76
+					goto l77
+				l78:
+					position, tokenIndex = position77, tokenIndex77
 					if buffer[position] != rune('F') {
-						goto l74
+						goto l75
 					}
 					position++
 				}
-			l76:
+			l77:
 				{
-					position78, tokenIndex78 := position, tokenIndex
+					position79, tokenIndex79 := position, tokenIndex
 					if buffer[position] != rune('i') {
-						goto l79
+						goto l80
 					}
 					position++
-					goto l78
-				l79:
-					position, tokenIndex = position78, tokenIndex78
+					goto l79
+				l80:
+					position, tokenIndex = position79, tokenIndex79
 					if buffer[position] != rune('I') {
-						goto l74
+						goto l75
 					}
 					position++
 				}
-			l78:
+			l79:
 				{
-					position80, tokenIndex80 := position, tokenIndex
+					position81, tokenIndex81 := position, tokenIndex
 					if buffer[position] != rune('l') {
-						goto l81
+						goto l82
 					}
 					position++
-					goto l80
-				l81:
-					position, tokenIndex = position80, tokenIndex80
+					goto l81
+				l82:
+					position, tokenIndex = position81, tokenIndex81
 					if buffer[position] != rune('L') {
-						goto l74
+						goto l75
 					}
 					position++
 				}
-			l80:
+			l81:
 				{
-					position82, tokenIndex82 := position, tokenIndex
+					position83, tokenIndex83 := position, tokenIndex
 					if buffer[position] != rune('e') {
-						goto l83
+						goto l84
 					}
 					position++
-					goto l82
-				l83:
-					position, tokenIndex = position82, tokenIndex82
+					goto l83
+				l84:
+					position, tokenIndex = position83, tokenIndex83
 					if buffer[position] != rune('E') {
-						goto l74
+						goto l75
 					}
 					position++
 				}
-			l82:
+			l83:
 				if !_rules[ruleWS]() {
-					goto l74
+					goto l75
 				}
 				{
+					position87, tokenIndex87 := position, tokenIndex
+					{
+						position88, tokenIndex88 := position, tokenIndex
+						if buffer[position] != rune('#') {
+							goto l89
+						}
+						position++
+						goto l88
+					l89:
+						position, tokenIndex = position88, tokenIndex88
+						if buffer[position] != rune('\n') {
+							goto l87
+						}
+						position++
+					}
+				l88:
+					goto l75
+				l87:
+					position, tokenIndex = position87, tokenIndex87
+				}
+				if !matchDot() {
+					goto l75
+				}
+			l85:
+				{
 					position86, tokenIndex86 := position, tokenIndex
 					{
-						position87, tokenIndex87 := position, tokenIndex
-						if buffer[position] != rune('#') {
-							goto l88
+						position90, tokenIndex90 := position, tokenIndex
+						{
+							position91, tokenIndex91 := position, tokenIndex
+							if buffer[position] != rune('#') {
+								goto l92
+							}
+							position++
+							goto l91
+						l92:
+							position, tokenIndex = position91, tokenIndex91
+							if buffer[position] != rune('\n') {
+								goto l90
+							}
+							position++
 						}
-						position++
-						goto l87
-					l88:
-						position, tokenIndex = position87, tokenIndex87
-						if buffer[position] != rune('\n') {
-							goto l86
-						}
-						position++
+					l91:
+						goto l86
+					l90:
+						position, tokenIndex = position90, tokenIndex90
 					}
-				l87:
-					goto l74
+					if !matchDot() {
+						goto l86
+					}
+					goto l85
 				l86:
 					position, tokenIndex = position86, tokenIndex86
 				}
-				if !matchDot() {
-					goto l74
-				}
-			l84:
-				{
-					position85, tokenIndex85 := position, tokenIndex
-					{
-						position89, tokenIndex89 := position, tokenIndex
-						{
-							position90, tokenIndex90 := position, tokenIndex
-							if buffer[position] != rune('#') {
-								goto l91
-							}
-							position++
-							goto l90
-						l91:
-							position, tokenIndex = position90, tokenIndex90
-							if buffer[position] != rune('\n') {
-								goto l89
-							}
-							position++
-						}
-					l90:
-						goto l85
-					l89:
-						position, tokenIndex = position89, tokenIndex89
-					}
-					if !matchDot() {
-						goto l85
-					}
-					goto l84
-				l85:
-					position, tokenIndex = position85, tokenIndex85
-				}
-				add(ruleFileDirective, position75)
+				add(ruleFileDirective, position76)
 			}
 			return true
-		l74:
-			position, tokenIndex = position74, tokenIndex74
+		l75:
+			position, tokenIndex = position75, tokenIndex75
 			return false
 		},
 		/* 7 LocDirective <- <('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') WS (!('#' / '/' / '\n') .)+)> */
 		func() bool {
-			position92, tokenIndex92 := position, tokenIndex
+			position93, tokenIndex93 := position, tokenIndex
 			{
-				position93 := position
+				position94 := position
 				if buffer[position] != rune('.') {
-					goto l92
+					goto l93
 				}
 				position++
 				{
-					position94, tokenIndex94 := position, tokenIndex
+					position95, tokenIndex95 := position, tokenIndex
 					if buffer[position] != rune('l') {
-						goto l95
+						goto l96
 					}
 					position++
-					goto l94
-				l95:
-					position, tokenIndex = position94, tokenIndex94
+					goto l95
+				l96:
+					position, tokenIndex = position95, tokenIndex95
 					if buffer[position] != rune('L') {
-						goto l92
+						goto l93
 					}
 					position++
 				}
-			l94:
+			l95:
 				{
-					position96, tokenIndex96 := position, tokenIndex
+					position97, tokenIndex97 := position, tokenIndex
 					if buffer[position] != rune('o') {
-						goto l97
+						goto l98
 					}
 					position++
-					goto l96
-				l97:
-					position, tokenIndex = position96, tokenIndex96
+					goto l97
+				l98:
+					position, tokenIndex = position97, tokenIndex97
 					if buffer[position] != rune('O') {
-						goto l92
+						goto l93
 					}
 					position++
 				}
-			l96:
+			l97:
 				{
-					position98, tokenIndex98 := position, tokenIndex
+					position99, tokenIndex99 := position, tokenIndex
 					if buffer[position] != rune('c') {
-						goto l99
+						goto l100
 					}
 					position++
-					goto l98
-				l99:
-					position, tokenIndex = position98, tokenIndex98
+					goto l99
+				l100:
+					position, tokenIndex = position99, tokenIndex99
 					if buffer[position] != rune('C') {
-						goto l92
+						goto l93
 					}
 					position++
 				}
-			l98:
+			l99:
 				if !_rules[ruleWS]() {
-					goto l92
+					goto l93
 				}
 				{
-					position102, tokenIndex102 := position, tokenIndex
+					position103, tokenIndex103 := position, tokenIndex
 					{
-						position103, tokenIndex103 := position, tokenIndex
+						position104, tokenIndex104 := position, tokenIndex
 						if buffer[position] != rune('#') {
-							goto l104
-						}
-						position++
-						goto l103
-					l104:
-						position, tokenIndex = position103, tokenIndex103
-						if buffer[position] != rune('/') {
 							goto l105
 						}
 						position++
-						goto l103
+						goto l104
 					l105:
-						position, tokenIndex = position103, tokenIndex103
+						position, tokenIndex = position104, tokenIndex104
+						if buffer[position] != rune('/') {
+							goto l106
+						}
+						position++
+						goto l104
+					l106:
+						position, tokenIndex = position104, tokenIndex104
 						if buffer[position] != rune('\n') {
-							goto l102
+							goto l103
 						}
 						position++
 					}
+				l104:
+					goto l93
 				l103:
-					goto l92
-				l102:
-					position, tokenIndex = position102, tokenIndex102
+					position, tokenIndex = position103, tokenIndex103
 				}
 				if !matchDot() {
-					goto l92
+					goto l93
 				}
-			l100:
+			l101:
 				{
-					position101, tokenIndex101 := position, tokenIndex
+					position102, tokenIndex102 := position, tokenIndex
 					{
-						position106, tokenIndex106 := position, tokenIndex
+						position107, tokenIndex107 := position, tokenIndex
 						{
-							position107, tokenIndex107 := position, tokenIndex
+							position108, tokenIndex108 := position, tokenIndex
 							if buffer[position] != rune('#') {
-								goto l108
-							}
-							position++
-							goto l107
-						l108:
-							position, tokenIndex = position107, tokenIndex107
-							if buffer[position] != rune('/') {
 								goto l109
 							}
 							position++
-							goto l107
+							goto l108
 						l109:
-							position, tokenIndex = position107, tokenIndex107
+							position, tokenIndex = position108, tokenIndex108
+							if buffer[position] != rune('/') {
+								goto l110
+							}
+							position++
+							goto l108
+						l110:
+							position, tokenIndex = position108, tokenIndex108
 							if buffer[position] != rune('\n') {
-								goto l106
+								goto l107
 							}
 							position++
 						}
+					l108:
+						goto l102
 					l107:
-						goto l101
-					l106:
-						position, tokenIndex = position106, tokenIndex106
+						position, tokenIndex = position107, tokenIndex107
 					}
 					if !matchDot() {
-						goto l101
+						goto l102
 					}
-					goto l100
-				l101:
-					position, tokenIndex = position101, tokenIndex101
+					goto l101
+				l102:
+					position, tokenIndex = position102, tokenIndex102
 				}
-				add(ruleLocDirective, position93)
+				add(ruleLocDirective, position94)
 			}
 			return true
-		l92:
-			position, tokenIndex = position92, tokenIndex92
+		l93:
+			position, tokenIndex = position93, tokenIndex93
 			return false
 		},
 		/* 8 Args <- <(Arg (WS? ',' WS? Arg)*)> */
 		func() bool {
-			position110, tokenIndex110 := position, tokenIndex
+			position111, tokenIndex111 := position, tokenIndex
 			{
-				position111 := position
+				position112 := position
 				if !_rules[ruleArg]() {
-					goto l110
+					goto l111
 				}
-			l112:
+			l113:
 				{
-					position113, tokenIndex113 := position, tokenIndex
+					position114, tokenIndex114 := position, tokenIndex
 					{
-						position114, tokenIndex114 := position, tokenIndex
+						position115, tokenIndex115 := position, tokenIndex
 						if !_rules[ruleWS]() {
-							goto l114
+							goto l115
 						}
-						goto l115
-					l114:
-						position, tokenIndex = position114, tokenIndex114
+						goto l116
+					l115:
+						position, tokenIndex = position115, tokenIndex115
 					}
-				l115:
+				l116:
 					if buffer[position] != rune(',') {
-						goto l113
+						goto l114
 					}
 					position++
 					{
-						position116, tokenIndex116 := position, tokenIndex
+						position117, tokenIndex117 := position, tokenIndex
 						if !_rules[ruleWS]() {
-							goto l116
+							goto l117
 						}
-						goto l117
-					l116:
-						position, tokenIndex = position116, tokenIndex116
+						goto l118
+					l117:
+						position, tokenIndex = position117, tokenIndex117
 					}
-				l117:
+				l118:
 					if !_rules[ruleArg]() {
-						goto l113
+						goto l114
 					}
-					goto l112
-				l113:
-					position, tokenIndex = position113, tokenIndex113
+					goto l113
+				l114:
+					position, tokenIndex = position114, tokenIndex114
 				}
-				add(ruleArgs, position111)
+				add(ruleArgs, position112)
 			}
 			return true
-		l110:
-			position, tokenIndex = position110, tokenIndex110
+		l111:
+			position, tokenIndex = position111, tokenIndex111
 			return false
 		},
-		/* 9 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '*' / '_' / '@' / '.')*)> */
+		/* 9 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '*' / '_' / '@' / '.' / '$')*)> */
 		func() bool {
 			{
-				position119 := position
+				position120 := position
 				{
-					position120, tokenIndex120 := position, tokenIndex
+					position121, tokenIndex121 := position, tokenIndex
 					if !_rules[ruleQuotedArg]() {
-						goto l121
+						goto l122
 					}
-					goto l120
-				l121:
-					position, tokenIndex = position120, tokenIndex120
+					goto l121
 				l122:
+					position, tokenIndex = position121, tokenIndex121
+				l123:
 					{
-						position123, tokenIndex123 := position, tokenIndex
+						position124, tokenIndex124 := position, tokenIndex
 						{
-							position124, tokenIndex124 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l125
-							}
-							position++
-							goto l124
-						l125:
-							position, tokenIndex = position124, tokenIndex124
+							position125, tokenIndex125 := position, tokenIndex
 							if c := buffer[position]; c < rune('0') || c > rune('9') {
 								goto l126
 							}
 							position++
-							goto l124
+							goto l125
 						l126:
-							position, tokenIndex = position124, tokenIndex124
-							{
-								position128, tokenIndex128 := position, tokenIndex
-								if c := buffer[position]; c < rune('a') || c > rune('z') {
-									goto l129
-								}
-								position++
-								goto l128
-							l129:
-								position, tokenIndex = position128, tokenIndex128
-								if c := buffer[position]; c < rune('A') || c > rune('Z') {
-									goto l127
-								}
-								position++
-							}
-						l128:
-							goto l124
-						l127:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('%') {
-								goto l130
+							position, tokenIndex = position125, tokenIndex125
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l127
 							}
 							position++
-							goto l124
-						l130:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('+') {
+							goto l125
+						l127:
+							position, tokenIndex = position125, tokenIndex125
+							{
+								position129, tokenIndex129 := position, tokenIndex
+								if c := buffer[position]; c < rune('a') || c > rune('z') {
+									goto l130
+								}
+								position++
+								goto l129
+							l130:
+								position, tokenIndex = position129, tokenIndex129
+								if c := buffer[position]; c < rune('A') || c > rune('Z') {
+									goto l128
+								}
+								position++
+							}
+						l129:
+							goto l125
+						l128:
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('%') {
 								goto l131
 							}
 							position++
-							goto l124
+							goto l125
 						l131:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('-') {
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('+') {
 								goto l132
 							}
 							position++
-							goto l124
+							goto l125
 						l132:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('*') {
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('-') {
 								goto l133
 							}
 							position++
-							goto l124
+							goto l125
 						l133:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('_') {
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('*') {
 								goto l134
 							}
 							position++
-							goto l124
+							goto l125
 						l134:
-							position, tokenIndex = position124, tokenIndex124
-							if buffer[position] != rune('@') {
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('_') {
 								goto l135
 							}
 							position++
-							goto l124
+							goto l125
 						l135:
-							position, tokenIndex = position124, tokenIndex124
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('@') {
+								goto l136
+							}
+							position++
+							goto l125
+						l136:
+							position, tokenIndex = position125, tokenIndex125
 							if buffer[position] != rune('.') {
-								goto l123
+								goto l137
+							}
+							position++
+							goto l125
+						l137:
+							position, tokenIndex = position125, tokenIndex125
+							if buffer[position] != rune('$') {
+								goto l124
 							}
 							position++
 						}
+					l125:
+						goto l123
 					l124:
-						goto l122
-					l123:
-						position, tokenIndex = position123, tokenIndex123
+						position, tokenIndex = position124, tokenIndex124
 					}
 				}
-			l120:
-				add(ruleArg, position119)
+			l121:
+				add(ruleArg, position120)
 			}
 			return true
 		},
 		/* 10 QuotedArg <- <('"' QuotedText '"')> */
 		func() bool {
-			position136, tokenIndex136 := position, tokenIndex
+			position138, tokenIndex138 := position, tokenIndex
 			{
-				position137 := position
+				position139 := position
 				if buffer[position] != rune('"') {
-					goto l136
+					goto l138
 				}
 				position++
 				if !_rules[ruleQuotedText]() {
-					goto l136
+					goto l138
 				}
 				if buffer[position] != rune('"') {
-					goto l136
+					goto l138
 				}
 				position++
-				add(ruleQuotedArg, position137)
+				add(ruleQuotedArg, position139)
 			}
 			return true
-		l136:
-			position, tokenIndex = position136, tokenIndex136
+		l138:
+			position, tokenIndex = position138, tokenIndex138
 			return false
 		},
 		/* 11 QuotedText <- <(EscapedChar / (!'"' .))*> */
 		func() bool {
 			{
-				position139 := position
-			l140:
+				position141 := position
+			l142:
 				{
-					position141, tokenIndex141 := position, tokenIndex
+					position143, tokenIndex143 := position, tokenIndex
 					{
-						position142, tokenIndex142 := position, tokenIndex
+						position144, tokenIndex144 := position, tokenIndex
 						if !_rules[ruleEscapedChar]() {
-							goto l143
+							goto l145
 						}
-						goto l142
-					l143:
-						position, tokenIndex = position142, tokenIndex142
+						goto l144
+					l145:
+						position, tokenIndex = position144, tokenIndex144
 						{
-							position144, tokenIndex144 := position, tokenIndex
+							position146, tokenIndex146 := position, tokenIndex
 							if buffer[position] != rune('"') {
-								goto l144
+								goto l146
 							}
 							position++
-							goto l141
-						l144:
-							position, tokenIndex = position144, tokenIndex144
+							goto l143
+						l146:
+							position, tokenIndex = position146, tokenIndex146
 						}
 						if !matchDot() {
-							goto l141
+							goto l143
 						}
 					}
-				l142:
-					goto l140
-				l141:
-					position, tokenIndex = position141, tokenIndex141
+				l144:
+					goto l142
+				l143:
+					position, tokenIndex = position143, tokenIndex143
 				}
-				add(ruleQuotedText, position139)
+				add(ruleQuotedText, position141)
 			}
 			return true
 		},
-		/* 12 LabelContainingDirective <- <(LabelContainingDirectiveName WS SymbolArgs)> */
-		func() bool {
-			position145, tokenIndex145 := position, tokenIndex
-			{
-				position146 := position
-				if !_rules[ruleLabelContainingDirectiveName]() {
-					goto l145
-				}
-				if !_rules[ruleWS]() {
-					goto l145
-				}
-				if !_rules[ruleSymbolArgs]() {
-					goto l145
-				}
-				add(ruleLabelContainingDirective, position146)
-			}
-			return true
-		l145:
-			position, tokenIndex = position145, tokenIndex145
-			return false
-		},
-		/* 13 LabelContainingDirectiveName <- <(('.' ('x' / 'X') ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('h' / 'H') ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('l' / 'L') ('o' / 'O') ('n' / 'N') ('g' / 'G')) / ('.' ('s' / 'S') ('e' / 'E') ('t' / 'T')) / ('.' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '8' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '4' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' ('q' / 'Q') ('u' / 'U') ('a' / 'A') ('d' / 'D')) / ('.' ('t' / 'T') ('c' / 'C')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') ('a' / 'A') ('l' / 'L') ('e' / 'E') ('n' / 'N') ('t' / 'T') ('r' / 'R') ('y' / 'Y')) / ('.' ('s' / 'S') ('i' / 'I') ('z' / 'Z') ('e' / 'E')) / ('.' ('t' / 'T') ('y' / 'Y') ('p' / 'P') ('e' / 'E')) / ('.' ('u' / 'U') ('l' / 'L') ('e' / 'E') ('b' / 'B') '1' '2' '8') / ('.' ('s' / 'S') ('l' / 'L') ('e' / 'E') ('b' / 'B') '1' '2' '8'))> */
+		/* 12 SymbolDefiningDirective <- <(SymbolDefiningDirectiveName WS (LocalSymbol / SymbolName) WS? ',' WS? SymbolArg)> */
 		func() bool {
 			position147, tokenIndex147 := position, tokenIndex
 			{
 				position148 := position
+				if !_rules[ruleSymbolDefiningDirectiveName]() {
+					goto l147
+				}
+				if !_rules[ruleWS]() {
+					goto l147
+				}
 				{
 					position149, tokenIndex149 := position, tokenIndex
-					if buffer[position] != rune('.') {
+					if !_rules[ruleLocalSymbol]() {
 						goto l150
 					}
+					goto l149
+				l150:
+					position, tokenIndex = position149, tokenIndex149
+					if !_rules[ruleSymbolName]() {
+						goto l147
+					}
+				}
+			l149:
+				{
+					position151, tokenIndex151 := position, tokenIndex
+					if !_rules[ruleWS]() {
+						goto l151
+					}
+					goto l152
+				l151:
+					position, tokenIndex = position151, tokenIndex151
+				}
+			l152:
+				if buffer[position] != rune(',') {
+					goto l147
+				}
+				position++
+				{
+					position153, tokenIndex153 := position, tokenIndex
+					if !_rules[ruleWS]() {
+						goto l153
+					}
+					goto l154
+				l153:
+					position, tokenIndex = position153, tokenIndex153
+				}
+			l154:
+				if !_rules[ruleSymbolArg]() {
+					goto l147
+				}
+				add(ruleSymbolDefiningDirective, position148)
+			}
+			return true
+		l147:
+			position, tokenIndex = position147, tokenIndex147
+			return false
+		},
+		/* 13 SymbolDefiningDirectiveName <- <(('.' ('e' / 'E') ('q' / 'Q') ('u' / 'U') ('i' / 'I') ('v' / 'V')) / ('.' ('e' / 'E') ('q' / 'Q') ('u' / 'U')) / ('.' ('s' / 'S') ('e' / 'E') ('t' / 'T')))> */
+		func() bool {
+			position155, tokenIndex155 := position, tokenIndex
+			{
+				position156 := position
+				{
+					position157, tokenIndex157 := position, tokenIndex
+					if buffer[position] != rune('.') {
+						goto l158
+					}
 					position++
 					{
-						position151, tokenIndex151 := position, tokenIndex
-						if buffer[position] != rune('x') {
-							goto l152
-						}
-						position++
-						goto l151
-					l152:
-						position, tokenIndex = position151, tokenIndex151
-						if buffer[position] != rune('X') {
-							goto l150
-						}
-						position++
-					}
-				l151:
-					{
-						position153, tokenIndex153 := position, tokenIndex
-						if buffer[position] != rune('w') {
-							goto l154
-						}
-						position++
-						goto l153
-					l154:
-						position, tokenIndex = position153, tokenIndex153
-						if buffer[position] != rune('W') {
-							goto l150
-						}
-						position++
-					}
-				l153:
-					{
-						position155, tokenIndex155 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l156
-						}
-						position++
-						goto l155
-					l156:
-						position, tokenIndex = position155, tokenIndex155
-						if buffer[position] != rune('O') {
-							goto l150
-						}
-						position++
-					}
-				l155:
-					{
-						position157, tokenIndex157 := position, tokenIndex
-						if buffer[position] != rune('r') {
-							goto l158
-						}
-						position++
-						goto l157
-					l158:
-						position, tokenIndex = position157, tokenIndex157
-						if buffer[position] != rune('R') {
-							goto l150
-						}
-						position++
-					}
-				l157:
-					{
 						position159, tokenIndex159 := position, tokenIndex
-						if buffer[position] != rune('d') {
+						if buffer[position] != rune('e') {
 							goto l160
 						}
 						position++
 						goto l159
 					l160:
 						position, tokenIndex = position159, tokenIndex159
-						if buffer[position] != rune('D') {
-							goto l150
+						if buffer[position] != rune('E') {
+							goto l158
 						}
 						position++
 					}
 				l159:
-					goto l149
-				l150:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
+					{
+						position161, tokenIndex161 := position, tokenIndex
+						if buffer[position] != rune('q') {
+							goto l162
+						}
+						position++
 						goto l161
+					l162:
+						position, tokenIndex = position161, tokenIndex161
+						if buffer[position] != rune('Q') {
+							goto l158
+						}
+						position++
+					}
+				l161:
+					{
+						position163, tokenIndex163 := position, tokenIndex
+						if buffer[position] != rune('u') {
+							goto l164
+						}
+						position++
+						goto l163
+					l164:
+						position, tokenIndex = position163, tokenIndex163
+						if buffer[position] != rune('U') {
+							goto l158
+						}
+						position++
+					}
+				l163:
+					{
+						position165, tokenIndex165 := position, tokenIndex
+						if buffer[position] != rune('i') {
+							goto l166
+						}
+						position++
+						goto l165
+					l166:
+						position, tokenIndex = position165, tokenIndex165
+						if buffer[position] != rune('I') {
+							goto l158
+						}
+						position++
+					}
+				l165:
+					{
+						position167, tokenIndex167 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l168
+						}
+						position++
+						goto l167
+					l168:
+						position, tokenIndex = position167, tokenIndex167
+						if buffer[position] != rune('V') {
+							goto l158
+						}
+						position++
+					}
+				l167:
+					goto l157
+				l158:
+					position, tokenIndex = position157, tokenIndex157
+					if buffer[position] != rune('.') {
+						goto l169
 					}
 					position++
 					{
-						position162, tokenIndex162 := position, tokenIndex
-						if buffer[position] != rune('w') {
-							goto l163
+						position170, tokenIndex170 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l171
 						}
 						position++
-						goto l162
-					l163:
-						position, tokenIndex = position162, tokenIndex162
-						if buffer[position] != rune('W') {
-							goto l161
-						}
-						position++
-					}
-				l162:
-					{
-						position164, tokenIndex164 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l165
-						}
-						position++
-						goto l164
-					l165:
-						position, tokenIndex = position164, tokenIndex164
-						if buffer[position] != rune('O') {
-							goto l161
-						}
-						position++
-					}
-				l164:
-					{
-						position166, tokenIndex166 := position, tokenIndex
-						if buffer[position] != rune('r') {
-							goto l167
-						}
-						position++
-						goto l166
-					l167:
-						position, tokenIndex = position166, tokenIndex166
-						if buffer[position] != rune('R') {
-							goto l161
-						}
-						position++
-					}
-				l166:
-					{
-						position168, tokenIndex168 := position, tokenIndex
-						if buffer[position] != rune('d') {
+						goto l170
+					l171:
+						position, tokenIndex = position170, tokenIndex170
+						if buffer[position] != rune('E') {
 							goto l169
 						}
 						position++
-						goto l168
-					l169:
-						position, tokenIndex = position168, tokenIndex168
-						if buffer[position] != rune('D') {
-							goto l161
-						}
-						position++
 					}
-				l168:
-					goto l149
-				l161:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
-						goto l170
-					}
-					position++
-					{
-						position171, tokenIndex171 := position, tokenIndex
-						if buffer[position] != rune('h') {
-							goto l172
-						}
-						position++
-						goto l171
-					l172:
-						position, tokenIndex = position171, tokenIndex171
-						if buffer[position] != rune('H') {
-							goto l170
-						}
-						position++
-					}
-				l171:
-					{
-						position173, tokenIndex173 := position, tokenIndex
-						if buffer[position] != rune('w') {
-							goto l174
-						}
-						position++
-						goto l173
-					l174:
-						position, tokenIndex = position173, tokenIndex173
-						if buffer[position] != rune('W') {
-							goto l170
-						}
-						position++
-					}
-				l173:
-					{
-						position175, tokenIndex175 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l176
-						}
-						position++
-						goto l175
-					l176:
-						position, tokenIndex = position175, tokenIndex175
-						if buffer[position] != rune('O') {
-							goto l170
-						}
-						position++
-					}
-				l175:
-					{
-						position177, tokenIndex177 := position, tokenIndex
-						if buffer[position] != rune('r') {
-							goto l178
-						}
-						position++
-						goto l177
-					l178:
-						position, tokenIndex = position177, tokenIndex177
-						if buffer[position] != rune('R') {
-							goto l170
-						}
-						position++
-					}
-				l177:
-					{
-						position179, tokenIndex179 := position, tokenIndex
-						if buffer[position] != rune('d') {
-							goto l180
-						}
-						position++
-						goto l179
-					l180:
-						position, tokenIndex = position179, tokenIndex179
-						if buffer[position] != rune('D') {
-							goto l170
-						}
-						position++
-					}
-				l179:
-					goto l149
 				l170:
-					position, tokenIndex = position149, tokenIndex149
+					{
+						position172, tokenIndex172 := position, tokenIndex
+						if buffer[position] != rune('q') {
+							goto l173
+						}
+						position++
+						goto l172
+					l173:
+						position, tokenIndex = position172, tokenIndex172
+						if buffer[position] != rune('Q') {
+							goto l169
+						}
+						position++
+					}
+				l172:
+					{
+						position174, tokenIndex174 := position, tokenIndex
+						if buffer[position] != rune('u') {
+							goto l175
+						}
+						position++
+						goto l174
+					l175:
+						position, tokenIndex = position174, tokenIndex174
+						if buffer[position] != rune('U') {
+							goto l169
+						}
+						position++
+					}
+				l174:
+					goto l157
+				l169:
+					position, tokenIndex = position157, tokenIndex157
 					if buffer[position] != rune('.') {
-						goto l181
+						goto l155
 					}
 					position++
 					{
-						position182, tokenIndex182 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l183
+						position176, tokenIndex176 := position, tokenIndex
+						if buffer[position] != rune('s') {
+							goto l177
 						}
 						position++
-						goto l182
-					l183:
-						position, tokenIndex = position182, tokenIndex182
-						if buffer[position] != rune('L') {
-							goto l181
+						goto l176
+					l177:
+						position, tokenIndex = position176, tokenIndex176
+						if buffer[position] != rune('S') {
+							goto l155
 						}
 						position++
 					}
-				l182:
+				l176:
 					{
-						position184, tokenIndex184 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l185
+						position178, tokenIndex178 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l179
 						}
 						position++
-						goto l184
-					l185:
-						position, tokenIndex = position184, tokenIndex184
-						if buffer[position] != rune('O') {
-							goto l181
+						goto l178
+					l179:
+						position, tokenIndex = position178, tokenIndex178
+						if buffer[position] != rune('E') {
+							goto l155
 						}
 						position++
 					}
-				l184:
+				l178:
 					{
-						position186, tokenIndex186 := position, tokenIndex
-						if buffer[position] != rune('n') {
-							goto l187
-						}
-						position++
-						goto l186
-					l187:
-						position, tokenIndex = position186, tokenIndex186
-						if buffer[position] != rune('N') {
+						position180, tokenIndex180 := position, tokenIndex
+						if buffer[position] != rune('t') {
 							goto l181
 						}
 						position++
+						goto l180
+					l181:
+						position, tokenIndex = position180, tokenIndex180
+						if buffer[position] != rune('T') {
+							goto l155
+						}
+						position++
 					}
-				l186:
+				l180:
+				}
+			l157:
+				add(ruleSymbolDefiningDirectiveName, position156)
+			}
+			return true
+		l155:
+			position, tokenIndex = position155, tokenIndex155
+			return false
+		},
+		/* 14 LabelContainingDirective <- <(LabelContainingDirectiveName WS SymbolArgs)> */
+		func() bool {
+			position182, tokenIndex182 := position, tokenIndex
+			{
+				position183 := position
+				if !_rules[ruleLabelContainingDirectiveName]() {
+					goto l182
+				}
+				if !_rules[ruleWS]() {
+					goto l182
+				}
+				if !_rules[ruleSymbolArgs]() {
+					goto l182
+				}
+				add(ruleLabelContainingDirective, position183)
+			}
+			return true
+		l182:
+			position, tokenIndex = position182, tokenIndex182
+			return false
+		},
+		/* 15 LabelContainingDirectiveName <- <(('.' ('x' / 'X') ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('h' / 'H') ('w' / 'W') ('o' / 'O') ('r' / 'R') ('d' / 'D')) / ('.' ('l' / 'L') ('o' / 'O') ('n' / 'N') ('g' / 'G')) / ('.' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '8' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '4' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' ('q' / 'Q') ('u' / 'U') ('a' / 'A') ('d' / 'D')) / ('.' ('t' / 'T') ('c' / 'C')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') ('a' / 'A') ('l' / 'L') ('e' / 'E') ('n' / 'N') ('t' / 'T') ('r' / 'R') ('y' / 'Y')) / ('.' ('s' / 'S') ('i' / 'I') ('z' / 'Z') ('e' / 'E')) / ('.' ('t' / 'T') ('y' / 'Y') ('p' / 'P') ('e' / 'E')) / ('.' ('u' / 'U') ('l' / 'L') ('e' / 'E') ('b' / 'B') '1' '2' '8') / ('.' ('s' / 'S') ('l' / 'L') ('e' / 'E') ('b' / 'B') '1' '2' '8'))> */
+		func() bool {
+			position184, tokenIndex184 := position, tokenIndex
+			{
+				position185 := position
+				{
+					position186, tokenIndex186 := position, tokenIndex
+					if buffer[position] != rune('.') {
+						goto l187
+					}
+					position++
 					{
 						position188, tokenIndex188 := position, tokenIndex
-						if buffer[position] != rune('g') {
+						if buffer[position] != rune('x') {
 							goto l189
 						}
 						position++
 						goto l188
 					l189:
 						position, tokenIndex = position188, tokenIndex188
-						if buffer[position] != rune('G') {
-							goto l181
+						if buffer[position] != rune('X') {
+							goto l187
 						}
 						position++
 					}
 				l188:
-					goto l149
-				l181:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
+					{
+						position190, tokenIndex190 := position, tokenIndex
+						if buffer[position] != rune('w') {
+							goto l191
+						}
+						position++
 						goto l190
-					}
-					position++
-					{
-						position191, tokenIndex191 := position, tokenIndex
-						if buffer[position] != rune('s') {
-							goto l192
-						}
-						position++
-						goto l191
-					l192:
-						position, tokenIndex = position191, tokenIndex191
-						if buffer[position] != rune('S') {
-							goto l190
+					l191:
+						position, tokenIndex = position190, tokenIndex190
+						if buffer[position] != rune('W') {
+							goto l187
 						}
 						position++
 					}
-				l191:
-					{
-						position193, tokenIndex193 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l194
-						}
-						position++
-						goto l193
-					l194:
-						position, tokenIndex = position193, tokenIndex193
-						if buffer[position] != rune('E') {
-							goto l190
-						}
-						position++
-					}
-				l193:
-					{
-						position195, tokenIndex195 := position, tokenIndex
-						if buffer[position] != rune('t') {
-							goto l196
-						}
-						position++
-						goto l195
-					l196:
-						position, tokenIndex = position195, tokenIndex195
-						if buffer[position] != rune('T') {
-							goto l190
-						}
-						position++
-					}
-				l195:
-					goto l149
 				l190:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
-						goto l197
-					}
-					position++
 					{
-						position198, tokenIndex198 := position, tokenIndex
-						if buffer[position] != rune('b') {
-							goto l199
+						position192, tokenIndex192 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l193
 						}
 						position++
+						goto l192
+					l193:
+						position, tokenIndex = position192, tokenIndex192
+						if buffer[position] != rune('O') {
+							goto l187
+						}
+						position++
+					}
+				l192:
+					{
+						position194, tokenIndex194 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l195
+						}
+						position++
+						goto l194
+					l195:
+						position, tokenIndex = position194, tokenIndex194
+						if buffer[position] != rune('R') {
+							goto l187
+						}
+						position++
+					}
+				l194:
+					{
+						position196, tokenIndex196 := position, tokenIndex
+						if buffer[position] != rune('d') {
+							goto l197
+						}
+						position++
+						goto l196
+					l197:
+						position, tokenIndex = position196, tokenIndex196
+						if buffer[position] != rune('D') {
+							goto l187
+						}
+						position++
+					}
+				l196:
+					goto l186
+				l187:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
 						goto l198
-					l199:
-						position, tokenIndex = position198, tokenIndex198
-						if buffer[position] != rune('B') {
-							goto l197
+					}
+					position++
+					{
+						position199, tokenIndex199 := position, tokenIndex
+						if buffer[position] != rune('w') {
+							goto l200
+						}
+						position++
+						goto l199
+					l200:
+						position, tokenIndex = position199, tokenIndex199
+						if buffer[position] != rune('W') {
+							goto l198
 						}
 						position++
 					}
+				l199:
+					{
+						position201, tokenIndex201 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l202
+						}
+						position++
+						goto l201
+					l202:
+						position, tokenIndex = position201, tokenIndex201
+						if buffer[position] != rune('O') {
+							goto l198
+						}
+						position++
+					}
+				l201:
+					{
+						position203, tokenIndex203 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l204
+						}
+						position++
+						goto l203
+					l204:
+						position, tokenIndex = position203, tokenIndex203
+						if buffer[position] != rune('R') {
+							goto l198
+						}
+						position++
+					}
+				l203:
+					{
+						position205, tokenIndex205 := position, tokenIndex
+						if buffer[position] != rune('d') {
+							goto l206
+						}
+						position++
+						goto l205
+					l206:
+						position, tokenIndex = position205, tokenIndex205
+						if buffer[position] != rune('D') {
+							goto l198
+						}
+						position++
+					}
+				l205:
+					goto l186
 				l198:
-					{
-						position200, tokenIndex200 := position, tokenIndex
-						if buffer[position] != rune('y') {
-							goto l201
-						}
-						position++
-						goto l200
-					l201:
-						position, tokenIndex = position200, tokenIndex200
-						if buffer[position] != rune('Y') {
-							goto l197
-						}
-						position++
-					}
-				l200:
-					{
-						position202, tokenIndex202 := position, tokenIndex
-						if buffer[position] != rune('t') {
-							goto l203
-						}
-						position++
-						goto l202
-					l203:
-						position, tokenIndex = position202, tokenIndex202
-						if buffer[position] != rune('T') {
-							goto l197
-						}
-						position++
-					}
-				l202:
-					{
-						position204, tokenIndex204 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l205
-						}
-						position++
-						goto l204
-					l205:
-						position, tokenIndex = position204, tokenIndex204
-						if buffer[position] != rune('E') {
-							goto l197
-						}
-						position++
-					}
-				l204:
-					goto l149
-				l197:
-					position, tokenIndex = position149, tokenIndex149
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
-						goto l206
-					}
-					position++
-					if buffer[position] != rune('8') {
-						goto l206
-					}
-					position++
-					{
-						position207, tokenIndex207 := position, tokenIndex
-						if buffer[position] != rune('b') {
-							goto l208
-						}
-						position++
 						goto l207
-					l208:
-						position, tokenIndex = position207, tokenIndex207
-						if buffer[position] != rune('B') {
-							goto l206
-						}
-						position++
-					}
-				l207:
-					{
-						position209, tokenIndex209 := position, tokenIndex
-						if buffer[position] != rune('y') {
-							goto l210
-						}
-						position++
-						goto l209
-					l210:
-						position, tokenIndex = position209, tokenIndex209
-						if buffer[position] != rune('Y') {
-							goto l206
-						}
-						position++
-					}
-				l209:
-					{
-						position211, tokenIndex211 := position, tokenIndex
-						if buffer[position] != rune('t') {
-							goto l212
-						}
-						position++
-						goto l211
-					l212:
-						position, tokenIndex = position211, tokenIndex211
-						if buffer[position] != rune('T') {
-							goto l206
-						}
-						position++
-					}
-				l211:
-					{
-						position213, tokenIndex213 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l214
-						}
-						position++
-						goto l213
-					l214:
-						position, tokenIndex = position213, tokenIndex213
-						if buffer[position] != rune('E') {
-							goto l206
-						}
-						position++
-					}
-				l213:
-					goto l149
-				l206:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
-						goto l215
 					}
 					position++
-					if buffer[position] != rune('4') {
-						goto l215
+					{
+						position208, tokenIndex208 := position, tokenIndex
+						if buffer[position] != rune('h') {
+							goto l209
+						}
+						position++
+						goto l208
+					l209:
+						position, tokenIndex = position208, tokenIndex208
+						if buffer[position] != rune('H') {
+							goto l207
+						}
+						position++
 					}
-					position++
+				l208:
+					{
+						position210, tokenIndex210 := position, tokenIndex
+						if buffer[position] != rune('w') {
+							goto l211
+						}
+						position++
+						goto l210
+					l211:
+						position, tokenIndex = position210, tokenIndex210
+						if buffer[position] != rune('W') {
+							goto l207
+						}
+						position++
+					}
+				l210:
+					{
+						position212, tokenIndex212 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l213
+						}
+						position++
+						goto l212
+					l213:
+						position, tokenIndex = position212, tokenIndex212
+						if buffer[position] != rune('O') {
+							goto l207
+						}
+						position++
+					}
+				l212:
+					{
+						position214, tokenIndex214 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l215
+						}
+						position++
+						goto l214
+					l215:
+						position, tokenIndex = position214, tokenIndex214
+						if buffer[position] != rune('R') {
+							goto l207
+						}
+						position++
+					}
+				l214:
 					{
 						position216, tokenIndex216 := position, tokenIndex
-						if buffer[position] != rune('b') {
+						if buffer[position] != rune('d') {
 							goto l217
 						}
 						position++
 						goto l216
 					l217:
 						position, tokenIndex = position216, tokenIndex216
-						if buffer[position] != rune('B') {
-							goto l215
+						if buffer[position] != rune('D') {
+							goto l207
 						}
 						position++
 					}
 				l216:
-					{
-						position218, tokenIndex218 := position, tokenIndex
-						if buffer[position] != rune('y') {
-							goto l219
-						}
-						position++
-						goto l218
-					l219:
-						position, tokenIndex = position218, tokenIndex218
-						if buffer[position] != rune('Y') {
-							goto l215
-						}
-						position++
-					}
-				l218:
-					{
-						position220, tokenIndex220 := position, tokenIndex
-						if buffer[position] != rune('t') {
-							goto l221
-						}
-						position++
-						goto l220
-					l221:
-						position, tokenIndex = position220, tokenIndex220
-						if buffer[position] != rune('T') {
-							goto l215
-						}
-						position++
-					}
-				l220:
-					{
-						position222, tokenIndex222 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l223
-						}
-						position++
-						goto l222
-					l223:
-						position, tokenIndex = position222, tokenIndex222
-						if buffer[position] != rune('E') {
-							goto l215
-						}
-						position++
-					}
-				l222:
-					goto l149
-				l215:
-					position, tokenIndex = position149, tokenIndex149
+					goto l186
+				l207:
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
-						goto l224
+						goto l218
 					}
 					position++
 					{
+						position219, tokenIndex219 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l220
+						}
+						position++
+						goto l219
+					l220:
+						position, tokenIndex = position219, tokenIndex219
+						if buffer[position] != rune('L') {
+							goto l218
+						}
+						position++
+					}
+				l219:
+					{
+						position221, tokenIndex221 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l222
+						}
+						position++
+						goto l221
+					l222:
+						position, tokenIndex = position221, tokenIndex221
+						if buffer[position] != rune('O') {
+							goto l218
+						}
+						position++
+					}
+				l221:
+					{
+						position223, tokenIndex223 := position, tokenIndex
+						if buffer[position] != rune('n') {
+							goto l224
+						}
+						position++
+						goto l223
+					l224:
+						position, tokenIndex = position223, tokenIndex223
+						if buffer[position] != rune('N') {
+							goto l218
+						}
+						position++
+					}
+				l223:
+					{
 						position225, tokenIndex225 := position, tokenIndex
-						if buffer[position] != rune('q') {
+						if buffer[position] != rune('g') {
 							goto l226
 						}
 						position++
 						goto l225
 					l226:
 						position, tokenIndex = position225, tokenIndex225
-						if buffer[position] != rune('Q') {
-							goto l224
+						if buffer[position] != rune('G') {
+							goto l218
 						}
 						position++
 					}
 				l225:
-					{
-						position227, tokenIndex227 := position, tokenIndex
-						if buffer[position] != rune('u') {
-							goto l228
-						}
-						position++
-						goto l227
-					l228:
-						position, tokenIndex = position227, tokenIndex227
-						if buffer[position] != rune('U') {
-							goto l224
-						}
-						position++
-					}
-				l227:
-					{
-						position229, tokenIndex229 := position, tokenIndex
-						if buffer[position] != rune('a') {
-							goto l230
-						}
-						position++
-						goto l229
-					l230:
-						position, tokenIndex = position229, tokenIndex229
-						if buffer[position] != rune('A') {
-							goto l224
-						}
-						position++
-					}
-				l229:
-					{
-						position231, tokenIndex231 := position, tokenIndex
-						if buffer[position] != rune('d') {
-							goto l232
-						}
-						position++
-						goto l231
-					l232:
-						position, tokenIndex = position231, tokenIndex231
-						if buffer[position] != rune('D') {
-							goto l224
-						}
-						position++
-					}
-				l231:
-					goto l149
-				l224:
-					position, tokenIndex = position149, tokenIndex149
+					goto l186
+				l218:
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
-						goto l233
+						goto l227
 					}
 					position++
 					{
-						position234, tokenIndex234 := position, tokenIndex
+						position228, tokenIndex228 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l229
+						}
+						position++
+						goto l228
+					l229:
+						position, tokenIndex = position228, tokenIndex228
+						if buffer[position] != rune('B') {
+							goto l227
+						}
+						position++
+					}
+				l228:
+					{
+						position230, tokenIndex230 := position, tokenIndex
+						if buffer[position] != rune('y') {
+							goto l231
+						}
+						position++
+						goto l230
+					l231:
+						position, tokenIndex = position230, tokenIndex230
+						if buffer[position] != rune('Y') {
+							goto l227
+						}
+						position++
+					}
+				l230:
+					{
+						position232, tokenIndex232 := position, tokenIndex
 						if buffer[position] != rune('t') {
+							goto l233
+						}
+						position++
+						goto l232
+					l233:
+						position, tokenIndex = position232, tokenIndex232
+						if buffer[position] != rune('T') {
+							goto l227
+						}
+						position++
+					}
+				l232:
+					{
+						position234, tokenIndex234 := position, tokenIndex
+						if buffer[position] != rune('e') {
 							goto l235
 						}
 						position++
 						goto l234
 					l235:
 						position, tokenIndex = position234, tokenIndex234
-						if buffer[position] != rune('T') {
-							goto l233
+						if buffer[position] != rune('E') {
+							goto l227
 						}
 						position++
 					}
 				l234:
-					{
-						position236, tokenIndex236 := position, tokenIndex
-						if buffer[position] != rune('c') {
-							goto l237
-						}
-						position++
-						goto l236
-					l237:
-						position, tokenIndex = position236, tokenIndex236
-						if buffer[position] != rune('C') {
-							goto l233
-						}
-						position++
-					}
-				l236:
-					goto l149
-				l233:
-					position, tokenIndex = position149, tokenIndex149
+					goto l186
+				l227:
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
-						goto l238
+						goto l236
+					}
+					position++
+					if buffer[position] != rune('8') {
+						goto l236
 					}
 					position++
 					{
+						position237, tokenIndex237 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l238
+						}
+						position++
+						goto l237
+					l238:
+						position, tokenIndex = position237, tokenIndex237
+						if buffer[position] != rune('B') {
+							goto l236
+						}
+						position++
+					}
+				l237:
+					{
 						position239, tokenIndex239 := position, tokenIndex
-						if buffer[position] != rune('l') {
+						if buffer[position] != rune('y') {
 							goto l240
 						}
 						position++
 						goto l239
 					l240:
 						position, tokenIndex = position239, tokenIndex239
-						if buffer[position] != rune('L') {
-							goto l238
+						if buffer[position] != rune('Y') {
+							goto l236
 						}
 						position++
 					}
 				l239:
 					{
 						position241, tokenIndex241 := position, tokenIndex
-						if buffer[position] != rune('o') {
+						if buffer[position] != rune('t') {
 							goto l242
 						}
 						position++
 						goto l241
 					l242:
 						position, tokenIndex = position241, tokenIndex241
-						if buffer[position] != rune('O') {
-							goto l238
+						if buffer[position] != rune('T') {
+							goto l236
 						}
 						position++
 					}
 				l241:
 					{
 						position243, tokenIndex243 := position, tokenIndex
-						if buffer[position] != rune('c') {
+						if buffer[position] != rune('e') {
 							goto l244
 						}
 						position++
 						goto l243
 					l244:
 						position, tokenIndex = position243, tokenIndex243
-						if buffer[position] != rune('C') {
-							goto l238
+						if buffer[position] != rune('E') {
+							goto l236
 						}
 						position++
 					}
 				l243:
-					{
-						position245, tokenIndex245 := position, tokenIndex
-						if buffer[position] != rune('a') {
-							goto l246
-						}
-						position++
+					goto l186
+				l236:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
 						goto l245
-					l246:
-						position, tokenIndex = position245, tokenIndex245
-						if buffer[position] != rune('A') {
-							goto l238
+					}
+					position++
+					if buffer[position] != rune('4') {
+						goto l245
+					}
+					position++
+					{
+						position246, tokenIndex246 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l247
+						}
+						position++
+						goto l246
+					l247:
+						position, tokenIndex = position246, tokenIndex246
+						if buffer[position] != rune('B') {
+							goto l245
 						}
 						position++
 					}
-				l245:
+				l246:
 					{
-						position247, tokenIndex247 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l248
+						position248, tokenIndex248 := position, tokenIndex
+						if buffer[position] != rune('y') {
+							goto l249
 						}
 						position++
-						goto l247
-					l248:
-						position, tokenIndex = position247, tokenIndex247
-						if buffer[position] != rune('L') {
-							goto l238
+						goto l248
+					l249:
+						position, tokenIndex = position248, tokenIndex248
+						if buffer[position] != rune('Y') {
+							goto l245
 						}
 						position++
 					}
-				l247:
+				l248:
 					{
-						position249, tokenIndex249 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l250
-						}
-						position++
-						goto l249
-					l250:
-						position, tokenIndex = position249, tokenIndex249
-						if buffer[position] != rune('E') {
-							goto l238
-						}
-						position++
-					}
-				l249:
-					{
-						position251, tokenIndex251 := position, tokenIndex
-						if buffer[position] != rune('n') {
-							goto l252
-						}
-						position++
-						goto l251
-					l252:
-						position, tokenIndex = position251, tokenIndex251
-						if buffer[position] != rune('N') {
-							goto l238
-						}
-						position++
-					}
-				l251:
-					{
-						position253, tokenIndex253 := position, tokenIndex
+						position250, tokenIndex250 := position, tokenIndex
 						if buffer[position] != rune('t') {
-							goto l254
+							goto l251
 						}
 						position++
-						goto l253
-					l254:
-						position, tokenIndex = position253, tokenIndex253
+						goto l250
+					l251:
+						position, tokenIndex = position250, tokenIndex250
 						if buffer[position] != rune('T') {
-							goto l238
+							goto l245
 						}
 						position++
 					}
-				l253:
+				l250:
+					{
+						position252, tokenIndex252 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l253
+						}
+						position++
+						goto l252
+					l253:
+						position, tokenIndex = position252, tokenIndex252
+						if buffer[position] != rune('E') {
+							goto l245
+						}
+						position++
+					}
+				l252:
+					goto l186
+				l245:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
+						goto l254
+					}
+					position++
 					{
 						position255, tokenIndex255 := position, tokenIndex
-						if buffer[position] != rune('r') {
+						if buffer[position] != rune('q') {
 							goto l256
 						}
 						position++
 						goto l255
 					l256:
 						position, tokenIndex = position255, tokenIndex255
-						if buffer[position] != rune('R') {
-							goto l238
+						if buffer[position] != rune('Q') {
+							goto l254
 						}
 						position++
 					}
 				l255:
 					{
 						position257, tokenIndex257 := position, tokenIndex
-						if buffer[position] != rune('y') {
+						if buffer[position] != rune('u') {
 							goto l258
 						}
 						position++
 						goto l257
 					l258:
 						position, tokenIndex = position257, tokenIndex257
-						if buffer[position] != rune('Y') {
-							goto l238
+						if buffer[position] != rune('U') {
+							goto l254
 						}
 						position++
 					}
 				l257:
-					goto l149
-				l238:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
+					{
+						position259, tokenIndex259 := position, tokenIndex
+						if buffer[position] != rune('a') {
+							goto l260
+						}
+						position++
 						goto l259
+					l260:
+						position, tokenIndex = position259, tokenIndex259
+						if buffer[position] != rune('A') {
+							goto l254
+						}
+						position++
+					}
+				l259:
+					{
+						position261, tokenIndex261 := position, tokenIndex
+						if buffer[position] != rune('d') {
+							goto l262
+						}
+						position++
+						goto l261
+					l262:
+						position, tokenIndex = position261, tokenIndex261
+						if buffer[position] != rune('D') {
+							goto l254
+						}
+						position++
+					}
+				l261:
+					goto l186
+				l254:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
+						goto l263
 					}
 					position++
 					{
-						position260, tokenIndex260 := position, tokenIndex
-						if buffer[position] != rune('s') {
-							goto l261
-						}
-						position++
-						goto l260
-					l261:
-						position, tokenIndex = position260, tokenIndex260
-						if buffer[position] != rune('S') {
-							goto l259
-						}
-						position++
-					}
-				l260:
-					{
-						position262, tokenIndex262 := position, tokenIndex
-						if buffer[position] != rune('i') {
-							goto l263
-						}
-						position++
-						goto l262
-					l263:
-						position, tokenIndex = position262, tokenIndex262
-						if buffer[position] != rune('I') {
-							goto l259
-						}
-						position++
-					}
-				l262:
-					{
 						position264, tokenIndex264 := position, tokenIndex
-						if buffer[position] != rune('z') {
+						if buffer[position] != rune('t') {
 							goto l265
 						}
 						position++
 						goto l264
 					l265:
 						position, tokenIndex = position264, tokenIndex264
-						if buffer[position] != rune('Z') {
-							goto l259
+						if buffer[position] != rune('T') {
+							goto l263
 						}
 						position++
 					}
 				l264:
 					{
 						position266, tokenIndex266 := position, tokenIndex
-						if buffer[position] != rune('e') {
+						if buffer[position] != rune('c') {
 							goto l267
 						}
 						position++
 						goto l266
 					l267:
 						position, tokenIndex = position266, tokenIndex266
-						if buffer[position] != rune('E') {
-							goto l259
+						if buffer[position] != rune('C') {
+							goto l263
 						}
 						position++
 					}
 				l266:
-					goto l149
-				l259:
-					position, tokenIndex = position149, tokenIndex149
+					goto l186
+				l263:
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
 						goto l268
 					}
 					position++
 					{
 						position269, tokenIndex269 := position, tokenIndex
-						if buffer[position] != rune('t') {
+						if buffer[position] != rune('l') {
 							goto l270
 						}
 						position++
 						goto l269
 					l270:
 						position, tokenIndex = position269, tokenIndex269
-						if buffer[position] != rune('T') {
+						if buffer[position] != rune('L') {
 							goto l268
 						}
 						position++
@@ -2350,14 +2348,14 @@
 				l269:
 					{
 						position271, tokenIndex271 := position, tokenIndex
-						if buffer[position] != rune('y') {
+						if buffer[position] != rune('o') {
 							goto l272
 						}
 						position++
 						goto l271
 					l272:
 						position, tokenIndex = position271, tokenIndex271
-						if buffer[position] != rune('Y') {
+						if buffer[position] != rune('O') {
 							goto l268
 						}
 						position++
@@ -2365,14 +2363,14 @@
 				l271:
 					{
 						position273, tokenIndex273 := position, tokenIndex
-						if buffer[position] != rune('p') {
+						if buffer[position] != rune('c') {
 							goto l274
 						}
 						position++
 						goto l273
 					l274:
 						position, tokenIndex = position273, tokenIndex273
-						if buffer[position] != rune('P') {
+						if buffer[position] != rune('C') {
 							goto l268
 						}
 						position++
@@ -2380,386 +2378,421 @@
 				l273:
 					{
 						position275, tokenIndex275 := position, tokenIndex
-						if buffer[position] != rune('e') {
+						if buffer[position] != rune('a') {
 							goto l276
 						}
 						position++
 						goto l275
 					l276:
 						position, tokenIndex = position275, tokenIndex275
-						if buffer[position] != rune('E') {
+						if buffer[position] != rune('A') {
 							goto l268
 						}
 						position++
 					}
 				l275:
-					goto l149
-				l268:
-					position, tokenIndex = position149, tokenIndex149
-					if buffer[position] != rune('.') {
-						goto l277
-					}
-					position++
 					{
-						position278, tokenIndex278 := position, tokenIndex
-						if buffer[position] != rune('u') {
-							goto l279
-						}
-						position++
-						goto l278
-					l279:
-						position, tokenIndex = position278, tokenIndex278
-						if buffer[position] != rune('U') {
-							goto l277
-						}
-						position++
-					}
-				l278:
-					{
-						position280, tokenIndex280 := position, tokenIndex
+						position277, tokenIndex277 := position, tokenIndex
 						if buffer[position] != rune('l') {
-							goto l281
+							goto l278
 						}
 						position++
-						goto l280
-					l281:
-						position, tokenIndex = position280, tokenIndex280
+						goto l277
+					l278:
+						position, tokenIndex = position277, tokenIndex277
 						if buffer[position] != rune('L') {
-							goto l277
+							goto l268
 						}
 						position++
 					}
-				l280:
-					{
-						position282, tokenIndex282 := position, tokenIndex
-						if buffer[position] != rune('e') {
-							goto l283
-						}
-						position++
-						goto l282
-					l283:
-						position, tokenIndex = position282, tokenIndex282
-						if buffer[position] != rune('E') {
-							goto l277
-						}
-						position++
-					}
-				l282:
-					{
-						position284, tokenIndex284 := position, tokenIndex
-						if buffer[position] != rune('b') {
-							goto l285
-						}
-						position++
-						goto l284
-					l285:
-						position, tokenIndex = position284, tokenIndex284
-						if buffer[position] != rune('B') {
-							goto l277
-						}
-						position++
-					}
-				l284:
-					if buffer[position] != rune('1') {
-						goto l277
-					}
-					position++
-					if buffer[position] != rune('2') {
-						goto l277
-					}
-					position++
-					if buffer[position] != rune('8') {
-						goto l277
-					}
-					position++
-					goto l149
 				l277:
-					position, tokenIndex = position149, tokenIndex149
+					{
+						position279, tokenIndex279 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l280
+						}
+						position++
+						goto l279
+					l280:
+						position, tokenIndex = position279, tokenIndex279
+						if buffer[position] != rune('E') {
+							goto l268
+						}
+						position++
+					}
+				l279:
+					{
+						position281, tokenIndex281 := position, tokenIndex
+						if buffer[position] != rune('n') {
+							goto l282
+						}
+						position++
+						goto l281
+					l282:
+						position, tokenIndex = position281, tokenIndex281
+						if buffer[position] != rune('N') {
+							goto l268
+						}
+						position++
+					}
+				l281:
+					{
+						position283, tokenIndex283 := position, tokenIndex
+						if buffer[position] != rune('t') {
+							goto l284
+						}
+						position++
+						goto l283
+					l284:
+						position, tokenIndex = position283, tokenIndex283
+						if buffer[position] != rune('T') {
+							goto l268
+						}
+						position++
+					}
+				l283:
+					{
+						position285, tokenIndex285 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l286
+						}
+						position++
+						goto l285
+					l286:
+						position, tokenIndex = position285, tokenIndex285
+						if buffer[position] != rune('R') {
+							goto l268
+						}
+						position++
+					}
+				l285:
+					{
+						position287, tokenIndex287 := position, tokenIndex
+						if buffer[position] != rune('y') {
+							goto l288
+						}
+						position++
+						goto l287
+					l288:
+						position, tokenIndex = position287, tokenIndex287
+						if buffer[position] != rune('Y') {
+							goto l268
+						}
+						position++
+					}
+				l287:
+					goto l186
+				l268:
+					position, tokenIndex = position186, tokenIndex186
 					if buffer[position] != rune('.') {
-						goto l147
+						goto l289
 					}
 					position++
 					{
-						position286, tokenIndex286 := position, tokenIndex
-						if buffer[position] != rune('s') {
-							goto l287
-						}
-						position++
-						goto l286
-					l287:
-						position, tokenIndex = position286, tokenIndex286
-						if buffer[position] != rune('S') {
-							goto l147
-						}
-						position++
-					}
-				l286:
-					{
-						position288, tokenIndex288 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l289
-						}
-						position++
-						goto l288
-					l289:
-						position, tokenIndex = position288, tokenIndex288
-						if buffer[position] != rune('L') {
-							goto l147
-						}
-						position++
-					}
-				l288:
-					{
 						position290, tokenIndex290 := position, tokenIndex
-						if buffer[position] != rune('e') {
+						if buffer[position] != rune('s') {
 							goto l291
 						}
 						position++
 						goto l290
 					l291:
 						position, tokenIndex = position290, tokenIndex290
-						if buffer[position] != rune('E') {
-							goto l147
+						if buffer[position] != rune('S') {
+							goto l289
 						}
 						position++
 					}
 				l290:
 					{
 						position292, tokenIndex292 := position, tokenIndex
-						if buffer[position] != rune('b') {
+						if buffer[position] != rune('i') {
 							goto l293
 						}
 						position++
 						goto l292
 					l293:
 						position, tokenIndex = position292, tokenIndex292
-						if buffer[position] != rune('B') {
-							goto l147
+						if buffer[position] != rune('I') {
+							goto l289
 						}
 						position++
 					}
 				l292:
+					{
+						position294, tokenIndex294 := position, tokenIndex
+						if buffer[position] != rune('z') {
+							goto l295
+						}
+						position++
+						goto l294
+					l295:
+						position, tokenIndex = position294, tokenIndex294
+						if buffer[position] != rune('Z') {
+							goto l289
+						}
+						position++
+					}
+				l294:
+					{
+						position296, tokenIndex296 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l297
+						}
+						position++
+						goto l296
+					l297:
+						position, tokenIndex = position296, tokenIndex296
+						if buffer[position] != rune('E') {
+							goto l289
+						}
+						position++
+					}
+				l296:
+					goto l186
+				l289:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
+						goto l298
+					}
+					position++
+					{
+						position299, tokenIndex299 := position, tokenIndex
+						if buffer[position] != rune('t') {
+							goto l300
+						}
+						position++
+						goto l299
+					l300:
+						position, tokenIndex = position299, tokenIndex299
+						if buffer[position] != rune('T') {
+							goto l298
+						}
+						position++
+					}
+				l299:
+					{
+						position301, tokenIndex301 := position, tokenIndex
+						if buffer[position] != rune('y') {
+							goto l302
+						}
+						position++
+						goto l301
+					l302:
+						position, tokenIndex = position301, tokenIndex301
+						if buffer[position] != rune('Y') {
+							goto l298
+						}
+						position++
+					}
+				l301:
+					{
+						position303, tokenIndex303 := position, tokenIndex
+						if buffer[position] != rune('p') {
+							goto l304
+						}
+						position++
+						goto l303
+					l304:
+						position, tokenIndex = position303, tokenIndex303
+						if buffer[position] != rune('P') {
+							goto l298
+						}
+						position++
+					}
+				l303:
+					{
+						position305, tokenIndex305 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l306
+						}
+						position++
+						goto l305
+					l306:
+						position, tokenIndex = position305, tokenIndex305
+						if buffer[position] != rune('E') {
+							goto l298
+						}
+						position++
+					}
+				l305:
+					goto l186
+				l298:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
+						goto l307
+					}
+					position++
+					{
+						position308, tokenIndex308 := position, tokenIndex
+						if buffer[position] != rune('u') {
+							goto l309
+						}
+						position++
+						goto l308
+					l309:
+						position, tokenIndex = position308, tokenIndex308
+						if buffer[position] != rune('U') {
+							goto l307
+						}
+						position++
+					}
+				l308:
+					{
+						position310, tokenIndex310 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l311
+						}
+						position++
+						goto l310
+					l311:
+						position, tokenIndex = position310, tokenIndex310
+						if buffer[position] != rune('L') {
+							goto l307
+						}
+						position++
+					}
+				l310:
+					{
+						position312, tokenIndex312 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l313
+						}
+						position++
+						goto l312
+					l313:
+						position, tokenIndex = position312, tokenIndex312
+						if buffer[position] != rune('E') {
+							goto l307
+						}
+						position++
+					}
+				l312:
+					{
+						position314, tokenIndex314 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l315
+						}
+						position++
+						goto l314
+					l315:
+						position, tokenIndex = position314, tokenIndex314
+						if buffer[position] != rune('B') {
+							goto l307
+						}
+						position++
+					}
+				l314:
 					if buffer[position] != rune('1') {
-						goto l147
+						goto l307
 					}
 					position++
 					if buffer[position] != rune('2') {
-						goto l147
+						goto l307
 					}
 					position++
 					if buffer[position] != rune('8') {
-						goto l147
+						goto l307
 					}
 					position++
-				}
-			l149:
-				add(ruleLabelContainingDirectiveName, position148)
-			}
-			return true
-		l147:
-			position, tokenIndex = position147, tokenIndex147
-			return false
-		},
-		/* 14 SymbolArgs <- <(SymbolArg (WS? ',' WS? SymbolArg)*)> */
-		func() bool {
-			position294, tokenIndex294 := position, tokenIndex
-			{
-				position295 := position
-				if !_rules[ruleSymbolArg]() {
-					goto l294
-				}
-			l296:
-				{
-					position297, tokenIndex297 := position, tokenIndex
-					{
-						position298, tokenIndex298 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l298
-						}
-						goto l299
-					l298:
-						position, tokenIndex = position298, tokenIndex298
-					}
-				l299:
-					if buffer[position] != rune(',') {
-						goto l297
+					goto l186
+				l307:
+					position, tokenIndex = position186, tokenIndex186
+					if buffer[position] != rune('.') {
+						goto l184
 					}
 					position++
 					{
-						position300, tokenIndex300 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l300
+						position316, tokenIndex316 := position, tokenIndex
+						if buffer[position] != rune('s') {
+							goto l317
 						}
-						goto l301
-					l300:
-						position, tokenIndex = position300, tokenIndex300
-					}
-				l301:
-					if !_rules[ruleSymbolArg]() {
-						goto l297
-					}
-					goto l296
-				l297:
-					position, tokenIndex = position297, tokenIndex297
-				}
-				add(ruleSymbolArgs, position295)
-			}
-			return true
-		l294:
-			position, tokenIndex = position294, tokenIndex294
-			return false
-		},
-		/* 15 SymbolArg <- <SymbolExpr> */
-		func() bool {
-			position302, tokenIndex302 := position, tokenIndex
-			{
-				position303 := position
-				if !_rules[ruleSymbolExpr]() {
-					goto l302
-				}
-				add(ruleSymbolArg, position303)
-			}
-			return true
-		l302:
-			position, tokenIndex = position302, tokenIndex302
-			return false
-		},
-		/* 16 SymbolExpr <- <(SymbolAtom (WS? SymbolOperator WS? SymbolExpr)?)> */
-		func() bool {
-			position304, tokenIndex304 := position, tokenIndex
-			{
-				position305 := position
-				if !_rules[ruleSymbolAtom]() {
-					goto l304
-				}
-				{
-					position306, tokenIndex306 := position, tokenIndex
-					{
-						position308, tokenIndex308 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l308
-						}
-						goto l309
-					l308:
-						position, tokenIndex = position308, tokenIndex308
-					}
-				l309:
-					if !_rules[ruleSymbolOperator]() {
-						goto l306
-					}
-					{
-						position310, tokenIndex310 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l310
-						}
-						goto l311
-					l310:
-						position, tokenIndex = position310, tokenIndex310
-					}
-				l311:
-					if !_rules[ruleSymbolExpr]() {
-						goto l306
-					}
-					goto l307
-				l306:
-					position, tokenIndex = position306, tokenIndex306
-				}
-			l307:
-				add(ruleSymbolExpr, position305)
-			}
-			return true
-		l304:
-			position, tokenIndex = position304, tokenIndex304
-			return false
-		},
-		/* 17 SymbolAtom <- <(LocalLabelRef / Offset / SymbolType / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?) / Dot / (OpenParen WS? SymbolExpr WS? CloseParen))> */
-		func() bool {
-			position312, tokenIndex312 := position, tokenIndex
-			{
-				position313 := position
-				{
-					position314, tokenIndex314 := position, tokenIndex
-					if !_rules[ruleLocalLabelRef]() {
-						goto l315
-					}
-					goto l314
-				l315:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleOffset]() {
+						position++
 						goto l316
+					l317:
+						position, tokenIndex = position316, tokenIndex316
+						if buffer[position] != rune('S') {
+							goto l184
+						}
+						position++
 					}
-					goto l314
 				l316:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleSymbolType]() {
-						goto l317
-					}
-					goto l314
-				l317:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleLocalSymbol]() {
-						goto l318
-					}
 					{
-						position319, tokenIndex319 := position, tokenIndex
-						if !_rules[ruleTCMarker]() {
+						position318, tokenIndex318 := position, tokenIndex
+						if buffer[position] != rune('l') {
 							goto l319
 						}
-						goto l320
+						position++
+						goto l318
 					l319:
-						position, tokenIndex = position319, tokenIndex319
+						position, tokenIndex = position318, tokenIndex318
+						if buffer[position] != rune('L') {
+							goto l184
+						}
+						position++
+					}
+				l318:
+					{
+						position320, tokenIndex320 := position, tokenIndex
+						if buffer[position] != rune('e') {
+							goto l321
+						}
+						position++
+						goto l320
+					l321:
+						position, tokenIndex = position320, tokenIndex320
+						if buffer[position] != rune('E') {
+							goto l184
+						}
+						position++
 					}
 				l320:
-					goto l314
-				l318:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleSymbolName]() {
-						goto l321
-					}
-					if !_rules[ruleOffset]() {
-						goto l321
-					}
-					goto l314
-				l321:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleSymbolName]() {
-						goto l322
-					}
 					{
-						position323, tokenIndex323 := position, tokenIndex
-						if !_rules[ruleTCMarker]() {
+						position322, tokenIndex322 := position, tokenIndex
+						if buffer[position] != rune('b') {
 							goto l323
 						}
-						goto l324
+						position++
+						goto l322
 					l323:
-						position, tokenIndex = position323, tokenIndex323
-					}
-				l324:
-					goto l314
-				l322:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleDot]() {
-						goto l325
-					}
-					goto l314
-				l325:
-					position, tokenIndex = position314, tokenIndex314
-					if !_rules[ruleOpenParen]() {
-						goto l312
-					}
-					{
-						position326, tokenIndex326 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l326
+						position, tokenIndex = position322, tokenIndex322
+						if buffer[position] != rune('B') {
+							goto l184
 						}
-						goto l327
-					l326:
-						position, tokenIndex = position326, tokenIndex326
+						position++
 					}
-				l327:
-					if !_rules[ruleSymbolExpr]() {
-						goto l312
+				l322:
+					if buffer[position] != rune('1') {
+						goto l184
 					}
+					position++
+					if buffer[position] != rune('2') {
+						goto l184
+					}
+					position++
+					if buffer[position] != rune('8') {
+						goto l184
+					}
+					position++
+				}
+			l186:
+				add(ruleLabelContainingDirectiveName, position185)
+			}
+			return true
+		l184:
+			position, tokenIndex = position184, tokenIndex184
+			return false
+		},
+		/* 16 SymbolArgs <- <(SymbolArg (WS? ',' WS? SymbolArg)*)> */
+		func() bool {
+			position324, tokenIndex324 := position, tokenIndex
+			{
+				position325 := position
+				if !_rules[ruleSymbolArg]() {
+					goto l324
+				}
+			l326:
+				{
+					position327, tokenIndex327 := position, tokenIndex
 					{
 						position328, tokenIndex328 := position, tokenIndex
 						if !_rules[ruleWS]() {
@@ -2770,4889 +2803,5126 @@
 						position, tokenIndex = position328, tokenIndex328
 					}
 				l329:
-					if !_rules[ruleCloseParen]() {
-						goto l312
+					if buffer[position] != rune(',') {
+						goto l327
 					}
+					position++
+					{
+						position330, tokenIndex330 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l330
+						}
+						goto l331
+					l330:
+						position, tokenIndex = position330, tokenIndex330
+					}
+				l331:
+					if !_rules[ruleSymbolArg]() {
+						goto l327
+					}
+					goto l326
+				l327:
+					position, tokenIndex = position327, tokenIndex327
 				}
-			l314:
-				add(ruleSymbolAtom, position313)
+				add(ruleSymbolArgs, position325)
 			}
 			return true
-		l312:
-			position, tokenIndex = position312, tokenIndex312
+		l324:
+			position, tokenIndex = position324, tokenIndex324
 			return false
 		},
-		/* 18 SymbolOperator <- <('+' / '-' / '|' / ('<' '<') / ('>' '>'))> */
+		/* 17 SymbolArg <- <SymbolExpr> */
 		func() bool {
-			position330, tokenIndex330 := position, tokenIndex
+			position332, tokenIndex332 := position, tokenIndex
 			{
-				position331 := position
+				position333 := position
+				if !_rules[ruleSymbolExpr]() {
+					goto l332
+				}
+				add(ruleSymbolArg, position333)
+			}
+			return true
+		l332:
+			position, tokenIndex = position332, tokenIndex332
+			return false
+		},
+		/* 18 SymbolExpr <- <(SymbolAtom (WS? SymbolOperator WS? SymbolExpr)?)> */
+		func() bool {
+			position334, tokenIndex334 := position, tokenIndex
+			{
+				position335 := position
+				if !_rules[ruleSymbolAtom]() {
+					goto l334
+				}
 				{
-					position332, tokenIndex332 := position, tokenIndex
-					if buffer[position] != rune('+') {
-						goto l333
+					position336, tokenIndex336 := position, tokenIndex
+					{
+						position338, tokenIndex338 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l338
+						}
+						goto l339
+					l338:
+						position, tokenIndex = position338, tokenIndex338
 					}
-					position++
-					goto l332
-				l333:
-					position, tokenIndex = position332, tokenIndex332
-					if buffer[position] != rune('-') {
-						goto l334
-					}
-					position++
-					goto l332
-				l334:
-					position, tokenIndex = position332, tokenIndex332
-					if buffer[position] != rune('|') {
-						goto l335
-					}
-					position++
-					goto l332
-				l335:
-					position, tokenIndex = position332, tokenIndex332
-					if buffer[position] != rune('<') {
+				l339:
+					if !_rules[ruleSymbolOperator]() {
 						goto l336
 					}
-					position++
-					if buffer[position] != rune('<') {
-						goto l336
-					}
-					position++
-					goto l332
-				l336:
-					position, tokenIndex = position332, tokenIndex332
-					if buffer[position] != rune('>') {
-						goto l330
-					}
-					position++
-					if buffer[position] != rune('>') {
-						goto l330
-					}
-					position++
-				}
-			l332:
-				add(ruleSymbolOperator, position331)
-			}
-			return true
-		l330:
-			position, tokenIndex = position330, tokenIndex330
-			return false
-		},
-		/* 19 OpenParen <- <'('> */
-		func() bool {
-			position337, tokenIndex337 := position, tokenIndex
-			{
-				position338 := position
-				if buffer[position] != rune('(') {
-					goto l337
-				}
-				position++
-				add(ruleOpenParen, position338)
-			}
-			return true
-		l337:
-			position, tokenIndex = position337, tokenIndex337
-			return false
-		},
-		/* 20 CloseParen <- <')'> */
-		func() bool {
-			position339, tokenIndex339 := position, tokenIndex
-			{
-				position340 := position
-				if buffer[position] != rune(')') {
-					goto l339
-				}
-				position++
-				add(ruleCloseParen, position340)
-			}
-			return true
-		l339:
-			position, tokenIndex = position339, tokenIndex339
-			return false
-		},
-		/* 21 SymbolType <- <(('@' / '%') (('f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('o' 'b' 'j' 'e' 'c' 't')))> */
-		func() bool {
-			position341, tokenIndex341 := position, tokenIndex
-			{
-				position342 := position
-				{
-					position343, tokenIndex343 := position, tokenIndex
-					if buffer[position] != rune('@') {
-						goto l344
-					}
-					position++
-					goto l343
-				l344:
-					position, tokenIndex = position343, tokenIndex343
-					if buffer[position] != rune('%') {
+					{
+						position340, tokenIndex340 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l340
+						}
 						goto l341
+					l340:
+						position, tokenIndex = position340, tokenIndex340
+					}
+				l341:
+					if !_rules[ruleSymbolExpr]() {
+						goto l336
+					}
+					goto l337
+				l336:
+					position, tokenIndex = position336, tokenIndex336
+				}
+			l337:
+				add(ruleSymbolExpr, position335)
+			}
+			return true
+		l334:
+			position, tokenIndex = position334, tokenIndex334
+			return false
+		},
+		/* 19 SymbolAtom <- <(LocalLabelRef / Offset / SymbolType / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?) / Dot / (OpenParen WS? SymbolExpr WS? CloseParen))> */
+		func() bool {
+			position342, tokenIndex342 := position, tokenIndex
+			{
+				position343 := position
+				{
+					position344, tokenIndex344 := position, tokenIndex
+					if !_rules[ruleLocalLabelRef]() {
+						goto l345
+					}
+					goto l344
+				l345:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleOffset]() {
+						goto l346
+					}
+					goto l344
+				l346:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleSymbolType]() {
+						goto l347
+					}
+					goto l344
+				l347:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleLocalSymbol]() {
+						goto l348
+					}
+					{
+						position349, tokenIndex349 := position, tokenIndex
+						if !_rules[ruleTCMarker]() {
+							goto l349
+						}
+						goto l350
+					l349:
+						position, tokenIndex = position349, tokenIndex349
+					}
+				l350:
+					goto l344
+				l348:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleSymbolName]() {
+						goto l351
+					}
+					if !_rules[ruleOffset]() {
+						goto l351
+					}
+					goto l344
+				l351:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleSymbolName]() {
+						goto l352
+					}
+					{
+						position353, tokenIndex353 := position, tokenIndex
+						if !_rules[ruleTCMarker]() {
+							goto l353
+						}
+						goto l354
+					l353:
+						position, tokenIndex = position353, tokenIndex353
+					}
+				l354:
+					goto l344
+				l352:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleDot]() {
+						goto l355
+					}
+					goto l344
+				l355:
+					position, tokenIndex = position344, tokenIndex344
+					if !_rules[ruleOpenParen]() {
+						goto l342
+					}
+					{
+						position356, tokenIndex356 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l356
+						}
+						goto l357
+					l356:
+						position, tokenIndex = position356, tokenIndex356
+					}
+				l357:
+					if !_rules[ruleSymbolExpr]() {
+						goto l342
+					}
+					{
+						position358, tokenIndex358 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l358
+						}
+						goto l359
+					l358:
+						position, tokenIndex = position358, tokenIndex358
+					}
+				l359:
+					if !_rules[ruleCloseParen]() {
+						goto l342
+					}
+				}
+			l344:
+				add(ruleSymbolAtom, position343)
+			}
+			return true
+		l342:
+			position, tokenIndex = position342, tokenIndex342
+			return false
+		},
+		/* 20 SymbolOperator <- <('+' / '-' / '|' / ('<' '<') / ('>' '>'))> */
+		func() bool {
+			position360, tokenIndex360 := position, tokenIndex
+			{
+				position361 := position
+				{
+					position362, tokenIndex362 := position, tokenIndex
+					if buffer[position] != rune('+') {
+						goto l363
+					}
+					position++
+					goto l362
+				l363:
+					position, tokenIndex = position362, tokenIndex362
+					if buffer[position] != rune('-') {
+						goto l364
+					}
+					position++
+					goto l362
+				l364:
+					position, tokenIndex = position362, tokenIndex362
+					if buffer[position] != rune('|') {
+						goto l365
+					}
+					position++
+					goto l362
+				l365:
+					position, tokenIndex = position362, tokenIndex362
+					if buffer[position] != rune('<') {
+						goto l366
+					}
+					position++
+					if buffer[position] != rune('<') {
+						goto l366
+					}
+					position++
+					goto l362
+				l366:
+					position, tokenIndex = position362, tokenIndex362
+					if buffer[position] != rune('>') {
+						goto l360
+					}
+					position++
+					if buffer[position] != rune('>') {
+						goto l360
 					}
 					position++
 				}
-			l343:
+			l362:
+				add(ruleSymbolOperator, position361)
+			}
+			return true
+		l360:
+			position, tokenIndex = position360, tokenIndex360
+			return false
+		},
+		/* 21 OpenParen <- <'('> */
+		func() bool {
+			position367, tokenIndex367 := position, tokenIndex
+			{
+				position368 := position
+				if buffer[position] != rune('(') {
+					goto l367
+				}
+				position++
+				add(ruleOpenParen, position368)
+			}
+			return true
+		l367:
+			position, tokenIndex = position367, tokenIndex367
+			return false
+		},
+		/* 22 CloseParen <- <')'> */
+		func() bool {
+			position369, tokenIndex369 := position, tokenIndex
+			{
+				position370 := position
+				if buffer[position] != rune(')') {
+					goto l369
+				}
+				position++
+				add(ruleCloseParen, position370)
+			}
+			return true
+		l369:
+			position, tokenIndex = position369, tokenIndex369
+			return false
+		},
+		/* 23 SymbolType <- <(('@' / '%') (('f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('o' 'b' 'j' 'e' 'c' 't')))> */
+		func() bool {
+			position371, tokenIndex371 := position, tokenIndex
+			{
+				position372 := position
 				{
-					position345, tokenIndex345 := position, tokenIndex
+					position373, tokenIndex373 := position, tokenIndex
+					if buffer[position] != rune('@') {
+						goto l374
+					}
+					position++
+					goto l373
+				l374:
+					position, tokenIndex = position373, tokenIndex373
+					if buffer[position] != rune('%') {
+						goto l371
+					}
+					position++
+				}
+			l373:
+				{
+					position375, tokenIndex375 := position, tokenIndex
 					if buffer[position] != rune('f') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('u') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('n') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('c') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('t') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('i') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('o') {
-						goto l346
+						goto l376
 					}
 					position++
 					if buffer[position] != rune('n') {
-						goto l346
-					}
-					position++
-					goto l345
-				l346:
-					position, tokenIndex = position345, tokenIndex345
-					if buffer[position] != rune('o') {
-						goto l341
-					}
-					position++
-					if buffer[position] != rune('b') {
-						goto l341
-					}
-					position++
-					if buffer[position] != rune('j') {
-						goto l341
-					}
-					position++
-					if buffer[position] != rune('e') {
-						goto l341
-					}
-					position++
-					if buffer[position] != rune('c') {
-						goto l341
-					}
-					position++
-					if buffer[position] != rune('t') {
-						goto l341
-					}
-					position++
-				}
-			l345:
-				add(ruleSymbolType, position342)
-			}
-			return true
-		l341:
-			position, tokenIndex = position341, tokenIndex341
-			return false
-		},
-		/* 22 Dot <- <'.'> */
-		func() bool {
-			position347, tokenIndex347 := position, tokenIndex
-			{
-				position348 := position
-				if buffer[position] != rune('.') {
-					goto l347
-				}
-				position++
-				add(ruleDot, position348)
-			}
-			return true
-		l347:
-			position, tokenIndex = position347, tokenIndex347
-			return false
-		},
-		/* 23 TCMarker <- <('[' 'T' 'C' ']')> */
-		func() bool {
-			position349, tokenIndex349 := position, tokenIndex
-			{
-				position350 := position
-				if buffer[position] != rune('[') {
-					goto l349
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l349
-				}
-				position++
-				if buffer[position] != rune('C') {
-					goto l349
-				}
-				position++
-				if buffer[position] != rune(']') {
-					goto l349
-				}
-				position++
-				add(ruleTCMarker, position350)
-			}
-			return true
-		l349:
-			position, tokenIndex = position349, tokenIndex349
-			return false
-		},
-		/* 24 EscapedChar <- <('\\' .)> */
-		func() bool {
-			position351, tokenIndex351 := position, tokenIndex
-			{
-				position352 := position
-				if buffer[position] != rune('\\') {
-					goto l351
-				}
-				position++
-				if !matchDot() {
-					goto l351
-				}
-				add(ruleEscapedChar, position352)
-			}
-			return true
-		l351:
-			position, tokenIndex = position351, tokenIndex351
-			return false
-		},
-		/* 25 WS <- <(' ' / '\t')+> */
-		func() bool {
-			position353, tokenIndex353 := position, tokenIndex
-			{
-				position354 := position
-				{
-					position357, tokenIndex357 := position, tokenIndex
-					if buffer[position] != rune(' ') {
-						goto l358
-					}
-					position++
-					goto l357
-				l358:
-					position, tokenIndex = position357, tokenIndex357
-					if buffer[position] != rune('\t') {
-						goto l353
-					}
-					position++
-				}
-			l357:
-			l355:
-				{
-					position356, tokenIndex356 := position, tokenIndex
-					{
-						position359, tokenIndex359 := position, tokenIndex
-						if buffer[position] != rune(' ') {
-							goto l360
-						}
-						position++
-						goto l359
-					l360:
-						position, tokenIndex = position359, tokenIndex359
-						if buffer[position] != rune('\t') {
-							goto l356
-						}
-						position++
-					}
-				l359:
-					goto l355
-				l356:
-					position, tokenIndex = position356, tokenIndex356
-				}
-				add(ruleWS, position354)
-			}
-			return true
-		l353:
-			position, tokenIndex = position353, tokenIndex353
-			return false
-		},
-		/* 26 Comment <- <((('/' '/') / '#') (!'\n' .)*)> */
-		func() bool {
-			position361, tokenIndex361 := position, tokenIndex
-			{
-				position362 := position
-				{
-					position363, tokenIndex363 := position, tokenIndex
-					if buffer[position] != rune('/') {
-						goto l364
-					}
-					position++
-					if buffer[position] != rune('/') {
-						goto l364
-					}
-					position++
-					goto l363
-				l364:
-					position, tokenIndex = position363, tokenIndex363
-					if buffer[position] != rune('#') {
-						goto l361
-					}
-					position++
-				}
-			l363:
-			l365:
-				{
-					position366, tokenIndex366 := position, tokenIndex
-					{
-						position367, tokenIndex367 := position, tokenIndex
-						if buffer[position] != rune('\n') {
-							goto l367
-						}
-						position++
-						goto l366
-					l367:
-						position, tokenIndex = position367, tokenIndex367
-					}
-					if !matchDot() {
-						goto l366
-					}
-					goto l365
-				l366:
-					position, tokenIndex = position366, tokenIndex366
-				}
-				add(ruleComment, position362)
-			}
-			return true
-		l361:
-			position, tokenIndex = position361, tokenIndex361
-			return false
-		},
-		/* 27 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */
-		func() bool {
-			position368, tokenIndex368 := position, tokenIndex
-			{
-				position369 := position
-				{
-					position370, tokenIndex370 := position, tokenIndex
-					if !_rules[ruleLocalSymbol]() {
-						goto l371
-					}
-					goto l370
-				l371:
-					position, tokenIndex = position370, tokenIndex370
-					if !_rules[ruleLocalLabel]() {
-						goto l372
-					}
-					goto l370
-				l372:
-					position, tokenIndex = position370, tokenIndex370
-					if !_rules[ruleSymbolName]() {
-						goto l368
-					}
-				}
-			l370:
-				if buffer[position] != rune(':') {
-					goto l368
-				}
-				position++
-				add(ruleLabel, position369)
-			}
-			return true
-		l368:
-			position, tokenIndex = position368, tokenIndex368
-			return false
-		},
-		/* 28 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */
-		func() bool {
-			position373, tokenIndex373 := position, tokenIndex
-			{
-				position374 := position
-				{
-					position375, tokenIndex375 := position, tokenIndex
-					if c := buffer[position]; c < rune('a') || c > rune('z') {
 						goto l376
 					}
 					position++
 					goto l375
 				l376:
 					position, tokenIndex = position375, tokenIndex375
-					if c := buffer[position]; c < rune('A') || c > rune('Z') {
-						goto l377
+					if buffer[position] != rune('o') {
+						goto l371
 					}
 					position++
-					goto l375
-				l377:
-					position, tokenIndex = position375, tokenIndex375
-					if buffer[position] != rune('.') {
-						goto l378
+					if buffer[position] != rune('b') {
+						goto l371
 					}
 					position++
-					goto l375
-				l378:
-					position, tokenIndex = position375, tokenIndex375
-					if buffer[position] != rune('_') {
-						goto l373
+					if buffer[position] != rune('j') {
+						goto l371
+					}
+					position++
+					if buffer[position] != rune('e') {
+						goto l371
+					}
+					position++
+					if buffer[position] != rune('c') {
+						goto l371
+					}
+					position++
+					if buffer[position] != rune('t') {
+						goto l371
 					}
 					position++
 				}
 			l375:
-			l379:
+				add(ruleSymbolType, position372)
+			}
+			return true
+		l371:
+			position, tokenIndex = position371, tokenIndex371
+			return false
+		},
+		/* 24 Dot <- <'.'> */
+		func() bool {
+			position377, tokenIndex377 := position, tokenIndex
+			{
+				position378 := position
+				if buffer[position] != rune('.') {
+					goto l377
+				}
+				position++
+				add(ruleDot, position378)
+			}
+			return true
+		l377:
+			position, tokenIndex = position377, tokenIndex377
+			return false
+		},
+		/* 25 TCMarker <- <('[' 'T' 'C' ']')> */
+		func() bool {
+			position379, tokenIndex379 := position, tokenIndex
+			{
+				position380 := position
+				if buffer[position] != rune('[') {
+					goto l379
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l379
+				}
+				position++
+				if buffer[position] != rune('C') {
+					goto l379
+				}
+				position++
+				if buffer[position] != rune(']') {
+					goto l379
+				}
+				position++
+				add(ruleTCMarker, position380)
+			}
+			return true
+		l379:
+			position, tokenIndex = position379, tokenIndex379
+			return false
+		},
+		/* 26 EscapedChar <- <('\\' .)> */
+		func() bool {
+			position381, tokenIndex381 := position, tokenIndex
+			{
+				position382 := position
+				if buffer[position] != rune('\\') {
+					goto l381
+				}
+				position++
+				if !matchDot() {
+					goto l381
+				}
+				add(ruleEscapedChar, position382)
+			}
+			return true
+		l381:
+			position, tokenIndex = position381, tokenIndex381
+			return false
+		},
+		/* 27 WS <- <(' ' / '\t')+> */
+		func() bool {
+			position383, tokenIndex383 := position, tokenIndex
+			{
+				position384 := position
 				{
-					position380, tokenIndex380 := position, tokenIndex
+					position387, tokenIndex387 := position, tokenIndex
+					if buffer[position] != rune(' ') {
+						goto l388
+					}
+					position++
+					goto l387
+				l388:
+					position, tokenIndex = position387, tokenIndex387
+					if buffer[position] != rune('\t') {
+						goto l383
+					}
+					position++
+				}
+			l387:
+			l385:
+				{
+					position386, tokenIndex386 := position, tokenIndex
 					{
-						position381, tokenIndex381 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l382
+						position389, tokenIndex389 := position, tokenIndex
+						if buffer[position] != rune(' ') {
+							goto l390
 						}
 						position++
-						goto l381
-					l382:
-						position, tokenIndex = position381, tokenIndex381
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l383
-						}
-						position++
-						goto l381
-					l383:
-						position, tokenIndex = position381, tokenIndex381
-						if buffer[position] != rune('.') {
-							goto l384
-						}
-						position++
-						goto l381
-					l384:
-						position, tokenIndex = position381, tokenIndex381
-						{
-							position386, tokenIndex386 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l387
-							}
-							position++
+						goto l389
+					l390:
+						position, tokenIndex = position389, tokenIndex389
+						if buffer[position] != rune('\t') {
 							goto l386
-						l387:
-							position, tokenIndex = position386, tokenIndex386
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l385
-							}
-							position++
-						}
-					l386:
-						goto l381
-					l385:
-						position, tokenIndex = position381, tokenIndex381
-						if buffer[position] != rune('$') {
-							goto l388
-						}
-						position++
-						goto l381
-					l388:
-						position, tokenIndex = position381, tokenIndex381
-						if buffer[position] != rune('_') {
-							goto l380
 						}
 						position++
 					}
-				l381:
-					goto l379
-				l380:
-					position, tokenIndex = position380, tokenIndex380
+				l389:
+					goto l385
+				l386:
+					position, tokenIndex = position386, tokenIndex386
 				}
-				add(ruleSymbolName, position374)
+				add(ruleWS, position384)
 			}
 			return true
-		l373:
-			position, tokenIndex = position373, tokenIndex373
+		l383:
+			position, tokenIndex = position383, tokenIndex383
 			return false
 		},
-		/* 29 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / ([a-z] / [A-Z]) / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */
+		/* 28 Comment <- <((('/' '/') / '#') (!'\n' .)*)> */
 		func() bool {
-			position389, tokenIndex389 := position, tokenIndex
+			position391, tokenIndex391 := position, tokenIndex
 			{
-				position390 := position
-				if buffer[position] != rune('.') {
-					goto l389
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l389
-				}
-				position++
+				position392 := position
 				{
 					position393, tokenIndex393 := position, tokenIndex
-					if c := buffer[position]; c < rune('a') || c > rune('z') {
+					if buffer[position] != rune('/') {
+						goto l394
+					}
+					position++
+					if buffer[position] != rune('/') {
 						goto l394
 					}
 					position++
 					goto l393
 				l394:
 					position, tokenIndex = position393, tokenIndex393
-					if c := buffer[position]; c < rune('A') || c > rune('Z') {
-						goto l395
-					}
-					position++
-					goto l393
-				l395:
-					position, tokenIndex = position393, tokenIndex393
-					{
-						position397, tokenIndex397 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l398
-						}
-						position++
-						goto l397
-					l398:
-						position, tokenIndex = position397, tokenIndex397
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l396
-						}
-						position++
-					}
-				l397:
-					goto l393
-				l396:
-					position, tokenIndex = position393, tokenIndex393
-					if buffer[position] != rune('.') {
-						goto l399
-					}
-					position++
-					goto l393
-				l399:
-					position, tokenIndex = position393, tokenIndex393
-					{
-						position401, tokenIndex401 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l402
-						}
-						position++
-						goto l401
-					l402:
-						position, tokenIndex = position401, tokenIndex401
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l400
-						}
-						position++
-					}
-				l401:
-					goto l393
-				l400:
-					position, tokenIndex = position393, tokenIndex393
-					if buffer[position] != rune('$') {
-						goto l403
-					}
-					position++
-					goto l393
-				l403:
-					position, tokenIndex = position393, tokenIndex393
-					if buffer[position] != rune('_') {
-						goto l389
+					if buffer[position] != rune('#') {
+						goto l391
 					}
 					position++
 				}
 			l393:
-			l391:
+			l395:
 				{
-					position392, tokenIndex392 := position, tokenIndex
+					position396, tokenIndex396 := position, tokenIndex
 					{
-						position404, tokenIndex404 := position, tokenIndex
+						position397, tokenIndex397 := position, tokenIndex
+						if buffer[position] != rune('\n') {
+							goto l397
+						}
+						position++
+						goto l396
+					l397:
+						position, tokenIndex = position397, tokenIndex397
+					}
+					if !matchDot() {
+						goto l396
+					}
+					goto l395
+				l396:
+					position, tokenIndex = position396, tokenIndex396
+				}
+				add(ruleComment, position392)
+			}
+			return true
+		l391:
+			position, tokenIndex = position391, tokenIndex391
+			return false
+		},
+		/* 29 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */
+		func() bool {
+			position398, tokenIndex398 := position, tokenIndex
+			{
+				position399 := position
+				{
+					position400, tokenIndex400 := position, tokenIndex
+					if !_rules[ruleLocalSymbol]() {
+						goto l401
+					}
+					goto l400
+				l401:
+					position, tokenIndex = position400, tokenIndex400
+					if !_rules[ruleLocalLabel]() {
+						goto l402
+					}
+					goto l400
+				l402:
+					position, tokenIndex = position400, tokenIndex400
+					if !_rules[ruleSymbolName]() {
+						goto l398
+					}
+				}
+			l400:
+				if buffer[position] != rune(':') {
+					goto l398
+				}
+				position++
+				add(ruleLabel, position399)
+			}
+			return true
+		l398:
+			position, tokenIndex = position398, tokenIndex398
+			return false
+		},
+		/* 30 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */
+		func() bool {
+			position403, tokenIndex403 := position, tokenIndex
+			{
+				position404 := position
+				{
+					position405, tokenIndex405 := position, tokenIndex
+					if c := buffer[position]; c < rune('a') || c > rune('z') {
+						goto l406
+					}
+					position++
+					goto l405
+				l406:
+					position, tokenIndex = position405, tokenIndex405
+					if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						goto l407
+					}
+					position++
+					goto l405
+				l407:
+					position, tokenIndex = position405, tokenIndex405
+					if buffer[position] != rune('.') {
+						goto l408
+					}
+					position++
+					goto l405
+				l408:
+					position, tokenIndex = position405, tokenIndex405
+					if buffer[position] != rune('_') {
+						goto l403
+					}
+					position++
+				}
+			l405:
+			l409:
+				{
+					position410, tokenIndex410 := position, tokenIndex
+					{
+						position411, tokenIndex411 := position, tokenIndex
 						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l405
-						}
-						position++
-						goto l404
-					l405:
-						position, tokenIndex = position404, tokenIndex404
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l406
-						}
-						position++
-						goto l404
-					l406:
-						position, tokenIndex = position404, tokenIndex404
-						{
-							position408, tokenIndex408 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l409
-							}
-							position++
-							goto l408
-						l409:
-							position, tokenIndex = position408, tokenIndex408
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l407
-							}
-							position++
-						}
-					l408:
-						goto l404
-					l407:
-						position, tokenIndex = position404, tokenIndex404
-						if buffer[position] != rune('.') {
-							goto l410
-						}
-						position++
-						goto l404
-					l410:
-						position, tokenIndex = position404, tokenIndex404
-						{
-							position412, tokenIndex412 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l413
-							}
-							position++
 							goto l412
-						l413:
-							position, tokenIndex = position412, tokenIndex412
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l411
-							}
-							position++
 						}
+						position++
+						goto l411
 					l412:
-						goto l404
-					l411:
-						position, tokenIndex = position404, tokenIndex404
-						if buffer[position] != rune('$') {
+						position, tokenIndex = position411, tokenIndex411
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l413
+						}
+						position++
+						goto l411
+					l413:
+						position, tokenIndex = position411, tokenIndex411
+						if buffer[position] != rune('.') {
 							goto l414
 						}
 						position++
-						goto l404
+						goto l411
 					l414:
-						position, tokenIndex = position404, tokenIndex404
-						if buffer[position] != rune('_') {
-							goto l392
+						position, tokenIndex = position411, tokenIndex411
+						{
+							position416, tokenIndex416 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l417
+							}
+							position++
+							goto l416
+						l417:
+							position, tokenIndex = position416, tokenIndex416
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l415
+							}
+							position++
 						}
-						position++
-					}
-				l404:
-					goto l391
-				l392:
-					position, tokenIndex = position392, tokenIndex392
-				}
-				add(ruleLocalSymbol, position390)
-			}
-			return true
-		l389:
-			position, tokenIndex = position389, tokenIndex389
-			return false
-		},
-		/* 30 LocalLabel <- <([0-9] ([0-9] / '$')*)> */
-		func() bool {
-			position415, tokenIndex415 := position, tokenIndex
-			{
-				position416 := position
-				if c := buffer[position]; c < rune('0') || c > rune('9') {
-					goto l415
-				}
-				position++
-			l417:
-				{
-					position418, tokenIndex418 := position, tokenIndex
-					{
-						position419, tokenIndex419 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l420
-						}
-						position++
-						goto l419
-					l420:
-						position, tokenIndex = position419, tokenIndex419
+					l416:
+						goto l411
+					l415:
+						position, tokenIndex = position411, tokenIndex411
 						if buffer[position] != rune('$') {
 							goto l418
 						}
 						position++
+						goto l411
+					l418:
+						position, tokenIndex = position411, tokenIndex411
+						if buffer[position] != rune('_') {
+							goto l410
+						}
+						position++
 					}
-				l419:
-					goto l417
-				l418:
-					position, tokenIndex = position418, tokenIndex418
+				l411:
+					goto l409
+				l410:
+					position, tokenIndex = position410, tokenIndex410
 				}
-				add(ruleLocalLabel, position416)
+				add(ruleSymbolName, position404)
 			}
 			return true
-		l415:
-			position, tokenIndex = position415, tokenIndex415
+		l403:
+			position, tokenIndex = position403, tokenIndex403
 			return false
 		},
-		/* 31 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */
+		/* 31 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / ([a-z] / [A-Z]) / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */
 		func() bool {
-			position421, tokenIndex421 := position, tokenIndex
+			position419, tokenIndex419 := position, tokenIndex
 			{
-				position422 := position
-				if c := buffer[position]; c < rune('0') || c > rune('9') {
-					goto l421
+				position420 := position
+				if buffer[position] != rune('.') {
+					goto l419
 				}
 				position++
-			l423:
+				if buffer[position] != rune('L') {
+					goto l419
+				}
+				position++
 				{
-					position424, tokenIndex424 := position, tokenIndex
+					position423, tokenIndex423 := position, tokenIndex
+					if c := buffer[position]; c < rune('a') || c > rune('z') {
+						goto l424
+					}
+					position++
+					goto l423
+				l424:
+					position, tokenIndex = position423, tokenIndex423
+					if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						goto l425
+					}
+					position++
+					goto l423
+				l425:
+					position, tokenIndex = position423, tokenIndex423
 					{
-						position425, tokenIndex425 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
+						position427, tokenIndex427 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l428
+						}
+						position++
+						goto l427
+					l428:
+						position, tokenIndex = position427, tokenIndex427
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
 							goto l426
 						}
 						position++
-						goto l425
-					l426:
-						position, tokenIndex = position425, tokenIndex425
-						if buffer[position] != rune('$') {
-							goto l424
+					}
+				l427:
+					goto l423
+				l426:
+					position, tokenIndex = position423, tokenIndex423
+					if buffer[position] != rune('.') {
+						goto l429
+					}
+					position++
+					goto l423
+				l429:
+					position, tokenIndex = position423, tokenIndex423
+					{
+						position431, tokenIndex431 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l432
+						}
+						position++
+						goto l431
+					l432:
+						position, tokenIndex = position431, tokenIndex431
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l430
 						}
 						position++
 					}
-				l425:
+				l431:
 					goto l423
-				l424:
-					position, tokenIndex = position424, tokenIndex424
-				}
-				{
-					position427, tokenIndex427 := position, tokenIndex
-					if buffer[position] != rune('b') {
-						goto l428
+				l430:
+					position, tokenIndex = position423, tokenIndex423
+					if buffer[position] != rune('$') {
+						goto l433
 					}
 					position++
-					goto l427
-				l428:
-					position, tokenIndex = position427, tokenIndex427
-					if buffer[position] != rune('f') {
-						goto l421
+					goto l423
+				l433:
+					position, tokenIndex = position423, tokenIndex423
+					if buffer[position] != rune('_') {
+						goto l419
 					}
 					position++
 				}
-			l427:
-				add(ruleLocalLabelRef, position422)
-			}
-			return true
-		l421:
-			position, tokenIndex = position421, tokenIndex421
-			return false
-		},
-		/* 32 InstructionPrefix <- <(('n' / 'N') ('o' / 'O') ('t' / 'T') ('r' / 'R') ('a' / 'A') ('c' / 'C') ('k' / 'K'))> */
-		func() bool {
-			position429, tokenIndex429 := position, tokenIndex
-			{
-				position430 := position
+			l423:
+			l421:
 				{
-					position431, tokenIndex431 := position, tokenIndex
-					if buffer[position] != rune('n') {
-						goto l432
-					}
-					position++
-					goto l431
-				l432:
-					position, tokenIndex = position431, tokenIndex431
-					if buffer[position] != rune('N') {
-						goto l429
-					}
-					position++
-				}
-			l431:
-				{
-					position433, tokenIndex433 := position, tokenIndex
-					if buffer[position] != rune('o') {
+					position422, tokenIndex422 := position, tokenIndex
+					{
+						position434, tokenIndex434 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l435
+						}
+						position++
 						goto l434
+					l435:
+						position, tokenIndex = position434, tokenIndex434
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l436
+						}
+						position++
+						goto l434
+					l436:
+						position, tokenIndex = position434, tokenIndex434
+						{
+							position438, tokenIndex438 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l439
+							}
+							position++
+							goto l438
+						l439:
+							position, tokenIndex = position438, tokenIndex438
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l437
+							}
+							position++
+						}
+					l438:
+						goto l434
+					l437:
+						position, tokenIndex = position434, tokenIndex434
+						if buffer[position] != rune('.') {
+							goto l440
+						}
+						position++
+						goto l434
+					l440:
+						position, tokenIndex = position434, tokenIndex434
+						{
+							position442, tokenIndex442 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l443
+							}
+							position++
+							goto l442
+						l443:
+							position, tokenIndex = position442, tokenIndex442
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l441
+							}
+							position++
+						}
+					l442:
+						goto l434
+					l441:
+						position, tokenIndex = position434, tokenIndex434
+						if buffer[position] != rune('$') {
+							goto l444
+						}
+						position++
+						goto l434
+					l444:
+						position, tokenIndex = position434, tokenIndex434
+						if buffer[position] != rune('_') {
+							goto l422
+						}
+						position++
 					}
-					position++
-					goto l433
 				l434:
-					position, tokenIndex = position433, tokenIndex433
-					if buffer[position] != rune('O') {
-						goto l429
-					}
-					position++
+					goto l421
+				l422:
+					position, tokenIndex = position422, tokenIndex422
 				}
-			l433:
-				{
-					position435, tokenIndex435 := position, tokenIndex
-					if buffer[position] != rune('t') {
-						goto l436
-					}
-					position++
-					goto l435
-				l436:
-					position, tokenIndex = position435, tokenIndex435
-					if buffer[position] != rune('T') {
-						goto l429
-					}
-					position++
-				}
-			l435:
-				{
-					position437, tokenIndex437 := position, tokenIndex
-					if buffer[position] != rune('r') {
-						goto l438
-					}
-					position++
-					goto l437
-				l438:
-					position, tokenIndex = position437, tokenIndex437
-					if buffer[position] != rune('R') {
-						goto l429
-					}
-					position++
-				}
-			l437:
-				{
-					position439, tokenIndex439 := position, tokenIndex
-					if buffer[position] != rune('a') {
-						goto l440
-					}
-					position++
-					goto l439
-				l440:
-					position, tokenIndex = position439, tokenIndex439
-					if buffer[position] != rune('A') {
-						goto l429
-					}
-					position++
-				}
-			l439:
-				{
-					position441, tokenIndex441 := position, tokenIndex
-					if buffer[position] != rune('c') {
-						goto l442
-					}
-					position++
-					goto l441
-				l442:
-					position, tokenIndex = position441, tokenIndex441
-					if buffer[position] != rune('C') {
-						goto l429
-					}
-					position++
-				}
-			l441:
-				{
-					position443, tokenIndex443 := position, tokenIndex
-					if buffer[position] != rune('k') {
-						goto l444
-					}
-					position++
-					goto l443
-				l444:
-					position, tokenIndex = position443, tokenIndex443
-					if buffer[position] != rune('K') {
-						goto l429
-					}
-					position++
-				}
-			l443:
-				add(ruleInstructionPrefix, position430)
+				add(ruleLocalSymbol, position420)
 			}
 			return true
-		l429:
-			position, tokenIndex = position429, tokenIndex429
+		l419:
+			position, tokenIndex = position419, tokenIndex419
 			return false
 		},
-		/* 33 Instruction <- <((InstructionPrefix WS)? InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)?)> */
+		/* 32 LocalLabel <- <([0-9] ([0-9] / '$')*)> */
 		func() bool {
 			position445, tokenIndex445 := position, tokenIndex
 			{
 				position446 := position
-				{
-					position447, tokenIndex447 := position, tokenIndex
-					if !_rules[ruleInstructionPrefix]() {
-						goto l447
-					}
-					if !_rules[ruleWS]() {
-						goto l447
-					}
-					goto l448
-				l447:
-					position, tokenIndex = position447, tokenIndex447
-				}
-			l448:
-				if !_rules[ruleInstructionName]() {
+				if c := buffer[position]; c < rune('0') || c > rune('9') {
 					goto l445
 				}
+				position++
+			l447:
 				{
-					position449, tokenIndex449 := position, tokenIndex
-					if !_rules[ruleWS]() {
-						goto l449
-					}
-					if !_rules[ruleInstructionArg]() {
-						goto l449
-					}
-				l451:
+					position448, tokenIndex448 := position, tokenIndex
 					{
-						position452, tokenIndex452 := position, tokenIndex
-						{
-							position453, tokenIndex453 := position, tokenIndex
-							if !_rules[ruleWS]() {
-								goto l453
-							}
-							goto l454
-						l453:
-							position, tokenIndex = position453, tokenIndex453
-						}
-					l454:
-						if buffer[position] != rune(',') {
-							goto l452
+						position449, tokenIndex449 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l450
 						}
 						position++
-						{
-							position455, tokenIndex455 := position, tokenIndex
-							if !_rules[ruleWS]() {
-								goto l455
-							}
-							goto l456
-						l455:
-							position, tokenIndex = position455, tokenIndex455
+						goto l449
+					l450:
+						position, tokenIndex = position449, tokenIndex449
+						if buffer[position] != rune('$') {
+							goto l448
 						}
-					l456:
-						if !_rules[ruleInstructionArg]() {
-							goto l452
-						}
-						goto l451
-					l452:
-						position, tokenIndex = position452, tokenIndex452
+						position++
 					}
-					goto l450
 				l449:
-					position, tokenIndex = position449, tokenIndex449
+					goto l447
+				l448:
+					position, tokenIndex = position448, tokenIndex448
 				}
-			l450:
-				add(ruleInstruction, position446)
+				add(ruleLocalLabel, position446)
 			}
 			return true
 		l445:
 			position, tokenIndex = position445, tokenIndex445
 			return false
 		},
-		/* 34 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */
+		/* 33 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */
 		func() bool {
-			position457, tokenIndex457 := position, tokenIndex
+			position451, tokenIndex451 := position, tokenIndex
 			{
-				position458 := position
+				position452 := position
+				if c := buffer[position]; c < rune('0') || c > rune('9') {
+					goto l451
+				}
+				position++
+			l453:
 				{
-					position459, tokenIndex459 := position, tokenIndex
-					if c := buffer[position]; c < rune('a') || c > rune('z') {
-						goto l460
+					position454, tokenIndex454 := position, tokenIndex
+					{
+						position455, tokenIndex455 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l456
+						}
+						position++
+						goto l455
+					l456:
+						position, tokenIndex = position455, tokenIndex455
+						if buffer[position] != rune('$') {
+							goto l454
+						}
+						position++
+					}
+				l455:
+					goto l453
+				l454:
+					position, tokenIndex = position454, tokenIndex454
+				}
+				{
+					position457, tokenIndex457 := position, tokenIndex
+					if buffer[position] != rune('b') {
+						goto l458
 					}
 					position++
-					goto l459
-				l460:
-					position, tokenIndex = position459, tokenIndex459
-					if c := buffer[position]; c < rune('A') || c > rune('Z') {
-						goto l457
+					goto l457
+				l458:
+					position, tokenIndex = position457, tokenIndex457
+					if buffer[position] != rune('f') {
+						goto l451
 					}
 					position++
 				}
-			l459:
-			l461:
+			l457:
+				add(ruleLocalLabelRef, position452)
+			}
+			return true
+		l451:
+			position, tokenIndex = position451, tokenIndex451
+			return false
+		},
+		/* 34 InstructionPrefix <- <(('n' / 'N') ('o' / 'O') ('t' / 'T') ('r' / 'R') ('a' / 'A') ('c' / 'C') ('k' / 'K'))> */
+		func() bool {
+			position459, tokenIndex459 := position, tokenIndex
+			{
+				position460 := position
 				{
-					position462, tokenIndex462 := position, tokenIndex
-					{
-						position463, tokenIndex463 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l464
-						}
-						position++
-						goto l463
-					l464:
-						position, tokenIndex = position463, tokenIndex463
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l465
-						}
-						position++
-						goto l463
-					l465:
-						position, tokenIndex = position463, tokenIndex463
-						if buffer[position] != rune('.') {
-							goto l466
-						}
-						position++
-						goto l463
-					l466:
-						position, tokenIndex = position463, tokenIndex463
-						{
-							position467, tokenIndex467 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l468
-							}
-							position++
-							goto l467
-						l468:
-							position, tokenIndex = position467, tokenIndex467
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l462
-							}
-							position++
-						}
-					l467:
+					position461, tokenIndex461 := position, tokenIndex
+					if buffer[position] != rune('n') {
+						goto l462
 					}
-				l463:
+					position++
 					goto l461
 				l462:
-					position, tokenIndex = position462, tokenIndex462
+					position, tokenIndex = position461, tokenIndex461
+					if buffer[position] != rune('N') {
+						goto l459
+					}
+					position++
 				}
+			l461:
+				{
+					position463, tokenIndex463 := position, tokenIndex
+					if buffer[position] != rune('o') {
+						goto l464
+					}
+					position++
+					goto l463
+				l464:
+					position, tokenIndex = position463, tokenIndex463
+					if buffer[position] != rune('O') {
+						goto l459
+					}
+					position++
+				}
+			l463:
+				{
+					position465, tokenIndex465 := position, tokenIndex
+					if buffer[position] != rune('t') {
+						goto l466
+					}
+					position++
+					goto l465
+				l466:
+					position, tokenIndex = position465, tokenIndex465
+					if buffer[position] != rune('T') {
+						goto l459
+					}
+					position++
+				}
+			l465:
+				{
+					position467, tokenIndex467 := position, tokenIndex
+					if buffer[position] != rune('r') {
+						goto l468
+					}
+					position++
+					goto l467
+				l468:
+					position, tokenIndex = position467, tokenIndex467
+					if buffer[position] != rune('R') {
+						goto l459
+					}
+					position++
+				}
+			l467:
 				{
 					position469, tokenIndex469 := position, tokenIndex
-					{
-						position471, tokenIndex471 := position, tokenIndex
-						if buffer[position] != rune('.') {
-							goto l472
-						}
-						position++
-						goto l471
-					l472:
-						position, tokenIndex = position471, tokenIndex471
-						if buffer[position] != rune('+') {
-							goto l473
-						}
-						position++
-						goto l471
-					l473:
-						position, tokenIndex = position471, tokenIndex471
-						if buffer[position] != rune('-') {
-							goto l469
-						}
-						position++
+					if buffer[position] != rune('a') {
+						goto l470
 					}
-				l471:
-					goto l470
-				l469:
+					position++
+					goto l469
+				l470:
 					position, tokenIndex = position469, tokenIndex469
+					if buffer[position] != rune('A') {
+						goto l459
+					}
+					position++
 				}
-			l470:
-				add(ruleInstructionName, position458)
-			}
-			return true
-		l457:
-			position, tokenIndex = position457, tokenIndex457
-			return false
-		},
-		/* 35 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token*)> */
-		func() bool {
-			position474, tokenIndex474 := position, tokenIndex
-			{
-				position475 := position
+			l469:
 				{
-					position476, tokenIndex476 := position, tokenIndex
-					if !_rules[ruleIndirectionIndicator]() {
-						goto l476
+					position471, tokenIndex471 := position, tokenIndex
+					if buffer[position] != rune('c') {
+						goto l472
 					}
-					goto l477
-				l476:
-					position, tokenIndex = position476, tokenIndex476
+					position++
+					goto l471
+				l472:
+					position, tokenIndex = position471, tokenIndex471
+					if buffer[position] != rune('C') {
+						goto l459
+					}
+					position++
 				}
-			l477:
+			l471:
 				{
-					position478, tokenIndex478 := position, tokenIndex
-					if !_rules[ruleARMConstantTweak]() {
-						goto l479
-					}
-					goto l478
-				l479:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleRegisterOrConstant]() {
-						goto l480
-					}
-					goto l478
-				l480:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleLocalLabelRef]() {
-						goto l481
-					}
-					goto l478
-				l481:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleTOCRefHigh]() {
-						goto l482
-					}
-					goto l478
-				l482:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleTOCRefLow]() {
-						goto l483
-					}
-					goto l478
-				l483:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleGOTLocation]() {
-						goto l484
-					}
-					goto l478
-				l484:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleGOTAddress]() {
-						goto l485
-					}
-					goto l478
-				l485:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleGOTSymbolOffset]() {
-						goto l486
-					}
-					goto l478
-				l486:
-					position, tokenIndex = position478, tokenIndex478
-					if !_rules[ruleMemoryRef]() {
+					position473, tokenIndex473 := position, tokenIndex
+					if buffer[position] != rune('k') {
 						goto l474
 					}
+					position++
+					goto l473
+				l474:
+					position, tokenIndex = position473, tokenIndex473
+					if buffer[position] != rune('K') {
+						goto l459
+					}
+					position++
+				}
+			l473:
+				add(ruleInstructionPrefix, position460)
+			}
+			return true
+		l459:
+			position, tokenIndex = position459, tokenIndex459
+			return false
+		},
+		/* 35 Instruction <- <((InstructionPrefix WS)? InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)?)> */
+		func() bool {
+			position475, tokenIndex475 := position, tokenIndex
+			{
+				position476 := position
+				{
+					position477, tokenIndex477 := position, tokenIndex
+					if !_rules[ruleInstructionPrefix]() {
+						goto l477
+					}
+					if !_rules[ruleWS]() {
+						goto l477
+					}
+					goto l478
+				l477:
+					position, tokenIndex = position477, tokenIndex477
 				}
 			l478:
-			l487:
+				if !_rules[ruleInstructionName]() {
+					goto l475
+				}
 				{
-					position488, tokenIndex488 := position, tokenIndex
-					if !_rules[ruleAVX512Token]() {
-						goto l488
+					position479, tokenIndex479 := position, tokenIndex
+					if !_rules[ruleWS]() {
+						goto l479
 					}
-					goto l487
-				l488:
-					position, tokenIndex = position488, tokenIndex488
-				}
-				add(ruleInstructionArg, position475)
-			}
-			return true
-		l474:
-			position, tokenIndex = position474, tokenIndex474
-			return false
-		},
-		/* 36 GOTLocation <- <('$' '_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '-' LocalSymbol)> */
-		func() bool {
-			position489, tokenIndex489 := position, tokenIndex
-			{
-				position490 := position
-				if buffer[position] != rune('$') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('G') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('B') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('A') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('F') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('F') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('S') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('E') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('A') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('B') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('E') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l489
-				}
-				position++
-				if buffer[position] != rune('-') {
-					goto l489
-				}
-				position++
-				if !_rules[ruleLocalSymbol]() {
-					goto l489
-				}
-				add(ruleGOTLocation, position490)
-			}
-			return true
-		l489:
-			position, tokenIndex = position489, tokenIndex489
-			return false
-		},
-		/* 37 GOTAddress <- <('_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '(' '%' 'r' 'i' 'p' ')')> */
-		func() bool {
-			position491, tokenIndex491 := position, tokenIndex
-			{
-				position492 := position
-				if buffer[position] != rune('_') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('G') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('B') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('A') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('F') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('F') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('S') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('E') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('A') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('B') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('L') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('E') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('_') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('(') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('%') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('r') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('i') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune('p') {
-					goto l491
-				}
-				position++
-				if buffer[position] != rune(')') {
-					goto l491
-				}
-				position++
-				add(ruleGOTAddress, position492)
-			}
-			return true
-		l491:
-			position, tokenIndex = position491, tokenIndex491
-			return false
-		},
-		/* 38 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */
-		func() bool {
-			position493, tokenIndex493 := position, tokenIndex
-			{
-				position494 := position
-				{
-					position495, tokenIndex495 := position, tokenIndex
-					if buffer[position] != rune('$') {
-						goto l496
+					if !_rules[ruleInstructionArg]() {
+						goto l479
 					}
-					position++
-					if !_rules[ruleSymbolName]() {
-						goto l496
-					}
-					if buffer[position] != rune('@') {
-						goto l496
-					}
-					position++
-					if buffer[position] != rune('G') {
-						goto l496
-					}
-					position++
-					if buffer[position] != rune('O') {
-						goto l496
-					}
-					position++
-					if buffer[position] != rune('T') {
-						goto l496
-					}
-					position++
+				l481:
 					{
-						position497, tokenIndex497 := position, tokenIndex
-						if buffer[position] != rune('O') {
-							goto l497
+						position482, tokenIndex482 := position, tokenIndex
+						{
+							position483, tokenIndex483 := position, tokenIndex
+							if !_rules[ruleWS]() {
+								goto l483
+							}
+							goto l484
+						l483:
+							position, tokenIndex = position483, tokenIndex483
+						}
+					l484:
+						if buffer[position] != rune(',') {
+							goto l482
 						}
 						position++
-						if buffer[position] != rune('F') {
-							goto l497
+						{
+							position485, tokenIndex485 := position, tokenIndex
+							if !_rules[ruleWS]() {
+								goto l485
+							}
+							goto l486
+						l485:
+							position, tokenIndex = position485, tokenIndex485
 						}
-						position++
-						if buffer[position] != rune('F') {
-							goto l497
+					l486:
+						if !_rules[ruleInstructionArg]() {
+							goto l482
 						}
-						position++
-						goto l498
-					l497:
-						position, tokenIndex = position497, tokenIndex497
+						goto l481
+					l482:
+						position, tokenIndex = position482, tokenIndex482
 					}
-				l498:
-					goto l495
-				l496:
-					position, tokenIndex = position495, tokenIndex495
-					if buffer[position] != rune(':') {
+					goto l480
+				l479:
+					position, tokenIndex = position479, tokenIndex479
+				}
+			l480:
+				add(ruleInstruction, position476)
+			}
+			return true
+		l475:
+			position, tokenIndex = position475, tokenIndex475
+			return false
+		},
+		/* 36 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */
+		func() bool {
+			position487, tokenIndex487 := position, tokenIndex
+			{
+				position488 := position
+				{
+					position489, tokenIndex489 := position, tokenIndex
+					if c := buffer[position]; c < rune('a') || c > rune('z') {
+						goto l490
+					}
+					position++
+					goto l489
+				l490:
+					position, tokenIndex = position489, tokenIndex489
+					if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						goto l487
+					}
+					position++
+				}
+			l489:
+			l491:
+				{
+					position492, tokenIndex492 := position, tokenIndex
+					{
+						position493, tokenIndex493 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l494
+						}
+						position++
 						goto l493
-					}
-					position++
-					{
-						position499, tokenIndex499 := position, tokenIndex
-						if buffer[position] != rune('g') {
-							goto l500
+					l494:
+						position, tokenIndex = position493, tokenIndex493
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l495
 						}
 						position++
-						goto l499
-					l500:
-						position, tokenIndex = position499, tokenIndex499
-						if buffer[position] != rune('G') {
-							goto l493
+						goto l493
+					l495:
+						position, tokenIndex = position493, tokenIndex493
+						if buffer[position] != rune('.') {
+							goto l496
 						}
 						position++
+						goto l493
+					l496:
+						position, tokenIndex = position493, tokenIndex493
+						{
+							position497, tokenIndex497 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l498
+							}
+							position++
+							goto l497
+						l498:
+							position, tokenIndex = position497, tokenIndex497
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l492
+							}
+							position++
+						}
+					l497:
 					}
-				l499:
+				l493:
+					goto l491
+				l492:
+					position, tokenIndex = position492, tokenIndex492
+				}
+				{
+					position499, tokenIndex499 := position, tokenIndex
 					{
 						position501, tokenIndex501 := position, tokenIndex
-						if buffer[position] != rune('o') {
+						if buffer[position] != rune('.') {
 							goto l502
 						}
 						position++
 						goto l501
 					l502:
 						position, tokenIndex = position501, tokenIndex501
-						if buffer[position] != rune('O') {
-							goto l493
+						if buffer[position] != rune('+') {
+							goto l503
+						}
+						position++
+						goto l501
+					l503:
+						position, tokenIndex = position501, tokenIndex501
+						if buffer[position] != rune('-') {
+							goto l499
 						}
 						position++
 					}
 				l501:
-					{
-						position503, tokenIndex503 := position, tokenIndex
-						if buffer[position] != rune('t') {
-							goto l504
-						}
-						position++
-						goto l503
-					l504:
-						position, tokenIndex = position503, tokenIndex503
-						if buffer[position] != rune('T') {
-							goto l493
-						}
-						position++
+					goto l500
+				l499:
+					position, tokenIndex = position499, tokenIndex499
+				}
+			l500:
+				add(ruleInstructionName, position488)
+			}
+			return true
+		l487:
+			position, tokenIndex = position487, tokenIndex487
+			return false
+		},
+		/* 37 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token*)> */
+		func() bool {
+			position504, tokenIndex504 := position, tokenIndex
+			{
+				position505 := position
+				{
+					position506, tokenIndex506 := position, tokenIndex
+					if !_rules[ruleIndirectionIndicator]() {
+						goto l506
 					}
-				l503:
-					if buffer[position] != rune(':') {
-						goto l493
+					goto l507
+				l506:
+					position, tokenIndex = position506, tokenIndex506
+				}
+			l507:
+				{
+					position508, tokenIndex508 := position, tokenIndex
+					if !_rules[ruleARMConstantTweak]() {
+						goto l509
+					}
+					goto l508
+				l509:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleRegisterOrConstant]() {
+						goto l510
+					}
+					goto l508
+				l510:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleLocalLabelRef]() {
+						goto l511
+					}
+					goto l508
+				l511:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleTOCRefHigh]() {
+						goto l512
+					}
+					goto l508
+				l512:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleTOCRefLow]() {
+						goto l513
+					}
+					goto l508
+				l513:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleGOTLocation]() {
+						goto l514
+					}
+					goto l508
+				l514:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleGOTAddress]() {
+						goto l515
+					}
+					goto l508
+				l515:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleGOTSymbolOffset]() {
+						goto l516
+					}
+					goto l508
+				l516:
+					position, tokenIndex = position508, tokenIndex508
+					if !_rules[ruleMemoryRef]() {
+						goto l504
+					}
+				}
+			l508:
+			l517:
+				{
+					position518, tokenIndex518 := position, tokenIndex
+					if !_rules[ruleAVX512Token]() {
+						goto l518
+					}
+					goto l517
+				l518:
+					position, tokenIndex = position518, tokenIndex518
+				}
+				add(ruleInstructionArg, position505)
+			}
+			return true
+		l504:
+			position, tokenIndex = position504, tokenIndex504
+			return false
+		},
+		/* 38 GOTLocation <- <('$' '_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '-' LocalSymbol)> */
+		func() bool {
+			position519, tokenIndex519 := position, tokenIndex
+			{
+				position520 := position
+				if buffer[position] != rune('$') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('G') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('B') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('A') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('F') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('F') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('S') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('E') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('A') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('B') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('E') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l519
+				}
+				position++
+				if buffer[position] != rune('-') {
+					goto l519
+				}
+				position++
+				if !_rules[ruleLocalSymbol]() {
+					goto l519
+				}
+				add(ruleGOTLocation, position520)
+			}
+			return true
+		l519:
+			position, tokenIndex = position519, tokenIndex519
+			return false
+		},
+		/* 39 GOTAddress <- <('_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '(' '%' 'r' 'i' 'p' ')')> */
+		func() bool {
+			position521, tokenIndex521 := position, tokenIndex
+			{
+				position522 := position
+				if buffer[position] != rune('_') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('G') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('B') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('A') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('F') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('F') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('S') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('E') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('A') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('B') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('L') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('E') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('_') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('(') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('%') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('r') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('i') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune('p') {
+					goto l521
+				}
+				position++
+				if buffer[position] != rune(')') {
+					goto l521
+				}
+				position++
+				add(ruleGOTAddress, position522)
+			}
+			return true
+		l521:
+			position, tokenIndex = position521, tokenIndex521
+			return false
+		},
+		/* 40 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */
+		func() bool {
+			position523, tokenIndex523 := position, tokenIndex
+			{
+				position524 := position
+				{
+					position525, tokenIndex525 := position, tokenIndex
+					if buffer[position] != rune('$') {
+						goto l526
 					}
 					position++
 					if !_rules[ruleSymbolName]() {
-						goto l493
+						goto l526
 					}
-				}
-			l495:
-				add(ruleGOTSymbolOffset, position494)
-			}
-			return true
-		l493:
-			position, tokenIndex = position493, tokenIndex493
-			return false
-		},
-		/* 39 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */
-		func() bool {
-			position505, tokenIndex505 := position, tokenIndex
-			{
-				position506 := position
-				{
-					position507, tokenIndex507 := position, tokenIndex
-					if !_rules[ruleWS]() {
-						goto l507
-					}
-					goto l508
-				l507:
-					position, tokenIndex = position507, tokenIndex507
-				}
-			l508:
-				if buffer[position] != rune('{') {
-					goto l505
-				}
-				position++
-				{
-					position509, tokenIndex509 := position, tokenIndex
-					if buffer[position] != rune('%') {
-						goto l509
+					if buffer[position] != rune('@') {
+						goto l526
 					}
 					position++
-					goto l510
-				l509:
-					position, tokenIndex = position509, tokenIndex509
-				}
-			l510:
-			l511:
-				{
-					position512, tokenIndex512 := position, tokenIndex
-					{
-						position513, tokenIndex513 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l514
-						}
-						position++
-						goto l513
-					l514:
-						position, tokenIndex = position513, tokenIndex513
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l512
-						}
-						position++
-					}
-				l513:
-					goto l511
-				l512:
-					position, tokenIndex = position512, tokenIndex512
-				}
-				if buffer[position] != rune('}') {
-					goto l505
-				}
-				position++
-				add(ruleAVX512Token, position506)
-			}
-			return true
-		l505:
-			position, tokenIndex = position505, tokenIndex505
-			return false
-		},
-		/* 40 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */
-		func() bool {
-			position515, tokenIndex515 := position, tokenIndex
-			{
-				position516 := position
-				if buffer[position] != rune('.') {
-					goto l515
-				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l515
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l515
-				}
-				position++
-				if buffer[position] != rune('C') {
-					goto l515
-				}
-				position++
-				if buffer[position] != rune('.') {
-					goto l515
-				}
-				position++
-				if buffer[position] != rune('-') {
-					goto l515
-				}
-				position++
-				{
-					position517, tokenIndex517 := position, tokenIndex
-					if buffer[position] != rune('0') {
-						goto l518
+					if buffer[position] != rune('G') {
+						goto l526
 					}
 					position++
-					if buffer[position] != rune('b') {
-						goto l518
+					if buffer[position] != rune('O') {
+						goto l526
 					}
 					position++
-					goto l517
-				l518:
-					position, tokenIndex = position517, tokenIndex517
-					if buffer[position] != rune('.') {
-						goto l515
-					}
-					position++
-					if buffer[position] != rune('L') {
-						goto l515
+					if buffer[position] != rune('T') {
+						goto l526
 					}
 					position++
 					{
-						position521, tokenIndex521 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l522
+						position527, tokenIndex527 := position, tokenIndex
+						if buffer[position] != rune('O') {
+							goto l527
 						}
 						position++
-						goto l521
-					l522:
-						position, tokenIndex = position521, tokenIndex521
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						if buffer[position] != rune('F') {
+							goto l527
+						}
+						position++
+						if buffer[position] != rune('F') {
+							goto l527
+						}
+						position++
+						goto l528
+					l527:
+						position, tokenIndex = position527, tokenIndex527
+					}
+				l528:
+					goto l525
+				l526:
+					position, tokenIndex = position525, tokenIndex525
+					if buffer[position] != rune(':') {
+						goto l523
+					}
+					position++
+					{
+						position529, tokenIndex529 := position, tokenIndex
+						if buffer[position] != rune('g') {
+							goto l530
+						}
+						position++
+						goto l529
+					l530:
+						position, tokenIndex = position529, tokenIndex529
+						if buffer[position] != rune('G') {
 							goto l523
 						}
 						position++
-						goto l521
-					l523:
-						position, tokenIndex = position521, tokenIndex521
-						if buffer[position] != rune('_') {
-							goto l524
-						}
-						position++
-						goto l521
-					l524:
-						position, tokenIndex = position521, tokenIndex521
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l515
-						}
-						position++
 					}
-				l521:
-				l519:
+				l529:
 					{
-						position520, tokenIndex520 := position, tokenIndex
-						{
-							position525, tokenIndex525 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l526
-							}
-							position++
-							goto l525
-						l526:
-							position, tokenIndex = position525, tokenIndex525
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l527
-							}
-							position++
-							goto l525
-						l527:
-							position, tokenIndex = position525, tokenIndex525
-							if buffer[position] != rune('_') {
-								goto l528
-							}
-							position++
-							goto l525
-						l528:
-							position, tokenIndex = position525, tokenIndex525
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l520
-							}
-							position++
+						position531, tokenIndex531 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l532
 						}
-					l525:
-						goto l519
-					l520:
-						position, tokenIndex = position520, tokenIndex520
+						position++
+						goto l531
+					l532:
+						position, tokenIndex = position531, tokenIndex531
+						if buffer[position] != rune('O') {
+							goto l523
+						}
+						position++
 					}
-				}
-			l517:
-				if buffer[position] != rune('@') {
-					goto l515
-				}
-				position++
-				{
-					position529, tokenIndex529 := position, tokenIndex
-					if buffer[position] != rune('h') {
-						goto l530
+				l531:
+					{
+						position533, tokenIndex533 := position, tokenIndex
+						if buffer[position] != rune('t') {
+							goto l534
+						}
+						position++
+						goto l533
+					l534:
+						position, tokenIndex = position533, tokenIndex533
+						if buffer[position] != rune('T') {
+							goto l523
+						}
+						position++
+					}
+				l533:
+					if buffer[position] != rune(':') {
+						goto l523
 					}
 					position++
-					goto l529
-				l530:
-					position, tokenIndex = position529, tokenIndex529
-					if buffer[position] != rune('H') {
-						goto l515
+					if !_rules[ruleSymbolName]() {
+						goto l523
 					}
-					position++
 				}
-			l529:
-				{
-					position531, tokenIndex531 := position, tokenIndex
-					if buffer[position] != rune('a') {
-						goto l532
-					}
-					position++
-					goto l531
-				l532:
-					position, tokenIndex = position531, tokenIndex531
-					if buffer[position] != rune('A') {
-						goto l515
-					}
-					position++
-				}
-			l531:
-				add(ruleTOCRefHigh, position516)
+			l525:
+				add(ruleGOTSymbolOffset, position524)
 			}
 			return true
-		l515:
-			position, tokenIndex = position515, tokenIndex515
+		l523:
+			position, tokenIndex = position523, tokenIndex523
 			return false
 		},
-		/* 41 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */
+		/* 41 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */
 		func() bool {
-			position533, tokenIndex533 := position, tokenIndex
+			position535, tokenIndex535 := position, tokenIndex
 			{
-				position534 := position
-				if buffer[position] != rune('.') {
-					goto l533
+				position536 := position
+				{
+					position537, tokenIndex537 := position, tokenIndex
+					if !_rules[ruleWS]() {
+						goto l537
+					}
+					goto l538
+				l537:
+					position, tokenIndex = position537, tokenIndex537
 				}
-				position++
-				if buffer[position] != rune('T') {
-					goto l533
-				}
-				position++
-				if buffer[position] != rune('O') {
-					goto l533
-				}
-				position++
-				if buffer[position] != rune('C') {
-					goto l533
-				}
-				position++
-				if buffer[position] != rune('.') {
-					goto l533
-				}
-				position++
-				if buffer[position] != rune('-') {
-					goto l533
+			l538:
+				if buffer[position] != rune('{') {
+					goto l535
 				}
 				position++
 				{
-					position535, tokenIndex535 := position, tokenIndex
-					if buffer[position] != rune('0') {
-						goto l536
+					position539, tokenIndex539 := position, tokenIndex
+					if buffer[position] != rune('%') {
+						goto l539
 					}
 					position++
-					if buffer[position] != rune('b') {
-						goto l536
-					}
-					position++
-					goto l535
-				l536:
-					position, tokenIndex = position535, tokenIndex535
-					if buffer[position] != rune('.') {
-						goto l533
-					}
-					position++
-					if buffer[position] != rune('L') {
-						goto l533
-					}
-					position++
+					goto l540
+				l539:
+					position, tokenIndex = position539, tokenIndex539
+				}
+			l540:
+			l541:
+				{
+					position542, tokenIndex542 := position, tokenIndex
 					{
-						position539, tokenIndex539 := position, tokenIndex
+						position543, tokenIndex543 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l544
+						}
+						position++
+						goto l543
+					l544:
+						position, tokenIndex = position543, tokenIndex543
 						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l540
-						}
-						position++
-						goto l539
-					l540:
-						position, tokenIndex = position539, tokenIndex539
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l541
-						}
-						position++
-						goto l539
-					l541:
-						position, tokenIndex = position539, tokenIndex539
-						if buffer[position] != rune('_') {
 							goto l542
 						}
 						position++
-						goto l539
-					l542:
-						position, tokenIndex = position539, tokenIndex539
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l533
-						}
-						position++
 					}
-				l539:
-				l537:
-					{
-						position538, tokenIndex538 := position, tokenIndex
-						{
-							position543, tokenIndex543 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l544
-							}
-							position++
-							goto l543
-						l544:
-							position, tokenIndex = position543, tokenIndex543
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l545
-							}
-							position++
-							goto l543
-						l545:
-							position, tokenIndex = position543, tokenIndex543
-							if buffer[position] != rune('_') {
-								goto l546
-							}
-							position++
-							goto l543
-						l546:
-							position, tokenIndex = position543, tokenIndex543
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l538
-							}
-							position++
-						}
-					l543:
-						goto l537
-					l538:
-						position, tokenIndex = position538, tokenIndex538
-					}
+				l543:
+					goto l541
+				l542:
+					position, tokenIndex = position542, tokenIndex542
 				}
-			l535:
-				if buffer[position] != rune('@') {
-					goto l533
+				if buffer[position] != rune('}') {
+					goto l535
+				}
+				position++
+				add(ruleAVX512Token, position536)
+			}
+			return true
+		l535:
+			position, tokenIndex = position535, tokenIndex535
+			return false
+		},
+		/* 42 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */
+		func() bool {
+			position545, tokenIndex545 := position, tokenIndex
+			{
+				position546 := position
+				if buffer[position] != rune('.') {
+					goto l545
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l545
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l545
+				}
+				position++
+				if buffer[position] != rune('C') {
+					goto l545
+				}
+				position++
+				if buffer[position] != rune('.') {
+					goto l545
+				}
+				position++
+				if buffer[position] != rune('-') {
+					goto l545
 				}
 				position++
 				{
 					position547, tokenIndex547 := position, tokenIndex
-					if buffer[position] != rune('l') {
+					if buffer[position] != rune('0') {
+						goto l548
+					}
+					position++
+					if buffer[position] != rune('b') {
 						goto l548
 					}
 					position++
 					goto l547
 				l548:
 					position, tokenIndex = position547, tokenIndex547
-					if buffer[position] != rune('L') {
-						goto l533
+					if buffer[position] != rune('.') {
+						goto l545
 					}
 					position++
+					if buffer[position] != rune('L') {
+						goto l545
+					}
+					position++
+					{
+						position551, tokenIndex551 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l552
+						}
+						position++
+						goto l551
+					l552:
+						position, tokenIndex = position551, tokenIndex551
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l553
+						}
+						position++
+						goto l551
+					l553:
+						position, tokenIndex = position551, tokenIndex551
+						if buffer[position] != rune('_') {
+							goto l554
+						}
+						position++
+						goto l551
+					l554:
+						position, tokenIndex = position551, tokenIndex551
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l545
+						}
+						position++
+					}
+				l551:
+				l549:
+					{
+						position550, tokenIndex550 := position, tokenIndex
+						{
+							position555, tokenIndex555 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l556
+							}
+							position++
+							goto l555
+						l556:
+							position, tokenIndex = position555, tokenIndex555
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l557
+							}
+							position++
+							goto l555
+						l557:
+							position, tokenIndex = position555, tokenIndex555
+							if buffer[position] != rune('_') {
+								goto l558
+							}
+							position++
+							goto l555
+						l558:
+							position, tokenIndex = position555, tokenIndex555
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l550
+							}
+							position++
+						}
+					l555:
+						goto l549
+					l550:
+						position, tokenIndex = position550, tokenIndex550
+					}
 				}
 			l547:
-				add(ruleTOCRefLow, position534)
-			}
-			return true
-		l533:
-			position, tokenIndex = position533, tokenIndex533
-			return false
-		},
-		/* 42 IndirectionIndicator <- <'*'> */
-		func() bool {
-			position549, tokenIndex549 := position, tokenIndex
-			{
-				position550 := position
-				if buffer[position] != rune('*') {
-					goto l549
+				if buffer[position] != rune('@') {
+					goto l545
 				}
 				position++
-				add(ruleIndirectionIndicator, position550)
-			}
-			return true
-		l549:
-			position, tokenIndex = position549, tokenIndex549
-			return false
-		},
-		/* 43 Float <- <([0-9]+ '.' [0-9]*)> */
-		func() bool {
-			position551, tokenIndex551 := position, tokenIndex
-			{
-				position552 := position
-				if c := buffer[position]; c < rune('0') || c > rune('9') {
-					goto l551
-				}
-				position++
-			l553:
-				{
-					position554, tokenIndex554 := position, tokenIndex
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l554
-					}
-					position++
-					goto l553
-				l554:
-					position, tokenIndex = position554, tokenIndex554
-				}
-				if buffer[position] != rune('.') {
-					goto l551
-				}
-				position++
-			l555:
-				{
-					position556, tokenIndex556 := position, tokenIndex
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l556
-					}
-					position++
-					goto l555
-				l556:
-					position, tokenIndex = position556, tokenIndex556
-				}
-				add(ruleFloat, position552)
-			}
-			return true
-		l551:
-			position, tokenIndex = position551, tokenIndex551
-			return false
-		},
-		/* 44 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Float) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */
-		func() bool {
-			position557, tokenIndex557 := position, tokenIndex
-			{
-				position558 := position
 				{
 					position559, tokenIndex559 := position, tokenIndex
-					if buffer[position] != rune('%') {
+					if buffer[position] != rune('h') {
 						goto l560
 					}
 					position++
-					{
-						position561, tokenIndex561 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l562
-						}
-						position++
-						goto l561
-					l562:
-						position, tokenIndex = position561, tokenIndex561
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l560
-						}
-						position++
-					}
-				l561:
-				l563:
-					{
-						position564, tokenIndex564 := position, tokenIndex
-						{
-							position565, tokenIndex565 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l566
-							}
-							position++
-							goto l565
-						l566:
-							position, tokenIndex = position565, tokenIndex565
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l567
-							}
-							position++
-							goto l565
-						l567:
-							position, tokenIndex = position565, tokenIndex565
-							{
-								position568, tokenIndex568 := position, tokenIndex
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l569
-								}
-								position++
-								goto l568
-							l569:
-								position, tokenIndex = position568, tokenIndex568
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l564
-								}
-								position++
-							}
-						l568:
-						}
-					l565:
-						goto l563
-					l564:
-						position, tokenIndex = position564, tokenIndex564
-					}
 					goto l559
 				l560:
 					position, tokenIndex = position559, tokenIndex559
-					{
-						position571, tokenIndex571 := position, tokenIndex
-						if buffer[position] != rune('$') {
-							goto l571
-						}
-						position++
-						goto l572
-					l571:
-						position, tokenIndex = position571, tokenIndex571
-					}
-				l572:
-					{
-						position573, tokenIndex573 := position, tokenIndex
-						if !_rules[ruleOffset]() {
-							goto l574
-						}
-						if !_rules[ruleOffset]() {
-							goto l574
-						}
-						goto l573
-					l574:
-						position, tokenIndex = position573, tokenIndex573
-						if !_rules[ruleOffset]() {
-							goto l570
-						}
-					}
-				l573:
-					goto l559
-				l570:
-					position, tokenIndex = position559, tokenIndex559
-					if buffer[position] != rune('#') {
-						goto l575
+					if buffer[position] != rune('H') {
+						goto l545
 					}
 					position++
-					if !_rules[ruleFloat]() {
-						goto l575
-					}
-					goto l559
-				l575:
-					position, tokenIndex = position559, tokenIndex559
-					if buffer[position] != rune('#') {
-						goto l576
-					}
-					position++
-					if !_rules[ruleOffset]() {
-						goto l576
-					}
-					{
-						position577, tokenIndex577 := position, tokenIndex
-						if buffer[position] != rune('*') {
-							goto l577
-						}
-						position++
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l577
-						}
-						position++
-					l579:
-						{
-							position580, tokenIndex580 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l580
-							}
-							position++
-							goto l579
-						l580:
-							position, tokenIndex = position580, tokenIndex580
-						}
-						{
-							position581, tokenIndex581 := position, tokenIndex
-							if buffer[position] != rune('-') {
-								goto l581
-							}
-							position++
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l581
-							}
-							position++
-						l583:
-							{
-								position584, tokenIndex584 := position, tokenIndex
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l584
-								}
-								position++
-								goto l583
-							l584:
-								position, tokenIndex = position584, tokenIndex584
-							}
-							goto l582
-						l581:
-							position, tokenIndex = position581, tokenIndex581
-						}
-					l582:
-						goto l578
-					l577:
-						position, tokenIndex = position577, tokenIndex577
-					}
-				l578:
-					goto l559
-				l576:
-					position, tokenIndex = position559, tokenIndex559
-					if buffer[position] != rune('#') {
-						goto l585
-					}
-					position++
-					{
-						position586, tokenIndex586 := position, tokenIndex
-						if buffer[position] != rune('~') {
-							goto l586
-						}
-						position++
-						goto l587
-					l586:
-						position, tokenIndex = position586, tokenIndex586
-					}
-				l587:
-					if buffer[position] != rune('(') {
-						goto l585
-					}
-					position++
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l585
-					}
-					position++
-					{
-						position588, tokenIndex588 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l588
-						}
-						goto l589
-					l588:
-						position, tokenIndex = position588, tokenIndex588
-					}
-				l589:
-					if buffer[position] != rune('<') {
-						goto l585
-					}
-					position++
-					if buffer[position] != rune('<') {
-						goto l585
-					}
-					position++
-					{
-						position590, tokenIndex590 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l590
-						}
-						goto l591
-					l590:
-						position, tokenIndex = position590, tokenIndex590
-					}
-				l591:
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l585
-					}
-					position++
-					if buffer[position] != rune(')') {
-						goto l585
-					}
-					position++
-					goto l559
-				l585:
-					position, tokenIndex = position559, tokenIndex559
-					if !_rules[ruleARMRegister]() {
-						goto l557
-					}
 				}
 			l559:
 				{
-					position592, tokenIndex592 := position, tokenIndex
+					position561, tokenIndex561 := position, tokenIndex
+					if buffer[position] != rune('a') {
+						goto l562
+					}
+					position++
+					goto l561
+				l562:
+					position, tokenIndex = position561, tokenIndex561
+					if buffer[position] != rune('A') {
+						goto l545
+					}
+					position++
+				}
+			l561:
+				add(ruleTOCRefHigh, position546)
+			}
+			return true
+		l545:
+			position, tokenIndex = position545, tokenIndex545
+			return false
+		},
+		/* 43 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */
+		func() bool {
+			position563, tokenIndex563 := position, tokenIndex
+			{
+				position564 := position
+				if buffer[position] != rune('.') {
+					goto l563
+				}
+				position++
+				if buffer[position] != rune('T') {
+					goto l563
+				}
+				position++
+				if buffer[position] != rune('O') {
+					goto l563
+				}
+				position++
+				if buffer[position] != rune('C') {
+					goto l563
+				}
+				position++
+				if buffer[position] != rune('.') {
+					goto l563
+				}
+				position++
+				if buffer[position] != rune('-') {
+					goto l563
+				}
+				position++
+				{
+					position565, tokenIndex565 := position, tokenIndex
+					if buffer[position] != rune('0') {
+						goto l566
+					}
+					position++
+					if buffer[position] != rune('b') {
+						goto l566
+					}
+					position++
+					goto l565
+				l566:
+					position, tokenIndex = position565, tokenIndex565
+					if buffer[position] != rune('.') {
+						goto l563
+					}
+					position++
+					if buffer[position] != rune('L') {
+						goto l563
+					}
+					position++
 					{
-						position593, tokenIndex593 := position, tokenIndex
-						if buffer[position] != rune('f') {
-							goto l594
+						position569, tokenIndex569 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l570
 						}
 						position++
-						goto l593
-					l594:
-						position, tokenIndex = position593, tokenIndex593
-						if buffer[position] != rune('b') {
-							goto l595
+						goto l569
+					l570:
+						position, tokenIndex = position569, tokenIndex569
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l571
 						}
 						position++
-						goto l593
-					l595:
-						position, tokenIndex = position593, tokenIndex593
-						if buffer[position] != rune(':') {
-							goto l596
+						goto l569
+					l571:
+						position, tokenIndex = position569, tokenIndex569
+						if buffer[position] != rune('_') {
+							goto l572
 						}
 						position++
-						goto l593
-					l596:
-						position, tokenIndex = position593, tokenIndex593
-						if buffer[position] != rune('(') {
-							goto l597
-						}
-						position++
-						goto l593
-					l597:
-						position, tokenIndex = position593, tokenIndex593
-						if buffer[position] != rune('+') {
-							goto l598
-						}
-						position++
-						goto l593
-					l598:
-						position, tokenIndex = position593, tokenIndex593
-						if buffer[position] != rune('-') {
-							goto l592
+						goto l569
+					l572:
+						position, tokenIndex = position569, tokenIndex569
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l563
 						}
 						position++
 					}
-				l593:
-					goto l557
-				l592:
-					position, tokenIndex = position592, tokenIndex592
+				l569:
+				l567:
+					{
+						position568, tokenIndex568 := position, tokenIndex
+						{
+							position573, tokenIndex573 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l574
+							}
+							position++
+							goto l573
+						l574:
+							position, tokenIndex = position573, tokenIndex573
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l575
+							}
+							position++
+							goto l573
+						l575:
+							position, tokenIndex = position573, tokenIndex573
+							if buffer[position] != rune('_') {
+								goto l576
+							}
+							position++
+							goto l573
+						l576:
+							position, tokenIndex = position573, tokenIndex573
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l568
+							}
+							position++
+						}
+					l573:
+						goto l567
+					l568:
+						position, tokenIndex = position568, tokenIndex568
+					}
 				}
-				add(ruleRegisterOrConstant, position558)
+			l565:
+				if buffer[position] != rune('@') {
+					goto l563
+				}
+				position++
+				{
+					position577, tokenIndex577 := position, tokenIndex
+					if buffer[position] != rune('l') {
+						goto l578
+					}
+					position++
+					goto l577
+				l578:
+					position, tokenIndex = position577, tokenIndex577
+					if buffer[position] != rune('L') {
+						goto l563
+					}
+					position++
+				}
+			l577:
+				add(ruleTOCRefLow, position564)
 			}
 			return true
-		l557:
-			position, tokenIndex = position557, tokenIndex557
+		l563:
+			position, tokenIndex = position563, tokenIndex563
 			return false
 		},
-		/* 45 ARMConstantTweak <- <((((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R'))) (WS '#' Offset)?) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' ('v' / 'V') ('l' / 'L')) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' '#' [0-9]))> */
+		/* 44 IndirectionIndicator <- <'*'> */
 		func() bool {
-			position599, tokenIndex599 := position, tokenIndex
+			position579, tokenIndex579 := position, tokenIndex
 			{
-				position600 := position
+				position580 := position
+				if buffer[position] != rune('*') {
+					goto l579
+				}
+				position++
+				add(ruleIndirectionIndicator, position580)
+			}
+			return true
+		l579:
+			position, tokenIndex = position579, tokenIndex579
+			return false
+		},
+		/* 45 Float <- <([0-9]+ '.' [0-9]*)> */
+		func() bool {
+			position581, tokenIndex581 := position, tokenIndex
+			{
+				position582 := position
+				if c := buffer[position]; c < rune('0') || c > rune('9') {
+					goto l581
+				}
+				position++
+			l583:
 				{
-					position601, tokenIndex601 := position, tokenIndex
+					position584, tokenIndex584 := position, tokenIndex
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l584
+					}
+					position++
+					goto l583
+				l584:
+					position, tokenIndex = position584, tokenIndex584
+				}
+				if buffer[position] != rune('.') {
+					goto l581
+				}
+				position++
+			l585:
+				{
+					position586, tokenIndex586 := position, tokenIndex
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l586
+					}
+					position++
+					goto l585
+				l586:
+					position, tokenIndex = position586, tokenIndex586
+				}
+				add(ruleFloat, position582)
+			}
+			return true
+		l581:
+			position, tokenIndex = position581, tokenIndex581
+			return false
+		},
+		/* 46 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Float) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */
+		func() bool {
+			position587, tokenIndex587 := position, tokenIndex
+			{
+				position588 := position
+				{
+					position589, tokenIndex589 := position, tokenIndex
+					if buffer[position] != rune('%') {
+						goto l590
+					}
+					position++
+					{
+						position591, tokenIndex591 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l592
+						}
+						position++
+						goto l591
+					l592:
+						position, tokenIndex = position591, tokenIndex591
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l590
+						}
+						position++
+					}
+				l591:
+				l593:
+					{
+						position594, tokenIndex594 := position, tokenIndex
+						{
+							position595, tokenIndex595 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l596
+							}
+							position++
+							goto l595
+						l596:
+							position, tokenIndex = position595, tokenIndex595
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l597
+							}
+							position++
+							goto l595
+						l597:
+							position, tokenIndex = position595, tokenIndex595
+							{
+								position598, tokenIndex598 := position, tokenIndex
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l599
+								}
+								position++
+								goto l598
+							l599:
+								position, tokenIndex = position598, tokenIndex598
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l594
+								}
+								position++
+							}
+						l598:
+						}
+					l595:
+						goto l593
+					l594:
+						position, tokenIndex = position594, tokenIndex594
+					}
+					goto l589
+				l590:
+					position, tokenIndex = position589, tokenIndex589
+					{
+						position601, tokenIndex601 := position, tokenIndex
+						if buffer[position] != rune('$') {
+							goto l601
+						}
+						position++
+						goto l602
+					l601:
+						position, tokenIndex = position601, tokenIndex601
+					}
+				l602:
 					{
 						position603, tokenIndex603 := position, tokenIndex
-						{
-							position605, tokenIndex605 := position, tokenIndex
-							if buffer[position] != rune('u') {
-								goto l606
-							}
-							position++
-							goto l605
-						l606:
-							position, tokenIndex = position605, tokenIndex605
-							if buffer[position] != rune('s') {
-								goto l604
-							}
-							position++
+						if !_rules[ruleOffset]() {
+							goto l604
 						}
-					l605:
-						{
-							position607, tokenIndex607 := position, tokenIndex
-							if buffer[position] != rune('x') {
-								goto l608
-							}
-							position++
+						if !_rules[ruleOffset]() {
+							goto l604
+						}
+						goto l603
+					l604:
+						position, tokenIndex = position603, tokenIndex603
+						if !_rules[ruleOffset]() {
+							goto l600
+						}
+					}
+				l603:
+					goto l589
+				l600:
+					position, tokenIndex = position589, tokenIndex589
+					if buffer[position] != rune('#') {
+						goto l605
+					}
+					position++
+					if !_rules[ruleFloat]() {
+						goto l605
+					}
+					goto l589
+				l605:
+					position, tokenIndex = position589, tokenIndex589
+					if buffer[position] != rune('#') {
+						goto l606
+					}
+					position++
+					if !_rules[ruleOffset]() {
+						goto l606
+					}
+					{
+						position607, tokenIndex607 := position, tokenIndex
+						if buffer[position] != rune('*') {
 							goto l607
-						l608:
-							position, tokenIndex = position607, tokenIndex607
-							if buffer[position] != rune('X') {
-								goto l604
-							}
-							position++
 						}
-					l607:
+						position++
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l607
+						}
+						position++
+					l609:
 						{
-							position609, tokenIndex609 := position, tokenIndex
-							if buffer[position] != rune('t') {
+							position610, tokenIndex610 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
 								goto l610
 							}
 							position++
 							goto l609
 						l610:
-							position, tokenIndex = position609, tokenIndex609
-							if buffer[position] != rune('T') {
-								goto l604
-							}
-							position++
+							position, tokenIndex = position610, tokenIndex610
 						}
-					l609:
 						{
 							position611, tokenIndex611 := position, tokenIndex
-							if buffer[position] != rune('x') {
-								goto l612
+							if buffer[position] != rune('-') {
+								goto l611
 							}
 							position++
-							goto l611
-						l612:
-							position, tokenIndex = position611, tokenIndex611
-							if buffer[position] != rune('w') {
-								goto l613
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l611
 							}
 							position++
-							goto l611
 						l613:
+							{
+								position614, tokenIndex614 := position, tokenIndex
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l614
+								}
+								position++
+								goto l613
+							l614:
+								position, tokenIndex = position614, tokenIndex614
+							}
+							goto l612
+						l611:
 							position, tokenIndex = position611, tokenIndex611
-							if buffer[position] != rune('h') {
-								goto l614
-							}
-							position++
-							goto l611
-						l614:
-							position, tokenIndex = position611, tokenIndex611
-							if buffer[position] != rune('b') {
-								goto l604
-							}
-							position++
 						}
-					l611:
-						goto l603
-					l604:
-						position, tokenIndex = position603, tokenIndex603
-						{
-							position616, tokenIndex616 := position, tokenIndex
-							if buffer[position] != rune('l') {
-								goto l617
-							}
-							position++
-							goto l616
-						l617:
-							position, tokenIndex = position616, tokenIndex616
-							if buffer[position] != rune('L') {
-								goto l615
-							}
-							position++
-						}
-					l616:
-						{
-							position618, tokenIndex618 := position, tokenIndex
-							if buffer[position] != rune('s') {
-								goto l619
-							}
-							position++
-							goto l618
-						l619:
-							position, tokenIndex = position618, tokenIndex618
-							if buffer[position] != rune('S') {
-								goto l615
-							}
-							position++
-						}
-					l618:
-						{
-							position620, tokenIndex620 := position, tokenIndex
-							if buffer[position] != rune('l') {
-								goto l621
-							}
-							position++
-							goto l620
-						l621:
-							position, tokenIndex = position620, tokenIndex620
-							if buffer[position] != rune('L') {
-								goto l615
-							}
-							position++
-						}
-					l620:
-						goto l603
-					l615:
-						position, tokenIndex = position603, tokenIndex603
-						{
-							position623, tokenIndex623 := position, tokenIndex
-							if buffer[position] != rune('l') {
-								goto l624
-							}
-							position++
-							goto l623
-						l624:
-							position, tokenIndex = position623, tokenIndex623
-							if buffer[position] != rune('L') {
-								goto l622
-							}
-							position++
-						}
-					l623:
-						{
-							position625, tokenIndex625 := position, tokenIndex
-							if buffer[position] != rune('s') {
-								goto l626
-							}
-							position++
-							goto l625
-						l626:
-							position, tokenIndex = position625, tokenIndex625
-							if buffer[position] != rune('S') {
-								goto l622
-							}
-							position++
-						}
-					l625:
-						{
-							position627, tokenIndex627 := position, tokenIndex
-							if buffer[position] != rune('r') {
-								goto l628
-							}
-							position++
-							goto l627
-						l628:
-							position, tokenIndex = position627, tokenIndex627
-							if buffer[position] != rune('R') {
-								goto l622
-							}
-							position++
-						}
-					l627:
-						goto l603
-					l622:
-						position, tokenIndex = position603, tokenIndex603
-						{
-							position630, tokenIndex630 := position, tokenIndex
-							if buffer[position] != rune('r') {
-								goto l631
-							}
-							position++
-							goto l630
-						l631:
-							position, tokenIndex = position630, tokenIndex630
-							if buffer[position] != rune('R') {
-								goto l629
-							}
-							position++
-						}
-					l630:
-						{
-							position632, tokenIndex632 := position, tokenIndex
-							if buffer[position] != rune('o') {
-								goto l633
-							}
-							position++
-							goto l632
-						l633:
-							position, tokenIndex = position632, tokenIndex632
-							if buffer[position] != rune('O') {
-								goto l629
-							}
-							position++
-						}
-					l632:
-						{
-							position634, tokenIndex634 := position, tokenIndex
-							if buffer[position] != rune('r') {
-								goto l635
-							}
-							position++
-							goto l634
-						l635:
-							position, tokenIndex = position634, tokenIndex634
-							if buffer[position] != rune('R') {
-								goto l629
-							}
-							position++
-						}
-					l634:
-						goto l603
-					l629:
-						position, tokenIndex = position603, tokenIndex603
-						{
-							position636, tokenIndex636 := position, tokenIndex
-							if buffer[position] != rune('a') {
-								goto l637
-							}
-							position++
-							goto l636
-						l637:
-							position, tokenIndex = position636, tokenIndex636
-							if buffer[position] != rune('A') {
-								goto l602
-							}
-							position++
-						}
-					l636:
-						{
-							position638, tokenIndex638 := position, tokenIndex
-							if buffer[position] != rune('s') {
-								goto l639
-							}
-							position++
-							goto l638
-						l639:
-							position, tokenIndex = position638, tokenIndex638
-							if buffer[position] != rune('S') {
-								goto l602
-							}
-							position++
-						}
-					l638:
-						{
-							position640, tokenIndex640 := position, tokenIndex
-							if buffer[position] != rune('r') {
-								goto l641
-							}
-							position++
-							goto l640
-						l641:
-							position, tokenIndex = position640, tokenIndex640
-							if buffer[position] != rune('R') {
-								goto l602
-							}
-							position++
-						}
-					l640:
+					l612:
+						goto l608
+					l607:
+						position, tokenIndex = position607, tokenIndex607
 					}
-				l603:
-					{
-						position642, tokenIndex642 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l642
-						}
-						if buffer[position] != rune('#') {
-							goto l642
-						}
-						position++
-						if !_rules[ruleOffset]() {
-							goto l642
-						}
-						goto l643
-					l642:
-						position, tokenIndex = position642, tokenIndex642
-					}
-				l643:
-					goto l601
-				l602:
-					position, tokenIndex = position601, tokenIndex601
-					{
-						position645, tokenIndex645 := position, tokenIndex
-						if buffer[position] != rune('m') {
-							goto l646
-						}
-						position++
-						goto l645
-					l646:
-						position, tokenIndex = position645, tokenIndex645
-						if buffer[position] != rune('M') {
-							goto l644
-						}
-						position++
-					}
-				l645:
-					{
-						position647, tokenIndex647 := position, tokenIndex
-						if buffer[position] != rune('u') {
-							goto l648
-						}
-						position++
-						goto l647
-					l648:
-						position, tokenIndex = position647, tokenIndex647
-						if buffer[position] != rune('U') {
-							goto l644
-						}
-						position++
-					}
-				l647:
-					{
-						position649, tokenIndex649 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l650
-						}
-						position++
-						goto l649
-					l650:
-						position, tokenIndex = position649, tokenIndex649
-						if buffer[position] != rune('L') {
-							goto l644
-						}
-						position++
-					}
-				l649:
-					if buffer[position] != rune(' ') {
-						goto l644
-					}
-					position++
-					{
-						position651, tokenIndex651 := position, tokenIndex
-						if buffer[position] != rune('v') {
-							goto l652
-						}
-						position++
-						goto l651
-					l652:
-						position, tokenIndex = position651, tokenIndex651
-						if buffer[position] != rune('V') {
-							goto l644
-						}
-						position++
-					}
-				l651:
-					{
-						position653, tokenIndex653 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l654
-						}
-						position++
-						goto l653
-					l654:
-						position, tokenIndex = position653, tokenIndex653
-						if buffer[position] != rune('L') {
-							goto l644
-						}
-						position++
-					}
-				l653:
-					goto l601
-				l644:
-					position, tokenIndex = position601, tokenIndex601
-					{
-						position655, tokenIndex655 := position, tokenIndex
-						if buffer[position] != rune('m') {
-							goto l656
-						}
-						position++
-						goto l655
-					l656:
-						position, tokenIndex = position655, tokenIndex655
-						if buffer[position] != rune('M') {
-							goto l599
-						}
-						position++
-					}
-				l655:
-					{
-						position657, tokenIndex657 := position, tokenIndex
-						if buffer[position] != rune('u') {
-							goto l658
-						}
-						position++
-						goto l657
-					l658:
-						position, tokenIndex = position657, tokenIndex657
-						if buffer[position] != rune('U') {
-							goto l599
-						}
-						position++
-					}
-				l657:
-					{
-						position659, tokenIndex659 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l660
-						}
-						position++
-						goto l659
-					l660:
-						position, tokenIndex = position659, tokenIndex659
-						if buffer[position] != rune('L') {
-							goto l599
-						}
-						position++
-					}
-				l659:
-					if buffer[position] != rune(' ') {
-						goto l599
-					}
-					position++
+				l608:
+					goto l589
+				l606:
+					position, tokenIndex = position589, tokenIndex589
 					if buffer[position] != rune('#') {
-						goto l599
+						goto l615
+					}
+					position++
+					{
+						position616, tokenIndex616 := position, tokenIndex
+						if buffer[position] != rune('~') {
+							goto l616
+						}
+						position++
+						goto l617
+					l616:
+						position, tokenIndex = position616, tokenIndex616
+					}
+				l617:
+					if buffer[position] != rune('(') {
+						goto l615
 					}
 					position++
 					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l599
+						goto l615
 					}
 					position++
+					{
+						position618, tokenIndex618 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l618
+						}
+						goto l619
+					l618:
+						position, tokenIndex = position618, tokenIndex618
+					}
+				l619:
+					if buffer[position] != rune('<') {
+						goto l615
+					}
+					position++
+					if buffer[position] != rune('<') {
+						goto l615
+					}
+					position++
+					{
+						position620, tokenIndex620 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l620
+						}
+						goto l621
+					l620:
+						position, tokenIndex = position620, tokenIndex620
+					}
+				l621:
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l615
+					}
+					position++
+					if buffer[position] != rune(')') {
+						goto l615
+					}
+					position++
+					goto l589
+				l615:
+					position, tokenIndex = position589, tokenIndex589
+					if !_rules[ruleARMRegister]() {
+						goto l587
+					}
 				}
-			l601:
-				add(ruleARMConstantTweak, position600)
+			l589:
+				{
+					position622, tokenIndex622 := position, tokenIndex
+					{
+						position623, tokenIndex623 := position, tokenIndex
+						if buffer[position] != rune('f') {
+							goto l624
+						}
+						position++
+						goto l623
+					l624:
+						position, tokenIndex = position623, tokenIndex623
+						if buffer[position] != rune('b') {
+							goto l625
+						}
+						position++
+						goto l623
+					l625:
+						position, tokenIndex = position623, tokenIndex623
+						if buffer[position] != rune(':') {
+							goto l626
+						}
+						position++
+						goto l623
+					l626:
+						position, tokenIndex = position623, tokenIndex623
+						if buffer[position] != rune('(') {
+							goto l627
+						}
+						position++
+						goto l623
+					l627:
+						position, tokenIndex = position623, tokenIndex623
+						if buffer[position] != rune('+') {
+							goto l628
+						}
+						position++
+						goto l623
+					l628:
+						position, tokenIndex = position623, tokenIndex623
+						if buffer[position] != rune('-') {
+							goto l622
+						}
+						position++
+					}
+				l623:
+					goto l587
+				l622:
+					position, tokenIndex = position622, tokenIndex622
+				}
+				add(ruleRegisterOrConstant, position588)
 			}
 			return true
-		l599:
-			position, tokenIndex = position599, tokenIndex599
+		l587:
+			position, tokenIndex = position587, tokenIndex587
 			return false
 		},
-		/* 46 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / SVE2PredicateRegister / ARMVectorRegister / SVE2SpecialValue / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */
+		/* 47 ARMConstantTweak <- <((((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R')) / (('m' / 'M') ('s' / 'S') ('l' / 'L'))) (WS '#' Offset)?) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' ('v' / 'V') ('l' / 'L')) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' '#' [0-9]))> */
 		func() bool {
-			position661, tokenIndex661 := position, tokenIndex
+			position629, tokenIndex629 := position, tokenIndex
 			{
-				position662 := position
+				position630 := position
 				{
-					position663, tokenIndex663 := position, tokenIndex
+					position631, tokenIndex631 := position, tokenIndex
 					{
-						position665, tokenIndex665 := position, tokenIndex
-						if buffer[position] != rune('s') {
-							goto l666
+						position633, tokenIndex633 := position, tokenIndex
+						{
+							position635, tokenIndex635 := position, tokenIndex
+							if buffer[position] != rune('u') {
+								goto l636
+							}
+							position++
+							goto l635
+						l636:
+							position, tokenIndex = position635, tokenIndex635
+							if buffer[position] != rune('s') {
+								goto l634
+							}
+							position++
 						}
-						position++
-						goto l665
-					l666:
-						position, tokenIndex = position665, tokenIndex665
-						if buffer[position] != rune('S') {
+					l635:
+						{
+							position637, tokenIndex637 := position, tokenIndex
+							if buffer[position] != rune('x') {
+								goto l638
+							}
+							position++
+							goto l637
+						l638:
+							position, tokenIndex = position637, tokenIndex637
+							if buffer[position] != rune('X') {
+								goto l634
+							}
+							position++
+						}
+					l637:
+						{
+							position639, tokenIndex639 := position, tokenIndex
+							if buffer[position] != rune('t') {
+								goto l640
+							}
+							position++
+							goto l639
+						l640:
+							position, tokenIndex = position639, tokenIndex639
+							if buffer[position] != rune('T') {
+								goto l634
+							}
+							position++
+						}
+					l639:
+						{
+							position641, tokenIndex641 := position, tokenIndex
+							if buffer[position] != rune('x') {
+								goto l642
+							}
+							position++
+							goto l641
+						l642:
+							position, tokenIndex = position641, tokenIndex641
+							if buffer[position] != rune('w') {
+								goto l643
+							}
+							position++
+							goto l641
+						l643:
+							position, tokenIndex = position641, tokenIndex641
+							if buffer[position] != rune('h') {
+								goto l644
+							}
+							position++
+							goto l641
+						l644:
+							position, tokenIndex = position641, tokenIndex641
+							if buffer[position] != rune('b') {
+								goto l634
+							}
+							position++
+						}
+					l641:
+						goto l633
+					l634:
+						position, tokenIndex = position633, tokenIndex633
+						{
+							position646, tokenIndex646 := position, tokenIndex
+							if buffer[position] != rune('l') {
+								goto l647
+							}
+							position++
+							goto l646
+						l647:
+							position, tokenIndex = position646, tokenIndex646
+							if buffer[position] != rune('L') {
+								goto l645
+							}
+							position++
+						}
+					l646:
+						{
+							position648, tokenIndex648 := position, tokenIndex
+							if buffer[position] != rune('s') {
+								goto l649
+							}
+							position++
+							goto l648
+						l649:
+							position, tokenIndex = position648, tokenIndex648
+							if buffer[position] != rune('S') {
+								goto l645
+							}
+							position++
+						}
+					l648:
+						{
+							position650, tokenIndex650 := position, tokenIndex
+							if buffer[position] != rune('l') {
+								goto l651
+							}
+							position++
+							goto l650
+						l651:
+							position, tokenIndex = position650, tokenIndex650
+							if buffer[position] != rune('L') {
+								goto l645
+							}
+							position++
+						}
+					l650:
+						goto l633
+					l645:
+						position, tokenIndex = position633, tokenIndex633
+						{
+							position653, tokenIndex653 := position, tokenIndex
+							if buffer[position] != rune('l') {
+								goto l654
+							}
+							position++
+							goto l653
+						l654:
+							position, tokenIndex = position653, tokenIndex653
+							if buffer[position] != rune('L') {
+								goto l652
+							}
+							position++
+						}
+					l653:
+						{
+							position655, tokenIndex655 := position, tokenIndex
+							if buffer[position] != rune('s') {
+								goto l656
+							}
+							position++
+							goto l655
+						l656:
+							position, tokenIndex = position655, tokenIndex655
+							if buffer[position] != rune('S') {
+								goto l652
+							}
+							position++
+						}
+					l655:
+						{
+							position657, tokenIndex657 := position, tokenIndex
+							if buffer[position] != rune('r') {
+								goto l658
+							}
+							position++
+							goto l657
+						l658:
+							position, tokenIndex = position657, tokenIndex657
+							if buffer[position] != rune('R') {
+								goto l652
+							}
+							position++
+						}
+					l657:
+						goto l633
+					l652:
+						position, tokenIndex = position633, tokenIndex633
+						{
+							position660, tokenIndex660 := position, tokenIndex
+							if buffer[position] != rune('r') {
+								goto l661
+							}
+							position++
+							goto l660
+						l661:
+							position, tokenIndex = position660, tokenIndex660
+							if buffer[position] != rune('R') {
+								goto l659
+							}
+							position++
+						}
+					l660:
+						{
+							position662, tokenIndex662 := position, tokenIndex
+							if buffer[position] != rune('o') {
+								goto l663
+							}
+							position++
+							goto l662
+						l663:
+							position, tokenIndex = position662, tokenIndex662
+							if buffer[position] != rune('O') {
+								goto l659
+							}
+							position++
+						}
+					l662:
+						{
+							position664, tokenIndex664 := position, tokenIndex
+							if buffer[position] != rune('r') {
+								goto l665
+							}
+							position++
 							goto l664
+						l665:
+							position, tokenIndex = position664, tokenIndex664
+							if buffer[position] != rune('R') {
+								goto l659
+							}
+							position++
 						}
-						position++
-					}
-				l665:
-					{
-						position667, tokenIndex667 := position, tokenIndex
-						if buffer[position] != rune('p') {
-							goto l668
+					l664:
+						goto l633
+					l659:
+						position, tokenIndex = position633, tokenIndex633
+						{
+							position667, tokenIndex667 := position, tokenIndex
+							if buffer[position] != rune('a') {
+								goto l668
+							}
+							position++
+							goto l667
+						l668:
+							position, tokenIndex = position667, tokenIndex667
+							if buffer[position] != rune('A') {
+								goto l666
+							}
+							position++
 						}
-						position++
-						goto l667
-					l668:
-						position, tokenIndex = position667, tokenIndex667
-						if buffer[position] != rune('P') {
-							goto l664
-						}
-						position++
-					}
-				l667:
-					goto l663
-				l664:
-					position, tokenIndex = position663, tokenIndex663
-					{
-						position670, tokenIndex670 := position, tokenIndex
-						if buffer[position] != rune('x') {
-							goto l671
-						}
-						position++
-						goto l670
-					l671:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('w') {
-							goto l672
-						}
-						position++
-						goto l670
-					l672:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('d') {
-							goto l673
-						}
-						position++
-						goto l670
-					l673:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('q') {
-							goto l674
-						}
-						position++
-						goto l670
-					l674:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('s') {
-							goto l675
-						}
-						position++
-						goto l670
-					l675:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('h') {
-							goto l676
-						}
-						position++
-						goto l670
-					l676:
-						position, tokenIndex = position670, tokenIndex670
-						if buffer[position] != rune('b') {
+					l667:
+						{
+							position669, tokenIndex669 := position, tokenIndex
+							if buffer[position] != rune('s') {
+								goto l670
+							}
+							position++
 							goto l669
+						l670:
+							position, tokenIndex = position669, tokenIndex669
+							if buffer[position] != rune('S') {
+								goto l666
+							}
+							position++
 						}
-						position++
-					}
-				l670:
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l669
-					}
-					position++
-					{
-						position677, tokenIndex677 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
+					l669:
+						{
+							position671, tokenIndex671 := position, tokenIndex
+							if buffer[position] != rune('r') {
+								goto l672
+							}
+							position++
+							goto l671
+						l672:
+							position, tokenIndex = position671, tokenIndex671
+							if buffer[position] != rune('R') {
+								goto l666
+							}
+							position++
+						}
+					l671:
+						goto l633
+					l666:
+						position, tokenIndex = position633, tokenIndex633
+						{
+							position673, tokenIndex673 := position, tokenIndex
+							if buffer[position] != rune('m') {
+								goto l674
+							}
+							position++
+							goto l673
+						l674:
+							position, tokenIndex = position673, tokenIndex673
+							if buffer[position] != rune('M') {
+								goto l632
+							}
+							position++
+						}
+					l673:
+						{
+							position675, tokenIndex675 := position, tokenIndex
+							if buffer[position] != rune('s') {
+								goto l676
+							}
+							position++
+							goto l675
+						l676:
+							position, tokenIndex = position675, tokenIndex675
+							if buffer[position] != rune('S') {
+								goto l632
+							}
+							position++
+						}
+					l675:
+						{
+							position677, tokenIndex677 := position, tokenIndex
+							if buffer[position] != rune('l') {
+								goto l678
+							}
+							position++
 							goto l677
+						l678:
+							position, tokenIndex = position677, tokenIndex677
+							if buffer[position] != rune('L') {
+								goto l632
+							}
+							position++
 						}
-						position++
-						goto l678
 					l677:
-						position, tokenIndex = position677, tokenIndex677
 					}
-				l678:
-					goto l663
-				l669:
-					position, tokenIndex = position663, tokenIndex663
+				l633:
 					{
-						position680, tokenIndex680 := position, tokenIndex
-						if buffer[position] != rune('x') {
-							goto l681
+						position679, tokenIndex679 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l679
 						}
-						position++
-						goto l680
-					l681:
-						position, tokenIndex = position680, tokenIndex680
-						if buffer[position] != rune('X') {
+						if buffer[position] != rune('#') {
 							goto l679
 						}
 						position++
+						if !_rules[ruleOffset]() {
+							goto l679
+						}
+						goto l680
+					l679:
+						position, tokenIndex = position679, tokenIndex679
 					}
 				l680:
+					goto l631
+				l632:
+					position, tokenIndex = position631, tokenIndex631
 					{
 						position682, tokenIndex682 := position, tokenIndex
-						if buffer[position] != rune('z') {
+						if buffer[position] != rune('m') {
 							goto l683
 						}
 						position++
 						goto l682
 					l683:
 						position, tokenIndex = position682, tokenIndex682
-						if buffer[position] != rune('Z') {
-							goto l679
+						if buffer[position] != rune('M') {
+							goto l681
 						}
 						position++
 					}
 				l682:
 					{
 						position684, tokenIndex684 := position, tokenIndex
-						if buffer[position] != rune('r') {
+						if buffer[position] != rune('u') {
 							goto l685
 						}
 						position++
 						goto l684
 					l685:
 						position, tokenIndex = position684, tokenIndex684
-						if buffer[position] != rune('R') {
-							goto l679
+						if buffer[position] != rune('U') {
+							goto l681
 						}
 						position++
 					}
 				l684:
-					goto l663
-				l679:
-					position, tokenIndex = position663, tokenIndex663
 					{
-						position687, tokenIndex687 := position, tokenIndex
-						if buffer[position] != rune('w') {
-							goto l688
+						position686, tokenIndex686 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l687
 						}
 						position++
-						goto l687
-					l688:
-						position, tokenIndex = position687, tokenIndex687
-						if buffer[position] != rune('W') {
-							goto l686
+						goto l686
+					l687:
+						position, tokenIndex = position686, tokenIndex686
+						if buffer[position] != rune('L') {
+							goto l681
 						}
 						position++
 					}
-				l687:
-					{
-						position689, tokenIndex689 := position, tokenIndex
-						if buffer[position] != rune('z') {
-							goto l690
-						}
-						position++
-						goto l689
-					l690:
-						position, tokenIndex = position689, tokenIndex689
-						if buffer[position] != rune('Z') {
-							goto l686
-						}
-						position++
-					}
-				l689:
-					{
-						position691, tokenIndex691 := position, tokenIndex
-						if buffer[position] != rune('r') {
-							goto l692
-						}
-						position++
-						goto l691
-					l692:
-						position, tokenIndex = position691, tokenIndex691
-						if buffer[position] != rune('R') {
-							goto l686
-						}
-						position++
-					}
-				l691:
-					goto l663
 				l686:
-					position, tokenIndex = position663, tokenIndex663
+					if buffer[position] != rune(' ') {
+						goto l681
+					}
+					position++
+					{
+						position688, tokenIndex688 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l689
+						}
+						position++
+						goto l688
+					l689:
+						position, tokenIndex = position688, tokenIndex688
+						if buffer[position] != rune('V') {
+							goto l681
+						}
+						position++
+					}
+				l688:
+					{
+						position690, tokenIndex690 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l691
+						}
+						position++
+						goto l690
+					l691:
+						position, tokenIndex = position690, tokenIndex690
+						if buffer[position] != rune('L') {
+							goto l681
+						}
+						position++
+					}
+				l690:
+					goto l631
+				l681:
+					position, tokenIndex = position631, tokenIndex631
+					{
+						position692, tokenIndex692 := position, tokenIndex
+						if buffer[position] != rune('m') {
+							goto l693
+						}
+						position++
+						goto l692
+					l693:
+						position, tokenIndex = position692, tokenIndex692
+						if buffer[position] != rune('M') {
+							goto l629
+						}
+						position++
+					}
+				l692:
 					{
 						position694, tokenIndex694 := position, tokenIndex
-						if buffer[position] != rune('n') {
+						if buffer[position] != rune('u') {
 							goto l695
 						}
 						position++
 						goto l694
 					l695:
 						position, tokenIndex = position694, tokenIndex694
-						if buffer[position] != rune('N') {
-							goto l693
+						if buffer[position] != rune('U') {
+							goto l629
 						}
 						position++
 					}
 				l694:
 					{
 						position696, tokenIndex696 := position, tokenIndex
-						if buffer[position] != rune('z') {
+						if buffer[position] != rune('l') {
 							goto l697
 						}
 						position++
 						goto l696
 					l697:
 						position, tokenIndex = position696, tokenIndex696
-						if buffer[position] != rune('Z') {
-							goto l693
+						if buffer[position] != rune('L') {
+							goto l629
 						}
 						position++
 					}
 				l696:
-					{
-						position698, tokenIndex698 := position, tokenIndex
-						if buffer[position] != rune('c') {
-							goto l699
-						}
-						position++
-						goto l698
-					l699:
-						position, tokenIndex = position698, tokenIndex698
-						if buffer[position] != rune('C') {
-							goto l693
-						}
-						position++
+					if buffer[position] != rune(' ') {
+						goto l629
 					}
-				l698:
+					position++
+					if buffer[position] != rune('#') {
+						goto l629
+					}
+					position++
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l629
+					}
+					position++
+				}
+			l631:
+				add(ruleARMConstantTweak, position630)
+			}
+			return true
+		l629:
+			position, tokenIndex = position629, tokenIndex629
+			return false
+		},
+		/* 48 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / SVE2PredicateRegister / ARMVectorRegister / SVE2SpecialValue / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */
+		func() bool {
+			position698, tokenIndex698 := position, tokenIndex
+			{
+				position699 := position
+				{
+					position700, tokenIndex700 := position, tokenIndex
 					{
-						position700, tokenIndex700 := position, tokenIndex
-						if buffer[position] != rune('v') {
+						position702, tokenIndex702 := position, tokenIndex
+						if buffer[position] != rune('s') {
+							goto l703
+						}
+						position++
+						goto l702
+					l703:
+						position, tokenIndex = position702, tokenIndex702
+						if buffer[position] != rune('S') {
 							goto l701
 						}
 						position++
-						goto l700
-					l701:
-						position, tokenIndex = position700, tokenIndex700
-						if buffer[position] != rune('V') {
-							goto l693
-						}
-						position++
 					}
-				l700:
-					goto l663
-				l693:
-					position, tokenIndex = position663, tokenIndex663
-					if !_rules[ruleSVE2PredicateRegister]() {
-						goto l702
-					}
-					goto l663
 				l702:
-					position, tokenIndex = position663, tokenIndex663
-					if !_rules[ruleARMVectorRegister]() {
-						goto l703
-					}
-					goto l663
-				l703:
-					position, tokenIndex = position663, tokenIndex663
-					if !_rules[ruleSVE2SpecialValue]() {
-						goto l704
-					}
-					goto l663
-				l704:
-					position, tokenIndex = position663, tokenIndex663
-					if buffer[position] != rune('{') {
-						goto l661
-					}
-					position++
 					{
-						position705, tokenIndex705 := position, tokenIndex
-						if !_rules[ruleWS]() {
+						position704, tokenIndex704 := position, tokenIndex
+						if buffer[position] != rune('p') {
 							goto l705
 						}
-						goto l706
+						position++
+						goto l704
 					l705:
-						position, tokenIndex = position705, tokenIndex705
+						position, tokenIndex = position704, tokenIndex704
+						if buffer[position] != rune('P') {
+							goto l701
+						}
+						position++
 					}
-				l706:
-					if !_rules[ruleARMVectorRegister]() {
-						goto l661
-					}
-				l707:
+				l704:
+					goto l700
+				l701:
+					position, tokenIndex = position700, tokenIndex700
 					{
-						position708, tokenIndex708 := position, tokenIndex
-						if buffer[position] != rune(',') {
+						position707, tokenIndex707 := position, tokenIndex
+						if buffer[position] != rune('x') {
 							goto l708
 						}
 						position++
-						{
-							position709, tokenIndex709 := position, tokenIndex
-							if !_rules[ruleWS]() {
-								goto l709
-							}
-							goto l710
-						l709:
-							position, tokenIndex = position709, tokenIndex709
-						}
-					l710:
-						if !_rules[ruleARMVectorRegister]() {
-							goto l708
-						}
 						goto l707
 					l708:
-						position, tokenIndex = position708, tokenIndex708
-					}
-					{
-						position711, tokenIndex711 := position, tokenIndex
-						if !_rules[ruleWS]() {
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('w') {
+							goto l709
+						}
+						position++
+						goto l707
+					l709:
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('d') {
+							goto l710
+						}
+						position++
+						goto l707
+					l710:
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('q') {
 							goto l711
 						}
-						goto l712
+						position++
+						goto l707
 					l711:
-						position, tokenIndex = position711, tokenIndex711
-					}
-				l712:
-					if buffer[position] != rune('}') {
-						goto l661
-					}
-					position++
-					{
-						position713, tokenIndex713 := position, tokenIndex
-						if buffer[position] != rune('[') {
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('s') {
+							goto l712
+						}
+						position++
+						goto l707
+					l712:
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('h') {
 							goto l713
 						}
 						position++
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l713
-						}
-						position++
-						{
-							position715, tokenIndex715 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l715
-							}
-							position++
-							goto l716
-						l715:
-							position, tokenIndex = position715, tokenIndex715
-						}
-					l716:
-						if buffer[position] != rune(']') {
-							goto l713
-						}
-						position++
-						goto l714
+						goto l707
 					l713:
-						position, tokenIndex = position713, tokenIndex713
-					}
-				l714:
-				}
-			l663:
-				add(ruleARMRegister, position662)
-			}
-			return true
-		l661:
-			position, tokenIndex = position661, tokenIndex661
-			return false
-		},
-		/* 47 ARMVectorRegister <- <(('p' / 'v' / 'z') [0-9] [0-9]? !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_') ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */
-		func() bool {
-			position717, tokenIndex717 := position, tokenIndex
-			{
-				position718 := position
-				{
-					position719, tokenIndex719 := position, tokenIndex
-					if buffer[position] != rune('p') {
-						goto l720
-					}
-					position++
-					goto l719
-				l720:
-					position, tokenIndex = position719, tokenIndex719
-					if buffer[position] != rune('v') {
-						goto l721
-					}
-					position++
-					goto l719
-				l721:
-					position, tokenIndex = position719, tokenIndex719
-					if buffer[position] != rune('z') {
-						goto l717
-					}
-					position++
-				}
-			l719:
-				if c := buffer[position]; c < rune('0') || c > rune('9') {
-					goto l717
-				}
-				position++
-				{
-					position722, tokenIndex722 := position, tokenIndex
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l722
-					}
-					position++
-					goto l723
-				l722:
-					position, tokenIndex = position722, tokenIndex722
-				}
-			l723:
-				{
-					position724, tokenIndex724 := position, tokenIndex
-					{
-						position725, tokenIndex725 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l726
+						position, tokenIndex = position707, tokenIndex707
+						if buffer[position] != rune('b') {
+							goto l706
 						}
 						position++
-						goto l725
-					l726:
-						position, tokenIndex = position725, tokenIndex725
+					}
+				l707:
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l706
+					}
+					position++
+					{
+						position714, tokenIndex714 := position, tokenIndex
 						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l714
+						}
+						position++
+						goto l715
+					l714:
+						position, tokenIndex = position714, tokenIndex714
+					}
+				l715:
+					goto l700
+				l706:
+					position, tokenIndex = position700, tokenIndex700
+					{
+						position717, tokenIndex717 := position, tokenIndex
+						if buffer[position] != rune('x') {
+							goto l718
+						}
+						position++
+						goto l717
+					l718:
+						position, tokenIndex = position717, tokenIndex717
+						if buffer[position] != rune('X') {
+							goto l716
+						}
+						position++
+					}
+				l717:
+					{
+						position719, tokenIndex719 := position, tokenIndex
+						if buffer[position] != rune('z') {
+							goto l720
+						}
+						position++
+						goto l719
+					l720:
+						position, tokenIndex = position719, tokenIndex719
+						if buffer[position] != rune('Z') {
+							goto l716
+						}
+						position++
+					}
+				l719:
+					{
+						position721, tokenIndex721 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l722
+						}
+						position++
+						goto l721
+					l722:
+						position, tokenIndex = position721, tokenIndex721
+						if buffer[position] != rune('R') {
+							goto l716
+						}
+						position++
+					}
+				l721:
+					goto l700
+				l716:
+					position, tokenIndex = position700, tokenIndex700
+					{
+						position724, tokenIndex724 := position, tokenIndex
+						if buffer[position] != rune('w') {
+							goto l725
+						}
+						position++
+						goto l724
+					l725:
+						position, tokenIndex = position724, tokenIndex724
+						if buffer[position] != rune('W') {
+							goto l723
+						}
+						position++
+					}
+				l724:
+					{
+						position726, tokenIndex726 := position, tokenIndex
+						if buffer[position] != rune('z') {
 							goto l727
 						}
 						position++
-						goto l725
+						goto l726
 					l727:
-						position, tokenIndex = position725, tokenIndex725
-						{
-							position729, tokenIndex729 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l730
-							}
-							position++
-							goto l729
-						l730:
-							position, tokenIndex = position729, tokenIndex729
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l728
-							}
-							position++
-						}
-					l729:
-						goto l725
-					l728:
-						position, tokenIndex = position725, tokenIndex725
-						if buffer[position] != rune('_') {
-							goto l724
+						position, tokenIndex = position726, tokenIndex726
+						if buffer[position] != rune('Z') {
+							goto l723
 						}
 						position++
 					}
-				l725:
-					goto l717
-				l724:
-					position, tokenIndex = position724, tokenIndex724
-				}
-				{
-					position731, tokenIndex731 := position, tokenIndex
-					if buffer[position] != rune('.') {
-						goto l731
-					}
-					position++
-				l733:
+				l726:
 					{
-						position734, tokenIndex734 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
+						position728, tokenIndex728 := position, tokenIndex
+						if buffer[position] != rune('r') {
+							goto l729
+						}
+						position++
+						goto l728
+					l729:
+						position, tokenIndex = position728, tokenIndex728
+						if buffer[position] != rune('R') {
+							goto l723
+						}
+						position++
+					}
+				l728:
+					goto l700
+				l723:
+					position, tokenIndex = position700, tokenIndex700
+					{
+						position731, tokenIndex731 := position, tokenIndex
+						if buffer[position] != rune('n') {
+							goto l732
+						}
+						position++
+						goto l731
+					l732:
+						position, tokenIndex = position731, tokenIndex731
+						if buffer[position] != rune('N') {
+							goto l730
+						}
+						position++
+					}
+				l731:
+					{
+						position733, tokenIndex733 := position, tokenIndex
+						if buffer[position] != rune('z') {
 							goto l734
 						}
 						position++
 						goto l733
 					l734:
-						position, tokenIndex = position734, tokenIndex734
+						position, tokenIndex = position733, tokenIndex733
+						if buffer[position] != rune('Z') {
+							goto l730
+						}
+						position++
 					}
+				l733:
 					{
 						position735, tokenIndex735 := position, tokenIndex
-						if buffer[position] != rune('b') {
+						if buffer[position] != rune('c') {
 							goto l736
 						}
 						position++
 						goto l735
 					l736:
 						position, tokenIndex = position735, tokenIndex735
-						if buffer[position] != rune('s') {
-							goto l737
-						}
-						position++
-						goto l735
-					l737:
-						position, tokenIndex = position735, tokenIndex735
-						if buffer[position] != rune('d') {
-							goto l738
-						}
-						position++
-						goto l735
-					l738:
-						position, tokenIndex = position735, tokenIndex735
-						if buffer[position] != rune('h') {
-							goto l739
-						}
-						position++
-						goto l735
-					l739:
-						position, tokenIndex = position735, tokenIndex735
-						if buffer[position] != rune('q') {
-							goto l731
+						if buffer[position] != rune('C') {
+							goto l730
 						}
 						position++
 					}
 				l735:
 					{
-						position740, tokenIndex740 := position, tokenIndex
-						if buffer[position] != rune('[') {
-							goto l740
+						position737, tokenIndex737 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l738
 						}
 						position++
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l740
+						goto l737
+					l738:
+						position, tokenIndex = position737, tokenIndex737
+						if buffer[position] != rune('V') {
+							goto l730
+						}
+						position++
+					}
+				l737:
+					goto l700
+				l730:
+					position, tokenIndex = position700, tokenIndex700
+					if !_rules[ruleSVE2PredicateRegister]() {
+						goto l739
+					}
+					goto l700
+				l739:
+					position, tokenIndex = position700, tokenIndex700
+					if !_rules[ruleARMVectorRegister]() {
+						goto l740
+					}
+					goto l700
+				l740:
+					position, tokenIndex = position700, tokenIndex700
+					if !_rules[ruleSVE2SpecialValue]() {
+						goto l741
+					}
+					goto l700
+				l741:
+					position, tokenIndex = position700, tokenIndex700
+					if buffer[position] != rune('{') {
+						goto l698
+					}
+					position++
+					{
+						position742, tokenIndex742 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l742
+						}
+						goto l743
+					l742:
+						position, tokenIndex = position742, tokenIndex742
+					}
+				l743:
+					if !_rules[ruleARMVectorRegister]() {
+						goto l698
+					}
+				l744:
+					{
+						position745, tokenIndex745 := position, tokenIndex
+						if buffer[position] != rune(',') {
+							goto l745
 						}
 						position++
 						{
-							position742, tokenIndex742 := position, tokenIndex
+							position746, tokenIndex746 := position, tokenIndex
+							if !_rules[ruleWS]() {
+								goto l746
+							}
+							goto l747
+						l746:
+							position, tokenIndex = position746, tokenIndex746
+						}
+					l747:
+						if !_rules[ruleARMVectorRegister]() {
+							goto l745
+						}
+						goto l744
+					l745:
+						position, tokenIndex = position745, tokenIndex745
+					}
+					{
+						position748, tokenIndex748 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l748
+						}
+						goto l749
+					l748:
+						position, tokenIndex = position748, tokenIndex748
+					}
+				l749:
+					if buffer[position] != rune('}') {
+						goto l698
+					}
+					position++
+					{
+						position750, tokenIndex750 := position, tokenIndex
+						if buffer[position] != rune('[') {
+							goto l750
+						}
+						position++
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l750
+						}
+						position++
+						{
+							position752, tokenIndex752 := position, tokenIndex
 							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l742
+								goto l752
 							}
 							position++
-							goto l743
-						l742:
-							position, tokenIndex = position742, tokenIndex742
+							goto l753
+						l752:
+							position, tokenIndex = position752, tokenIndex752
 						}
-					l743:
+					l753:
 						if buffer[position] != rune(']') {
-							goto l740
+							goto l750
 						}
 						position++
-						goto l741
-					l740:
-						position, tokenIndex = position740, tokenIndex740
-					}
-				l741:
-					goto l732
-				l731:
-					position, tokenIndex = position731, tokenIndex731
-				}
-			l732:
-				add(ruleARMVectorRegister, position718)
-			}
-			return true
-		l717:
-			position, tokenIndex = position717, tokenIndex717
-			return false
-		},
-		/* 48 SVE2PredicateRegister <- <(('p' / 'P') [0-9] [0-9]? '/' ('m' / 'M' / ('z' / 'Z')))> */
-		func() bool {
-			position744, tokenIndex744 := position, tokenIndex
-			{
-				position745 := position
-				{
-					position746, tokenIndex746 := position, tokenIndex
-					if buffer[position] != rune('p') {
-						goto l747
-					}
-					position++
-					goto l746
-				l747:
-					position, tokenIndex = position746, tokenIndex746
-					if buffer[position] != rune('P') {
-						goto l744
-					}
-					position++
-				}
-			l746:
-				if c := buffer[position]; c < rune('0') || c > rune('9') {
-					goto l744
-				}
-				position++
-				{
-					position748, tokenIndex748 := position, tokenIndex
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l748
-					}
-					position++
-					goto l749
-				l748:
-					position, tokenIndex = position748, tokenIndex748
-				}
-			l749:
-				if buffer[position] != rune('/') {
-					goto l744
-				}
-				position++
-				{
-					position750, tokenIndex750 := position, tokenIndex
-					if buffer[position] != rune('m') {
 						goto l751
+					l750:
+						position, tokenIndex = position750, tokenIndex750
 					}
-					position++
-					goto l750
 				l751:
-					position, tokenIndex = position750, tokenIndex750
-					if buffer[position] != rune('M') {
-						goto l752
-					}
-					position++
-					goto l750
-				l752:
-					position, tokenIndex = position750, tokenIndex750
-					{
-						position753, tokenIndex753 := position, tokenIndex
-						if buffer[position] != rune('z') {
-							goto l754
-						}
-						position++
-						goto l753
-					l754:
-						position, tokenIndex = position753, tokenIndex753
-						if buffer[position] != rune('Z') {
-							goto l744
-						}
-						position++
-					}
-				l753:
 				}
-			l750:
-				add(ruleSVE2PredicateRegister, position745)
+			l700:
+				add(ruleARMRegister, position699)
 			}
 			return true
-		l744:
-			position, tokenIndex = position744, tokenIndex744
+		l698:
+			position, tokenIndex = position698, tokenIndex698
 			return false
 		},
-		/* 49 SVE2SpecialValue <- <(((('p' / 'P') ('o' / 'O') ('w' / 'W') '2') / (('v' / 'V') ('l' / 'L') ('1' / '2' / '3' / '4' / '5' / '6' / '7' / '8') ![0-9]) / (('v' / 'V') ('l' / 'L') '1' '6') / (('v' / 'V') ('l' / 'L') '3' '2') / (('v' / 'V') ('l' / 'L') '6' '4') / (('v' / 'V') ('l' / 'L') '1' '2' '8') / (('v' / 'V') ('l' / 'L') '2' '5' '6') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '3') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '4') / (('a' / 'A') ('l' / 'L') ('l' / 'L'))) !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_'))> */
+		/* 49 ARMVectorRegister <- <(('p' / 'v' / 'z') [0-9] [0-9]? !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_') ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */
 		func() bool {
-			position755, tokenIndex755 := position, tokenIndex
+			position754, tokenIndex754 := position, tokenIndex
 			{
-				position756 := position
+				position755 := position
 				{
-					position757, tokenIndex757 := position, tokenIndex
-					{
-						position759, tokenIndex759 := position, tokenIndex
-						if buffer[position] != rune('p') {
-							goto l760
-						}
-						position++
-						goto l759
-					l760:
-						position, tokenIndex = position759, tokenIndex759
-						if buffer[position] != rune('P') {
-							goto l758
-						}
-						position++
+					position756, tokenIndex756 := position, tokenIndex
+					if buffer[position] != rune('p') {
+						goto l757
 					}
-				l759:
-					{
-						position761, tokenIndex761 := position, tokenIndex
-						if buffer[position] != rune('o') {
-							goto l762
-						}
-						position++
-						goto l761
-					l762:
-						position, tokenIndex = position761, tokenIndex761
-						if buffer[position] != rune('O') {
-							goto l758
-						}
-						position++
-					}
-				l761:
-					{
-						position763, tokenIndex763 := position, tokenIndex
-						if buffer[position] != rune('w') {
-							goto l764
-						}
-						position++
-						goto l763
-					l764:
-						position, tokenIndex = position763, tokenIndex763
-						if buffer[position] != rune('W') {
-							goto l758
-						}
-						position++
-					}
-				l763:
-					if buffer[position] != rune('2') {
+					position++
+					goto l756
+				l757:
+					position, tokenIndex = position756, tokenIndex756
+					if buffer[position] != rune('v') {
 						goto l758
 					}
 					position++
-					goto l757
+					goto l756
 				l758:
-					position, tokenIndex = position757, tokenIndex757
+					position, tokenIndex = position756, tokenIndex756
+					if buffer[position] != rune('z') {
+						goto l754
+					}
+					position++
+				}
+			l756:
+				if c := buffer[position]; c < rune('0') || c > rune('9') {
+					goto l754
+				}
+				position++
+				{
+					position759, tokenIndex759 := position, tokenIndex
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l759
+					}
+					position++
+					goto l760
+				l759:
+					position, tokenIndex = position759, tokenIndex759
+				}
+			l760:
+				{
+					position761, tokenIndex761 := position, tokenIndex
 					{
-						position766, tokenIndex766 := position, tokenIndex
-						if buffer[position] != rune('v') {
-							goto l767
+						position762, tokenIndex762 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l763
 						}
 						position++
-						goto l766
-					l767:
-						position, tokenIndex = position766, tokenIndex766
-						if buffer[position] != rune('V') {
-							goto l765
+						goto l762
+					l763:
+						position, tokenIndex = position762, tokenIndex762
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l764
+						}
+						position++
+						goto l762
+					l764:
+						position, tokenIndex = position762, tokenIndex762
+						{
+							position766, tokenIndex766 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l767
+							}
+							position++
+							goto l766
+						l767:
+							position, tokenIndex = position766, tokenIndex766
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l765
+							}
+							position++
+						}
+					l766:
+						goto l762
+					l765:
+						position, tokenIndex = position762, tokenIndex762
+						if buffer[position] != rune('_') {
+							goto l761
 						}
 						position++
 					}
-				l766:
-					{
-						position768, tokenIndex768 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l769
-						}
-						position++
+				l762:
+					goto l754
+				l761:
+					position, tokenIndex = position761, tokenIndex761
+				}
+				{
+					position768, tokenIndex768 := position, tokenIndex
+					if buffer[position] != rune('.') {
 						goto l768
-					l769:
-						position, tokenIndex = position768, tokenIndex768
-						if buffer[position] != rune('L') {
-							goto l765
-						}
-						position++
 					}
-				l768:
+					position++
+				l770:
 					{
-						position770, tokenIndex770 := position, tokenIndex
-						if buffer[position] != rune('1') {
+						position771, tokenIndex771 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
 							goto l771
 						}
 						position++
 						goto l770
 					l771:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('2') {
-							goto l772
-						}
-						position++
-						goto l770
-					l772:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('3') {
+						position, tokenIndex = position771, tokenIndex771
+					}
+					{
+						position772, tokenIndex772 := position, tokenIndex
+						if buffer[position] != rune('b') {
 							goto l773
 						}
 						position++
-						goto l770
+						goto l772
 					l773:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('4') {
+						position, tokenIndex = position772, tokenIndex772
+						if buffer[position] != rune('s') {
 							goto l774
 						}
 						position++
-						goto l770
+						goto l772
 					l774:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('5') {
+						position, tokenIndex = position772, tokenIndex772
+						if buffer[position] != rune('d') {
 							goto l775
 						}
 						position++
-						goto l770
+						goto l772
 					l775:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('6') {
+						position, tokenIndex = position772, tokenIndex772
+						if buffer[position] != rune('h') {
 							goto l776
 						}
 						position++
-						goto l770
+						goto l772
 					l776:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('7') {
+						position, tokenIndex = position772, tokenIndex772
+						if buffer[position] != rune('q') {
+							goto l768
+						}
+						position++
+					}
+				l772:
+					{
+						position777, tokenIndex777 := position, tokenIndex
+						if buffer[position] != rune('[') {
 							goto l777
 						}
 						position++
-						goto l770
-					l777:
-						position, tokenIndex = position770, tokenIndex770
-						if buffer[position] != rune('8') {
-							goto l765
-						}
-						position++
-					}
-				l770:
-					{
-						position778, tokenIndex778 := position, tokenIndex
 						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l778
+							goto l777
 						}
 						position++
-						goto l765
-					l778:
-						position, tokenIndex = position778, tokenIndex778
+						{
+							position779, tokenIndex779 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l779
+							}
+							position++
+							goto l780
+						l779:
+							position, tokenIndex = position779, tokenIndex779
+						}
+					l780:
+						if buffer[position] != rune(']') {
+							goto l777
+						}
+						position++
+						goto l778
+					l777:
+						position, tokenIndex = position777, tokenIndex777
 					}
-					goto l757
-				l765:
-					position, tokenIndex = position757, tokenIndex757
-					{
-						position780, tokenIndex780 := position, tokenIndex
-						if buffer[position] != rune('v') {
-							goto l781
-						}
-						position++
-						goto l780
-					l781:
-						position, tokenIndex = position780, tokenIndex780
-						if buffer[position] != rune('V') {
-							goto l779
-						}
-						position++
-					}
-				l780:
-					{
-						position782, tokenIndex782 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l783
-						}
-						position++
-						goto l782
-					l783:
-						position, tokenIndex = position782, tokenIndex782
-						if buffer[position] != rune('L') {
-							goto l779
-						}
-						position++
-					}
-				l782:
-					if buffer[position] != rune('1') {
-						goto l779
-					}
-					position++
-					if buffer[position] != rune('6') {
-						goto l779
-					}
-					position++
-					goto l757
-				l779:
-					position, tokenIndex = position757, tokenIndex757
-					{
-						position785, tokenIndex785 := position, tokenIndex
-						if buffer[position] != rune('v') {
-							goto l786
-						}
-						position++
-						goto l785
-					l786:
-						position, tokenIndex = position785, tokenIndex785
-						if buffer[position] != rune('V') {
-							goto l784
-						}
-						position++
-					}
-				l785:
-					{
-						position787, tokenIndex787 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l788
-						}
-						position++
-						goto l787
-					l788:
-						position, tokenIndex = position787, tokenIndex787
-						if buffer[position] != rune('L') {
-							goto l784
-						}
-						position++
-					}
-				l787:
-					if buffer[position] != rune('3') {
+				l778:
+					goto l769
+				l768:
+					position, tokenIndex = position768, tokenIndex768
+				}
+			l769:
+				add(ruleARMVectorRegister, position755)
+			}
+			return true
+		l754:
+			position, tokenIndex = position754, tokenIndex754
+			return false
+		},
+		/* 50 SVE2PredicateRegister <- <(('p' / 'P') [0-9] [0-9]? '/' ('m' / 'M' / ('z' / 'Z')))> */
+		func() bool {
+			position781, tokenIndex781 := position, tokenIndex
+			{
+				position782 := position
+				{
+					position783, tokenIndex783 := position, tokenIndex
+					if buffer[position] != rune('p') {
 						goto l784
 					}
 					position++
-					if buffer[position] != rune('2') {
-						goto l784
-					}
-					position++
-					goto l757
+					goto l783
 				l784:
-					position, tokenIndex = position757, tokenIndex757
+					position, tokenIndex = position783, tokenIndex783
+					if buffer[position] != rune('P') {
+						goto l781
+					}
+					position++
+				}
+			l783:
+				if c := buffer[position]; c < rune('0') || c > rune('9') {
+					goto l781
+				}
+				position++
+				{
+					position785, tokenIndex785 := position, tokenIndex
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l785
+					}
+					position++
+					goto l786
+				l785:
+					position, tokenIndex = position785, tokenIndex785
+				}
+			l786:
+				if buffer[position] != rune('/') {
+					goto l781
+				}
+				position++
+				{
+					position787, tokenIndex787 := position, tokenIndex
+					if buffer[position] != rune('m') {
+						goto l788
+					}
+					position++
+					goto l787
+				l788:
+					position, tokenIndex = position787, tokenIndex787
+					if buffer[position] != rune('M') {
+						goto l789
+					}
+					position++
+					goto l787
+				l789:
+					position, tokenIndex = position787, tokenIndex787
 					{
 						position790, tokenIndex790 := position, tokenIndex
-						if buffer[position] != rune('v') {
+						if buffer[position] != rune('z') {
 							goto l791
 						}
 						position++
 						goto l790
 					l791:
 						position, tokenIndex = position790, tokenIndex790
-						if buffer[position] != rune('V') {
-							goto l789
+						if buffer[position] != rune('Z') {
+							goto l781
 						}
 						position++
 					}
 				l790:
+				}
+			l787:
+				add(ruleSVE2PredicateRegister, position782)
+			}
+			return true
+		l781:
+			position, tokenIndex = position781, tokenIndex781
+			return false
+		},
+		/* 51 SVE2SpecialValue <- <(((('p' / 'P') ('o' / 'O') ('w' / 'W') '2') / (('v' / 'V') ('l' / 'L') ('1' / '2' / '3' / '4' / '5' / '6' / '7' / '8') ![0-9]) / (('v' / 'V') ('l' / 'L') '1' '6') / (('v' / 'V') ('l' / 'L') '3' '2') / (('v' / 'V') ('l' / 'L') '6' '4') / (('v' / 'V') ('l' / 'L') '1' '2' '8') / (('v' / 'V') ('l' / 'L') '2' '5' '6') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '3') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '4') / (('a' / 'A') ('l' / 'L') ('l' / 'L'))) !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_'))> */
+		func() bool {
+			position792, tokenIndex792 := position, tokenIndex
+			{
+				position793 := position
+				{
+					position794, tokenIndex794 := position, tokenIndex
 					{
-						position792, tokenIndex792 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l793
+						position796, tokenIndex796 := position, tokenIndex
+						if buffer[position] != rune('p') {
+							goto l797
 						}
 						position++
-						goto l792
-					l793:
-						position, tokenIndex = position792, tokenIndex792
-						if buffer[position] != rune('L') {
-							goto l789
+						goto l796
+					l797:
+						position, tokenIndex = position796, tokenIndex796
+						if buffer[position] != rune('P') {
+							goto l795
 						}
 						position++
 					}
-				l792:
-					if buffer[position] != rune('6') {
-						goto l789
-					}
-					position++
-					if buffer[position] != rune('4') {
-						goto l789
-					}
-					position++
-					goto l757
-				l789:
-					position, tokenIndex = position757, tokenIndex757
+				l796:
 					{
-						position795, tokenIndex795 := position, tokenIndex
-						if buffer[position] != rune('v') {
-							goto l796
+						position798, tokenIndex798 := position, tokenIndex
+						if buffer[position] != rune('o') {
+							goto l799
 						}
 						position++
-						goto l795
-					l796:
-						position, tokenIndex = position795, tokenIndex795
-						if buffer[position] != rune('V') {
-							goto l794
+						goto l798
+					l799:
+						position, tokenIndex = position798, tokenIndex798
+						if buffer[position] != rune('O') {
+							goto l795
 						}
 						position++
 					}
-				l795:
-					{
-						position797, tokenIndex797 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l798
-						}
-						position++
-						goto l797
-					l798:
-						position, tokenIndex = position797, tokenIndex797
-						if buffer[position] != rune('L') {
-							goto l794
-						}
-						position++
-					}
-				l797:
-					if buffer[position] != rune('1') {
-						goto l794
-					}
-					position++
-					if buffer[position] != rune('2') {
-						goto l794
-					}
-					position++
-					if buffer[position] != rune('8') {
-						goto l794
-					}
-					position++
-					goto l757
-				l794:
-					position, tokenIndex = position757, tokenIndex757
+				l798:
 					{
 						position800, tokenIndex800 := position, tokenIndex
-						if buffer[position] != rune('v') {
+						if buffer[position] != rune('w') {
 							goto l801
 						}
 						position++
 						goto l800
 					l801:
 						position, tokenIndex = position800, tokenIndex800
-						if buffer[position] != rune('V') {
-							goto l799
+						if buffer[position] != rune('W') {
+							goto l795
 						}
 						position++
 					}
 				l800:
-					{
-						position802, tokenIndex802 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l803
-						}
-						position++
-						goto l802
-					l803:
-						position, tokenIndex = position802, tokenIndex802
-						if buffer[position] != rune('L') {
-							goto l799
-						}
-						position++
-					}
-				l802:
 					if buffer[position] != rune('2') {
-						goto l799
+						goto l795
 					}
 					position++
-					if buffer[position] != rune('5') {
-						goto l799
+					goto l794
+				l795:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position803, tokenIndex803 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l804
+						}
+						position++
+						goto l803
+					l804:
+						position, tokenIndex = position803, tokenIndex803
+						if buffer[position] != rune('V') {
+							goto l802
+						}
+						position++
 					}
-					position++
-					if buffer[position] != rune('6') {
-						goto l799
-					}
-					position++
-					goto l757
-				l799:
-					position, tokenIndex = position757, tokenIndex757
+				l803:
 					{
 						position805, tokenIndex805 := position, tokenIndex
-						if buffer[position] != rune('m') {
+						if buffer[position] != rune('l') {
 							goto l806
 						}
 						position++
 						goto l805
 					l806:
 						position, tokenIndex = position805, tokenIndex805
-						if buffer[position] != rune('M') {
-							goto l804
+						if buffer[position] != rune('L') {
+							goto l802
 						}
 						position++
 					}
 				l805:
 					{
 						position807, tokenIndex807 := position, tokenIndex
-						if buffer[position] != rune('u') {
+						if buffer[position] != rune('1') {
 							goto l808
 						}
 						position++
 						goto l807
 					l808:
 						position, tokenIndex = position807, tokenIndex807
-						if buffer[position] != rune('U') {
-							goto l804
+						if buffer[position] != rune('2') {
+							goto l809
+						}
+						position++
+						goto l807
+					l809:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('3') {
+							goto l810
+						}
+						position++
+						goto l807
+					l810:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('4') {
+							goto l811
+						}
+						position++
+						goto l807
+					l811:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('5') {
+							goto l812
+						}
+						position++
+						goto l807
+					l812:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('6') {
+							goto l813
+						}
+						position++
+						goto l807
+					l813:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('7') {
+							goto l814
+						}
+						position++
+						goto l807
+					l814:
+						position, tokenIndex = position807, tokenIndex807
+						if buffer[position] != rune('8') {
+							goto l802
 						}
 						position++
 					}
 				l807:
 					{
-						position809, tokenIndex809 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l810
-						}
-						position++
-						goto l809
-					l810:
-						position, tokenIndex = position809, tokenIndex809
-						if buffer[position] != rune('L') {
-							goto l804
-						}
-						position++
-					}
-				l809:
-					if buffer[position] != rune('3') {
-						goto l804
-					}
-					position++
-					goto l757
-				l804:
-					position, tokenIndex = position757, tokenIndex757
-					{
-						position812, tokenIndex812 := position, tokenIndex
-						if buffer[position] != rune('m') {
-							goto l813
-						}
-						position++
-						goto l812
-					l813:
-						position, tokenIndex = position812, tokenIndex812
-						if buffer[position] != rune('M') {
-							goto l811
-						}
-						position++
-					}
-				l812:
-					{
-						position814, tokenIndex814 := position, tokenIndex
-						if buffer[position] != rune('u') {
+						position815, tokenIndex815 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
 							goto l815
 						}
 						position++
-						goto l814
+						goto l802
 					l815:
-						position, tokenIndex = position814, tokenIndex814
-						if buffer[position] != rune('U') {
-							goto l811
-						}
-						position++
+						position, tokenIndex = position815, tokenIndex815
 					}
-				l814:
+					goto l794
+				l802:
+					position, tokenIndex = position794, tokenIndex794
 					{
-						position816, tokenIndex816 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l817
+						position817, tokenIndex817 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l818
 						}
 						position++
-						goto l816
-					l817:
-						position, tokenIndex = position816, tokenIndex816
-						if buffer[position] != rune('L') {
-							goto l811
+						goto l817
+					l818:
+						position, tokenIndex = position817, tokenIndex817
+						if buffer[position] != rune('V') {
+							goto l816
 						}
 						position++
 					}
-				l816:
-					if buffer[position] != rune('4') {
-						goto l811
+				l817:
+					{
+						position819, tokenIndex819 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l820
+						}
+						position++
+						goto l819
+					l820:
+						position, tokenIndex = position819, tokenIndex819
+						if buffer[position] != rune('L') {
+							goto l816
+						}
+						position++
+					}
+				l819:
+					if buffer[position] != rune('1') {
+						goto l816
 					}
 					position++
-					goto l757
-				l811:
-					position, tokenIndex = position757, tokenIndex757
-					{
-						position818, tokenIndex818 := position, tokenIndex
-						if buffer[position] != rune('a') {
-							goto l819
-						}
-						position++
-						goto l818
-					l819:
-						position, tokenIndex = position818, tokenIndex818
-						if buffer[position] != rune('A') {
-							goto l755
-						}
-						position++
+					if buffer[position] != rune('6') {
+						goto l816
 					}
-				l818:
-					{
-						position820, tokenIndex820 := position, tokenIndex
-						if buffer[position] != rune('l') {
-							goto l821
-						}
-						position++
-						goto l820
-					l821:
-						position, tokenIndex = position820, tokenIndex820
-						if buffer[position] != rune('L') {
-							goto l755
-						}
-						position++
-					}
-				l820:
+					position++
+					goto l794
+				l816:
+					position, tokenIndex = position794, tokenIndex794
 					{
 						position822, tokenIndex822 := position, tokenIndex
-						if buffer[position] != rune('l') {
+						if buffer[position] != rune('v') {
 							goto l823
 						}
 						position++
 						goto l822
 					l823:
 						position, tokenIndex = position822, tokenIndex822
-						if buffer[position] != rune('L') {
-							goto l755
+						if buffer[position] != rune('V') {
+							goto l821
 						}
 						position++
 					}
 				l822:
-				}
-			l757:
-				{
-					position824, tokenIndex824 := position, tokenIndex
 					{
-						position825, tokenIndex825 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
+						position824, tokenIndex824 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l825
+						}
+						position++
+						goto l824
+					l825:
+						position, tokenIndex = position824, tokenIndex824
+						if buffer[position] != rune('L') {
+							goto l821
+						}
+						position++
+					}
+				l824:
+					if buffer[position] != rune('3') {
+						goto l821
+					}
+					position++
+					if buffer[position] != rune('2') {
+						goto l821
+					}
+					position++
+					goto l794
+				l821:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position827, tokenIndex827 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l828
+						}
+						position++
+						goto l827
+					l828:
+						position, tokenIndex = position827, tokenIndex827
+						if buffer[position] != rune('V') {
 							goto l826
 						}
 						position++
-						goto l825
-					l826:
-						position, tokenIndex = position825, tokenIndex825
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l827
-						}
-						position++
-						goto l825
-					l827:
-						position, tokenIndex = position825, tokenIndex825
-						{
-							position829, tokenIndex829 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('z') {
-								goto l830
-							}
-							position++
-							goto l829
-						l830:
-							position, tokenIndex = position829, tokenIndex829
-							if c := buffer[position]; c < rune('A') || c > rune('Z') {
-								goto l828
-							}
-							position++
-						}
-					l829:
-						goto l825
-					l828:
-						position, tokenIndex = position825, tokenIndex825
-						if buffer[position] != rune('_') {
-							goto l824
-						}
-						position++
 					}
-				l825:
-					goto l755
-				l824:
-					position, tokenIndex = position824, tokenIndex824
-				}
-				add(ruleSVE2SpecialValue, position756)
-			}
-			return true
-		l755:
-			position, tokenIndex = position755, tokenIndex755
-			return false
-		},
-		/* 50 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */
-		func() bool {
-			position831, tokenIndex831 := position, tokenIndex
-			{
-				position832 := position
-				{
-					position833, tokenIndex833 := position, tokenIndex
-					if !_rules[ruleSymbolRef]() {
-						goto l834
-					}
-					if !_rules[ruleBaseIndexScale]() {
-						goto l834
-					}
-					goto l833
-				l834:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleSymbolRef]() {
-						goto l835
-					}
-					goto l833
-				l835:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleLow12BitsSymbolRef]() {
-						goto l836
-					}
-					goto l833
-				l836:
-					position, tokenIndex = position833, tokenIndex833
-				l838:
+				l827:
 					{
-						position839, tokenIndex839 := position, tokenIndex
-						if !_rules[ruleOffset]() {
-							goto l839
+						position829, tokenIndex829 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l830
 						}
-						goto l838
-					l839:
-						position, tokenIndex = position839, tokenIndex839
+						position++
+						goto l829
+					l830:
+						position, tokenIndex = position829, tokenIndex829
+						if buffer[position] != rune('L') {
+							goto l826
+						}
+						position++
 					}
-					if !_rules[ruleBaseIndexScale]() {
-						goto l837
+				l829:
+					if buffer[position] != rune('6') {
+						goto l826
 					}
-					goto l833
-				l837:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleSegmentRegister]() {
-						goto l840
+					position++
+					if buffer[position] != rune('4') {
+						goto l826
 					}
-					if !_rules[ruleOffset]() {
-						goto l840
+					position++
+					goto l794
+				l826:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position832, tokenIndex832 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l833
+						}
+						position++
+						goto l832
+					l833:
+						position, tokenIndex = position832, tokenIndex832
+						if buffer[position] != rune('V') {
+							goto l831
+						}
+						position++
 					}
-					if !_rules[ruleBaseIndexScale]() {
-						goto l840
+				l832:
+					{
+						position834, tokenIndex834 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l835
+						}
+						position++
+						goto l834
+					l835:
+						position, tokenIndex = position834, tokenIndex834
+						if buffer[position] != rune('L') {
+							goto l831
+						}
+						position++
 					}
-					goto l833
-				l840:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleSegmentRegister]() {
-						goto l841
-					}
-					if !_rules[ruleBaseIndexScale]() {
-						goto l841
-					}
-					goto l833
-				l841:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleSegmentRegister]() {
-						goto l842
-					}
-					if !_rules[ruleOffset]() {
-						goto l842
-					}
-					goto l833
-				l842:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleARMBaseIndexScale]() {
-						goto l843
-					}
-					goto l833
-				l843:
-					position, tokenIndex = position833, tokenIndex833
-					if !_rules[ruleBaseIndexScale]() {
+				l834:
+					if buffer[position] != rune('1') {
 						goto l831
 					}
-				}
-			l833:
-				add(ruleMemoryRef, position832)
-			}
-			return true
-		l831:
-			position, tokenIndex = position831, tokenIndex831
-			return false
-		},
-		/* 51 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */
-		func() bool {
-			position844, tokenIndex844 := position, tokenIndex
-			{
-				position845 := position
-				{
-					position846, tokenIndex846 := position, tokenIndex
-				l848:
+					position++
+					if buffer[position] != rune('2') {
+						goto l831
+					}
+					position++
+					if buffer[position] != rune('8') {
+						goto l831
+					}
+					position++
+					goto l794
+				l831:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position837, tokenIndex837 := position, tokenIndex
+						if buffer[position] != rune('v') {
+							goto l838
+						}
+						position++
+						goto l837
+					l838:
+						position, tokenIndex = position837, tokenIndex837
+						if buffer[position] != rune('V') {
+							goto l836
+						}
+						position++
+					}
+				l837:
+					{
+						position839, tokenIndex839 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l840
+						}
+						position++
+						goto l839
+					l840:
+						position, tokenIndex = position839, tokenIndex839
+						if buffer[position] != rune('L') {
+							goto l836
+						}
+						position++
+					}
+				l839:
+					if buffer[position] != rune('2') {
+						goto l836
+					}
+					position++
+					if buffer[position] != rune('5') {
+						goto l836
+					}
+					position++
+					if buffer[position] != rune('6') {
+						goto l836
+					}
+					position++
+					goto l794
+				l836:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position842, tokenIndex842 := position, tokenIndex
+						if buffer[position] != rune('m') {
+							goto l843
+						}
+						position++
+						goto l842
+					l843:
+						position, tokenIndex = position842, tokenIndex842
+						if buffer[position] != rune('M') {
+							goto l841
+						}
+						position++
+					}
+				l842:
+					{
+						position844, tokenIndex844 := position, tokenIndex
+						if buffer[position] != rune('u') {
+							goto l845
+						}
+						position++
+						goto l844
+					l845:
+						position, tokenIndex = position844, tokenIndex844
+						if buffer[position] != rune('U') {
+							goto l841
+						}
+						position++
+					}
+				l844:
+					{
+						position846, tokenIndex846 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l847
+						}
+						position++
+						goto l846
+					l847:
+						position, tokenIndex = position846, tokenIndex846
+						if buffer[position] != rune('L') {
+							goto l841
+						}
+						position++
+					}
+				l846:
+					if buffer[position] != rune('3') {
+						goto l841
+					}
+					position++
+					goto l794
+				l841:
+					position, tokenIndex = position794, tokenIndex794
 					{
 						position849, tokenIndex849 := position, tokenIndex
-						if !_rules[ruleOffset]() {
-							goto l849
+						if buffer[position] != rune('m') {
+							goto l850
 						}
-						goto l848
-					l849:
+						position++
+						goto l849
+					l850:
 						position, tokenIndex = position849, tokenIndex849
+						if buffer[position] != rune('M') {
+							goto l848
+						}
+						position++
 					}
-					if buffer[position] != rune('+') {
-						goto l846
-					}
-					position++
-					goto l847
-				l846:
-					position, tokenIndex = position846, tokenIndex846
-				}
-			l847:
-				{
-					position850, tokenIndex850 := position, tokenIndex
-					if !_rules[ruleLocalSymbol]() {
+				l849:
+					{
+						position851, tokenIndex851 := position, tokenIndex
+						if buffer[position] != rune('u') {
+							goto l852
+						}
+						position++
 						goto l851
+					l852:
+						position, tokenIndex = position851, tokenIndex851
+						if buffer[position] != rune('U') {
+							goto l848
+						}
+						position++
 					}
-					goto l850
 				l851:
-					position, tokenIndex = position850, tokenIndex850
-					if !_rules[ruleSymbolName]() {
-						goto l844
-					}
-				}
-			l850:
-			l852:
-				{
-					position853, tokenIndex853 := position, tokenIndex
-					if !_rules[ruleOffset]() {
+					{
+						position853, tokenIndex853 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l854
+						}
+						position++
 						goto l853
+					l854:
+						position, tokenIndex = position853, tokenIndex853
+						if buffer[position] != rune('L') {
+							goto l848
+						}
+						position++
 					}
-					goto l852
 				l853:
-					position, tokenIndex = position853, tokenIndex853
-				}
-				{
-					position854, tokenIndex854 := position, tokenIndex
-					if buffer[position] != rune('@') {
-						goto l854
+					if buffer[position] != rune('4') {
+						goto l848
 					}
 					position++
-					if !_rules[ruleSection]() {
-						goto l854
+					goto l794
+				l848:
+					position, tokenIndex = position794, tokenIndex794
+					{
+						position855, tokenIndex855 := position, tokenIndex
+						if buffer[position] != rune('a') {
+							goto l856
+						}
+						position++
+						goto l855
+					l856:
+						position, tokenIndex = position855, tokenIndex855
+						if buffer[position] != rune('A') {
+							goto l792
+						}
+						position++
 					}
-				l856:
+				l855:
 					{
 						position857, tokenIndex857 := position, tokenIndex
-						if !_rules[ruleOffset]() {
-							goto l857
+						if buffer[position] != rune('l') {
+							goto l858
 						}
-						goto l856
-					l857:
+						position++
+						goto l857
+					l858:
 						position, tokenIndex = position857, tokenIndex857
+						if buffer[position] != rune('L') {
+							goto l792
+						}
+						position++
 					}
-					goto l855
-				l854:
-					position, tokenIndex = position854, tokenIndex854
+				l857:
+					{
+						position859, tokenIndex859 := position, tokenIndex
+						if buffer[position] != rune('l') {
+							goto l860
+						}
+						position++
+						goto l859
+					l860:
+						position, tokenIndex = position859, tokenIndex859
+						if buffer[position] != rune('L') {
+							goto l792
+						}
+						position++
+					}
+				l859:
 				}
-			l855:
-				add(ruleSymbolRef, position845)
-			}
-			return true
-		l844:
-			position, tokenIndex = position844, tokenIndex844
-			return false
-		},
-		/* 52 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */
-		func() bool {
-			position858, tokenIndex858 := position, tokenIndex
-			{
-				position859 := position
-				if buffer[position] != rune(':') {
-					goto l858
-				}
-				position++
+			l794:
 				{
-					position860, tokenIndex860 := position, tokenIndex
-					if buffer[position] != rune('l') {
-						goto l861
+					position861, tokenIndex861 := position, tokenIndex
+					{
+						position862, tokenIndex862 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l863
+						}
+						position++
+						goto l862
+					l863:
+						position, tokenIndex = position862, tokenIndex862
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l864
+						}
+						position++
+						goto l862
+					l864:
+						position, tokenIndex = position862, tokenIndex862
+						{
+							position866, tokenIndex866 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('z') {
+								goto l867
+							}
+							position++
+							goto l866
+						l867:
+							position, tokenIndex = position866, tokenIndex866
+							if c := buffer[position]; c < rune('A') || c > rune('Z') {
+								goto l865
+							}
+							position++
+						}
+					l866:
+						goto l862
+					l865:
+						position, tokenIndex = position862, tokenIndex862
+						if buffer[position] != rune('_') {
+							goto l861
+						}
+						position++
 					}
-					position++
-					goto l860
+				l862:
+					goto l792
 				l861:
-					position, tokenIndex = position860, tokenIndex860
-					if buffer[position] != rune('L') {
-						goto l858
-					}
-					position++
+					position, tokenIndex = position861, tokenIndex861
 				}
-			l860:
-				{
-					position862, tokenIndex862 := position, tokenIndex
-					if buffer[position] != rune('o') {
-						goto l863
-					}
-					position++
-					goto l862
-				l863:
-					position, tokenIndex = position862, tokenIndex862
-					if buffer[position] != rune('O') {
-						goto l858
-					}
-					position++
-				}
-			l862:
-				if buffer[position] != rune('1') {
-					goto l858
-				}
-				position++
-				if buffer[position] != rune('2') {
-					goto l858
-				}
-				position++
-				if buffer[position] != rune(':') {
-					goto l858
-				}
-				position++
-				{
-					position864, tokenIndex864 := position, tokenIndex
-					if !_rules[ruleLocalSymbol]() {
-						goto l865
-					}
-					goto l864
-				l865:
-					position, tokenIndex = position864, tokenIndex864
-					if !_rules[ruleSymbolName]() {
-						goto l858
-					}
-				}
-			l864:
-				{
-					position866, tokenIndex866 := position, tokenIndex
-					if !_rules[ruleOffset]() {
-						goto l866
-					}
-					goto l867
-				l866:
-					position, tokenIndex = position866, tokenIndex866
-				}
-			l867:
-				add(ruleLow12BitsSymbolRef, position859)
+				add(ruleSVE2SpecialValue, position793)
 			}
 			return true
-		l858:
-			position, tokenIndex = position858, tokenIndex858
+		l792:
+			position, tokenIndex = position792, tokenIndex792
 			return false
 		},
-		/* 53 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */
+		/* 52 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */
 		func() bool {
 			position868, tokenIndex868 := position, tokenIndex
 			{
 				position869 := position
-				if buffer[position] != rune('[') {
-					goto l868
-				}
-				position++
-				if !_rules[ruleARMRegister]() {
-					goto l868
-				}
 				{
 					position870, tokenIndex870 := position, tokenIndex
-					if buffer[position] != rune(',') {
-						goto l870
+					if !_rules[ruleSymbolRef]() {
+						goto l871
 					}
-					position++
-					{
-						position872, tokenIndex872 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l872
-						}
-						goto l873
-					l872:
-						position, tokenIndex = position872, tokenIndex872
+					if !_rules[ruleBaseIndexScale]() {
+						goto l871
 					}
-				l873:
-					{
-						position874, tokenIndex874 := position, tokenIndex
-						if buffer[position] != rune('#') {
-							goto l875
-						}
-						position++
-						if !_rules[ruleOffset]() {
-							goto l875
-						}
-						{
-							position876, tokenIndex876 := position, tokenIndex
-							{
-								position878, tokenIndex878 := position, tokenIndex
-								if buffer[position] != rune('*') {
-									goto l879
-								}
-								position++
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l879
-								}
-								position++
-							l880:
-								{
-									position881, tokenIndex881 := position, tokenIndex
-									if c := buffer[position]; c < rune('0') || c > rune('9') {
-										goto l881
-									}
-									position++
-									goto l880
-								l881:
-									position, tokenIndex = position881, tokenIndex881
-								}
-								goto l878
-							l879:
-								position, tokenIndex = position878, tokenIndex878
-								if buffer[position] != rune('*') {
-									goto l882
-								}
-								position++
-								if buffer[position] != rune('(') {
-									goto l882
-								}
-								position++
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l882
-								}
-								position++
-							l883:
-								{
-									position884, tokenIndex884 := position, tokenIndex
-									if c := buffer[position]; c < rune('0') || c > rune('9') {
-										goto l884
-									}
-									position++
-									goto l883
-								l884:
-									position, tokenIndex = position884, tokenIndex884
-								}
-								if !_rules[ruleOperator]() {
-									goto l882
-								}
-								if c := buffer[position]; c < rune('0') || c > rune('9') {
-									goto l882
-								}
-								position++
-							l885:
-								{
-									position886, tokenIndex886 := position, tokenIndex
-									if c := buffer[position]; c < rune('0') || c > rune('9') {
-										goto l886
-									}
-									position++
-									goto l885
-								l886:
-									position, tokenIndex = position886, tokenIndex886
-								}
-								if buffer[position] != rune(')') {
-									goto l882
-								}
-								position++
-								goto l878
-							l882:
-								position, tokenIndex = position878, tokenIndex878
-							l887:
-								{
-									position888, tokenIndex888 := position, tokenIndex
-									if buffer[position] != rune('+') {
-										goto l888
-									}
-									position++
-									if c := buffer[position]; c < rune('0') || c > rune('9') {
-										goto l888
-									}
-									position++
-								l889:
-									{
-										position890, tokenIndex890 := position, tokenIndex
-										if c := buffer[position]; c < rune('0') || c > rune('9') {
-											goto l890
-										}
-										position++
-										goto l889
-									l890:
-										position, tokenIndex = position890, tokenIndex890
-									}
-									goto l887
-								l888:
-									position, tokenIndex = position888, tokenIndex888
-								}
-							}
-						l878:
-							goto l877
-
-							position, tokenIndex = position876, tokenIndex876
-						}
-					l877:
-						goto l874
-					l875:
-						position, tokenIndex = position874, tokenIndex874
-						if !_rules[ruleARMGOTLow12]() {
-							goto l891
-						}
-						goto l874
-					l891:
-						position, tokenIndex = position874, tokenIndex874
-						if !_rules[ruleLow12BitsSymbolRef]() {
-							goto l892
-						}
-						goto l874
-					l892:
-						position, tokenIndex = position874, tokenIndex874
-						if !_rules[ruleARMRegister]() {
-							goto l870
-						}
-					}
-				l874:
-					{
-						position893, tokenIndex893 := position, tokenIndex
-						if buffer[position] != rune(',') {
-							goto l893
-						}
-						position++
-						{
-							position895, tokenIndex895 := position, tokenIndex
-							if !_rules[ruleWS]() {
-								goto l895
-							}
-							goto l896
-						l895:
-							position, tokenIndex = position895, tokenIndex895
-						}
-					l896:
-						if !_rules[ruleARMConstantTweak]() {
-							goto l893
-						}
-						goto l894
-					l893:
-						position, tokenIndex = position893, tokenIndex893
-					}
-				l894:
-					goto l871
-				l870:
+					goto l870
+				l871:
 					position, tokenIndex = position870, tokenIndex870
-				}
-			l871:
-				if buffer[position] != rune(']') {
-					goto l868
-				}
-				position++
-				{
-					position897, tokenIndex897 := position, tokenIndex
-					if !_rules[ruleARMPostincrement]() {
-						goto l897
+					if !_rules[ruleSymbolRef]() {
+						goto l872
 					}
-					goto l898
-				l897:
-					position, tokenIndex = position897, tokenIndex897
+					goto l870
+				l872:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleLow12BitsSymbolRef]() {
+						goto l873
+					}
+					goto l870
+				l873:
+					position, tokenIndex = position870, tokenIndex870
+				l875:
+					{
+						position876, tokenIndex876 := position, tokenIndex
+						if !_rules[ruleOffset]() {
+							goto l876
+						}
+						goto l875
+					l876:
+						position, tokenIndex = position876, tokenIndex876
+					}
+					if !_rules[ruleBaseIndexScale]() {
+						goto l874
+					}
+					goto l870
+				l874:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleSegmentRegister]() {
+						goto l877
+					}
+					if !_rules[ruleOffset]() {
+						goto l877
+					}
+					if !_rules[ruleBaseIndexScale]() {
+						goto l877
+					}
+					goto l870
+				l877:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleSegmentRegister]() {
+						goto l878
+					}
+					if !_rules[ruleBaseIndexScale]() {
+						goto l878
+					}
+					goto l870
+				l878:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleSegmentRegister]() {
+						goto l879
+					}
+					if !_rules[ruleOffset]() {
+						goto l879
+					}
+					goto l870
+				l879:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleARMBaseIndexScale]() {
+						goto l880
+					}
+					goto l870
+				l880:
+					position, tokenIndex = position870, tokenIndex870
+					if !_rules[ruleBaseIndexScale]() {
+						goto l868
+					}
 				}
-			l898:
-				add(ruleARMBaseIndexScale, position869)
+			l870:
+				add(ruleMemoryRef, position869)
 			}
 			return true
 		l868:
 			position, tokenIndex = position868, tokenIndex868
 			return false
 		},
-		/* 54 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */
+		/* 53 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */
 		func() bool {
-			position899, tokenIndex899 := position, tokenIndex
+			position881, tokenIndex881 := position, tokenIndex
 			{
-				position900 := position
+				position882 := position
+				{
+					position883, tokenIndex883 := position, tokenIndex
+				l885:
+					{
+						position886, tokenIndex886 := position, tokenIndex
+						if !_rules[ruleOffset]() {
+							goto l886
+						}
+						goto l885
+					l886:
+						position, tokenIndex = position886, tokenIndex886
+					}
+					if buffer[position] != rune('+') {
+						goto l883
+					}
+					position++
+					goto l884
+				l883:
+					position, tokenIndex = position883, tokenIndex883
+				}
+			l884:
+				{
+					position887, tokenIndex887 := position, tokenIndex
+					if !_rules[ruleLocalSymbol]() {
+						goto l888
+					}
+					goto l887
+				l888:
+					position, tokenIndex = position887, tokenIndex887
+					if !_rules[ruleSymbolName]() {
+						goto l881
+					}
+				}
+			l887:
+			l889:
+				{
+					position890, tokenIndex890 := position, tokenIndex
+					if !_rules[ruleOffset]() {
+						goto l890
+					}
+					goto l889
+				l890:
+					position, tokenIndex = position890, tokenIndex890
+				}
+				{
+					position891, tokenIndex891 := position, tokenIndex
+					if buffer[position] != rune('@') {
+						goto l891
+					}
+					position++
+					if !_rules[ruleSection]() {
+						goto l891
+					}
+				l893:
+					{
+						position894, tokenIndex894 := position, tokenIndex
+						if !_rules[ruleOffset]() {
+							goto l894
+						}
+						goto l893
+					l894:
+						position, tokenIndex = position894, tokenIndex894
+					}
+					goto l892
+				l891:
+					position, tokenIndex = position891, tokenIndex891
+				}
+			l892:
+				add(ruleSymbolRef, position882)
+			}
+			return true
+		l881:
+			position, tokenIndex = position881, tokenIndex881
+			return false
+		},
+		/* 54 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */
+		func() bool {
+			position895, tokenIndex895 := position, tokenIndex
+			{
+				position896 := position
 				if buffer[position] != rune(':') {
+					goto l895
+				}
+				position++
+				{
+					position897, tokenIndex897 := position, tokenIndex
+					if buffer[position] != rune('l') {
+						goto l898
+					}
+					position++
+					goto l897
+				l898:
+					position, tokenIndex = position897, tokenIndex897
+					if buffer[position] != rune('L') {
+						goto l895
+					}
+					position++
+				}
+			l897:
+				{
+					position899, tokenIndex899 := position, tokenIndex
+					if buffer[position] != rune('o') {
+						goto l900
+					}
+					position++
 					goto l899
+				l900:
+					position, tokenIndex = position899, tokenIndex899
+					if buffer[position] != rune('O') {
+						goto l895
+					}
+					position++
+				}
+			l899:
+				if buffer[position] != rune('1') {
+					goto l895
+				}
+				position++
+				if buffer[position] != rune('2') {
+					goto l895
+				}
+				position++
+				if buffer[position] != rune(':') {
+					goto l895
 				}
 				position++
 				{
 					position901, tokenIndex901 := position, tokenIndex
-					if buffer[position] != rune('g') {
+					if !_rules[ruleLocalSymbol]() {
 						goto l902
 					}
-					position++
 					goto l901
 				l902:
 					position, tokenIndex = position901, tokenIndex901
-					if buffer[position] != rune('G') {
-						goto l899
+					if !_rules[ruleSymbolName]() {
+						goto l895
 					}
-					position++
 				}
 			l901:
 				{
 					position903, tokenIndex903 := position, tokenIndex
-					if buffer[position] != rune('o') {
-						goto l904
+					if !_rules[ruleOffset]() {
+						goto l903
 					}
-					position++
-					goto l903
-				l904:
+					goto l904
+				l903:
 					position, tokenIndex = position903, tokenIndex903
-					if buffer[position] != rune('O') {
-						goto l899
-					}
-					position++
 				}
-			l903:
-				{
-					position905, tokenIndex905 := position, tokenIndex
-					if buffer[position] != rune('t') {
-						goto l906
-					}
-					position++
+			l904:
+				add(ruleLow12BitsSymbolRef, position896)
+			}
+			return true
+		l895:
+			position, tokenIndex = position895, tokenIndex895
+			return false
+		},
+		/* 55 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */
+		func() bool {
+			position905, tokenIndex905 := position, tokenIndex
+			{
+				position906 := position
+				if buffer[position] != rune('[') {
 					goto l905
-				l906:
-					position, tokenIndex = position905, tokenIndex905
-					if buffer[position] != rune('T') {
-						goto l899
-					}
-					position++
-				}
-			l905:
-				if buffer[position] != rune('_') {
-					goto l899
 				}
 				position++
+				if !_rules[ruleARMRegister]() {
+					goto l905
+				}
 				{
 					position907, tokenIndex907 := position, tokenIndex
-					if buffer[position] != rune('l') {
-						goto l908
-					}
-					position++
-					goto l907
-				l908:
-					position, tokenIndex = position907, tokenIndex907
-					if buffer[position] != rune('L') {
-						goto l899
-					}
-					position++
-				}
-			l907:
-				{
-					position909, tokenIndex909 := position, tokenIndex
-					if buffer[position] != rune('o') {
-						goto l910
-					}
-					position++
-					goto l909
-				l910:
-					position, tokenIndex = position909, tokenIndex909
-					if buffer[position] != rune('O') {
-						goto l899
-					}
-					position++
-				}
-			l909:
-				if buffer[position] != rune('1') {
-					goto l899
-				}
-				position++
-				if buffer[position] != rune('2') {
-					goto l899
-				}
-				position++
-				if buffer[position] != rune(':') {
-					goto l899
-				}
-				position++
-				if !_rules[ruleSymbolName]() {
-					goto l899
-				}
-				add(ruleARMGOTLow12, position900)
-			}
-			return true
-		l899:
-			position, tokenIndex = position899, tokenIndex899
-			return false
-		},
-		/* 55 ARMPostincrement <- <'!'> */
-		func() bool {
-			position911, tokenIndex911 := position, tokenIndex
-			{
-				position912 := position
-				if buffer[position] != rune('!') {
-					goto l911
-				}
-				position++
-				add(ruleARMPostincrement, position912)
-			}
-			return true
-		l911:
-			position, tokenIndex = position911, tokenIndex911
-			return false
-		},
-		/* 56 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */
-		func() bool {
-			position913, tokenIndex913 := position, tokenIndex
-			{
-				position914 := position
-				if buffer[position] != rune('(') {
-					goto l913
-				}
-				position++
-				{
-					position915, tokenIndex915 := position, tokenIndex
-					if !_rules[ruleRegisterOrConstant]() {
-						goto l915
-					}
-					goto l916
-				l915:
-					position, tokenIndex = position915, tokenIndex915
-				}
-			l916:
-				{
-					position917, tokenIndex917 := position, tokenIndex
-					if !_rules[ruleWS]() {
-						goto l917
-					}
-					goto l918
-				l917:
-					position, tokenIndex = position917, tokenIndex917
-				}
-			l918:
-				{
-					position919, tokenIndex919 := position, tokenIndex
 					if buffer[position] != rune(',') {
-						goto l919
+						goto l907
 					}
 					position++
 					{
-						position921, tokenIndex921 := position, tokenIndex
+						position909, tokenIndex909 := position, tokenIndex
 						if !_rules[ruleWS]() {
-							goto l921
+							goto l909
 						}
-						goto l922
-					l921:
-						position, tokenIndex = position921, tokenIndex921
+						goto l910
+					l909:
+						position, tokenIndex = position909, tokenIndex909
 					}
-				l922:
-					if !_rules[ruleRegisterOrConstant]() {
-						goto l919
-					}
+				l910:
 					{
-						position923, tokenIndex923 := position, tokenIndex
-						if !_rules[ruleWS]() {
-							goto l923
-						}
-						goto l924
-					l923:
-						position, tokenIndex = position923, tokenIndex923
-					}
-				l924:
-					{
-						position925, tokenIndex925 := position, tokenIndex
-						if buffer[position] != rune(',') {
-							goto l925
+						position911, tokenIndex911 := position, tokenIndex
+						if buffer[position] != rune('#') {
+							goto l912
 						}
 						position++
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l925
+						if !_rules[ruleOffset]() {
+							goto l912
 						}
-						position++
-					l927:
 						{
-							position928, tokenIndex928 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l928
+							position913, tokenIndex913 := position, tokenIndex
+							{
+								position915, tokenIndex915 := position, tokenIndex
+								if buffer[position] != rune('*') {
+									goto l916
+								}
+								position++
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l916
+								}
+								position++
+							l917:
+								{
+									position918, tokenIndex918 := position, tokenIndex
+									if c := buffer[position]; c < rune('0') || c > rune('9') {
+										goto l918
+									}
+									position++
+									goto l917
+								l918:
+									position, tokenIndex = position918, tokenIndex918
+								}
+								goto l915
+							l916:
+								position, tokenIndex = position915, tokenIndex915
+								if buffer[position] != rune('*') {
+									goto l919
+								}
+								position++
+								if buffer[position] != rune('(') {
+									goto l919
+								}
+								position++
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l919
+								}
+								position++
+							l920:
+								{
+									position921, tokenIndex921 := position, tokenIndex
+									if c := buffer[position]; c < rune('0') || c > rune('9') {
+										goto l921
+									}
+									position++
+									goto l920
+								l921:
+									position, tokenIndex = position921, tokenIndex921
+								}
+								if !_rules[ruleOperator]() {
+									goto l919
+								}
+								if c := buffer[position]; c < rune('0') || c > rune('9') {
+									goto l919
+								}
+								position++
+							l922:
+								{
+									position923, tokenIndex923 := position, tokenIndex
+									if c := buffer[position]; c < rune('0') || c > rune('9') {
+										goto l923
+									}
+									position++
+									goto l922
+								l923:
+									position, tokenIndex = position923, tokenIndex923
+								}
+								if buffer[position] != rune(')') {
+									goto l919
+								}
+								position++
+								goto l915
+							l919:
+								position, tokenIndex = position915, tokenIndex915
+							l924:
+								{
+									position925, tokenIndex925 := position, tokenIndex
+									if buffer[position] != rune('+') {
+										goto l925
+									}
+									position++
+									if c := buffer[position]; c < rune('0') || c > rune('9') {
+										goto l925
+									}
+									position++
+								l926:
+									{
+										position927, tokenIndex927 := position, tokenIndex
+										if c := buffer[position]; c < rune('0') || c > rune('9') {
+											goto l927
+										}
+										position++
+										goto l926
+									l927:
+										position, tokenIndex = position927, tokenIndex927
+									}
+									goto l924
+								l925:
+									position, tokenIndex = position925, tokenIndex925
+								}
 							}
-							position++
-							goto l927
-						l928:
-							position, tokenIndex = position928, tokenIndex928
+						l915:
+							goto l914
+
+							position, tokenIndex = position913, tokenIndex913
 						}
-						goto l926
-					l925:
-						position, tokenIndex = position925, tokenIndex925
+					l914:
+						goto l911
+					l912:
+						position, tokenIndex = position911, tokenIndex911
+						if !_rules[ruleARMGOTLow12]() {
+							goto l928
+						}
+						goto l911
+					l928:
+						position, tokenIndex = position911, tokenIndex911
+						if !_rules[ruleLow12BitsSymbolRef]() {
+							goto l929
+						}
+						goto l911
+					l929:
+						position, tokenIndex = position911, tokenIndex911
+						if !_rules[ruleARMRegister]() {
+							goto l907
+						}
 					}
-				l926:
-					goto l920
-				l919:
-					position, tokenIndex = position919, tokenIndex919
+				l911:
+					{
+						position930, tokenIndex930 := position, tokenIndex
+						if buffer[position] != rune(',') {
+							goto l930
+						}
+						position++
+						{
+							position932, tokenIndex932 := position, tokenIndex
+							if !_rules[ruleWS]() {
+								goto l932
+							}
+							goto l933
+						l932:
+							position, tokenIndex = position932, tokenIndex932
+						}
+					l933:
+						if !_rules[ruleARMConstantTweak]() {
+							goto l930
+						}
+						goto l931
+					l930:
+						position, tokenIndex = position930, tokenIndex930
+					}
+				l931:
+					goto l908
+				l907:
+					position, tokenIndex = position907, tokenIndex907
 				}
-			l920:
-				if buffer[position] != rune(')') {
-					goto l913
+			l908:
+				if buffer[position] != rune(']') {
+					goto l905
 				}
 				position++
-				add(ruleBaseIndexScale, position914)
-			}
-			return true
-		l913:
-			position, tokenIndex = position913, tokenIndex913
-			return false
-		},
-		/* 57 Operator <- <('+' / '-')> */
-		func() bool {
-			position929, tokenIndex929 := position, tokenIndex
-			{
-				position930 := position
 				{
-					position931, tokenIndex931 := position, tokenIndex
-					if buffer[position] != rune('+') {
-						goto l932
+					position934, tokenIndex934 := position, tokenIndex
+					if !_rules[ruleARMPostincrement]() {
+						goto l934
 					}
-					position++
-					goto l931
-				l932:
-					position, tokenIndex = position931, tokenIndex931
-					if buffer[position] != rune('-') {
-						goto l929
-					}
-					position++
+					goto l935
+				l934:
+					position, tokenIndex = position934, tokenIndex934
 				}
-			l931:
-				add(ruleOperator, position930)
+			l935:
+				add(ruleARMBaseIndexScale, position906)
 			}
 			return true
-		l929:
-			position, tokenIndex = position929, tokenIndex929
+		l905:
+			position, tokenIndex = position905, tokenIndex905
 			return false
 		},
-		/* 58 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */
+		/* 56 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */
 		func() bool {
-			position933, tokenIndex933 := position, tokenIndex
+			position936, tokenIndex936 := position, tokenIndex
 			{
-				position934 := position
-				{
-					position935, tokenIndex935 := position, tokenIndex
-					if buffer[position] != rune('+') {
-						goto l935
-					}
-					position++
+				position937 := position
+				if buffer[position] != rune(':') {
 					goto l936
-				l935:
-					position, tokenIndex = position935, tokenIndex935
 				}
-			l936:
+				position++
 				{
-					position937, tokenIndex937 := position, tokenIndex
-					if buffer[position] != rune('-') {
-						goto l937
+					position938, tokenIndex938 := position, tokenIndex
+					if buffer[position] != rune('g') {
+						goto l939
 					}
 					position++
 					goto l938
-				l937:
-					position, tokenIndex = position937, tokenIndex937
+				l939:
+					position, tokenIndex = position938, tokenIndex938
+					if buffer[position] != rune('G') {
+						goto l936
+					}
+					position++
 				}
 			l938:
 				{
-					position939, tokenIndex939 := position, tokenIndex
-					if buffer[position] != rune('0') {
-						goto l940
-					}
-					position++
-					{
-						position941, tokenIndex941 := position, tokenIndex
-						if buffer[position] != rune('b') {
-							goto l942
-						}
-						position++
+					position940, tokenIndex940 := position, tokenIndex
+					if buffer[position] != rune('o') {
 						goto l941
-					l942:
-						position, tokenIndex = position941, tokenIndex941
-						if buffer[position] != rune('B') {
-							goto l940
-						}
-						position++
 					}
+					position++
+					goto l940
 				l941:
-					{
-						position945, tokenIndex945 := position, tokenIndex
-						if buffer[position] != rune('0') {
-							goto l946
-						}
-						position++
-						goto l945
-					l946:
-						position, tokenIndex = position945, tokenIndex945
-						if buffer[position] != rune('1') {
-							goto l940
-						}
-						position++
-					}
-				l945:
-				l943:
-					{
-						position944, tokenIndex944 := position, tokenIndex
-						{
-							position947, tokenIndex947 := position, tokenIndex
-							if buffer[position] != rune('0') {
-								goto l948
-							}
-							position++
-							goto l947
-						l948:
-							position, tokenIndex = position947, tokenIndex947
-							if buffer[position] != rune('1') {
-								goto l944
-							}
-							position++
-						}
-					l947:
-						goto l943
-					l944:
-						position, tokenIndex = position944, tokenIndex944
-					}
-					goto l939
-				l940:
-					position, tokenIndex = position939, tokenIndex939
-					if buffer[position] != rune('0') {
-						goto l949
+					position, tokenIndex = position940, tokenIndex940
+					if buffer[position] != rune('O') {
+						goto l936
 					}
 					position++
-					{
-						position950, tokenIndex950 := position, tokenIndex
-						if buffer[position] != rune('x') {
-							goto l951
-						}
-						position++
-						goto l950
-					l951:
-						position, tokenIndex = position950, tokenIndex950
-						if buffer[position] != rune('X') {
-							goto l949
-						}
-						position++
-					}
-				l950:
-					{
-						position954, tokenIndex954 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l955
-						}
-						position++
-						goto l954
-					l955:
-						position, tokenIndex = position954, tokenIndex954
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l956
-						}
-						position++
-						goto l954
-					l956:
-						position, tokenIndex = position954, tokenIndex954
-						{
-							position957, tokenIndex957 := position, tokenIndex
-							if c := buffer[position]; c < rune('a') || c > rune('f') {
-								goto l958
-							}
-							position++
-							goto l957
-						l958:
-							position, tokenIndex = position957, tokenIndex957
-							if c := buffer[position]; c < rune('A') || c > rune('F') {
-								goto l949
-							}
-							position++
-						}
-					l957:
-					}
-				l954:
-				l952:
-					{
-						position953, tokenIndex953 := position, tokenIndex
-						{
-							position959, tokenIndex959 := position, tokenIndex
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l960
-							}
-							position++
-							goto l959
-						l960:
-							position, tokenIndex = position959, tokenIndex959
-							if c := buffer[position]; c < rune('0') || c > rune('9') {
-								goto l961
-							}
-							position++
-							goto l959
-						l961:
-							position, tokenIndex = position959, tokenIndex959
-							{
-								position962, tokenIndex962 := position, tokenIndex
-								if c := buffer[position]; c < rune('a') || c > rune('f') {
-									goto l963
-								}
-								position++
-								goto l962
-							l963:
-								position, tokenIndex = position962, tokenIndex962
-								if c := buffer[position]; c < rune('A') || c > rune('F') {
-									goto l953
-								}
-								position++
-							}
-						l962:
-						}
-					l959:
-						goto l952
-					l953:
-						position, tokenIndex = position953, tokenIndex953
-					}
-					goto l939
-				l949:
-					position, tokenIndex = position939, tokenIndex939
-					if c := buffer[position]; c < rune('0') || c > rune('9') {
-						goto l933
-					}
-					position++
-				l964:
-					{
-						position965, tokenIndex965 := position, tokenIndex
-						if c := buffer[position]; c < rune('0') || c > rune('9') {
-							goto l965
-						}
-						position++
-						goto l964
-					l965:
-						position, tokenIndex = position965, tokenIndex965
-					}
 				}
-			l939:
-				add(ruleOffset, position934)
+			l940:
+				{
+					position942, tokenIndex942 := position, tokenIndex
+					if buffer[position] != rune('t') {
+						goto l943
+					}
+					position++
+					goto l942
+				l943:
+					position, tokenIndex = position942, tokenIndex942
+					if buffer[position] != rune('T') {
+						goto l936
+					}
+					position++
+				}
+			l942:
+				if buffer[position] != rune('_') {
+					goto l936
+				}
+				position++
+				{
+					position944, tokenIndex944 := position, tokenIndex
+					if buffer[position] != rune('l') {
+						goto l945
+					}
+					position++
+					goto l944
+				l945:
+					position, tokenIndex = position944, tokenIndex944
+					if buffer[position] != rune('L') {
+						goto l936
+					}
+					position++
+				}
+			l944:
+				{
+					position946, tokenIndex946 := position, tokenIndex
+					if buffer[position] != rune('o') {
+						goto l947
+					}
+					position++
+					goto l946
+				l947:
+					position, tokenIndex = position946, tokenIndex946
+					if buffer[position] != rune('O') {
+						goto l936
+					}
+					position++
+				}
+			l946:
+				if buffer[position] != rune('1') {
+					goto l936
+				}
+				position++
+				if buffer[position] != rune('2') {
+					goto l936
+				}
+				position++
+				if buffer[position] != rune(':') {
+					goto l936
+				}
+				position++
+				if !_rules[ruleSymbolName]() {
+					goto l936
+				}
+				add(ruleARMGOTLow12, position937)
 			}
 			return true
-		l933:
-			position, tokenIndex = position933, tokenIndex933
+		l936:
+			position, tokenIndex = position936, tokenIndex936
 			return false
 		},
-		/* 59 Section <- <([a-z] / [A-Z] / '@')+> */
+		/* 57 ARMPostincrement <- <'!'> */
+		func() bool {
+			position948, tokenIndex948 := position, tokenIndex
+			{
+				position949 := position
+				if buffer[position] != rune('!') {
+					goto l948
+				}
+				position++
+				add(ruleARMPostincrement, position949)
+			}
+			return true
+		l948:
+			position, tokenIndex = position948, tokenIndex948
+			return false
+		},
+		/* 58 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */
+		func() bool {
+			position950, tokenIndex950 := position, tokenIndex
+			{
+				position951 := position
+				if buffer[position] != rune('(') {
+					goto l950
+				}
+				position++
+				{
+					position952, tokenIndex952 := position, tokenIndex
+					if !_rules[ruleRegisterOrConstant]() {
+						goto l952
+					}
+					goto l953
+				l952:
+					position, tokenIndex = position952, tokenIndex952
+				}
+			l953:
+				{
+					position954, tokenIndex954 := position, tokenIndex
+					if !_rules[ruleWS]() {
+						goto l954
+					}
+					goto l955
+				l954:
+					position, tokenIndex = position954, tokenIndex954
+				}
+			l955:
+				{
+					position956, tokenIndex956 := position, tokenIndex
+					if buffer[position] != rune(',') {
+						goto l956
+					}
+					position++
+					{
+						position958, tokenIndex958 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l958
+						}
+						goto l959
+					l958:
+						position, tokenIndex = position958, tokenIndex958
+					}
+				l959:
+					if !_rules[ruleRegisterOrConstant]() {
+						goto l956
+					}
+					{
+						position960, tokenIndex960 := position, tokenIndex
+						if !_rules[ruleWS]() {
+							goto l960
+						}
+						goto l961
+					l960:
+						position, tokenIndex = position960, tokenIndex960
+					}
+				l961:
+					{
+						position962, tokenIndex962 := position, tokenIndex
+						if buffer[position] != rune(',') {
+							goto l962
+						}
+						position++
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l962
+						}
+						position++
+					l964:
+						{
+							position965, tokenIndex965 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l965
+							}
+							position++
+							goto l964
+						l965:
+							position, tokenIndex = position965, tokenIndex965
+						}
+						goto l963
+					l962:
+						position, tokenIndex = position962, tokenIndex962
+					}
+				l963:
+					goto l957
+				l956:
+					position, tokenIndex = position956, tokenIndex956
+				}
+			l957:
+				if buffer[position] != rune(')') {
+					goto l950
+				}
+				position++
+				add(ruleBaseIndexScale, position951)
+			}
+			return true
+		l950:
+			position, tokenIndex = position950, tokenIndex950
+			return false
+		},
+		/* 59 Operator <- <('+' / '-')> */
 		func() bool {
 			position966, tokenIndex966 := position, tokenIndex
 			{
 				position967 := position
 				{
-					position970, tokenIndex970 := position, tokenIndex
-					if c := buffer[position]; c < rune('a') || c > rune('z') {
-						goto l971
+					position968, tokenIndex968 := position, tokenIndex
+					if buffer[position] != rune('+') {
+						goto l969
 					}
 					position++
-					goto l970
-				l971:
-					position, tokenIndex = position970, tokenIndex970
-					if c := buffer[position]; c < rune('A') || c > rune('Z') {
-						goto l972
-					}
-					position++
-					goto l970
-				l972:
-					position, tokenIndex = position970, tokenIndex970
-					if buffer[position] != rune('@') {
+					goto l968
+				l969:
+					position, tokenIndex = position968, tokenIndex968
+					if buffer[position] != rune('-') {
 						goto l966
 					}
 					position++
 				}
-			l970:
 			l968:
-				{
-					position969, tokenIndex969 := position, tokenIndex
-					{
-						position973, tokenIndex973 := position, tokenIndex
-						if c := buffer[position]; c < rune('a') || c > rune('z') {
-							goto l974
-						}
-						position++
-						goto l973
-					l974:
-						position, tokenIndex = position973, tokenIndex973
-						if c := buffer[position]; c < rune('A') || c > rune('Z') {
-							goto l975
-						}
-						position++
-						goto l973
-					l975:
-						position, tokenIndex = position973, tokenIndex973
-						if buffer[position] != rune('@') {
-							goto l969
-						}
-						position++
-					}
-				l973:
-					goto l968
-				l969:
-					position, tokenIndex = position969, tokenIndex969
-				}
-				add(ruleSection, position967)
+				add(ruleOperator, position967)
 			}
 			return true
 		l966:
 			position, tokenIndex = position966, tokenIndex966
 			return false
 		},
-		/* 60 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */
+		/* 60 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */
 		func() bool {
-			position976, tokenIndex976 := position, tokenIndex
+			position970, tokenIndex970 := position, tokenIndex
 			{
-				position977 := position
-				if buffer[position] != rune('%') {
+				position971 := position
+				{
+					position972, tokenIndex972 := position, tokenIndex
+					if buffer[position] != rune('+') {
+						goto l972
+					}
+					position++
+					goto l973
+				l972:
+					position, tokenIndex = position972, tokenIndex972
+				}
+			l973:
+				{
+					position974, tokenIndex974 := position, tokenIndex
+					if buffer[position] != rune('-') {
+						goto l974
+					}
+					position++
+					goto l975
+				l974:
+					position, tokenIndex = position974, tokenIndex974
+				}
+			l975:
+				{
+					position976, tokenIndex976 := position, tokenIndex
+					if buffer[position] != rune('0') {
+						goto l977
+					}
+					position++
+					{
+						position978, tokenIndex978 := position, tokenIndex
+						if buffer[position] != rune('b') {
+							goto l979
+						}
+						position++
+						goto l978
+					l979:
+						position, tokenIndex = position978, tokenIndex978
+						if buffer[position] != rune('B') {
+							goto l977
+						}
+						position++
+					}
+				l978:
+					{
+						position982, tokenIndex982 := position, tokenIndex
+						if buffer[position] != rune('0') {
+							goto l983
+						}
+						position++
+						goto l982
+					l983:
+						position, tokenIndex = position982, tokenIndex982
+						if buffer[position] != rune('1') {
+							goto l977
+						}
+						position++
+					}
+				l982:
+				l980:
+					{
+						position981, tokenIndex981 := position, tokenIndex
+						{
+							position984, tokenIndex984 := position, tokenIndex
+							if buffer[position] != rune('0') {
+								goto l985
+							}
+							position++
+							goto l984
+						l985:
+							position, tokenIndex = position984, tokenIndex984
+							if buffer[position] != rune('1') {
+								goto l981
+							}
+							position++
+						}
+					l984:
+						goto l980
+					l981:
+						position, tokenIndex = position981, tokenIndex981
+					}
 					goto l976
+				l977:
+					position, tokenIndex = position976, tokenIndex976
+					if buffer[position] != rune('0') {
+						goto l986
+					}
+					position++
+					{
+						position987, tokenIndex987 := position, tokenIndex
+						if buffer[position] != rune('x') {
+							goto l988
+						}
+						position++
+						goto l987
+					l988:
+						position, tokenIndex = position987, tokenIndex987
+						if buffer[position] != rune('X') {
+							goto l986
+						}
+						position++
+					}
+				l987:
+					{
+						position991, tokenIndex991 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l992
+						}
+						position++
+						goto l991
+					l992:
+						position, tokenIndex = position991, tokenIndex991
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l993
+						}
+						position++
+						goto l991
+					l993:
+						position, tokenIndex = position991, tokenIndex991
+						{
+							position994, tokenIndex994 := position, tokenIndex
+							if c := buffer[position]; c < rune('a') || c > rune('f') {
+								goto l995
+							}
+							position++
+							goto l994
+						l995:
+							position, tokenIndex = position994, tokenIndex994
+							if c := buffer[position]; c < rune('A') || c > rune('F') {
+								goto l986
+							}
+							position++
+						}
+					l994:
+					}
+				l991:
+				l989:
+					{
+						position990, tokenIndex990 := position, tokenIndex
+						{
+							position996, tokenIndex996 := position, tokenIndex
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l997
+							}
+							position++
+							goto l996
+						l997:
+							position, tokenIndex = position996, tokenIndex996
+							if c := buffer[position]; c < rune('0') || c > rune('9') {
+								goto l998
+							}
+							position++
+							goto l996
+						l998:
+							position, tokenIndex = position996, tokenIndex996
+							{
+								position999, tokenIndex999 := position, tokenIndex
+								if c := buffer[position]; c < rune('a') || c > rune('f') {
+									goto l1000
+								}
+								position++
+								goto l999
+							l1000:
+								position, tokenIndex = position999, tokenIndex999
+								if c := buffer[position]; c < rune('A') || c > rune('F') {
+									goto l990
+								}
+								position++
+							}
+						l999:
+						}
+					l996:
+						goto l989
+					l990:
+						position, tokenIndex = position990, tokenIndex990
+					}
+					goto l976
+				l986:
+					position, tokenIndex = position976, tokenIndex976
+					if c := buffer[position]; c < rune('0') || c > rune('9') {
+						goto l970
+					}
+					position++
+				l1001:
+					{
+						position1002, tokenIndex1002 := position, tokenIndex
+						if c := buffer[position]; c < rune('0') || c > rune('9') {
+							goto l1002
+						}
+						position++
+						goto l1001
+					l1002:
+						position, tokenIndex = position1002, tokenIndex1002
+					}
+				}
+			l976:
+				add(ruleOffset, position971)
+			}
+			return true
+		l970:
+			position, tokenIndex = position970, tokenIndex970
+			return false
+		},
+		/* 61 Section <- <([a-z] / [A-Z] / '@')+> */
+		func() bool {
+			position1003, tokenIndex1003 := position, tokenIndex
+			{
+				position1004 := position
+				{
+					position1007, tokenIndex1007 := position, tokenIndex
+					if c := buffer[position]; c < rune('a') || c > rune('z') {
+						goto l1008
+					}
+					position++
+					goto l1007
+				l1008:
+					position, tokenIndex = position1007, tokenIndex1007
+					if c := buffer[position]; c < rune('A') || c > rune('Z') {
+						goto l1009
+					}
+					position++
+					goto l1007
+				l1009:
+					position, tokenIndex = position1007, tokenIndex1007
+					if buffer[position] != rune('@') {
+						goto l1003
+					}
+					position++
+				}
+			l1007:
+			l1005:
+				{
+					position1006, tokenIndex1006 := position, tokenIndex
+					{
+						position1010, tokenIndex1010 := position, tokenIndex
+						if c := buffer[position]; c < rune('a') || c > rune('z') {
+							goto l1011
+						}
+						position++
+						goto l1010
+					l1011:
+						position, tokenIndex = position1010, tokenIndex1010
+						if c := buffer[position]; c < rune('A') || c > rune('Z') {
+							goto l1012
+						}
+						position++
+						goto l1010
+					l1012:
+						position, tokenIndex = position1010, tokenIndex1010
+						if buffer[position] != rune('@') {
+							goto l1006
+						}
+						position++
+					}
+				l1010:
+					goto l1005
+				l1006:
+					position, tokenIndex = position1006, tokenIndex1006
+				}
+				add(ruleSection, position1004)
+			}
+			return true
+		l1003:
+			position, tokenIndex = position1003, tokenIndex1003
+			return false
+		},
+		/* 62 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */
+		func() bool {
+			position1013, tokenIndex1013 := position, tokenIndex
+			{
+				position1014 := position
+				if buffer[position] != rune('%') {
+					goto l1013
 				}
 				position++
 				{
-					position978, tokenIndex978 := position, tokenIndex
+					position1015, tokenIndex1015 := position, tokenIndex
 					if c := buffer[position]; c < rune('c') || c > rune('g') {
-						goto l979
+						goto l1016
 					}
 					position++
-					goto l978
-				l979:
-					position, tokenIndex = position978, tokenIndex978
+					goto l1015
+				l1016:
+					position, tokenIndex = position1015, tokenIndex1015
 					if buffer[position] != rune('s') {
-						goto l976
+						goto l1013
 					}
 					position++
 				}
-			l978:
+			l1015:
 				if buffer[position] != rune('s') {
-					goto l976
+					goto l1013
 				}
 				position++
 				if buffer[position] != rune(':') {
-					goto l976
+					goto l1013
 				}
 				position++
-				add(ruleSegmentRegister, position977)
+				add(ruleSegmentRegister, position1014)
 			}
 			return true
-		l976:
-			position, tokenIndex = position976, tokenIndex976
+		l1013:
+			position, tokenIndex = position1013, tokenIndex1013
 			return false
 		},
 	}
diff --git a/src/util/fipstools/delocate/testdata/aarch64-Basic/in.s b/src/util/fipstools/delocate/testdata/aarch64-Basic/in.s
index 114ff4f..a2334f0 100644
--- a/src/util/fipstools/delocate/testdata/aarch64-Basic/in.s
+++ b/src/util/fipstools/delocate/testdata/aarch64-Basic/in.s
@@ -25,14 +25,6 @@
 	adrp x0, .Llocal_data
 	add x0, x0, :lo12:.Llocal_data
 
-	// armcap
-	adrp x1, OPENSSL_armcap_P
-	ldr w2, [x1, :lo12:OPENSSL_armcap_P]
-
-	// armcap to w0
-	adrp x0, OPENSSL_armcap_P
-	ldr w1, [x1, :lo12:OPENSSL_armcap_P]
-
 	// Load from local symbol
 	adrp x10, .Llocal_data2
 	ldr q0, [x10, :lo12:.Llocal_data2]
@@ -81,6 +73,7 @@
 	add w0, w1, b2, sxth
 	add w0, w1, b2, sxtw
 	add w0, w1, b2, sxtx
+	movi v0.4s, #3, msl #8
 
 	// Aarch64 SVE2 added these forms:
 	ld1d { z1.d }, p91/z, [x13, x11, lsl #3]
diff --git a/src/util/fipstools/delocate/testdata/aarch64-Basic/out.s b/src/util/fipstools/delocate/testdata/aarch64-Basic/out.s
index d77695d..9ff57b5 100644
--- a/src/util/fipstools/delocate/testdata/aarch64-Basic/out.s
+++ b/src/util/fipstools/delocate/testdata/aarch64-Basic/out.s
@@ -53,27 +53,6 @@
 	adr x0, .Llocal_data
 // WAS add x0, x0, :lo12:.Llocal_data
 
-	// armcap
-// WAS adrp x1, OPENSSL_armcap_P
-	sub sp, sp, 128
-	stp x0, lr, [sp, #-16]!
-	bl .LOPENSSL_armcap_P_addr
-	mov x1, x0
-	ldp x0, lr, [sp], #16
-	add sp, sp, 128
-// WAS ldr w2, [x1, :lo12:OPENSSL_armcap_P]
-	ldr	w2, [x1]
-
-	// armcap to w0
-// WAS adrp x0, OPENSSL_armcap_P
-	sub sp, sp, 128
-	stp x0, lr, [sp, #-16]!
-	bl .LOPENSSL_armcap_P_addr
-	ldp xzr, lr, [sp], #16
-	add sp, sp, 128
-// WAS ldr w1, [x1, :lo12:OPENSSL_armcap_P]
-	ldr	w1, [x1]
-
 	// Load from local symbol
 // WAS adrp x10, .Llocal_data2
 	adr x10, .Llocal_data2
@@ -130,6 +109,7 @@
 	add w0, w1, b2, sxth
 	add w0, w1, b2, sxtw
 	add w0, w1, b2, sxtx
+	movi v0.4s, #3, msl #8
 
 	// Aarch64 SVE2 added these forms:
 	ld1d { z1.d }, p91/z, [x13, x11, lsl #3]
@@ -219,17 +199,6 @@
 	ret
 .cfi_endproc
 .size .Lboringssl_loadgot_stderr, .-.Lboringssl_loadgot_stderr
-.p2align 2
-.hidden .LOPENSSL_armcap_P_addr
-.type .LOPENSSL_armcap_P_addr, @function
-.LOPENSSL_armcap_P_addr:
-.cfi_startproc
-	hint #34 // bti c
-	adrp x0, OPENSSL_armcap_P
-	add x0, x0, :lo12:OPENSSL_armcap_P
-	ret
-.cfi_endproc
-.size .LOPENSSL_armcap_P_addr, .-.LOPENSSL_armcap_P_addr
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/generic-FileDirectives/out.s b/src/util/fipstools/delocate/testdata/generic-FileDirectives/out.s
index 84b5134..b2e3daa 100644
--- a/src/util/fipstools/delocate/testdata/generic-FileDirectives/out.s
+++ b/src/util/fipstools/delocate/testdata/generic-FileDirectives/out.s
@@ -11,17 +11,6 @@
 .text
 .loc 1002 2 0
 BORINGSSL_bcm_text_end:
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s b/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s
index 2d31363..1dceb5b 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s
@@ -19,15 +19,26 @@
 
 	# .bss handling is terminated by a .text directive.
 	.text
+not_bss1:
+	ret
+
+	# The .bss directive can introduce BSS.
+	.bss
+test:
+	.quad 0
+	.text
+not_bss2:
+	ret
+
 	.section .bss,"awT",@nobits
 y:
 	.quad 0
 
-	# Or a .section directive.
+	# A .section directive also terminates BSS.
 	.section .rodata
 	.quad 0
 
-	# Or the end of the file.
+	# The end of the file terminates BSS.
 	.section .bss,"awT",@nobits
 z:
 	.quad 0
diff --git a/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s b/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s
index 2bb54a8..4a5be91 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s
@@ -25,18 +25,33 @@
 
 	# .bss handling is terminated by a .text directive.
 	.text
+.Lnot_bss1_local_target:
+not_bss1:
+	ret
+
+	# The .bss directive can introduce BSS.
+	.bss
+test:
+.Ltest_local_target:
+
+	.quad 0
+	.text
+.Lnot_bss2_local_target:
+not_bss2:
+	ret
+
 	.section .bss,"awT",@nobits
 y:
 .Ly_local_target:
 
 	.quad 0
 
-	# Or a .section directive.
+	# A .section directive also terminates BSS.
 # WAS .section .rodata
 .text
 	.quad 0
 
-	# Or the end of the file.
+	# The end of the file terminates BSS.
 	.section .bss,"awT",@nobits
 z:
 .Lz_local_target:
@@ -53,6 +68,10 @@
 aes_128_ctr_generic_storage2_bss_get:
 	leaq	aes_128_ctr_generic_storage2(%rip), %rax
 	ret
+.type test_bss_get, @function
+test_bss_get:
+	leaq	.Ltest_local_target(%rip), %rax
+	ret
 .type x_bss_get, @function
 x_bss_get:
 	leaq	.Lx_local_target(%rip), %rax
@@ -65,17 +84,6 @@
 z_bss_get:
 	leaq	.Lz_local_target(%rip), %rax
 	ret
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s b/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s
index f9c9fce..b0b90b0 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s
@@ -60,17 +60,6 @@
 .text
 .loc 2 2 0
 BORINGSSL_bcm_text_end:
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
index 3b7a1ed..bec92c5 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
@@ -1,18 +1,6 @@
 	.text
 foo:
 bar:
-	# leaq of OPENSSL_ia32cap_P is supported.
-	leaq OPENSSL_ia32cap_P(%rip), %r11
-
-	# As is the equivalent GOTPCREL movq.
-	movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12
-
-	# And a non-movq instruction via the GOT.
-	orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12
-
-	# ... which targets the default temp register
-	orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax
-
 	# Test that GOTPCREL accesses get translated. They are handled
 	# differently for local and external symbols.
 
@@ -39,7 +27,6 @@
 	# Synthesized symbols do not use the GOT.
 	movq BORINGSSL_bcm_text_start@GOTPCREL(%rip), %r11
 	movq foobar_bss_get@GOTPCREL(%rip), %r11
-	movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11
 
 	# Transforming moves run the transform in-place after the load.
 	vpbroadcastq stderr@GOTPCREL(%rip), %xmm0
diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
index ae47e41..f77f907 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
@@ -7,48 +7,6 @@
 foo:
 .Lbar_local_target:
 bar:
-	# leaq of OPENSSL_ia32cap_P is supported.
-# WAS leaq OPENSSL_ia32cap_P(%rip), %r11
-	leaq -128(%rsp), %rsp
-	pushfq
-	leaq	OPENSSL_ia32cap_addr_delta(%rip), %r11
-	addq	(%r11), %r11
-	popfq
-	leaq 128(%rsp), %rsp
-
-	# As is the equivalent GOTPCREL movq.
-# WAS movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12
-	leaq -128(%rsp), %rsp
-	pushfq
-	leaq	OPENSSL_ia32cap_addr_delta(%rip), %r12
-	addq	(%r12), %r12
-	popfq
-	leaq 128(%rsp), %rsp
-
-	# And a non-movq instruction via the GOT.
-# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12
-	leaq -128(%rsp), %rsp
-	pushq %rax
-	pushfq
-	leaq	OPENSSL_ia32cap_addr_delta(%rip), %rax
-	addq	(%rax), %rax
-	popfq
-	orq %rax, %r12
-	popq %rax
-	leaq 128(%rsp), %rsp
-
-	# ... which targets the default temp register
-# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax
-	leaq -128(%rsp), %rsp
-	pushq %rbx
-	pushfq
-	leaq	OPENSSL_ia32cap_addr_delta(%rip), %rbx
-	addq	(%rbx), %rbx
-	popfq
-	orq %rbx, %rax
-	popq %rbx
-	leaq 128(%rsp), %rsp
-
 	# Test that GOTPCREL accesses get translated. They are handled
 	# differently for local and external symbols.
 
@@ -149,8 +107,6 @@
 	leaq	BORINGSSL_bcm_text_start(%rip), %r11
 # WAS movq foobar_bss_get@GOTPCREL(%rip), %r11
 	leaq	foobar_bss_get(%rip), %r11
-# WAS movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11
-	leaq	.LOPENSSL_ia32cap_get_local_target(%rip), %r11
 
 	# Transforming moves run the transform in-place after the load.
 # WAS vpbroadcastq stderr@GOTPCREL(%rip), %xmm0
@@ -296,17 +252,6 @@
 stderr_GOTPCREL_external:
 	.long stderr@GOTPCREL
 	.long 0
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .Lboringssl_got_delta:
 	.quad _GLOBAL_OFFSET_TABLE_-.Lboringssl_got_delta
 .type BORINGSSL_bcm_text_hash, @object
diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
index 92a3a7b..5c2bc62 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
@@ -12,6 +12,11 @@
 	jbe foo
 	jne foo
 
+	# This also applies to symbols defined with .set
+	call foo1
+	call foo2
+	call foo3
+
 	# Jumps to PLT symbols are rewritten through redirectors.
 	call memcpy@PLT
 	jmp memcpy@PLT
@@ -24,9 +29,6 @@
 	notrack jmp foo@PLT
 	jbe foo@PLT
 
-	# Synthesized symbols are treated as local ones.
-	call OPENSSL_ia32cap_get@PLT
-
 	# References to local labels are left as-is in the first file.
 .Llocal_label:
 	jbe .Llocal_label
@@ -50,3 +52,12 @@
 
 	.quad 2b - 1b
 	.quad 2b - .L2
+
+	# .set directives should get local targets and have their references (above)
+	# rewritten.
+	.globl foo1
+	.globl foo2
+	.globl foo3
+	.set foo1, foo
+	.equ foo2, foo
+	.equiv foo3, foo
diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
index b925655..e86f5b2 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
@@ -1,4 +1,4 @@
-	# References to local labels are rewrittenn in subsequent files.
+	# References to local labels are rewritten in subsequent files.
 .Llocal_label:
 	jbe .Llocal_label
 	leaq .Llocal_label+2048(%rip), %r14
@@ -17,3 +17,19 @@
 # will store offsets in it.
 .byte   (.LBB231_40-.LBB231_19)>>2, 4, .Lfoo, (.Lfoo), .Lfoo<<400, (   .Lfoo ) <<  66
 .byte   421
+
+# .set directives defining local symbols should be rewritten.
+.set .Llocally_set_symbol1, 1
+.equ .Llocally_set_symbol2, 2
+.equiv .Llocally_set_symbol3, 3
+
+# References to local symbols in .set directives should be rewritten.
+.set alias_to_local_label, .Llocal_label
+.equ alias_to_local_label, .Llocal_label
+.equiv alias_to_local_label, .Llocal_label
+.set .Llocal_alias_to_local_label, .Llocal_label
+.equ .Llocal_alias_to_local_label, .Llocal_label
+.equiv .Llocal_alias_to_local_label, .Llocal_label
+
+	# When rewritten, AVX-512 tokens are preserved.
+	vpcmpneqq .Llabel(%rip){1to8}, %zmm1, %k0
diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
index f786f13..abc0b71 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
@@ -23,6 +23,14 @@
 # WAS jne foo
 	jne	.Lfoo_local_target
 
+	# This also applies to symbols defined with .set
+# WAS call foo1
+	call	.Lfoo1_local_target
+# WAS call foo2
+	call	.Lfoo2_local_target
+# WAS call foo3
+	call	.Lfoo3_local_target
+
 	# Jumps to PLT symbols are rewritten through redirectors.
 # WAS call memcpy@PLT
 	call	bcm_redirector_memcpy
@@ -43,10 +51,6 @@
 # WAS jbe foo@PLT
 	jbe	.Lfoo_local_target
 
-	# Synthesized symbols are treated as local ones.
-# WAS call OPENSSL_ia32cap_get@PLT
-	call	.LOPENSSL_ia32cap_get_local_target
-
 	# References to local labels are left as-is in the first file.
 .Llocal_label:
 
@@ -76,7 +80,19 @@
 
 	.quad 2b - 1b
 	.quad 2b - .L2
-	# References to local labels are rewrittenn in subsequent files.
+
+	# .set directives should get local targets and have their references (above)
+	# rewritten.
+	.globl foo1
+	.globl foo2
+	.globl foo3
+	.set foo1, foo
+	.set	.Lfoo1_local_target, foo
+	.equ foo2, foo
+	.equ	.Lfoo2_local_target, foo
+	.equiv foo3, foo
+	.equiv	.Lfoo3_local_target, foo
+	# References to local labels are rewritten in subsequent files.
 .Llocal_label_BCM_1:
 
 # WAS jbe .Llocal_label
@@ -106,23 +122,41 @@
 # WAS .byte   (.LBB231_40-.LBB231_19)>>2, 4, .Lfoo, (.Lfoo), .Lfoo<<400, (   .Lfoo ) <<  66
 	.byte	(.LBB231_40_BCM_1-.LBB231_19_BCM_1)>>2, 4, .Lfoo_BCM_1, (.Lfoo_BCM_1), .Lfoo_BCM_1<<400, (.Lfoo_BCM_1)<<66
 .byte   421
+
+# .set directives defining local symbols should be rewritten.
+# WAS .set .Llocally_set_symbol1, 1
+	.set	.Llocally_set_symbol1_BCM_1, 1
+# WAS .equ .Llocally_set_symbol2, 2
+	.equ	.Llocally_set_symbol2_BCM_1, 2
+# WAS .equiv .Llocally_set_symbol3, 3
+	.equiv	.Llocally_set_symbol3_BCM_1, 3
+
+# References to local symbols in .set directives should be rewritten.
+# WAS .set alias_to_local_label, .Llocal_label
+	.set	alias_to_local_label, .Llocal_label_BCM_1
+	.set	.Lalias_to_local_label_local_target, .Llocal_label_BCM_1
+# WAS .equ alias_to_local_label, .Llocal_label
+	.equ	alias_to_local_label, .Llocal_label_BCM_1
+	.equ	.Lalias_to_local_label_local_target, .Llocal_label_BCM_1
+# WAS .equiv alias_to_local_label, .Llocal_label
+	.equiv	alias_to_local_label, .Llocal_label_BCM_1
+	.equiv	.Lalias_to_local_label_local_target, .Llocal_label_BCM_1
+# WAS .set .Llocal_alias_to_local_label, .Llocal_label
+	.set	.Llocal_alias_to_local_label_BCM_1, .Llocal_label_BCM_1
+# WAS .equ .Llocal_alias_to_local_label, .Llocal_label
+	.equ	.Llocal_alias_to_local_label_BCM_1, .Llocal_label_BCM_1
+# WAS .equiv .Llocal_alias_to_local_label, .Llocal_label
+	.equiv	.Llocal_alias_to_local_label_BCM_1, .Llocal_label_BCM_1
+
+	# When rewritten, AVX-512 tokens are preserved.
+# WAS vpcmpneqq .Llabel(%rip){1to8}, %zmm1, %k0
+	vpcmpneqq	.Llabel_BCM_1(%rip){1to8}, %zmm1, %k0
 .text
 .loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type bcm_redirector_memcpy, @function
 bcm_redirector_memcpy:
 	jmp	memcpy@PLT
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-LargeMemory/out.s b/src/util/fipstools/delocate/testdata/x86_64-LargeMemory/out.s
index 091e8b7..ebdf28b 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-LargeMemory/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-LargeMemory/out.s
@@ -41,17 +41,6 @@
 .text
 .loc 1 2 0
 BORINGSSL_bcm_text_end:
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .Lboringssl_got_delta:
 	.quad _GLOBAL_OFFSET_TABLE_-.Lboringssl_got_delta
 .Lboringssl_got_h:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s b/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s
index 1112387..c35826b 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s
@@ -47,17 +47,6 @@
 .text
 .loc 1 2 0
 BORINGSSL_bcm_text_end:
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s b/src/util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s
index 7a57ed4..2e4ba11 100644
--- a/src/util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s
+++ b/src/util/fipstools/delocate/testdata/x86_64-ThreeArg/out.s
@@ -34,17 +34,6 @@
 .text
 .loc 1 2 0
 BORINGSSL_bcm_text_end:
-.type OPENSSL_ia32cap_get, @function
-.globl OPENSSL_ia32cap_get
-.LOPENSSL_ia32cap_get_local_target:
-OPENSSL_ia32cap_get:
-	leaq OPENSSL_ia32cap_P(%rip), %rax
-	ret
-.extern OPENSSL_ia32cap_P
-.type OPENSSL_ia32cap_addr_delta, @object
-.size OPENSSL_ia32cap_addr_delta, 8
-OPENSSL_ia32cap_addr_delta:
-.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta
 .type BORINGSSL_bcm_text_hash, @object
 .size BORINGSSL_bcm_text_hash, 32
 BORINGSSL_bcm_text_hash:
diff --git a/src/util/fipstools/hex-search-modify.go b/src/util/fipstools/hex-search-modify.go
index 7484f25..f52b9c0 100644
--- a/src/util/fipstools/hex-search-modify.go
+++ b/src/util/fipstools/hex-search-modify.go
@@ -32,7 +32,6 @@
 	"bytes"
 	"encoding/hex"
 	"fmt"
-	"io/ioutil"
 	"os"
 )
 
@@ -53,7 +52,7 @@
 	}
 
 	// Read file contents
-	content, err := ioutil.ReadFile(filePath)
+	content, err := os.ReadFile(filePath)
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Error reading file:", err)
 		os.Exit(1)
diff --git a/src/util/fipstools/test-break-kat.sh b/src/util/fipstools/test-break-kat.sh
index b3b6283..01c13c3 100644
--- a/src/util/fipstools/test-break-kat.sh
+++ b/src/util/fipstools/test-break-kat.sh
@@ -18,7 +18,7 @@
 set -x
 set -e
 
-TEST_FIPS_BIN="build/util/fipstools/test_fips"
+TEST_FIPS_BIN="build/test_fips"
 
 if [ ! -f $TEST_FIPS_BIN ]; then
   echo "$TEST_FIPS_BIN is missing. Run this script from the top level of a"
diff --git a/src/util/fipstools/test_fips.cc b/src/util/fipstools/test_fips.cc
index 2411248..998f5c6 100644
--- a/src/util/fipstools/test_fips.cc
+++ b/src/util/fipstools/test_fips.cc
@@ -20,6 +20,7 @@
 #include <openssl/aead.h>
 #include <openssl/aes.h>
 #include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/ctrdrbg.h>
 #include <openssl/des.h>
@@ -33,6 +34,7 @@
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
+#include "../../crypto/fipsmodule/bcm_interface.h"
 #include "../../crypto/fipsmodule/rand/internal.h"
 #include "../../crypto/fipsmodule/tls/internal.h"
 #include "../../crypto/internal.h"
@@ -134,8 +136,8 @@
   size_t out_len;
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
   OPENSSL_memset(nonce, 0, sizeof(nonce));
-  EVP_AEAD_CTX aead_ctx;
-  if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
+  bssl::ScopedEVP_AEAD_CTX aead_ctx;
+  if (!EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm(), kAESKey,
                          sizeof(kAESKey), 0, NULL)) {
     printf("EVP_AEAD_CTX_init failed\n");
     return 0;
@@ -144,8 +146,8 @@
   /* AES-GCM Encryption */
   printf("About to AES-GCM seal ");
   hexdump(output, sizeof(kPlaintext));
-  if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+  if (!EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
                          kPlaintext, sizeof(kPlaintext), NULL, 0)) {
     printf("AES-GCM encrypt failed\n");
     return 0;
@@ -156,17 +158,15 @@
   /* AES-GCM Decryption */
   printf("About to AES-GCM open ");
   hexdump(output, out_len);
-  if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
-                         EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), output,
-                         out_len, NULL, 0)) {
+  if (!EVP_AEAD_CTX_open(aead_ctx.get(), output, &out_len, sizeof(output),
+                         nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
+                         output, out_len, NULL, 0)) {
     printf("AES-GCM decrypt failed\n");
     return 0;
   }
   printf("  got ");
   hexdump(output, out_len);
 
-  EVP_AEAD_CTX_cleanup(&aead_ctx);
-
   DES_key_schedule des1, des2, des3;
   DES_cblock des_iv;
   DES_set_key(&kDESKey1, &des1);
@@ -406,6 +406,108 @@
   printf("  got ");
   hexdump(dh_result, sizeof(dh_result));
 
+  /* ML-KEM */
+  printf("About to generate ML-KEM key:\n");
+  auto mlkem_public_key_bytes =
+      std::make_unique<uint8_t[]>(BCM_MLKEM768_PUBLIC_KEY_BYTES);
+  auto mlkem_private_key = std::make_unique<BCM_mlkem768_private_key>();
+  if (BCM_mlkem768_generate_key_fips(mlkem_public_key_bytes.get(), nullptr,
+                                     mlkem_private_key.get()) !=
+      bcm_status::approved) {
+    fprintf(stderr, "ML-KEM generation failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(mlkem_public_key_bytes.get(), BCM_MLKEM768_PUBLIC_KEY_BYTES);
+
+  printf("About to do ML-KEM encap:\n");
+  auto mlkem_ciphertext =
+      std::make_unique<uint8_t[]>(BCM_MLKEM768_CIPHERTEXT_BYTES);
+  uint8_t mlkem_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
+  auto mlkem_public_key = std::make_unique<BCM_mlkem768_public_key>();
+  BCM_mlkem768_public_from_private(mlkem_public_key.get(),
+                                   mlkem_private_key.get());
+  if (BCM_mlkem768_encap(mlkem_ciphertext.get(), mlkem_shared_secret,
+                         mlkem_public_key.get()) != bcm_infallible::approved) {
+    fprintf(stderr, "ML-KEM encap failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(mlkem_shared_secret, sizeof(mlkem_shared_secret));
+
+  printf("About to do ML-KEM decap:\n");
+  if (BCM_mlkem768_decap(mlkem_shared_secret, mlkem_ciphertext.get(),
+                         BCM_MLKEM768_CIPHERTEXT_BYTES,
+                         mlkem_private_key.get()) != bcm_status::approved) {
+    fprintf(stderr, "ML-KEM decap failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(mlkem_shared_secret, sizeof(mlkem_shared_secret));
+
+  /* ML-DSA */
+  printf("About to generate ML-DSA key:\n");
+  auto mldsa_public_key_bytes =
+      std::make_unique<uint8_t[]>(BCM_MLDSA65_PUBLIC_KEY_BYTES);
+  uint8_t mldsa_seed[BCM_MLDSA_SEED_BYTES];
+  auto mldsa_priv = std::make_unique<BCM_mldsa65_private_key>();
+  if (BCM_mldsa65_generate_key_fips(mldsa_public_key_bytes.get(), mldsa_seed,
+                                    mldsa_priv.get()) != bcm_status::approved) {
+    fprintf(stderr, "ML-DSA keygen failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(mldsa_public_key_bytes.get(), BCM_MLDSA65_PUBLIC_KEY_BYTES);
+
+  printf("About to ML-DSA sign:\n");
+  auto mldsa_sig = std::make_unique<uint8_t[]>(BCM_MLDSA65_SIGNATURE_BYTES);
+  if (BCM_mldsa65_sign(mldsa_sig.get(), mldsa_priv.get(), nullptr, 0, nullptr,
+                       0) != bcm_status::approved) {
+    fprintf(stderr, "ML-DSA sign failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(mldsa_sig.get(), BCM_MLDSA65_SIGNATURE_BYTES);
+
+  printf("About to ML-DSA verify:\n");
+  auto mldsa_pub = std::make_unique<BCM_mldsa65_public_key>();
+  if (BCM_mldsa65_public_from_private(mldsa_pub.get(), mldsa_priv.get()) !=
+          bcm_status::approved ||
+      BCM_mldsa65_verify(mldsa_pub.get(), mldsa_sig.get(), nullptr, 0, nullptr,
+                         0) != bcm_status::approved) {
+    fprintf(stderr, "ML-DSA verify failed");
+    return 0;
+  }
+
+  /* SLH-DSA */
+  printf("About to generate SLH-DSA key:\n");
+  uint8_t slhdsa_seed[3 * BCM_SLHDSA_SHA2_128S_N] = {0};
+  uint8_t slhdsa_pub[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES];
+  uint8_t slhdsa_priv[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES];
+  BCM_slhdsa_sha2_128s_generate_key_from_seed(slhdsa_pub, slhdsa_priv,
+                                              slhdsa_seed);
+  printf("  got ");
+  hexdump(slhdsa_pub, sizeof(slhdsa_pub));
+
+  printf("About to SLH-DSA sign:\n");
+  auto slhdsa_sig =
+      std::make_unique<uint8_t[]>(BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES);
+  if (BCM_slhdsa_sha2_128s_sign(slhdsa_sig.get(), slhdsa_priv, nullptr, 0,
+                                nullptr, 0) != bcm_status::approved) {
+    fprintf(stderr, "SLH-DSA sign failed");
+    return 0;
+  }
+  printf("  got ");
+  hexdump(slhdsa_sig.get(), 128);  // value too long to fully print
+
+  printf("About to SLH-DSA verify:\n");
+  if (BCM_slhdsa_sha2_128s_verify(
+          slhdsa_sig.get(), BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES, slhdsa_pub,
+          nullptr, 0, nullptr, 0) != bcm_status::approved) {
+    fprintf(stderr, "SLH-DSA verify failed");
+    return 0;
+  }
+
   printf("PASS\n");
   return 1;
 #endif  // !defined(BORINGSSL_FIPS)
diff --git a/src/util/generate_build_files.py b/src/util/generate_build_files.py
index 3a9f2ca..7c5b181 100644
--- a/src/util/generate_build_files.py
+++ b/src/util/generate_build_files.py
@@ -30,6 +30,9 @@
   return x if not PREFIX else os.path.join(PREFIX, x)
 
 
+TARGET_PREFIX = ''
+
+
 LICENSE_TEMPLATE = """Copyright 2015 The BoringSSL Authors
 
 Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,6 +66,7 @@
 """
 
   def PrintVariableSection(self, out, name, files):
+    name = f'{TARGET_PREFIX}{name}'
     out.write('%s := \\\n' % name)
     for f in sorted(files):
       out.write('  %s\\\n' % f)
@@ -98,6 +102,7 @@
 
   def PrintDefaults(self, blueprint, name, files, asm_files=[], data=[]):
     """Print a cc_defaults section from a list of C files and optionally assembly outputs"""
+    name = f'{TARGET_PREFIX}{name}'
     if asm_files:
       blueprint.write('\n')
       blueprint.write('%s_asm = [\n' % name)
@@ -668,12 +673,15 @@
 
 if __name__ == '__main__':
   parser = optparse.OptionParser(
-      usage='Usage: %%prog [--prefix=<path>] [all|%s]' %
+      usage='Usage: %%prog [--prefix=<path>] [--target-prefix=<prefix>] [all|%s]' %
       '|'.join(sorted(ALL_PLATFORMS.keys())))
   parser.add_option('--prefix', dest='prefix',
       help='For Bazel, prepend argument to all source files')
+  parser.add_option('--target-prefix', dest='target_prefix', default='',
+      help='For Android, prepend argument to all target names')
   options, args = parser.parse_args(sys.argv[1:])
   PREFIX = options.prefix
+  TARGET_PREFIX = options.target_prefix
 
   if not args:
     parser.print_help()
diff --git a/src/util/pregenerate/build.go b/src/util/pregenerate/build.go
index 8d62d62..ed73a71 100644
--- a/src/util/pregenerate/build.go
+++ b/src/util/pregenerate/build.go
@@ -234,7 +234,9 @@
 }
 
 func writeMakeVariable(b *bytes.Buffer, name string, val []string) {
-	fmt.Fprintf(b, "\n%s := \\\n", name)
+	// Prefix the variable names to avoid collisions. make builds often use
+	// by inclusion, so variables may not be scoped.
+	fmt.Fprintf(b, "\nboringssl_%s := \\\n", name)
 	for i, v := range val {
 		if i == len(val)-1 {
 			fmt.Fprintf(b, "  %s\n", v)
@@ -312,6 +314,7 @@
 		buildVariablesTask(targets, "gen/sources.bzl", "#", writeBazelVariable),
 		buildVariablesTask(targets, "gen/sources.cmake", "#", writeCMakeVariable),
 		buildVariablesTask(targets, "gen/sources.gni", "#", writeGNVariable),
+		buildVariablesTask(targets, "gen/sources.mk", "#", writeMakeVariable),
 		jsonTask(targets, "gen/sources.json"),
 	}
 }
diff --git a/src/util/pregenerate/err_data.go b/src/util/pregenerate/err_data.go
index e88bef9..8eb1a06 100644
--- a/src/util/pregenerate/err_data.go
+++ b/src/util/pregenerate/err_data.go
@@ -61,6 +61,7 @@
 	"CIPHER",
 	"HKDF",
 	"TRUST_TOKEN",
+	"CMS",
 	"USER",
 }